diff --git a/src/main/resources/config_bz.xml b/src/main/resources/config_bz.xml
index b1381dfe78515794a103c6f3067c3b7d199ccec0..b267c34ef824bb1ffb1a7b28a89921f98b2ba4c2 100644
--- a/src/main/resources/config_bz.xml
+++ b/src/main/resources/config_bz.xml
@@ -34,7 +34,6 @@
 	<entry key="sql.spatial.dim2.lower">5142889</entry>
 	<entry key="sql.spatial.dim2.upper">5159502</entry>
 	<entry key="sql.spatial.dim2.tolerance">0.001</entry>
-	<entry key="sql.spatial.srid">82344</entry>
 
 	<!-- Tables for MrneX -->
 	<entry key="tbl.edge.density">bz_edge_density</entry>
diff --git a/src/main/webapp/META-INF/MANIFEST.MF b/src/main/webapp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..275bbb5efe10cdeaef0cfeeaac967eac653ad746
--- /dev/null
+++ b/src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Class-Path: 
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000000000000000000000000000000000..892bba75dd7f8888e1d291f48853bc33cacbe21a
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app id="minex" version="2.5" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">
+	<display-name>Using Isochrones for Geospatial Analysis</display-name>
+	<welcome-file-list>
+		<welcome-file>index.jsp</welcome-file>
+	</welcome-file-list>
+	<context-param>
+		<param-name>Debug</param-name>
+		<param-value>true</param-value>
+	</context-param>
+	<servlet>
+		<servlet-name>cometd</servlet-name>
+		<servlet-class>org.cometd.server.CometdServlet</servlet-class>
+		<init-param>
+			<param-name>transports</param-name>
+			<param-value>org.cometd.websocket.server.WebSocketTransport</param-value>
+		</init-param>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>cometd</servlet-name>
+		<url-pattern>/cometd/*</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>initializer</servlet-name>
+		<servlet-class>it.unibz.inf.isoga.comet.IsochronesCometdServlet</servlet-class>
+		<load-on-startup>2</load-on-startup>
+	</servlet>
+	<servlet>
+		<servlet-name>proxy</servlet-name>
+		<servlet-class>it.unibz.inf.isoga.proxy.OpenLayersProxy</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>proxy</servlet-name>
+		<url-pattern>/proxy/*</url-pattern>
+	</servlet-mapping>
+	<filter>
+		<filter-name>
+			cross-origin
+		</filter-name>
+		<filter-class>
+			org.eclipse.jetty.servlets.CrossOriginFilter
+		</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>
+			cross-origin
+		</filter-name>
+		<url-pattern>
+			/cometd/*
+		</url-pattern>
+	</filter-mapping>
+</web-app>
diff --git a/src/main/webapp/css/isodemo.css b/src/main/webapp/css/isodemo.css
new file mode 100644
index 0000000000000000000000000000000000000000..d7936c4e27785c809ba32a307e92c2038459a933
--- /dev/null
+++ b/src/main/webapp/css/isodemo.css
@@ -0,0 +1,111 @@
+/*#map {
+                clear: both;
+                position: relative;
+                width: 400px;
+                height: 450px;
+                border: 1px solid black;
+            }
+            
+            html, body {
+            font: normal 12px verdana;
+            margin: 0;
+            padding: 0;
+            border: 0 none;
+            overflow: hidden;
+            height: 100%;
+            }*/
+.settings .x-panel-body {
+	padding: 10px 5px 0px 10px;
+	/*padding-top:10px;
+                padding-left:10px;
+                text-align:center;*/
+	font-family: tahoma, arial, helvetica, sans-serif;
+	font-weight: normal;
+	/*font-style:italic;
+                color: gray;*/
+	font-size: 12px;
+}
+
+#ext-gen29 {
+	margin-left: 50px;
+	margin-top: 15px;
+}
+
+#ext-gen31 {
+	margin-left: 50px;
+	margin-top: 10px;
+}
+
+#ext-gen97 {
+	padding-left: 0px !important;
+	padding-top: 30px;
+	width: 172px;
+}
+
+#ext-gen100 {
+	padding-bottom: 15px;
+}
+
+.olControlAttribution {
+	left: 2px;
+	right: inherit;
+	bottom: 3px;
+	line-height: 11px;
+}
+
+.olControlLoadingPanel {
+	background-image: url(./img/ajax-loader.gif);
+	margin-left: 46%;
+	margin-top: 35%;
+	position: relative;
+	width: 66px;
+	height: 66px;
+	background-position: center;
+	background-repeat: no-repeat;
+	display: none;
+}
+
+.olControlScaleLineTop {
+	background: lightgrey;
+	padding: 1px;
+	font-size: 10px;
+	margin-bottom: -10px !important;
+}
+
+.olControlMousePosition {
+	background: lightgrey;
+	padding: 1px !important;
+	font-size: 10px !important;
+	margin-bottom: 10px;
+	margin-right: 5px;
+}
+
+.x-tree-node {
+	border-bottom: 0px solid #dddddd;
+	padding-bottom: 3px;
+}
+
+.x-tree-ec-icon {
+	display: none;
+}
+
+.x-grid3-row {
+	padding: 3px 0px 3px 0px;
+	/*border-right-color:#ffffff;*/
+}
+
+.bnt_last {
+	background-image: url(img/page-last.gif) !important;
+}
+
+.bnt_first {
+	background-image: url(img/page-first.gif) !important;
+}
+
+.bnt_next {
+	background-image: url(img/page-next.gif) !important;
+}
+
+.bnt_prev {
+	background-image: url(img/page-prev.gif) !important;
+}
\ No newline at end of file
diff --git a/src/main/webapp/css/styles.css b/src/main/webapp/css/styles.css
new file mode 100644
index 0000000000000000000000000000000000000000..a71c508fe38a168a025e1f99a52d617508bb91f7
--- /dev/null
+++ b/src/main/webapp/css/styles.css
@@ -0,0 +1,254 @@
+.styleIsoTabMenu {
+	position: absolute;
+  top: 5px; 
+  right: 9px;
+  width: 125px; 
+  height: 20px;
+  z-index: 106; 
+  background: #cccccc;
+	background-image: url("../img/arrowDown.png") no-repeat scroll right top;
+	background-size: 10px;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: center;
+  font-style: normal;
+}
+
+.styleHomeTabMenu {
+	position: absolute;
+  top: 5px; 
+  right: 255px;
+  width: 125px; 
+  height: 20px;
+  z-index: 106; 
+  background: #cccccc;
+	background-size: 10px;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: center;
+  font-style: normal;
+}
+
+.styleHelpTabMenu {
+	position: absolute;
+  top: 5px; 
+  right: 135px;
+  width: 130px; 
+  height: 20px;
+  z-index: 106; 
+  /*display: none;*/
+	background: #cccccc;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: center;	
+}
+
+.styleIsoTabPane {
+	position: absolute;
+	top: 20px;
+	left: -245px;
+	width: 350px;
+	z-index: 999;
+	/*display: none;*/
+	background: #cccccc;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  font-size:smaller;
+  font-family: sans-serif;
+}
+
+
+
+.styleHelpTabPane {
+		position: absolute;
+	top: 20px;
+	left: -391px;
+	/*height: 550px;*/
+	width: 520px;
+	z-index: 999;
+	background: #cccccc;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: left;
+  font-size:smaller;
+  font-family: sans-serif;
+}
+
+.styleResultTabPane{
+	position: absolute;
+	bottom: 50px;
+	left: 10px;
+	/*
+	top: 280px;
+	right: 9px;
+	*/
+	height: 100px;
+	width: 250px;
+	z-index: 999;
+	background: #cccccc;
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: left;
+  font-size: large;
+}
+
+.styleLegendPane{
+	position: absolute;
+	bottom: 50px;
+	left: 10px;
+	/*
+	top: 280px;
+	right: 9px;
+	*/
+	height: 80px;
+	width: 120px;
+	z-index: 999;
+	/*background: #cccccc;*/
+  border: thin; 
+  border-top-style: solid;
+  border-left-style: solid;
+  border-right-style: solid;
+  border-bottom-style: solid;
+  text-align: left;
+  font-size: large;
+}
+
+
+
+.styleArrows {
+	height: 10px;
+	width: 	10px;
+}
+
+.nwIcon {
+	height: 15px;
+	width: 	15px;
+}
+
+.styleTapPaneLink {
+	text-decoration: none;
+}
+
+.inputText{
+	margin-left:15px;
+	font-family: Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+	font-size: 10pt;
+	font-weight: bold; 
+}
+
+input.btn { 
+	  color:white; 
+	  font: bold 84% 'trebuchet ms',helvetica,sans-serif; 
+	  background-color:#7bc142; 
+	  border: 1px solid; 	  
+} 
+
+.menuText{
+	margin-left:15px;
+	margin-right:20px;
+	font-family: Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+	font-size: 10pt;
+}
+
+.menuItem{
+	color:black;
+	font-weight: bold; 
+	font-family: Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+
+.styleProgressBar {
+	z-index:200;
+	visibility:collapse;
+	position:absolute;
+	width: 200px;
+}
+
+.styleParameters {
+	border:thin;
+	border-color:black;
+	border-style:solid;
+}
+
+fieldset
+{
+	border: 1px solid #000000;
+	border:thin;
+	border-color:black;
+	border-style:solid;
+	font-weight: bold;
+	font-size: 10pt;
+}
+
+label {
+	font-family: Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+	font-weight: lighter;
+}
+
+.styleLabel {
+	font-family: Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+	font-weight: lighter;
+}
+
+/** 
+Overriding Openlayers properties
+**/
+
+/* required to position the layer switcher in a bottom right position*/
+.olControlLayerSwitcher {
+	top: 75%;
+}
+
+/* removes the annoying label in google maps */
+.olLayerGoogleV3 {
+	visibility: hidden;
+}
+
+.olControlLoadingPanel {
+	background-image: url(../img/ajax-loader.gif);
+	margin-left: 46%;
+	margin-top: 35%;
+	position: relative;
+	width: 66px;
+	height: 66px;
+	background-position: center;
+	background-repeat: no-repeat;
+	display: none;
+}
+
+
+/*
+.ui-progressbar-value { background-image: url(../lib/jquery/css/images/pbar-ani.gif); }
+*/
+
+/* the time picker */
+/* css for timepicker */
+.ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }
+.ui-timepicker-div dl{ text-align: left; }
+.ui-timepicker-div dl dt{ height: 25px; }
+.ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }
+.ui-timepicker-div .ui_tpicker_hour div { padding-right: 2px; }
+.ui-timepicker-div .ui_tpicker_minute div { padding-right: 6px; }
+.ui-timepicker-div .ui_tpicker_second div { padding-right: 6px; }
+.ui-timepicker-div td { font-size: 90%; }
+
diff --git a/src/main/webapp/img/Thumbs.db b/src/main/webapp/img/Thumbs.db
new file mode 100644
index 0000000000000000000000000000000000000000..a837b9c7dfcc5482316d434374b601e7089be2a1
Binary files /dev/null and b/src/main/webapp/img/Thumbs.db differ
diff --git a/src/main/webapp/img/ajax-loader.gif b/src/main/webapp/img/ajax-loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0ca7ada960568fff04400cda966fbdcb106abfa2
Binary files /dev/null and b/src/main/webapp/img/ajax-loader.gif differ
diff --git a/src/main/webapp/img/arrowDown.png b/src/main/webapp/img/arrowDown.png
new file mode 100644
index 0000000000000000000000000000000000000000..970c6c651a3f3766c3e9e386b383354ca25346a8
Binary files /dev/null and b/src/main/webapp/img/arrowDown.png differ
diff --git a/src/main/webapp/img/arrowUp.png b/src/main/webapp/img/arrowUp.png
new file mode 100644
index 0000000000000000000000000000000000000000..fcdc5200ed968b02efbcd9bf3a9b48b2e4fad542
Binary files /dev/null and b/src/main/webapp/img/arrowUp.png differ
diff --git a/src/main/webapp/img/bus.png b/src/main/webapp/img/bus.png
new file mode 100755
index 0000000000000000000000000000000000000000..4516c824c31092ea3135e054947b73b4ec8f0d14
Binary files /dev/null and b/src/main/webapp/img/bus.png differ
diff --git a/src/main/webapp/img/cal.gif b/src/main/webapp/img/cal.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8526cf5d19a915aa8073cf344873c4505491970d
Binary files /dev/null and b/src/main/webapp/img/cal.gif differ
diff --git a/src/main/webapp/img/car.png b/src/main/webapp/img/car.png
new file mode 100755
index 0000000000000000000000000000000000000000..6c020437963e0ab51c9b41c4035f7a8f5e9d05c5
Binary files /dev/null and b/src/main/webapp/img/car.png differ
diff --git a/src/main/webapp/img/clock.png b/src/main/webapp/img/clock.png
new file mode 100644
index 0000000000000000000000000000000000000000..d563812ada883088d52890abb4cca5a992a39af4
Binary files /dev/null and b/src/main/webapp/img/clock.png differ
diff --git a/src/main/webapp/img/folder.gif b/src/main/webapp/img/folder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..501e75c01938b9e355a695e707911606c044121b
Binary files /dev/null and b/src/main/webapp/img/folder.gif differ
diff --git a/src/main/webapp/img/funicular.png b/src/main/webapp/img/funicular.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0a48f939cfcda7fc79c7186a925e30e1149713b
Binary files /dev/null and b/src/main/webapp/img/funicular.png differ
diff --git a/src/main/webapp/img/gondola.png b/src/main/webapp/img/gondola.png
new file mode 100644
index 0000000000000000000000000000000000000000..33117ca434322b1e76679746f8e5630015af77da
Binary files /dev/null and b/src/main/webapp/img/gondola.png differ
diff --git a/src/main/webapp/img/kindergarten.png b/src/main/webapp/img/kindergarten.png
new file mode 100644
index 0000000000000000000000000000000000000000..68dc2fcb92fc179d127ae1f1de02d3bcb87992af
Binary files /dev/null and b/src/main/webapp/img/kindergarten.png differ
diff --git a/src/main/webapp/img/next_mon.gif b/src/main/webapp/img/next_mon.gif
new file mode 100644
index 0000000000000000000000000000000000000000..14c622f91400c9a8d8b9d41918e1c2c1cd6ac987
Binary files /dev/null and b/src/main/webapp/img/next_mon.gif differ
diff --git a/src/main/webapp/img/next_year.gif b/src/main/webapp/img/next_year.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b66f2888bc2596174993d91dc1cdf758408096f9
Binary files /dev/null and b/src/main/webapp/img/next_year.gif differ
diff --git a/src/main/webapp/img/no_cal.gif b/src/main/webapp/img/no_cal.gif
new file mode 100644
index 0000000000000000000000000000000000000000..adc58e2a840ee4b95febddf7e9dcb0be27ea1ede
Binary files /dev/null and b/src/main/webapp/img/no_cal.gif differ
diff --git a/src/main/webapp/img/outdoor.png b/src/main/webapp/img/outdoor.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e8b91f227d50b4858ab4b93603c0e1df9021c53
Binary files /dev/null and b/src/main/webapp/img/outdoor.png differ
diff --git a/src/main/webapp/img/ped.png b/src/main/webapp/img/ped.png
new file mode 100644
index 0000000000000000000000000000000000000000..e604ea33f2ed5ba575c5adb692eba265621472cd
Binary files /dev/null and b/src/main/webapp/img/ped.png differ
diff --git a/src/main/webapp/img/pixel.gif b/src/main/webapp/img/pixel.gif
new file mode 100644
index 0000000000000000000000000000000000000000..46a2cf086ca4829b2afacec093d4562ec6c16f59
Binary files /dev/null and b/src/main/webapp/img/pixel.gif differ
diff --git a/src/main/webapp/img/poi.png b/src/main/webapp/img/poi.png
new file mode 100755
index 0000000000000000000000000000000000000000..45d734f33864b8a3d325907898f885e9c96aeb3b
Binary files /dev/null and b/src/main/webapp/img/poi.png differ
diff --git a/src/main/webapp/img/poi_black.png b/src/main/webapp/img/poi_black.png
new file mode 100644
index 0000000000000000000000000000000000000000..e20c6bf27a86a53e797ec8e1bb13ae5f13be4bac
Binary files /dev/null and b/src/main/webapp/img/poi_black.png differ
diff --git a/src/main/webapp/img/poi_red.png b/src/main/webapp/img/poi_red.png
new file mode 100644
index 0000000000000000000000000000000000000000..208e691e16ca2451b8f81ebbf2fc502a4706d13c
Binary files /dev/null and b/src/main/webapp/img/poi_red.png differ
diff --git a/src/main/webapp/img/prev_mon.gif b/src/main/webapp/img/prev_mon.gif
new file mode 100644
index 0000000000000000000000000000000000000000..12ce7ff5015454f8a1761372e4dd41247b26120a
Binary files /dev/null and b/src/main/webapp/img/prev_mon.gif differ
diff --git a/src/main/webapp/img/prev_year.gif b/src/main/webapp/img/prev_year.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c726b0e45b97072d3e5c177d41f88a6a83a4f1d9
Binary files /dev/null and b/src/main/webapp/img/prev_year.gif differ
diff --git a/src/main/webapp/img/prim_school.gif b/src/main/webapp/img/prim_school.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8fa4eb166d010242a74c9d7c6091412131a71483
Binary files /dev/null and b/src/main/webapp/img/prim_school.gif differ
diff --git a/src/main/webapp/img/prim_school.png b/src/main/webapp/img/prim_school.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b1c40b7caebfd58078d9e9e5ceaadedb42e8d99
Binary files /dev/null and b/src/main/webapp/img/prim_school.png differ
diff --git a/src/main/webapp/img/school-icon.png b/src/main/webapp/img/school-icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..8bce62db8a33b025cab7d179342955cb62228055
Binary files /dev/null and b/src/main/webapp/img/school-icon.png differ
diff --git a/src/main/webapp/img/sec_school.png b/src/main/webapp/img/sec_school.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d53e138036338f6d495c92bdc6c2696302dd4b2
Binary files /dev/null and b/src/main/webapp/img/sec_school.png differ
diff --git a/src/main/webapp/img/shade_bl.png b/src/main/webapp/img/shade_bl.png
new file mode 100644
index 0000000000000000000000000000000000000000..29bd5543b95125ef5e09fb8ad433fb5f83eceb39
Binary files /dev/null and b/src/main/webapp/img/shade_bl.png differ
diff --git a/src/main/webapp/img/shade_bm.png b/src/main/webapp/img/shade_bm.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c4e0af92017b65046a13098918f1e3eef644bb3
Binary files /dev/null and b/src/main/webapp/img/shade_bm.png differ
diff --git a/src/main/webapp/img/shade_br.png b/src/main/webapp/img/shade_br.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce8a2fad28005dadd783895d07d46462ed38dd9f
Binary files /dev/null and b/src/main/webapp/img/shade_br.png differ
diff --git a/src/main/webapp/img/shade_mr.png b/src/main/webapp/img/shade_mr.png
new file mode 100644
index 0000000000000000000000000000000000000000..4594bc4e22e1ef12bc1b19e62ff1925d0c8678cd
Binary files /dev/null and b/src/main/webapp/img/shade_mr.png differ
diff --git a/src/main/webapp/img/star.png b/src/main/webapp/img/star.png
new file mode 100644
index 0000000000000000000000000000000000000000..e698b9c58697668bafb73c185a4b4fe23dbfaec3
Binary files /dev/null and b/src/main/webapp/img/star.png differ
diff --git a/src/main/webapp/img/swimming.svg b/src/main/webapp/img/swimming.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b01946a6a031bf380e4e6c1ec9870a04935f1c20
--- /dev/null
+++ b/src/main/webapp/img/swimming.svg
@@ -0,0 +1,2451 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 10.0, SVG Export Plug-In . SVG Version: 3.0.0 Build 77)  --><svg enable-background="new 0 0 455.148 454.788" height="454.788" i:pageBounds="0 792 612 0" i:rulerOrigin="0 0" i:viewOrigin="78 623" overflow="visible" space="preserve" viewBox="0 0 455.148 454.788" width="455.148" xmlns="http://www.w3.org/2000/svg" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <metadata>
+    <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+      <cc:Work rdf:about="">
+        <dc:title>Hotel Icon Swimming Pool</dc:title>
+        <dc:description>Part of Hotel Icons Collection</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>symbol</rdf:li>
+            <rdf:li>hotel</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent rdf:about="http://www.openclipart.org/">
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Gerald G.</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Gerald G.</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date></dc:date>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+        <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+        <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+        <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <switch>
+    <foreignObject height="1" requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" width="1" x="0" y="0">
+      <i:pgfRef xlink:href="#adobe_illustrator_pgf"></i:pgfRef>
+    </foreignObject>
+    <g i:extraneous="self">
+      <g i:dimmedPercent="50" i:layer="yes" i:rgbTrio="#4F008000FFFF" id="Layer_1">
+        <path clip-rule="evenodd" d="M227.394,0H18C8.059,0,0,8.059,0,18v418.788      c0,9.94,8.059,18,18,18h418.787c9.941,0,18-8.06,18-18V18c0-9.941-8.059-18-18-18H227.394z" fill="#E5E5E5" fill-rule="evenodd" i:knockout="Off"/>
+        <linearGradient gradientUnits="userSpaceOnUse" id="XMLID_1_" x1="424.3672" x2="455.1484" y1="227.7358" y2="227.7358">
+          <stop offset="0" style="stop-color:#E5E5E5"/>
+          <stop offset="0.1696" style="stop-color:#E2E2E2"/>
+          <stop offset="0.3059" style="stop-color:#D8D8D8"/>
+          <stop offset="0.4306" style="stop-color:#C7C7C7"/>
+          <stop offset="0.5484" style="stop-color:#B0B0B0"/>
+          <stop offset="0.6614" style="stop-color:#919191"/>
+          <stop offset="0.7707" style="stop-color:#6B6B6B"/>
+          <stop offset="0.8772" style="stop-color:#3E3E3E"/>
+          <stop offset="0.9788" style="stop-color:#0C0C0C"/>
+          <stop offset="1" style="stop-color:#000000"/>
+          <a:midPointStop offset="0" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="0.75" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="1" style="stop-color:#000000"/>
+        </linearGradient>
+        <path clip-rule="evenodd" d="M449.748,449.964l-25.381-25.344      c0.865-0.828,1.584-1.8,2.305-2.772c0.576-1.08,1.367-2.088,1.836-3.168c0.469-1.188,0.648-2.16,0.936-3.348      c0.18-1.188,0.289-2.521,0.324-3.853l-0.145-369.396l0.145,1.908c-0.035-1.368-0.145-2.7-0.324-3.852      c-0.287-1.296-0.467-2.268-0.936-3.348c-0.469-1.188-1.26-2.196-1.836-3.168c-0.721-1.044-1.439-1.908-2.305-2.736l25.381-25.38      c0.684,0.576,1.295,1.332,1.98,2.268c0.611,0.792,1.295,2.016,1.908,3.276c0.432,1.296,1.115,2.916,1.367,4.572      c0.145,1.44,0.145,2.952,0.145,4.68c-0.037,1.692-0.037,3.816,0,5.976v402.912c0.035,2.124,0.035,4.248,0,5.977      c0.035,1.656-0.072,3.168-0.18,4.68c-0.289,1.584-0.865,3.168-1.332,4.608c-0.613,1.224-1.297,2.304-1.908,3.24      C451.043,448.596,450.432,449.352,449.748,449.964z" fill="url(#XMLID_1_)" fill-rule="evenodd" i:knockout="Off"/>
+        <linearGradient gradientUnits="userSpaceOnUse" id="XMLID_2_" x1="30.8516" x2="0.0713" y1="227.376" y2="227.376">
+          <stop offset="0" style="stop-color:#E5E5E5"/>
+          <stop offset="0.2675" style="stop-color:#E2E2E2"/>
+          <stop offset="0.4824" style="stop-color:#D8D8D8"/>
+          <stop offset="0.679" style="stop-color:#C7C7C7"/>
+          <stop offset="0.8635" style="stop-color:#B0B0B0"/>
+          <stop offset="1" style="stop-color:#999999"/>
+          <a:midPointStop offset="0" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="0.75" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="1" style="stop-color:#999999"/>
+        </linearGradient>
+        <path clip-rule="evenodd" d="M5.472,449.604l25.38-25.344      c-0.9-0.828-1.62-1.8-2.304-2.771c-0.684-1.08-1.476-2.089-1.836-3.168c-0.432-1.188-0.792-2.16-0.936-3.349      c-0.252-1.188-0.36-2.52-0.324-3.852l0.144-369.396l-0.144,1.908c-0.036-1.368,0.072-2.7,0.324-3.852      c0.144-1.296,0.504-2.268,0.936-3.348c0.36-1.188,1.152-2.196,1.836-3.168c0.684-1.044,1.404-1.908,2.304-2.736L5.472,5.148      C4.752,5.724,4.14,6.48,3.492,7.416c-0.72,0.828-1.404,1.908-1.908,3.24c-0.54,1.368-1.188,2.952-1.368,4.608      C0,16.704,0,18.216,0.072,19.944c-0.036,1.692-0.036,3.816,0,5.976v402.912c-0.036,2.124-0.036,4.248,0,5.976      C0,436.464,0,437.976,0.216,439.488c0.18,1.584,0.828,3.168,1.368,4.607c0.504,1.225,1.188,2.304,1.908,3.24      C4.14,448.235,4.752,448.992,5.472,449.604z" fill="url(#XMLID_2_)" fill-rule="evenodd" i:knockout="Off"/>
+        <linearGradient gradientUnits="userSpaceOnUse" id="XMLID_3_" x1="227.7358" x2="227.7358" y1="30.8521" y2="0.0718">
+          <stop offset="0" style="stop-color:#E5E5E5"/>
+          <stop offset="0.2675" style="stop-color:#E2E2E2"/>
+          <stop offset="0.4824" style="stop-color:#D8D8D8"/>
+          <stop offset="0.679" style="stop-color:#C7C7C7"/>
+          <stop offset="0.8635" style="stop-color:#B0B0B0"/>
+          <stop offset="1" style="stop-color:#999999"/>
+          <a:midPointStop offset="0" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="0.75" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="1" style="stop-color:#999999"/>
+        </linearGradient>
+        <path clip-rule="evenodd" d="M449.963,5.472l-25.344,25.38      c-0.828-0.9-1.799-1.62-2.771-2.304c-1.08-0.684-2.088-1.476-3.168-1.836c-1.115-0.432-2.123-0.792-3.313-0.936      c-1.223-0.252-2.52-0.36-3.887-0.324L42.084,25.596l1.908-0.144c-1.368,0.036-2.7,0-3.852,0.288      c-1.296,0.144-2.268,0.468-3.348,0.972c-1.188,0.36-2.196,1.152-3.168,1.836c-1.044,0.684-1.908,1.404-2.736,2.304L5.508,5.472      C6.084,4.788,6.84,4.068,7.776,3.456C8.568,2.7,9.792,2.124,11.052,1.584c1.296-0.54,2.916-1.188,4.572-1.368      C17.064,0,18.576,0,20.304,0.072c1.692-0.036,3.816-0.036,5.976,0h402.912c2.125-0.036,4.248-0.036,5.977,0      C436.824,0,438.336,0,439.848,0.216c1.584,0.18,3.168,0.828,4.607,1.368c1.225,0.504,2.305,1.188,3.24,1.908      C448.596,4.14,449.352,4.752,449.963,5.472z" fill="url(#XMLID_3_)" fill-rule="evenodd" i:knockout="Off"/>
+        <linearGradient gradientUnits="userSpaceOnUse" id="XMLID_4_" x1="227.376" x2="227.376" y1="423.8994" y2="454.6797">
+          <stop offset="0" style="stop-color:#E5E5E5"/>
+          <stop offset="0.1696" style="stop-color:#E2E2E2"/>
+          <stop offset="0.3059" style="stop-color:#D8D8D8"/>
+          <stop offset="0.4306" style="stop-color:#C7C7C7"/>
+          <stop offset="0.5484" style="stop-color:#B0B0B0"/>
+          <stop offset="0.6614" style="stop-color:#919191"/>
+          <stop offset="0.7707" style="stop-color:#6B6B6B"/>
+          <stop offset="0.8772" style="stop-color:#3E3E3E"/>
+          <stop offset="0.9788" style="stop-color:#0C0C0C"/>
+          <stop offset="1" style="stop-color:#000000"/>
+          <a:midPointStop offset="0" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="0.75" style="stop-color:#E5E5E5"/>
+          <a:midPointStop offset="1" style="stop-color:#000000"/>
+        </linearGradient>
+        <path clip-rule="evenodd" d="M449.604,449.28l-25.344-25.381      c-0.828,0.828-1.801,1.656-2.771,2.341c-1.08,0.647-2.088,1.296-3.168,1.8c-1.117,0.396-2.125,0.72-3.313,0.972      c-1.225,0.18-2.52,0.288-3.889,0.324l-369.396-0.18l1.908,0.18c-1.368-0.036-2.7-0.145-3.852-0.324      c-1.296-0.252-2.268-0.576-3.348-0.972c-1.188-0.504-2.196-1.152-3.168-1.8c-1.044-0.721-1.908-1.44-2.736-2.305L5.148,449.28      c0.576,0.647,1.332,1.367,2.268,2.016c0.792,0.612,2.016,1.296,3.276,1.908c1.296,0.468,2.916,1.044,4.572,1.332      c1.44,0.144,2.952,0.144,4.68,0.144c1.692-0.036,3.816-0.036,5.976,0h402.912c2.123-0.036,4.248-0.036,5.977,0      c1.654,0,3.168,0,4.68-0.144c1.584-0.252,3.168-0.937,4.607-1.368c1.225-0.648,2.305-1.224,3.24-1.872      C448.236,450.647,448.992,449.928,449.604,449.28z" fill="url(#XMLID_4_)" fill-rule="evenodd" i:knockout="Off"/>
+        <g>
+          <path clip-rule="evenodd" d="M406.968,259.841       c-3.131,0.875-7.366,0.737-12.704-0.415c-5.383-1.197-10.456-7.094-19.5-6.678c-9.31,0.321-22.457,8.66-35.162,8.66       c-12.883-0.229-27.354-9.123-40.5-9.076c-13.103,0.045-25.015,9.261-37.587,9.49c-12.795,0.046-25.544-8.478-38.075-8.66       c-12.705-0.322-24.749,7.554-36.617,7.463c-11.867-0.184-21.97-8.755-33.705-8.293c-11.912,0.416-24.971,9.813-36.617,10.273       c-11.648,0.185-22.367-8.568-32.691-8.66c-10.367-0.186-22.279,6.402-29.294,7.877c-7.06,1.428-11.515,1.383-13.191,0.368       v24.418c1.677,1.015,6.132,1.06,13.191-0.367c7.015-1.475,18.927-8.063,29.294-7.879c10.324,0.093,21.043,8.846,32.691,8.662       c11.646-0.554,24.705-9.767,36.617-10.229c11.735-0.368,21.838,8.016,33.705,8.248c11.868,0.09,23.912-7.786,36.617-7.464       c12.531,0.183,25.28,8.706,38.075,8.661c12.572-0.277,24.484-9.354,37.587-9.445c13.146,0,27.617,8.753,40.5,9.03       c12.705,0,25.853-8.338,35.162-8.661c9.044-0.414,14.117,5.481,19.5,6.679c5.338,1.152,9.573,1.29,12.704,0.415V259.841z" fill="#7F7F7F" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M197.896,246.849l100.896-53.857       c-7.984-17.415-13.456-30.545-16.764-39.897c-3.354-9.307-4.767-11.38-2.869-15.803c1.94-4.561-0.75-5.252,14.03-11.288       c14.822-6.219,58.896-24.325,73.367-25.155c14.029-0.691,13.632,14.789,11.25,20.134c-2.56,5.067-15.706,6.542-25.677,10.458       c-10.06,3.87-21.309,8.201-34.103,12.992l46.234,101.635c-5.956,5.021-13.853,7.048-24.528,6.266       c-10.809-1.06-25.412-11.381-38.868-11.426c-13.589,0.184-28.765,11.471-41.117,11.842       c-12.441-0.049-22.06-9.999-32.427-11.015C216.955,240.722,207.205,242.426,197.896,246.849z" fill="#7F7F7F" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M379.146,158.95       c15.561,0,28.19,13.189,28.19,29.44c0,16.25-12.63,29.438-28.19,29.438c-15.562,0-28.192-13.188-28.192-29.438       C350.954,172.139,363.585,158.95,379.146,158.95" fill="#7F7F7F" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M129.734,248.83       c-11.955-2.212-24.131-5.573-37.367-10.273c-13.323-4.931-36.043-11.335-41.426-17.784c-5.383-6.451-1.456-19.812,9.396-20.363       c10.854-0.691,32.604,9.214,55.015,17.092c22.323,7.878,47.911,17.877,77.955,30.177c-3.705,2.027-8.603,2.627-14.867,1.798       c-6.353-1.061-14.383-6.911-22.544-7.097C147.69,242.242,139.088,244.454,129.734,248.83z" fill="#7F7F7F" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M406.968,300.706       c-3.131,0.877-7.366,0.737-12.704-0.412c-5.383-1.2-10.456-7.097-19.5-6.682c-9.31,0.322-22.457,8.661-35.162,8.661       c-12.883-0.23-27.354-9.121-40.5-9.076c-13.103,0.093-25.015,9.169-37.587,9.446c-12.795,0.045-25.544-8.479-38.075-8.663       c-12.705-0.23-24.749,7.603-36.617,7.511c-11.867-0.186-21.97-8.754-33.705-8.294c-11.912,0.415-24.971,9.813-36.617,10.273       c-11.648,0.229-22.367-8.661-32.691-8.706c-10.367-0.186-22.279,6.404-29.294,7.879c-7.06,1.334-11.515,1.472-13.191,0.412       v24.418c1.677,1.016,6.132,1.061,13.191-0.367c7.015-1.475,18.927-8.063,29.294-7.879c10.324,0.093,21.043,8.847,32.691,8.661       c11.646-0.46,24.705-9.858,36.617-10.273c11.735-0.46,21.838,8.108,33.705,8.294c11.868-0.047,23.912-7.648,36.617-7.512       c12.531,0.093,25.28,8.801,38.075,8.709c12.572-0.23,24.484-9.446,37.587-9.491c13.146-0.045,27.617,8.846,40.5,9.076       c12.705,0,25.853-8.339,35.162-8.661c9.044-0.415,14.117,5.481,19.5,6.68c5.338,1.152,9.573,1.291,12.704,0.414V300.706z" fill="#7F7F7F" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M402.602,255.279       c-3.177,0.97-7.28,0.784-12.662-0.367c-5.47-1.245-10.456-7.049-19.544-6.728c-9.309,0.323-22.457,8.662-35.161,8.662       c-12.884-0.274-27.354-9.031-40.501-9.031c-13.103,0.093-25.015,9.168-37.588,9.445c-12.794,0.045-25.544-8.476-38.073-8.66       c-12.705-0.322-24.75,7.557-36.617,7.463c-11.691-0.229-22.059-8.616-33.662-8.248c-11.911,0.463-24.971,9.676-36.617,10.229       c-11.734,0.185-22.367-8.568-32.735-8.662c-10.455-0.184-22.19,6.404-29.249,7.879c-7.059,1.338-11.516,1.476-13.191,0.415       v24.419c1.676,1.059,6.133,0.922,13.191-0.415c7.059-1.475,18.794-8.063,29.249-7.879c10.368,0.093,21.001,8.846,32.735,8.66       c11.646-0.459,24.706-9.905,36.617-10.228c11.604-0.46,21.971,8.109,33.662,8.293c11.867,0.094,23.912-7.738,36.617-7.508       c12.529,0.183,25.279,8.705,38.073,8.661c12.573-0.277,24.485-9.354,37.588-9.446c13.147-0.044,27.617,8.847,40.501,9.079       c12.704,0,25.853-8.342,35.161-8.663c9.088-0.416,14.074,5.482,19.544,6.68c5.382,1.152,9.485,1.336,12.662,0.368V255.279z" fill="#3D258E" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M193.528,242.289l100.94-53.858       c-7.939-17.416-13.543-30.545-16.808-39.898c-3.354-9.307-4.765-11.38-2.868-15.803c1.941-4.561-0.75-5.252,14.03-11.287       c14.778-6.266,58.984-24.234,73.41-25.109c14.118-0.737,13.545,14.835,11.207,20.088c-2.56,5.113-15.707,6.403-25.677,10.458       c-10.104,3.87-21.221,8.2-34.059,12.992l46.19,101.634c-5.955,5.113-13.853,7.096-24.529,6.311       c-10.853-1.057-25.324-11.377-38.823-11.426c-13.456,0.049-28.809,11.566-41.117,11.795       c-12.353-0.047-22.147-9.997-32.471-11.009C212.588,236.16,202.837,237.864,193.528,242.289z" fill="#17057A" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M374.881,154.343       c15.562,0,28.19,13.188,28.19,29.439s-12.629,29.439-28.19,29.439s-28.191-13.188-28.191-29.439       S359.319,154.343,374.881,154.343" fill="#17057A" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M125.411,244.269       c-11.956-2.212-24.132-5.618-37.367-10.229C74.72,229.159,52,222.615,46.617,216.211c-5.382-6.588-1.455-19.764,9.398-20.363       c10.896-0.599,32.514,9.076,54.969,17.093c22.324,7.926,47.867,17.831,78,30.224c-3.705,2.027-8.603,2.672-14.867,1.75       c-6.354-1.061-14.383-6.912-22.545-7.095C143.367,237.681,134.764,239.893,125.411,244.269z" fill="#17057A" fill-rule="evenodd" i:knockout="Off"/>
+          <path clip-rule="evenodd" d="M402.602,296.147       c-3.177,0.874-7.28,0.737-12.662-0.415c-5.47-1.197-10.456-7.097-19.544-6.682c-9.309,0.322-22.457,8.661-35.161,8.661       c-12.884-0.275-27.354-9.029-40.501-9.029c-13.103,0.093-25.015,9.169-37.588,9.444c-12.794,0.047-25.544-8.476-38.073-8.661       c-12.705-0.323-24.75,7.556-36.617,7.464c-11.691-0.23-22.059-8.616-33.662-8.247c-11.911,0.46-24.971,9.674-36.617,10.229       c-11.734,0.183-22.367-8.571-32.735-8.663c-10.455-0.183-22.19,6.404-29.249,7.879c-7.059,1.43-11.516,1.382-13.191,0.369       v24.418c1.676,1.013,6.133,1.061,13.191-0.369c7.059-1.476,18.794-8.062,29.249-7.879c10.368,0.092,21.001,8.846,32.735,8.663       c11.646-0.555,24.706-9.769,36.617-10.229c11.604-0.369,21.971,8.017,33.662,8.247c11.867,0.092,23.912-7.787,36.617-7.464       c12.529,0.185,25.279,8.708,38.073,8.661c12.573-0.275,24.485-9.354,37.588-9.444c13.147,0,27.617,8.754,40.501,9.029       c12.704,0,25.853-8.339,35.161-8.661c9.088-0.323,14.074,5.481,19.544,6.727c5.382,1.152,9.485,1.337,12.662,0.37V296.147z" fill="#17057A" fill-rule="evenodd" i:knockout="Off"/>
+        </g>
+      </g>
+    </g>
+  </switch>
+  <i:pgf id="adobe_illustrator_pgf"><![CDATA[
+		eJzsvWtzXblxKPpdVfoP+35I1bhuhl54Az6pVJGUmPiEftTYTnIqPuWSNfJE16I0pdHY1+fXn34D
+ay3sTWq0J3ZsEraGu7k2FtDobvQLjb/7f37+i88vv3z321efh4vl8PTJ3/3d9ftXLz68e/+jA4EP
+P37z5ttvPrxH0Gdf/ODglosFn7r8cf2NPPmvr95/8/rd2x/Z327w25/90z/94PDZF8+uf4CgX77+
+8OYVAK9/9OtfP3v+ix//00+ff/HrX//s+vL2179+78qvf/3i9a9//c0fX9/dvX771eHrd+/eXLx4
+/QMbDnT/7MUH6KD+MP7QL0s6uB+FePj5T/CJq3ffvv0Svnb17v//0aHUg8v1kOCv2Qf88z+//uLV
+N5NnLrxzDR4MFy5We/rZu5ff3r16++Hn79+9fPXNN9fv3rx7/82PDtd/evH28JMXX8FfXhz+16s3
+b9798XD15sXL38N3Ln+cfnPz+s0rmPbdiw+HTEi4/HH4DX35V9/At6AD/J3g5Tc/vgPQL159+AAD
+gr4JZ9c/+V//Mr4TsCnts//44tVXr2kJAA3/+weM/cy9/+LV1y/4D9Aff+cz+OPh2avfvfj2zQd+
+7aE/Bb9++AEt8/97+NnXCPmGvpUPC/yH/89NXl8NoO1zh//rj+1/w9/9IRwiv+fnP3+G7/D8QF4O
+McGfvXzB7V7g4Kuf0SARib98dff1G1h7Wrmw5It0CC3hv/13fRQWgR6DUTt/SC3CUuti9IV99YfX
+r/74o8NP3719Jat3+f7DL17/H1ilDF8rzQv4i2/fvHr/q7evPwCOGNYY6z959+WrNwqjr9+8efEV
+YbJPif6VJ3754v1Xrz4AHb578+0H4pW66N9++u3d7Ys/vUIqc/KSn3396u0v3/0rDRMos7WDg6m6
+BITbgGY9r5Zzh1yGtdIO8dv4Xe214DL8HEjuZ+9ff/X67Y8IO0xF4Tc/f/H1q/dfvHr54UefAxzQ
+RWj7vD/wExg6fwmAh8/1y0jH//T+9ZedjIs/VP6HZn5Rh/83/b9MEND14cOrt0L7z99+ef3uDhfn
+G+JnIPe3wAtv3n0lf+0f6G/wzm+/fvrEH67eypQJ/E/vX3z5GjoBMfOrt29f3L368vCVgA4uAt9M
+wTBW6OjLp0/+4+mTf3j65Hl+ns7ZoMf7n4oPaoEb9BgmzU+bm7Rl3Z7dPH3y7GbVnq/a+ud6aFdD
+uxwaLPOzJq1aK9aytWQtSgvSvDTHDXpcuF3fSHsujQejP1fULqU1apVaoZappWtYGfg3SgvQPDVH
+bcF2dUPtOTWcJHeOP5fUGrUKrWB7+uQqQ0vQIrUAzVNz0Jar5fIG2nNqiCgcInaEPw1apVagZWjp
+EsZ4GaEFaB6ag7ZcLu0G2nNoiOBrGgR+HX8qtAItQwNGhhageWiuLW2psNb1pj6H9oyQgoO/xC9V
+/Ck1Q0vQYg3QfHXQlnID7Tm0Z4TCKxwgvAQeL6Xkp09KLqlEaKF4aK4s+Qbac1ria0QJTKdh17lk
+/Ek55gDNZ5eXvKQbYAIkgmtAHUz76ZPUYBAlwYMppZgCNJ9cWuINtOdAJteAXkRNg627ROguphhj
+iD46aEu4AZZ4BouKS3AZgB5hOgVeCXoBtBB8cGHxN8Aiz2DRcYkuAUkVhp998tEH773zi7uB9hzI
+7xoW8NI1QEdx2SUHW5sLDjQItyw3yERILrg0C6ALp7TAIBboAMX8Pz59shz+7jdX70nIoMBOILMX
+gv0CJNhvBtAViECSlYeSDsMTHYRPXD0TwQfCUcXeg0VhmYvCclZROBFgO8E1F1SDYNqIo1EAET+C
+UGDBM4qaLmK6WFGBgqJERYiKDhUaJCxAKKioICFhooGEgogDFgVXIgKY+bMwfSBmV0YHFgcWviL2
+ZtZGto7Ezo4Y+bmwMLDvjlAu8oRURuB5iOU3oAn9/P3rt7iPP33yU9hZXTy+tZLW+/eHf/vP1x9e
+Hb4A8Is3SE8zMKmBnZ5ubm6ew3JeAxIvQYJVkCr5JgFHhxsPfLY8v3n+HJb5GqTtJUi3ChInEyUF
+oo+FKOEZrT2ueIXVL7TKkVbX0bo+pxXl1ayyilFWcJHV47XjleN1k1WDtZJVszU7uWIkbFnQBhax
+JFyfkWBFsQpjJKHKAtWLMGVBeiVCtIj4DCY6n4vYZKFZTGCSuAThyOKShaUKShaTKiS7iFQB2cXj
+KBxBNAYYo4nGvWA8JhanQlFFIlDldxCKrMmm5bAWjAOY6N003okQXf3hIwXl9buvQRVGWpbfkIcG
+8iW5prsU7VOAfEQ/LoDuVbgMul/RYtie9Zwk0TUtC+1dT5/g9gzLgwvU9zBcJlwo2clouW5IXj6j
+RbM9DZeOdjVcPFw+0BZkd8NlxIWEpaTF5OV8RgoO73W4rLiwuLS4uLi8uMC8xLjIsMwelkl2wOek
+hF3TkuOi47LjwvPS4+Lj8iMBIAkgEThaYsCbMMqaVdbMYuxiGkhcaR/KMMQyoG8o06zZZs04a9YR
+5tloGsw8oLetGGjNQmsmWrPRyEjESspItBIjM63Zac1Qa5a6VrzJNnI2cQSiSDF8JnH09MmA07OI
+I8DbgMWPE0eKN6K/3rY/y7qBoFq3nXkEIufZql3v2tWmXW5aWzfosW5a2bS8aWnT4rpBjyha181v
+2m7q/EN4cyKKAX8lfFTzu+aGBlOBHnlKN9aeS1MzkI2yK7EULoV/1WIoZjUg3UEDumOORp5WCwKo
+0Djn+gFt+3NprQ12Hdl20COreGrdJbPuwtS667Zdt+yK8S5wLygafuBg42GdgVnP21Z3rUzs6rVN
+DcwFPYbBnu5WdFeC1WpuojiNCrA39ckUKMDJ5UyJ0hmQlOttQia7ljctDQ3WnHYn3qG0edurZL8S
+i+1GbIlntmv1fct2LiD6Mtu9tvwA0g2oi9gQH8ahBaJDpEf8QfpESm1EuUgkSM24EEjjN0T9+Cqc
+JHDMsC9eAbKfweqDNgxiwgFFBKCORCxQgGYaUM8VLArS0/PLG6AxBzgORH0JXlQA+w1WAX/GfYOf
+WT9xDev2/OoGxJWD1QywrgmGWWC1L2Hlr4EGnl/fAGU4oJEAVJNgAgXoqw1yFfGDeEqENZwUbtGI
+T8TrFeEZMY64h1WgFXG0RrhauHa4lojC4usWzyCKUCrhl1B6oVxDSYeIRxRWkp0oTZHVUOoiGaOE
+BqlNAs0RGdgYofPtOHmUx8bppuMsRL+osgB3kvaE7ICshLs66FYkbPG1+OVAGhgqgCiicLlRR0Nd
+DTWEK9LfkCFRnwP9AXRAnCgOGF+LX46kZSCBoVaI2iFqiSg2cNmviaVRmwStkrYCJF4cLr40Jpg1
+7L1ImqgeoW6KOirqqii2kKGfoR6ra0o4V3wnwnQ1LF8Tfm8Is44wyyvfsXlFeCQs8koDhoJhrxDe
+Lg1jzwlXjrAUCEuZ8MPYuSLMAFYEI55xARhSTDTCwbXOn+buadaR5lxotjpTnOcN8axybCJeBbqj
+veWS+BR59IZ41BF3RkAbMnQBTaiByL4CQYii9Xm5gW3aASkEXBJAbAZNqoJGdUma1RXoWM9A17oB
+IkWG8DCpCKjPoJGh7tu6bDecrzG+xvca2yOuBdOCZ8AyyVrF8xrLI47XGDb8EnbXuAWqHHC7xuwa
+rwNW1xjd4LOQzt7xucbmiMs1HtdYbKPEhB10LTHX8lKk5YBz/dlqQSpztm2rTYWdvhVNRm3bVntT
+GbZuKw3QdMI2aVt98nKncapMHBr0qFJy3bYarsjQbdujCSTq7Getb+/2z61NaT7V0Z7s1mSZWpOq
+qcNYSR9XrftS3AvVtOYkboZgOu+iVKAOD7GZT1kY97s8YKwwzZXbY+f0mLs9/gGl/tYJ83E2z3Y0
+pMucHsuRkUz5Yd4e9LPitQd+Y6NvqVeF/SrsWWHfCntX2L8SRDV0bLGbp+VGvM3P1N8C2GY7niMG
+l7Sfst+FPS/se2Hrnj0w7IMJonA69cSIzQ+yRzzYz8wno16ZS/HMsG+mipGU1UMj8Qf20QRRY2HJ
+oEcnRtuN+Guei8+GvTbst2HPDftu2kqzHjVmGrSu78YS6XaIehG8xZTW8aTus1GPAvkUQG9Vv4J6
+FnoEqXtv4i56tI0dFfXhwN4wRI7M43B/5Eh9D+x9UP8D0A7QUI8drb066otYx4/Wvh1vfjf1uV2Z
+XbZxQX+qA5osy5UL+lM9PhLfe7bxqX2Cxwf0pY0L+lM9PiZ7jntdxPcybXv/i+wG0ONsX9zvnhOf
+jLR6ZFfe795zP83cWzP4bAbNQdte05j7b+ZeHLeSnxQ2WmCxDsuFAxUL/+MCpmCApA0Tp/lDHuYw
+U8gVUzjyEvH53KLHB2Hb4QdrGjq9/1nuMybMZbkADRX/UwFHOIaU0ItfwkVzIWMcq3f8wC88aMQ5
+PHzE8GwPPkg8IsR5nALg/H4XWoFeUFXH/yRHmPVNMDt8/f5HZUbATji80vCBWlLA51KVxfLjhO57
+9CPDI1+8eP32t+/+iPER/RWzucb43hlieqNABXF7hpjeKFBhOzxDTG8UqCBuzxDTGwXqkPzwCTG9
+UZ1k5eJTY3qjQgmkuFEpOZ53AdjxLNrnIvA7N+lxLm6/U4Mez9jbpsdj28VHNujxTD0d6XEbhvgO
+bR/MYFpY6fTP66q1E+3yRLvSBj1ebdr1ifbsRJMf6HH/c3O8TQxmM5y5gUB0k+ZPtHC0keoKPcZp
+SydaPtpAakGP5UirJ1obm/mHH+iveqi3CsTWA/1VD/VWgSb7QH/VQ71VIP4f6K96iLcK/fawJz/U
+c1/v993DpopJUtewxT5/dgMqtYNtN8D2m2AbLsSJl8Q7yAc3RLueqC0RfeBKw9BuLLZwRGt+WHuQ
+8Di/OPqzCOE/19bzSVvsXmyfEqqn21Y8HxPbn9h2PZ7aPh7UoMeP/c6p7Qwa9HjPEx/bpMf6XZuJ
+7HDe9hfeI/nxaKM6a/vL61HX91Osr5nt9fTJp1hfM9vr6ZNPsb5mttfTJ59ifc1sr6dPPsX6mtle
+T598ivW1tImo/tQo4lYrA+3rE6OIW60MDNtPjCJutTLQvj4xirjVyp4+OaaXfVetjM6tTPWy+7Uy
+07oeFmEc2/0azf261H363OBNhR5nPtaZN/ZExHISvZzFL++PZk4jmyt/8z2Rzk078jPEQ/09bbKx
+iYh+6KZ/XvXlU1Ssj7G8p+2kYnnKVj/aoMeT1v3H/3ysP2BsM/F8zMl/rG2DBLOEz09rcw/beX12
+35+H7UyetgcYd9/BAFXmPpcnXHUx0L/O5AlXXQw2vDN5wlUXA/3rTJ5w1cUope0snnDVxUD/OpMn
+XP3gyD3qA3ehrNifY3JLoYPQtVJgCfQyDRdtwnEnn5MDXyWn4RnXsj5TV4fATj0mPS2Nwn2lRnob
+Bokk4LXq6dRj0pNPiR6J9E7Auj4SVz2deox74jnLeAmb+ohfIerUY9KTc4TLvNTNIw==
+		]]><![CDATA[
+		q45OPPWRMbJfvn/39euXL94cfvHt229efcBY2RaEh/c0ZrZwvu4ptr3PiJowrp24KevMjU3Wxpiz
+kaYnbpSNocd1xsa9+RpN8vY1YyOO2frolLbTVNer01Snz1LtT1P181SgpWxye45l9mhuj2b3+JXl
+POyPnJtrWdU32k4ordrc/Q1EuX9gCw9r0GOw8+wPbelUoxPyx1r+Lg16nMHLd2/kkihzg3jevqMr
+98HazMfGND9OazupNU70zHkSyfG2Sy75bkmBg+l6hhTn7pygnfsMKc7dOSEJ85+c4tydE6QBnSHF
+uTsnSEs7ETQ65pzYGJnq/y3W9CTW/tz+/oz+cD4fepyf0H8+KROyLxCyPcwE6KKz3LMjTPvCILvS
+IHygaVUahHXlsTxILxBybWfALjdlQrRQSC8WUgYh1cVhF58qfFVUdwGvWWk3VzNz0LhtFiKeFW15
+tmur7QQ676ectu1y0tqu1XWDHjUfe9vypKVJmzm1Z275mb9k9jPJR5/6cx6aSTjJIZxmED40e3Cd
+APEPdM6kDppQP8EYtucX9QSjnE5e60V2zpzyWrf60VpDWutI6zPnV3sNiU7XZMt+HfOeTRtanT9/
+Nsl1XuU5P32yyXLWk+jjWfTnm/Po6xPp6zPpSU7+rc/7rU/6nTjlN9Cs0aQElTqdDacLhFb6qV5d
+7a48yCb/eJ7nv/48z8d44qmUy4MyJE554ifC+7weGCnydEYPTAGD9bweGDpWeFYPjIcxHvfArFhL
+j4T2A6FlWR8H7YdBZ0dBkx0D5U1tPAb6bDi+uD8CKgdV9fjncPjTjn5SbuX+6GcZDjauj33eDAcc
+1wc+5bgnlQWZHPckk8EJG/dDj3l1zHN1yFOOLTsq0zAeW+6Hlo28N+4qykHGPOs69VLN/ywJ0hcl
+yT9YyTFdAB7DIZULkGKrhOmTz93nCkrpIrv6IHeQPCop2TTu6Hq2dowXLYaxq+PPcB91TPZ27QLp
+bfj69M+fWLRrVrHrMf36Mf16eUy/nvX4iUGhjwgOfVqP30u+43c42fmg9t+qx7P9fPx51r+EHrdn
+ah/z7x/z7x/z7x/z7x+QLX/2/ejPsgv/uXSPT9Kx/pETBbBc8WMS/mMS/l9Cyvz5e/wLTZk/f4+P
+Sfh/A0n43yW185724B4fHNSHHj82DeAvq8c/i3W5q0/4eMLi8YRFb/frrPdry48nLLQ9nrB4PGHx
+sScs/uHMnrTv1yP5ae0veTf/FB1m+t1/fDw683h05vHozOPRmf+aozPkcnvg+Zn1s8cP0QzP3XuS
+Zv3s8eM0fFLlYWdq1s/+tz9Ys7+tbH6HGV45NeZEPO4dj3vH497xt7l3PLpsHl02jy6bR5fNo8vm
+0WXz6LL5L3XZPKYsPKg9pix8HwkG5+/xLzTB4DFl4TFl4TFl4S+0xz+L5vGY9v2Y9v2Y9v2Y9v2Y
+9v1AN/a5HOOf5K6fp30/Hud8PM75eJyT2idKkk+SKB/T4/ciRx+Pcy6Pxzn3V/ydJQJ/zpyA7yNj
+4XvJrPgeMkDOl6HySTkRfp4U4VdFR/+Bchh6paJjAdK5WTE1LE5ULJoHSo+ZF2ZgPH2yMjHmRsax
+gOlgZpjwPEPwdzSYQAm4P/j7UeYSKCqfHPpFc8luqmU7+6a3VQSwl5bzQwtDi0MDNIOhzgUC89DK
+0OZuhnl4bR3wOhaamhv9O6N+U4erV+Lqtbg6hXc66JTQaWFF51Slz1HFsbAqB9SoWtlVLwRElNGN
+6U7vG4qnirJuoJFuVndK6bTSqaXTC1HM1s2zUoWPKcNzN+VUHYZxHlOJ50rxvbeoAy5HxXiuGh/L
+9BiUY13rP5OZ8BHOW0wVOYeRYDlN7KoaqX8sedhdZOPPyFmbIJu58o4FpDo/l0nB0EnRUOhxXTp0
+XT7UDzJnLMw4SCgeqM643+ct69JXpq9NX51uxvU1WtEtrMiVVSwsch+7utqVevt69RXra7ahYGDC
+K6k1WK3GIK9ep+NOyZa11A09chTvqnU87s+P+/Pj/vy4Pz/uz4/78+P+/Be2P5P7BV6HjgEQAw3t
++Yj/hpTbzOi//1k9VJEKegUSPVFhHOocKPViqa2tHDv3Pct9nn53Chct+Pzgserz943Xf8R4/UeM
+9+FY/XRnytyXQq4Uv76/ZdnWf76vAvQ9ug3I4tP6zX3J57uQLewXay3nZNj2Xj0HNJ2nT07oOvdV
+hJ4kolvF9E/Wr9ZvhJ3ok1Lf9+FioKpPSn3fh4tBF3xg6vt94WJUIm9u7tW3Om126uz02XVvpVCh
+Ubm1QOm0a+F1KI78TAsj72i1U6vSK+wkE5rtiQZdN79X4yLa7Vp6p99OSZ2WOjUpPXWK6jRFVLWT
+/Chy0EsNAmgm7Od/lsLIKKHqxE2/+8sny64yF14Fj8fFwREcgiyRVq5OfDOBLNdYwXpew9qta1jT
+dQLdUFypzJslVOGj4qcLoG4yjrkjozhYC4StSJgLBRMLIBKOnYh5gGBQ5nrE3CPmHjH33wJzgyF+
+Tx7YR2/qeBeErs5j35u+1zdmXMLfMzzrwdZ6TvlFjXKLMLMI84owq4hzvXs+0T6bSPKJnj6hjCLO
+KaKsouFyw2d0gdMV5Rdd2jWHlTKNCmUbZbnykK89pAZ0hhlI2vyqbe9G0nYylYPOYZ61PbxHXdtH
+vD/i/RHvj3j/XvG+coxhXkv/P9gz7QIUjpXn5ugj7ALKmL6z+mef63P8GbuhZfi/O7gAf7tI60ta
+pk/w98mzZP+f+PSOPPDJhlubG24NDbdgbqcLt/tn2GzXVvuDomb7gwCDX0ms9OWBcRGNoql/qV9Q
+pNcTAYJWnia21SeXE5EC2VVI8T2Z5e7oDmKy3p8+oet+E6mVbMerctlIwbwUm/5K7nWU2yYH1/nm
+HAYygR2xeMToI0YfMfq3hNHVpob+vP7/XShi+me5bmzzJ7zmrAV/iCe+3p85uhn5dOHr0k5vSPrQ
+p25KcbonxVUkBAOgNzfPb57dXN9c3Vye4+wK3Qh88lTxx55dAVv3nlPFH3t2hbwTJ08Vf2zQGx3Y
+p08Vf+zZFWDke04Vf2zYm2rG7EoxWchUA6bLym0+cZWPWpPjj/3vBvhU8k1pSr8A3jjDd3G8c97j
++rE3uU4PXT59cm8Eb5ZztY2lDe44kKDr+MfaIacuuR5X48iaRvNavVyVddGDG35VZGRd9259pIft
+iHXxJCqD9PSJlULaFjValydaFxtalWyQeBbHXMGYo1XjprZVkzjXpV0KeiX76LVcD6pXhFLOkaQ1
+yQRhhbWWkf4EadFakpatFWt1cv0mZs+cNWJ55R4Ys9w78yhuqStsdmqT61AvJc9Kr0W91nvZJaFE
+T1czGejSKIqCOLTjxKGd5T7pYpZyk3Yp7WqOueGS9+EG+iG1Rq6Ht0pZusQ8cL1gni+cB1aCTSjJ
+hfSqPPCV9XyB/SXFba8odntN8dtnFMOVzL5VLp/k7z19Irl7PVuv5+f1nLx+tF6z7nqmnWbWyRF1
+Op6uR877EfJGUWGMC1/xlCk6DF30CDEFCjRYcC2Tf84hg1XQQCVSj9BuwwakC7J8WkmoE/rgEDyY
+ySqSVpQ792wT/V/H//fhg2PF74ijgLs+kqeOXpErt7zGfIGDPrQLRNA6rDt7QLQ6dFy4lLw+VC+W
+ktshhgvkilG1u+fJ7vLwQS+ebRewY8dDcRcoGjd+j6OPyUZ8gYeeZgeYZn/7yO35X1+/e/Pqw+H5
+n17hrjx8wh7X2iT/bAtArPLRbq437WrTLrVBj/p727VZrYVZbYZVHQfokX+b13+YV4yIJ2pNeEsi
+nLVZTYtpquHYoMdZCuLx9nEV4D6+Jt3H1r17UHWwM1QLO39tr3P0+F1qe52/Wthjj5/c4z92C/m5
+SK0rk0XVZEsyCeGVq4UnlXeujC6oGpul/CaxpIMl8mrq7nOyqp+JgnJF1vUlKS+V6kMUUm4oe+oZ
+qBJkbQdRh1AxWsjuviHb+7moU9dkg1+RHX5Jtjha45Us8kJWOdrl2KBH1A1Yv2AdUXRr0uxFTDMT
+iibFHV/xz6W0Ro2CLbDd1Cvx6lyRl+gqSYvSVK/x1lSzlxKrl31jAHQ+fSIM98zatTUbwuX404ZW
+hyY+J+ixkG9hbGnV4qqFTfPbBj26XZsUl91vbtQmZPn0Cf332cl2fW+76g16vDrRLj++QY/829l+
+oMdjP/W7NejxO37zv3ePYvafquHx3SuTJPImnaV9r9Xu/ly16f66qnv0dvbKGY89Pvb48B5NT0Md
+DbWzQjoZaGOkh6H+hZoX6luoaaGGhZoV6lMcq0DNieMUqCFxjCKRDhQkQqHxCY1OaF2tHpfoUYl1
+TGKISIA8H2MSD6lyejQiwTGJp08sKjHGJXpkoh/I09iERifWh78oRoFRCnIGcaSCYxUcreB4RT8G
+Fsi95FBUkxmshxivSYW7HA6EFTrUq8fC9FijHA4jYXxjR8SekarJyh8fFWvivCxyZAwjHnjUhp20
+7JPkA2TYWMiycf1cjpM9o5jINcVFruRgGR8uaxQlofb0iTiYs7QkTR3S6gdVz3H/6UJwMNrxgKGe
+xBtavxNgfXfAShU8VgfQakw9pHrefJ8+fS3OGarADjviuXebM8qL8/X1/fW4qQjbDYB9fe+yaXnX
+0rbZodKxhU3zu+Z2zaI70OPs6KkdP121/Y/5/FWat0+uDL2WmHj07QFHlz8igguS8hPrQnMEdx4S
+MYyYgS1GbjMvQJXQxuAJOOoHwMuQnosXQD0Aav93yz9KVN6zpS9W/jPZ/a7Eomc7PoNFnyxO79lK
+l0i97okardedUSP2fX9c5W7CquuaD6tugaxtSE6CcRbc6oEtDWo9t2NtiwWxgoatpNiEnsG4lIDu
+tQZThjSa7SG3NoRPhkSap09Wpy7Wx9yOHdE8eViSqpvvzlp8L3dyLPfIsT+v9XGPzaU8NEZjP0lc
+7IUFqFofWUj+vpQPzNX6LgLjeMoHqTH33r61S/lAbM3wscfIXoDucUJYAVZY42WPmT1u9sJ0wA5g
+a19fQDG0x9EeS7vUGMDWDFN7XO2w9Vdo9n+acDjyjTVT/gf+isHIBYsA4K9OQqw+XdToyxCxPPmY
+VISkcpYXqWXXY5sRs9KrH4tBnnpMgrCwl2CwNiZ9JLuLFGo65HgBIruMkdh7n5VAccZ4LSX2LYuV
+3SzLhfdx7O/0c3YEeagTkZMrk3D18MePDO7+23++/vDq7w9Xb168/D2Gd1efH9MFH9MFPyJdcDm4
+6fn69R92ZL199qFn6gHym5++e/vz96/ffnj99qvPPx9JfPzL0yc//Zr+FvhvP3/x4cOr92+B+i//
+z7fvXx2+gGe+QeIfPx68B8akf1KVf3CM3z7FcToZ6b//icf9P+H3/w+gfzzEw08O//G/l8OX9Ny/
+f4F/713d2Ufq9BY/WvfDR3rkdv1d+viWuv1CxBsWT8HSvC3SaP6F5OdFSYc/wmNx0Q==
+		]]><![CDATA[
+		fumt9DHCx1TzIfiLGJd2ICD1Tr+9pA7gY2qOIXH4UtT+6DH8lCt04+JBv1Kydke/0XP6KoJQn/qt
+PkB68Bsdc8cUfaTOxzHbkHcjFqB+w560AVMfw4Bn81/hhv7Rb/Wn1wOmf/qAw7IecF/C/l0dgE1E
+vxRXYyGUL+sxdwLpuNNXEYTxugxj7h3imDvB3RnB6RrT11aTHxCz7JAm39qMhj7qKuu3+vp32tC3
+EYS+r9/qY1wPu9MGfdSVtmHbqHeD1i/rVzYLQr/pQq9musHCCkM0CP1WH+B6zJ08+PFlPeZOfv27
+OoA+SP3WhlgZ88t62AMV1O2wO2L1W/1pG3ZfDxo2L52sNa3Qav4DudYd3lR2rEezlgN1oBB6plOI
+vo0g9I9+qz+9HnanEPqoy23DtlHvBq1jNvGxXpO1KBhnusHCCkM0CP1WH+B6zJ1C+PFlPebOXsNo
+6ihARrGzode1NKgDhWx4TN/WV0C/1cdow/7V0+eypcI2LBvqfI+9fnH37tvfvXnxFaUPDp9IKSgB
+/rfeV/2D91Xs4I5/gX5of6T+7FfHvzn9hXfPn8mJVFLlnR/K2XvYOn/Pb17v8PSCu1VfvfvhnX0g
+v3tKJc9adFTlzNNGzf/x/A4HeI6x9Z7ls/Qa80WpwW8/2pv6t4f3OS5T77iwfuNKa1TJjV/pYAzO
+G9rkY7woDkbWLjyWt/cXtbqgnzKebKq88AJymI8agJgufNp8CBe1BNu7EFIuMKsXH0M33O6zdxdL
+A4LkTVGB8YJmDl0vdfsJ5p1TtC8gDNgrLAWo+iL5Je0+5oslgqLEYlBg7aIsHtbSwWRhetvPmKib
+srxEYeViSTkfYAYZuXv9EXgF1HhBlMLiRVxigIEUsDF2HysW1/M6LoKBPYl+QcBmzsHtPiZA3mLo
+ZVi7cGBaHHQt4XNwNdpnoI9r2igK6IkwPqUX/azPgxxZwIaw/uzz+E4DyrhgMVbj1M+rqRlQpg+W
+vEsp7D+PGFSgYhk6qWB37z8PC6UwXUwYrQPrZv95JAgDCtH4fBFaTLvPK7ozIJMm/Acss7r7ONK2
+ApUBPNYPC5PPIwsZUJjMo5shpd3nkUkVJmys6yw8rh8dU0UXCIMQad6hbPRcALKRt4Mv/iAhEoEf
+SlIZIp+we5QCgLWK3hp8ebWP4/gUZoID/TNx8nklSxQo2IK3gsntd59XKDcgLwuQChaQ3n2khRVq
+UCCvfkbSAZO+7T+PJGRAojN6qGDVzO3nkVYNJvQcE2Cl5d3nFVMYUDgnoqSHpd59HtlPgSZLYOfz
+te0/r4SLAkUayCqrsJCPKltSA/JIfW/Sz/B49K5hEVLqusBQGiyxfs75IjsYN0tABXp028Ek00VF
+Htt+hs6BMvVLCgS5vnic04J73vYjTLVWwbwCQRVyEaeIfriQ9p9BH3SLvMeAC7yv4BiaL2X7MZQL
+X02iKzCAygWbVAKZkbPfffYNpJZtTwrMeGCEZ9Bw19t+BnoMKo0UCCpBrsDMyYMEwL13+zmBhpPl
+SwZ0F8FDz4CyErPbfS5ACDkZtgkWLlqpB13lyCyjH0WymJQwwfJwlfGf37199aeX7+5+ixpj/4CK
+eatATw5emUCWAsnWBZgFVieXVFWNdIfLr2dK3H3qpHan3d+Job565+0IlBczcDOaNXD19bc0yGc8
+JvHlHC2OS04dTx6dHEGXA/yDlAttyTxABYJgX0AI3crigigF7MMmGoUpkaUjMu3wnMK0w9WXQTC6
+ULzMY/PqWzUEfnj5/sOz1y8/vH739sX7Px1+hPAf7gCX79+/kN/94Yc/fvvh8Pf4+/84fPaLV2/+
++cUH6ASAr97/+Nk39OgP+O/j9z5rPzj88Bcf3r9++9X+y89efHgxfnH82y9f/PbNKxyR/g3/Ydwr
+nfBSUHmbyD7+1jzd94Sf2K3GPjUg/YTaFki2GppsgQIERl6qWyMxAqssikOQ5Si5xucUph2uVyAC
+Lzohmu2rv/sKhL+YFVBOVWZ4EBeAlI2lMSVGXgEBIWmDfXIrCmRpMTILKNtGtIzWzymMunNu/WVk
+gajUvn7v3ygDoMLl/IYBFDgStqJwZIAAuC5xzQAKW5G14X9kgO2r/zoY4CMIH7GR0ecEshhUaAkm
+CBC9PzE1259yjWAlBcBjM9/E+hnuJ+X1V1DhrEkWbPvGvw6if7i0B6UfIGCxONDrRNgzDD16yW9w
+B8YV6LNFcAdaWWZDsj+pQO1y9fWYLxpYyiLu1+/+myP2grp0IdILpQjyFQiEXKsqNqBi5YWcRg7D
++ryDwmbpalo/qEDqMqfVt8FEcF5XafvuvzGyTzB9DzIbaA9sXC+hCwECOZfm1shDpwKqJuINZd14
+9aACtcvx22Dyhq43bd79N0f3KH/jlu4VuCLn0FCWtDXhw1LQ11ZPKnBF+Pp1ovygwefN2//GKB+w
+lqt3a8pX4IqgDflI+k5EPlByjKGun1Qg9tk1Ifk60X5TVWjz9r8O2v/uGn4G5KTWVio+yPCajdhV
+xywovDXYIwr96kkFaperrxf8oxL75t1/HQzwndV8dAqi8rJS89ENVOIGiYmiaGudfvUgAYu3LtdL
+AINqS1or+qsn/xb5QJ0uK0ZQ4Iq+zd0wcoJ6d1ZPKnBF4Pr1FSds3/43ygrqd1mxggJXFK5YHFlB
+/TurBxW4InBbg5EVti//a2CFh/uB/+e3b7968+qAb//6FWXobSAHQLOjGHjaJOc9PImAu5A9Bvqx
+mP7wq1MZVuxX9OF+25Px3IHf+y/8yk32QJVtDcd7J33Cr2/w119QzC1ITjFoADloP+2er/3qqRIp
+vetLoq3DZz84/Pu/fRyif/Lqy9fw6/sXb1+9eHv45es3jO0ZGB06EYSJw8zn4DG45dFDkCjit16E
+h7veN53eDTDp2fSm4W0rmH73dtKfrZgmf8jgJNdDXPAU7iypp1LCsjB2L1xslM9TLCyAKds1MEw9
+Kmi/4xKh16WDUOnzAbM0RSbQd1s40PMKxHphS2NYrQYb3kug3z6VTilvBZOF+3hA8h8K6jnxxHum
+I/L5ovpG/qIWFt3FA2ux9A2/AcJ7wGro3w60m2EO8fCaPsbV2DuOjqMSYYm0irzUoU/0j4CNCBvl
+8HIPK4fAsoQ+ylrImZWd2wDxPebgkonztI4uI458i467o4ibdTp7OQWbSxKYbiI4Y1hB+nLYAOk1
+amjT1wFIA1LgdNF+y2H94pPF85X4bY/LuHSyqrrFEWy6/PfSxKZHgmEQcIuwu1OrgHQ6g02xvQLi
+q5T8hSU6rc1YD5MsJrAZO42w3z3t6yBLezeuzZQA76XKTY/rGXVOWXHPilNEcMxgOy7bcN7HRWp/
+/qf3L+5ef0m7hf3O53YaZlK2bdL8d0ruo754xNrr+FH92bMkP02IoxR5WDjS8BxsHUfS/KhHRayk
+tyXecfu73wzPvlGkYcYECcFIO7j9p8AC/H4Y7JHO4S/DW8ZuJXnQ80Wsnl+y4Jmo36/xNOlzHO3Y
+Z2yEiQDy56DKx4V3wEa/X0/1FCqmaDlJP9/l0Eblv129//ab/7S+Pvvpqz8e5BPs8j/AIyWX+M+/
+//Hpk2+frtd1TmlMZ5+XCuuDZU4v8FwuzvfzUhJ6z0IY4LdbuMO9qDJcupiA+rffPsVh/QxH89W2
+r4AbTtV3O0QzQSv6jW4VGjJYz3gSiZNodiOSXgD+uyMGwmefY0bUUlruOv1nV1eXL19+e/fFuw8v
+8OG1to5v8BdoEcEL/AVssE6HGWCYrTK8xpZ1QJ5SYnj8GaQXP4vFXRmYCuwH/GBojKUIChzoPNfa
+wZL4heTYLAdBSuPvF/TMC0YamLoEpLSoa8VUjovAY3BZXrYsQXqofrERFO0hg53VR+BdjNLDIsN1
+F9VVBYaWBJiDk4lR3lbvgccLOIMebAhFng1LLAKk3EgCuhxd72CN9LOvKoyhyGyKi7WvasBkJF6p
+0NxBlzrryPua+lxk5N7DYK+tB8wf4odbSfJwDl56yC6Ew2wI1+efYxEShUUHptFJAl0BYpWcnI6G
+lDBe35gM2ILOZbHlBYKNsNhEokvkrXP6wrMvW7qILsvIYRw6I8zdk7XAATMIUwBlKD4JLC/69RpA
+u73Wr6eQBd4w41/7TDqZFLSH9fvPvmb5woclDW+9U/iSi0iLpS5ORlOzsl/TNTs+SdKhRQRErw+7
+ouIKGFCBvig209BBTTIyyrCVRzFBhPkXJLQAvXEGdN+pplblDJcyjzZium1UzihegKkWocWAKc02
+giWmyGKhhWTbEowCrSyG45EDBsKvMrScQfWbovfsC3iUQkMn0QRyUBGVVARgZiEDXWt+ANrkfdOH
+cZ+VXtE12WXIfwmN4vIoIYXFdbESlJRKiLZDY+K3SpsUiuvwdS9nlxVgEVeTRrhB3ik8GmH4lJQw
+OiM0gyX0KbBIzNF26AJkqJI7Nsc0i3ETlSELKKsChPURwqSkSOuhoTuTlYdidFzZW8AcottEAYVC
++ZYmNJ3b2Re5ku1FI/S4R9wZuDkGhyB4qrCASbZ7WGCnwFqlg3HvADjo8ALPMseKudjWrT/MBnDu
+GWICeNKNuiijZrEKWPXoZJwXoxpvewQC8SJAEX+sq6F323ZBD7ayzDxT5QQBg6Utz4IlIwRSEUs4
+czAmsiADtDITAA2UMWOkaB1Eo6TWWITgm7IXWgRdMvQe6pKEyNMipNRASDcZV6whCvJbDbKkDXaL
+vnrRFdU5Y+2Eq3vLCmlEGQqn41r8wqUE6cRHkdbNdE5PW7iN2Ncs00tYzUI6SAqkg0byqsboRXoL
+eejB9PSkfNnsYTzclHXdcmD8OvbuXCudRNmiQIUVnRCAYIiq5ptZv9hS1PdAsXVR2sx58UqzTm0O
+wMfCGVQCDopSW6t9J+cWvDnwKQkhM7PsssdKJIKfpZnJhHBXVIlIrMZkTBcwKS1I9xg2FKRHdGZc
+awcRT/F0jYOBPqm9QSceBIgnIZjfqq+9h+wXgRtzwmiKk911KWw05cCnTHmwJVgPuJ2JuGrIpvKs
+bCDwtlSiABsOnQl16WQW0IEiYESfwJyrSukC6owSW+3frpGfdCyNeUx0ioWfjczaOfEhQ15/5Fqb
+QHMq4ES/yKiyxdHIlV6zihwsH6IdQMelmihiwpLno2pzMYmIAhPCTItk6NrQzdkZyOMZVzXEO//I
+motkjUoqoZX+qNCZU3WLfjPqCYgcfhYsKqM/nWFugvztAM4+Q9ASdcFQKt0ZdAlO19Y7IQRn1EFH
+WE5RR2Krg8WoPetU4tqsN+8/+/zw8JrqXsH70GcI284oAm4Vbpsu2fO3nVb18bQYu1Qz3Unfm77w
+3FOqlBii4hvl253BxWkgXhIEoqFXZH2K2Lo4h5T9sP3yopGhJhRIPiXp1bbqJsorALt1Mgg1Vs2z
+7mi16cPJcCp6CPqwfHRqWKU0DMGYX3da8iaofhKLDAznk5QJuy8JJY8pLeRNlIfNGA==
+		]]><![CDATA[
+		KpVpD4GYVsDvQt+a9IDbuVmCrTDOMAehysNxWYiiSxttxo6H0gYBIUgvlfEv44pJgItT3SaagChg
+kjW1JHJmlad4dBCqMoWGOgIXPrLET6JBLfzX4G2C3sUl2zrbYH8HMerx0KJidxGdCWAqAVB01d5t
+SOZEDKwR4rHFptspHayUN2U1Q6LzrvewmCXSEr8MT045c5hlHhUYSCHJq5LIBoZjsWHdHpw+3Heu
+5kRgFRO/np0V1kMs1vPCtnXGM7fKVVXcjVnOLfOT+GeTbrmZR6zJBpDN5dy9CvhkVOS6JaTeQzJF
+XmkMexDZgUpBVmDECDeLzWZ+W4DD+qnBA4QsrwPTJyln16DAmIqqCsuASfWwemZyIQbVlWV5ysIG
+DM8BaFCpFA0Xda8QypjIisMSdKoGMa8VtHeUTpfmqgCr6TAxF2MfZDvVoCubd2XcksBEiQJcBDei
+IRr/+NaCksOiPQzrIxZZSezJ5lehLWo9UPkInjOKVZlbtmiDYzkEEJKAjHJvQDzhLKq0sXU2816I
+QR6Nii7PxgnA2uJV20FHvHQw0j5lnrEM6c7zxCxJwkaBMZh4RbhvugdHezjXRTX80ooAu/2KZoF1
+UHPQ/URGC7Bl0VXonXY3hMtdtDX2oXRiEqBruiH5nBW4ON3nmjm2AF6TDCwk9ivWhQ8jMxLRY8fA
+HJSlWyi2x2AKW1E39eKVbkHuuy4cccNhoK0kKam8cUSTgs65MGw9pgs59pOTeq32pCK3Yp6NxisG
+TxHAc1UiD6I21R6LQWeH072L1p95d9z81OLxfJacgU3dLUUEBc5QnbOLM58rPlrMVPZVt9/WOxX7
+ea+FnF3P2U7xTsG6ZXreSmTLxgVmoJc5opnLsldCjX1/z0FDkE1x1PVYLIGsSI5q5ZFJaFhy5j9e
+JD6HQJFweAYpHFul/zJdsDpdRwnJUSRUxWpQ3UrCowzEYNW19qDxKgk8CjAaecg2+/1TAnJ8U0Ov
+LEk9yKh+mauYdgwBZvWx5ZpUwEwVtYoVdFT4ZpY7dRl0fTFsUb64rEol2p/XR0Z2bucIvCFENelR
+t7Kpu2Z7d3EqiJuKGpJrp3eC7oQlh54AzQlLpD8bwdmXN5pyjoK1Ly/WAEg6H3F24sNBgV5162iu
+OOQzUzYLRov0YSe2ACoNXl/nc7Ju12P4HsRZl6IkNO7U4onmjaMN8dYsIVthX4O6R/b9nJvkWhy0
+XrKEeKQtmBc0sjuNgeo7BjkgZk1D5UKjj7Qd83o0p+7gyHsaPxsXddJReIsfDKp9gZ2Y+/dV/4kX
+kieH4IWPDHG/4nir1dY+Wtimor2l/B6HLaFQCjrrW4UNEIDR2S7mbbdYB94SI0IbOiDNmuFiPgAw
+J90SUhatBFVD1bZwcL2H1NT6jpyGAc9G8f2h/1y242y9ShRXOsgafEfkNtVYAeyqBarEfsfCOOq5
+oM5YjreqviZyQNlOQFmEgjPftAenZpxqovBkqSo5yf0jPQDHaQdLiOpC6O7DIvo8AI0VUhy+HpN6
+QIs4WwGo+30WQQUzXaqFe2OfQLfiPFtj/P1q5l5MilliwGrhB+sgm3JALh9DbVeslMKyhV0xfuB1
+zeuithppUNaxBuQ9W+9MCBrlxbeJr6LwtsXvqs0NVJPUiUq73a3Cu55u9FiHsWVxnFes2SD0QVF2
+6biyaSzPVpszVj1UkdqapnLUhsJYPb+Z4/IATE09UgsW8WFmzeIlF5f9tTGxEYS6B/Fh07SKeOrb
+wuWJ+nJYDyEoTS6ZlcCGZbLU/51UNlBFBX0XqovXOoti+g2ZpjIwMzJ1p4Qnm4UQ1rNI2xAASK3F
+q9WoISUA0t4jdoG5FpqzjtEjGkVE+qUo/3Bso3kzET278uX73hLcPIf4b1V4LxacNjGLqTsWCRLN
+voVBgVowAH+tPfRwDG2y1nN2KsDVbGroFzGXEHvLGib/CAjN72vdbRanci9I3sxRYHMCJN+H9eA0
+3Ur90gDr66OZDg3zQXQlq/li4NniNUrZxH+Fm2DP7NKVpJzpfYQfR2AZMAt7XnG04uGRpKfp1np2
+NaMMPiSYrKkZxwVFdy8Rr0knVR3EVIpu2vO5x95WmRaZT/EwvAVdTFV2W7noxr1jbxvAivkGSrAd
+oJGLxMxddnG2MmTT0OYtPSzquB06KFjCy4Le7Fdrlc9d8mKKNQTA1CzHqsd8AN5XXv0ArQvZYPo2
+Ai2biUxR66EMnhPWEBrYAUH3BRtDGyLQg2MbezCHt2fvYF0WPrZYzYfGPdB5diF0SzalnjWMLZml
+1IO4dKMa3wjsvi5NKxK4CWmJnSHQefW8JPEOwruaJUt0PQnAxXzrotNTr81cN7EUAaoXHfWB5nUI
+jlNHq0UOEIg0oDNOLjEQfVxZNd62WA/ekneiLiYCvSlgkf2LCFS/QmRBaD2IVQbKKdqN+qzmA1Ac
+lQfbLE9IZTFCc7E8PN5uj8zLYTaMCTfd3xGuztvI/tRbXR9NVIABJyXTruOr46BlTRuLnJVhnAIc
+qv2i6n6r8EXDJ013mszOPtFkWQfEfqNlRHevPcApRVSEgGV6A7znL3rcJxlIOR38MCthNGCLXfSQ
+E8BdNF9Y1UH03VnpMRvti8tevp8GJU58dgArWf2sGl4HYDCTGy9K7AOQ/MeeXIKD8mYkBJVN3SE6
+ZHDvxebZLcLEBM3owGyFO4Vn3Xl9T+PBiXp1X5Mv5fZIN9/DQNUVjaWwqusDrU7tRnE64+CNB8Vh
+h7CqYa9Wl5FGTEANa0QqHss9W/jNAM68SSLjLrZhNwwY3JlIsJxxsrJuFa6kjAp+G+G2/S0q8BzW
+MNRdNQV3mL7x7HNCl0wRTBI3y5xEtBCcckFZUjfJa4tcApeBoA2L2OnRQpSpyfYm2WHxYW9yRzzi
+1IMqA2hpy/dRu6+WhZeaPKpedjG1GQi7dtQ3ZRtBHJROMo8ZSHufSEkR1WhoKz2imWodDI6MFg5b
+mNjkEyyefZ0KRrjUiOikVy3ZI/TdrBqzm8qEwOJVVPVMbYTn2mVw0g7M77AsXmA9ekQmnn1fMwR8
+1yoqn6kUTcEzkhubUNWcCdIDwJeowWKWuNhDt6KbbumVs/14DECVvYcmAWsMNzl9XeoB/sIzc2DA
+ZkWjq5p7iPCu8Uh0HsQWV9oSIMkpBC6mZeZsHbghEidhMAT2pFOS0gjsKUzeEtsFns2Fk8hvgD1o
+dmfXjQio+3T3tlQHU2qqZEqKAAK9mLBRwysIpIhaNa+b9dDMI5hSKPJwn5rkpiGQrBN+chk6yBbT
+aGx9VofCwvIvODqHQAtVk64oHURKRuLv46KxyMSCwGbcZ8FuYouPp8vnd0BrGXLyF/MvIHwR1R7d
+GaocgX4Gy7k56lBdZb1MRhEZ622Iozv1XyJYbfPxdFn16CpR7c/zySrsONohrCCI6ImzYWQLLB6p
+caSaFh1DtZNojk924JtS0V6Lrzplv3Cech0see7B9H1O4MYnfbSQu4gvhvfsH7woVB6mcszVfAEM
+bNmZEFefCI3B0hLJeY5AxxXeRRTR9o3AbjKQ20x68KYto8NUPc8IbyqOxPVRvfAuE1VgivBzSvVi
+tAlY5hZs0SKLBwaqmSY+BOnBIbOI0Ce1mCe86LYJFJtk1TWzKnKKs6xw5eA6Ty045lcQ9Em3U59L
+FqBGrfFMSjAaAbiIgcSyHyDBIgWgxzYFip7cVSNmCnKlVDuqKX0W9fW0akCiIBlAar0HW4XM7gGE
+aeKNbMACrCqGfFEVnvgyqD0nrgB6eCkbMnfZ/JwwBNSrrlU01LyY2ZSdcrYcG6pmJrHo9OYQl6Q8
+2lbUniIfR9+XzBtAZyNvbc+1A2tNNpYFEaQuGjmpV5eM5y+1h8W2q9x9VmSW3CpYU2cG+zxxfZDV
+auCTfvE7ZOLDEovHjMRFe9AIHSox1q2mEaILr5vXach0I5q6VXhaukegaCfmKaTrLEQ9wkMIMoRc
+uirlnQqIsjgvHXRFRYIsNF5nQtJ39wUQhUl2ORWHwKIRHV1jVJXGXNdBT1GzLiz6ZE/6IJtjpmmd
+XZXL5uGJLLruDC6BrKgpKLTUSV0bKiuPrn+2fSvqwV3qVnJlo2kF+zGce5Y7sXunYI2mAFhlbtH4
+neQEIrBH9/u5GFh20BVNYkZ7Nlg6qigHM6l/3lXcmgxmNzXjKzV6RlgQKj/OJ6rwbR5W82LstSkR
+bIwWLOhQh7Dw5nWqkE+snnPjiEIbVf07hqMSx0jNrYI7g9POdzvv5cyui+pxw0qqdOpKErSY01ez
+AwhuDgnnMus/eChRjViOY+y6PTd2QzRr3PNJvTuFFzk5y/mDtwa2A1ql8bYMQFDPVMsUibHv+NxD
+Tz2VJJBhzSNfnbKVggiVTgdbhkBmCYi3j5ga2xMMCa4WUFl0Z8Ujo5ZeKDUVKpVhSso/ouulbBZm
+ZPeF9Vu7EJVrJRjuuq4jBhMOQnLxYZ6iwqVkaS6RoybXOmfNaIt8AYfgp7uOOXUAgbCFKr8mzT6o
+Sdy6ovJR6n/VN+k+kqKlVsHEfBu+nFSIiPsfYb6Yxziw+pU83y3GOExmIyR0p7MPNWm0rlKl3qT7
+OushaRmd9Ba3BZMJpIG3/YlVCwDq6ZvI9WkQWO3kCAosjUsgvKhqKSkkNWI0admsLgCrnP6JF5aC
+gmDQeTTFjNLOKtVtYx6ABXLJC7CYid6PTtTYT55ESSSmZ3eerhjtTRKjtA4o0L/qYNZptBNpkR0K
+9n1Ah5BA5LOlCByPNRXG4cqFV8x3ENHnYCZCFiQGjvwLITA/xjA4gohkpAc5JCzqMtuFEdNxNbAi
+QbJKleKVaYjNrYdFDWxV0fBmrMW8iN4pkO4YEs1zsXUAsqsahlElHIAqxeU8FYKGUy2hr6MUNuWp
+ia8EL/TKtl2xihlWRj+etuEO8H6tRZ1piZ+l76tLo3I6Jz5YTB2mbOE+ArNgi7iRYs+6CLxFylwl
+L1IyTq0H4G41exyrU1J4kJ8VB0yoAxIszRxIzlJ3g1nsYbRgNfIXyCNoBFp6B0AHsmL8YB7KSSRx
+e4SevC/qvHw9WwQjUuKu7F5p6ENSwmhLU/NV0glroFFraMCZjzDE4TwfZW0IsFklBHEGYw89GwvP
+9vceFqfyy/NW6YczZ06+780hHji/Sr7vB3vSe7Ybgxu8gU3YPCxDSiTFGKUHLMemxqAE0wmYbC8V
+viOgPknHv6UHB0Mv6u3lw9AETLbkYtAGz56guk4kxIeT+iwositvy+qAH4bQPXGU52WTCFXpYwh/
++gYavcJ1HwBgsQolQXZHXzH5Tj0BzibnG3v8eOl9MVcR1jXP5tFgN6xPZiBEs7bxFhH1g/UUQwR7
+SwNK1cuj1Qx+ihMLsGna+hB693gWSTVBtsDonrRmh6lYMPkxwbCnJp3SRfvJtuTZO4DTNe+9HItB
+YCc+MiauFTcpqf9F3ZSEMJVOSVzRWD9eDx6SvWUdABp1rxcnOV0vkkZVXoGaUdbL3Q==
+		]]><![CDATA[
+		4HLqaWQ5oHTbe9Z8rKouvmquLA0PI8xLGhImXpWRHtSGVMPXYxqF5V0prS/sFeMOUh46qAavmNtg
+pLo+oSTkbrwpJ4yoYys6Yce3EJysNocGppDpvTlAZbgBdzS1IbJV3SIuNA29tizPaqqjFQNDNu5J
+H8ESUhDuvR0y4rM8KPm8lfjSKQRlCc9nOuX7YeApV9nVGqKVKZMVZmCMeubHJT+I0xJU2afYOYt5
+Pekc+NSZApV7bKMLeM7ZjvFzpAEtl17pLR23ZqTXfv7MziIR3IhJGAJhdtBCTogT0HJbeygJwKHp
+2Uf1iQIw2rGyJSftoIR9PAzBemxAMoQRltKiB5w4f5Q7zZrkbGfwcAvt2bjqUQl4ylK5jA5n8l6t
+eSue74C0PbwbYqo9w36/ZHP8L+Wg2oJTjcuqgeCz5hqUjFL6vrdORZULdRgWLbh1MBwwqUKfjUUU
+Y1HEHQC7Ryl0wYQXV7Ro684aLT2sgST1eKPWprnHlueDKp6d1FYk4g2lQQ+jkNuUgdX1yGg3S1ax
+D4noE1CzxqozBQ+2e80QtPJ+qON5y1fPSfW+aCVrhGtQxY3KpDW12L9fnBu56VYVbVesJIoXywDH
+Y3nlnBGNyr7mYsoRRzMXLAJJ+TS3ZscUTdQpQiNkCenuGUTzimgjq6o9GPAxa22NoOdwK900qxEJ
+OUJOQAvu06Fu60A9XYFzoBlIJ0x5vE0U88zndEVeWn4W3kww6E5ieZWBcBYlh8JjlH1SC4SQoToU
+DGRXS8RMSAs9F06Uw1vuYzDflu2JsVlKtpW0I6vaKe1IgjsCQ9Fsv352AOGqDHXrL2EF1bg16Brv
+LPyuugxjqPJwTy5Ea32Jqi8ISTYOFdSNOxqL+gY1UYIYdHjlgGnXVaK2WJ3SFMil25TJjeXl+gaM
+TodUTfIFdVtUbyZsaur3WHuazu3KAioaimUiQ98p3E5OaCVsBuuJCrSjQ+twUEt0N5SNL6J3yRLs
+JGiyf+H3MKXNGPuUkkp1r3yYuQK0LFGoJ1kLuXtVmkC6tX1BzjvSGIIaKiEM3L1H33ldk9kIXPbJ
+O/MAumA+LVa5sL6ct/PMSuFliKbHwdNXzKLSOjXca696EhS4GcLZ/a9lSE3NPXqB8wkqo0jcm5uz
+9Ui1ZYBO+jn3chTc2jSgjj4MHmjxXCOGwORsulW4ZudGrUIGxg67BflhOsSBMF9VuPUiZAgvSR2P
+xLcIjJxxTUA5fodAPT2XWEm/1iEs5lduomjlapmqoB6y0MtZFc046o+5Z9VGLmbBU8u92iSXb0QY
+fnMRL6VUzqxU90rdpLEnX+dgZJXYf3arcNnEErMUwsY0a8n7r1SPLAnO7BAHgTU4lYZundV3iKYD
+ItCLha56NFZti5pRN2g/GY8c6hhSXVzveDFnVBDFDkv5Zc3cCFzAC4EaUY/MXdIzwLP2XCSPES9O
+txOOUt8Ugd0xm3tuAJUT1CCbWD9YIbCGAe3IIM2y7iJb+SILmlnYkUq46rNNB8VZewizkQ5eMizj
+V+VZKeyDMD2YnNRhjLUuQ9Dtulg61FDuEjMsFpVm/ZCCKqz4pKmFvUwHvq2LCl3eobqgVD/iOXhj
+KSJhw4Ha/ZF3t1uF6zmOZN5KRJgdBZPqiby+WSnB0rJpJaxnzcIh9KrvfFHtCd5lJ84H/CIxBFU5
+NaaSezWWqPUviEot+4ryQTv19treeuiHGMCq0uhxCaoKqJuAY28JcCDNnUVrz8nCumTm4nYcrMDv
+eytZyyfM6E2W2Em5lDawXuFE1yj30g5YYIot59wdlpHHZUMIlvckoZHsLcU/6qkvBKpHAjvQWhcI
+74jUIPdc5PjukOuFHhFcmvIaLGXuoszb2Y50UIi3BWaXfg5DgaPs9EgnSUg74NLEg3Kshy4svNNT
+OgjvBazIk8SSuyeX6umSnIekZW8+TCyGlHSvUgMVgMUSyasSDaZwmKVU/dCBFaqp4o/DekNStzHy
+bwI0d2noGXdY0cmUcT3MkiufwlntPt3CFkKQDirveyz0FkvZw2pVXoWp4gEvEZMsTswWY1EGu353
+Pgc7Z4pwC16FYJu+41q2spdzxgOWQnJN4pKL2IHFW7GayLSve7ZIYsk1Q63D6d6leSY7VeTcWhnW
+TFg09NFws7hTeHZ6komycm/teXGQRq2CV7HWUlDtQ9zSWJRJ4pZpDBuWfipTotCi7NjDur0i0Jvu
+0CxdhR7mbTfpAVkCJuVOkMrpMJ3cudFXFzvXnvhYBaOvOjsIlvTAPAEXp0oPm/MIS/og3SYuk8SK
+brqxBsdJg1j7aVHUiSeo9KBz4hCRdFAueoic6+YgTKu/RC1vVEv3/0dO+pUOejWCNFqNWAHLqRrM
+9XRosSX9I1kSbEnmZ4hjYALhxfRoiRZiBS6Rrol3AH5V17paT2ZE+FLrXhPPF6Y4kRgycGgmXKzM
+I6GjWhKmpC5iMS5xHSdL8oUnm+HCjTju9DUySR0KYiTxYmC1FZMYNm0QTxLJiJvlj1Fzp7KkiGNp
+Fjv0AkLhX/VRPd4S9foQBAISLcODlT2sIpM1R2TY2bDcjZwlSlpGinpwmpWSFTkNVUAdbjPPfF2s
+Rm/kegUI9JbmnphkGNgNhV5aB+GidyetFVLJGR6FhqVyeCWvhPJFD5ep1covE08i+UaNUqv02TPV
+ejUB7lZ1+SJxXVSX1LDL3t7fY3idJMkvouQrih75/bKMX2oXrm++sblrpZWsiLNNUuOde0lzdlnm
+rMRgouqUJso0PIJ3XrD3GMWWaLuJg1snZBl2vKjAFuEAMC0tmczhWXs+fhoz+ncjO6vF/6unTW+F
+/NVTulLp+dsv1xcqPeyipbi9aImvtZ1ftwSa5/zCJU8V/RtTw90GFD15cVjMECntITX3YGbv6VYv
+WeIh0VVLeNQCL3XE263oGi4Pg3Ooi+PNjp9TAEeM2SQq051GSkSiYtIU7yOoyFLKCqVGsSGXURCS
+oNbvv1SPR+AUwOTsYaRwGq0+yywkE28sao3b5NGxWgkJOHZXoF82sVcPVUvWv+imnqLqsY/SAaWr
+vVR/x5Joa8I7iuTAe46qodPFRV69ILGQHpQ8RXJeqg0n2d0wMTIeP6coh9T6Qd+yKLcYbLIpYI7Q
+Sw3ESdAOr8uRKDZmcZAcSd3d6QHLfMAJs+TwrBR3APCYpF+6sodhjl02CJQTe95ujlAkXg9UEwec
+S4zSD2su9cYw0Om4NCrOV+O/O6p5ifyK9JbwYjS83hmpbUVI6GGxjG3CGK0DOj2k2xj1WbxnQLIX
+MMIh7+IbIV6qs17H1bS4MaqD/WU6AyMlfdOGwrKc2DSVQfKF0eryYpMkpXI0wL1ZtwqUeNdL8zQI
+PNrDESMQPF/fc4KaLgSWPkdlzkhEytEOY8B8Gh1v9WWzwjqJ7QrrnLcrPGC9rzAa94vXNKz1stkC
+bwTKdhr9zqJxzkGjOgNyki3bCpMU8TJmVbjva9wXKBqRjItZkt8uMZqDwxJXo71qa4G3fLPAQhNY
+8DsMLI8LlK1g6PphqYtNdX8XBUpeIwGNegtGfwOD9fQjZoeyUwyL9mosz+nMBPZS2Upx2581EkFL
+1zJ0ZG0UBzsKiXrJ5orIkh3uG6ixI3y/5kYgMB34tyKpzAiE0LUjkM4UU/Y5xmtTxpyy8I7d91Kg
+o2FKY1NqPEa6UzqfMcQUkUexPlme3UpOFngg/pkYmcubmXCay3ijUaUxWV6jZ4XvKF/S5o5wyTGO
+mvLenFFnXD3l/52s2IoQx0HorR5SnGWH52gvq/ww6wusNKGmhA+aABCfEQZxhNWzsi9eVsxaNCYl
+81gVuCWP4WHUIuRhb0JhkABujKPvJcOGQLoQ6cJmWMjdoncB0DLes0z3q24pRKXVlkIGKTaVjQ+S
+o0JNU7qbDffY1B4kR1/ej617xPix/XRYc78Sl0Yf3mi509Ew/k5zjdlZmKHTZ9Pw0EDIfi8rC1/D
+uWWFzBl3O1ZIllSSrehP6XmoeJ+OjDWMmlzT00IlmqjELA+h70zPsvi0AfSvUxY66Yf9ya7noCsq
+7ZYwjymDA5yna7qSrkKwrWVgu74G+/U6sRfuGXq7uJ2fZ0LiiDyZyp6plNpJtO3qjkiYkseMjo6Q
+3JQ8Z3Q8xeExhE+XZreMu9VdSfCprJxK1akIPrIRDhQ6rO2KmG1xR7K33WJkkUHcr/gpy2iHxckc
+et9waSh73m2MMNOElXdq30utiCQwj65512fQp9rVnKSm99ABIsyejapOVAPWUYMLaYALMYVgdw04
+yyQcFrKtDu+ObB1K2Zk66HgW9K5kha3vdtFObmQbGTRZ4GKWzl6sHRGBU3E5Faw7IbyXzR0HUwKZ
+ktIxupsS6ZScZ1g8hvHp2uzWcbK8w7YzFfGzvWCyaxw1ZIuGKEoZQ2V4VMrgqnevSF8HsGKT0LX5
+gadkFlvu0x5GTp1YsuhVdVVPtyBhCKMs5oBHDUMG1uxd5rtDT2vfeqtK8tqLucR+00c0ujMsSoLm
+y76ZWWn9ZP4EPUyBqaVFd2S9KdyxH1+cWeNdjksM5s1qehOjuik6IShwRyBttGRHGaK2VrR17Ajf
+L/rp3VtCuCitcndnRT0fRpGhKKdl5S40XAc5X48JLsw6hc/XCn04zS9GKs2c4jzQR9vL97rMt+82
+XIGyJjG3WPaCEmky9KZm5JzZC2QSngkHBqxhpik/TPF4FOlhIFwviR2rlQxYz3m7wviwVc5fL7Gr
+TR1XjSIreFGCIHK/avfv4BiY8d1Q6TyRTOMYuCfaNjUy2qh7j0ypdveafTf8j5zu7eBABx/z/W9Z
+hL58qx5jrU/j+EzS53QyqD+sG6+3e7AYZksYdUzyZFeKKJeiuK2Q0Lnfv5OKRNkhugufqZiaS7Sp
+8JuKyZ1I3SJajnKYR6h5r+JE7SzMpC7Shx6uQq9V1OqKsbN4akOWiBYUmdLVDI3HUB6SJXR5K6aF
+p6ucHtWhY61mrGoWj1UxJQs2aiEM9ZkPlCTHCnas6Ljen51dA2SreK8+as9yqtNZVCNgeNbFAWh6
+IPBoXT+MVrPVKSp8c9hsKzrKyxwCwkPvIyvLOsTEuWErCotFObGHu9LK5WjrGLtJ1CksBiOPHtqK
+rAZvKAyPYyQtu96DY7Gp6rIKoske1gNu8pwpGBab092uh/AGwWuRm9XXhyjPwsJ7pWIhmSaX15Sh
+w98FlWS2JnukZ4WvZE+MPRpiwkeBG+kzPIsn2mW9ul66Xe9T0meHh13Ys+NsgtsjqzBbsMm67ihg
+TxhDWG4WNZ2GV4/FYmdx21l8dxrVWxOHWx0B3QUL95HFScRxoPkphc1pcUK3x9T4Pl/JjLnbKLsx
+Wx4mvEIXMtnJo6yqEFXQ8Mr50fd+1aAbiVNOX6zoOC3GYiPNy6N9Y0balaVZcdJweHGdI6DEYTQz
+g8XxfN5KRmlIfxRmRkdb/J0K7Wwne7fjWZnrDHvHMD1blWSV2obly+bFGcb6Ofn9Yw==
+		]]><![CDATA[
+		20xrNv8dqracuJJlmLOV6PhQlIKJrARIxSzso5kSoLSWRndWwiIDdHtP7K6R6Y40EWbH5N5MQB4V
+pjPJO5XRe4E+EfQDeU1peUb0M/44mjsg3gfKgLBsmej1nMMo/RYp/YpCSsoTH8vhWOd7cCXWdWZI
+05BfTyLJLnTqGhJO+BabTWpK5gMGqzSWvJf0YF2trTUJTKVogjZ3JMhRr89HfwKwxSCqk3nZtOcV
+NyEW1Eq3KEWKLHpN2PuSZWy5Og2IiA2HwGWrCei7tgSik+6aAN8hQzkqmuMy5LIktf6neS/osY2M
+XioJxEqj57KmWK7KqQG4IZqTesA2SWdIT9km9ExTf06kCW2pcUq20+Eem9oeA6eQtU0ommceTbKU
+jvrHqnIuUB3JcPOPyf0kCbOw+RgNUoqnA/Ap9ZNLxeg2jdqrNyRk8yMN3NCBnXPKeDa6gxsbiJbL
+3vNddB/piUPVWGSVZLTYnj0kJBVbsZ66pC9b6VOpbbwfmlyzdCXcDw/v4/gK3LGTTNnitMqTxSxl
+LhMhGVQDq2+W7dSGvpvINmFrGPMcP3NcTvE+W6DdWm4zNVYpTdOUr2ly2JFEsnnS2Sw9bZYTtV7i
+IX9qlmm1T8vaLfGKfKd0MqeoGfn97ulUzlvIYr8pTLePY3vNdGOabmG77W7LtCvCnvL9VEIckSZT
+yTOVUVPOOMpGM4bbc+duSVdb/HQnne+5sw36d0/PlsuczpLLjHXoWM2mRHhJKI8DaMxbTnzI8nb8
+6hQ4fPnjc5rJqUZpQ2THujFKR8eEI15P7vUINVcBitU8Yhip4hNlsXHxyWsVNYkr4MD+3Zyzo8NV
+TgYkZ7cppKjlL3CvlxOV+Hc+L0Gbbd9mihQYGvblaJflDjs4lhgMqi8Nuz26BjmKwjnBQvCFq+0M
+KcHIBXy10DoluMPXvgfytSk8LFZlRQrJDf6APdKPqvVo1nOnq5TgZKWTBpFJNQJ4wNVOWOTF3jVK
+cgyi8AmRVK3UY45S7QZ3Aokv5WKqOgYMx3OWcmFXllO3t6pVy4F4zNuT+u4o3/i4Bn4t2cYjeKSk
+OUvPiHZTJ2XYpSpLLMdncrRaQn0l1omKA3y1//UVGhOpbYVoS5KSt1u0n9D0VvMYd42ohb9yr9iO
++znXxM/9EjnMyGOuwBn3sqgoJvkCHzzQuVhmP5a3zWQZ4wHQwtXLUHaSDkxZU8JEUZlIgeYzkMoA
+w8MdxT0/q2Nyneq3wnwPJA6rhEmXUt2mr2c0stwj7YSetacUw/CErGYEuKfWa1WmN5g3Kt4v03xB
+ZxM5Nus5fra4nKB4yDmcc8KMZ6YMdkTMGKGs01JT0usNx7TUxFKagFS9jGlSbtoB4HAzUEpaQAgz
+gpwdzklWFA7hWuogyjFNyh6StwWlVQVuETw8HKM97DthdyJepXHtiXuL4c4InWNGROywdsp83jOj
+4XjPuFMO34mDaxUHG9TfaseTdZqu6Gwix2b9MDnx8gGovE9SHZW4YVjlUR4QB7oBzj3L5b8EjAqU
++msE9EPBLKkFjok1vdwVVkjiihiYHYRloxGIVdpIeBS5+W6NiVXW0QAfkwYHgu3peQNpD/PYTfqU
+xNwxjUnMPYNNOXHHttfawQZxxs4TLE/XYzaPY5Oeo2eLyh2GV9mLc5kwkx5TUXMkXtq0gEbJ7PS6
+U/WUw7hgmVFRPaOfxTfJb7EkML0qZLFqxsMcVol7K6rqSWsx6OVzSJbBa0gmJkmf8lqCezfc61OS
+ascFd0cmPZRU275xOrTtNCazG/LW5gw2Y8X9iK9P5IwXS1JtXO7MMuz1jie8TEuvD0e41k9FBtGS
+iiFz0YrF7gfAAIxUjRbgS52HXlI6PNzLY6Db1G2kB0b2l17afaSLQd/CwiOLZDhlqRcbk1UTXMzX
+sJ/z9YnMrS0R3x3Bm+Fn8sI+NGf1e4bpLUd2YjGdjHU7j/iYtVrdjpe2A74+yreLFu/Mg0NWzqXn
+blgPl8r2ukhkJtptgloNEOuQNkkgkVO2EoeSJCCr2DS+/PZUus+OEC1zbt2tFROlIgGclSLn41ZD
+laSx9bx62e491d2qqaylqZ3VcpsT8zHKP8ImM37aTPnoEmLFPhY3q1wVyqonKhwig5jLz3eNDjFE
+KmqRJGI67EDFsvKi1H37XIo8OIkiFvGEYL4aH82nsJxVvMUUP75eMDa+y9C8HqzNYV3SnhicnGYa
+RN2UxFZfZUoMPoQBid3b0NMBVq4JMjp2LotVkDZamfshmNkXeEwisQVex0ij3d44PJy8IXjIhN4u
+28mEty0muldqi7QJbvfLIMuzc1bZ8uwcWzMH2NRvs14gNx7QnriDdr6jiU+JFm7nUxpWeUoPE9o5
+tgEW04goE8CpfCler3hAdlw4M7eYKwTLCKvHomkZDDxA1u8zRLOW6+7iw0krDooqiclhzmnyt9xu
+vMlmSFz8TFIfnFb57USmKRIjQfbMkRXx6qMjlZvYHlmCgNeb7WCbJVJ3MHGMYRobOsYs8UEurcex
+qMixAspYt7kmDehsluGURr9D2J068qphfEmLFnSQOl8A1Etfjq0Z1uli3Ymu3JHaNpGzhAmYJSGb
+dCtjYRnw5xSFkOJIMVhpmUULUcdgBRJr0OrdWNY69yMZXq88iVhqL6tmgZV0uDAtok3jYNW4W2vM
+DQPD/MOsFSyQdkUQ9VTF2T4xE07HBNlU5B2Vj1NhOhW7Oxk9kd0bZWRP1TPyP8IpE6aact+UVSle
+9lE78WQpji7bfoWnlLAnGyGn3fZsrLnfy+e7/jEVYaZPPJiiCGl7NrwzWt3J2blEnsmNo0JmJo72
+ssuijBv+ND7cM/OM649KiKk4mQmeqZQ6ogha2dp1ylOKeu84PFEl+QOPenIN1OTsljSMUnHpUIxS
+odvURKKUXE1y74QoCllLvafh+G3TWwZwGGIBdCfXOmWI6uBrSLMuWupAbgwe4pxD9CnNLUGNiw22
+SQ9h2cEDLi9GoS4O6ByNi0WtFT+kzPT72iizRlyIO7yfdHvuAnm2Svuo3yw8uA8l9hDjevFMm9uv
+9JQmphM5Nus5fk4gcx+RnIQup2HOo35Pp5KcQvCmt6WgxUUpXp80w1mqpiaxt1jILCy/VlkA6LTF
+opQMlrMDAOSChSnZ5cJl0fKICMR5id5XtMBqqmPtvxzVZU2JLNGq2rK9Sie8ipb27XHKIROmxzSL
+3Vrco5+U67EN2VFax0Q5pxwQp7Gu/vA+EKPAHcsV7sGUc+Xb0pXzMgRhLVdkt3CnNL3dRLYx33HW
+M/wcweUc79MV2i2nLfMmGGzLvA8cTyPM82j0NHI9j3FPArPrRe5B3Hm4dxcb3i2yYHdrgY2UMqOp
+KQGynrTbDO5Up9/vHNM9Zr8hXSvjbvjxVuEz3p0y+UwgTIXHVMxMSfsYH8w5ZsdeuxVJG6fgZLuc
+7KvTPXiVFfTtMQNZLp/rGTd36kBIVsRzyMRBv3e/Q1BqoxfLnMaKwNF8T/JkWViTMt1NitFiwnRJ
+WqFWHGWYvZWsxC2flEXHRCzDbii3neJ2CvPuOX+VPXAoIFStjHrTWe511DE7kEeQOWPXVDe5iQqL
+YDdTQeUyeaxhnYpu1I4v+c2Fh/ZSsSmXRmENDLm7EkM3ciOww6r5vD3t8H5U+cOjBHxlIp0jVyGJ
+h/PJjYgh71yHGxa8ixIf14RziopT0XaUX3L+FfMD+O6+HMcFylRz1/PkVAXG9AFWQdC0aFZ/y2oN
+6xx4wMuMdrBU1sKRqMb0yg9zHyiJs7fDE6sZnwhxUH13rvUjs7hTOAgcpwu/aKF7qTedqeiWArMQ
+pBhc12rc8ZV+SCXOEtbxSHSoEujVrASgOL1Iw9l9CHmOHSztrSVvR+xgGneJGwzbhXbrtdhM+cQe
+u19lI58pSUyJZ01ollCyQZvNY4rj6Wrs53Fi0hP07HBpY1uj3oY2IeIpuc9444htVliZ4Hh+WzTG
+RrkKHEIUk593+sWJ9NTLE/AmcrmzbDWJHf3c6vv2pDajyR39Xh8Z7+0JPTzZGfmFbzm+U/28Ouoc
+TfRuNia9RQ7DU+ofkIzO4dKhRW3nzYyDlcpeTzmI45sKO/MZad7oJOqqRsp+uCdif0cXbteJBf4n
+b5wNbTcNSxDaLLRlr+yJYko9uxEfj/5VubEBKzyYCxXNvaZbkU9NjbWQ9XoiZ6mCwhSbKWBFgmUv
+vOjCdbkIovsFRIhz/XGvRiDH2ehCgWZ3bW2GeypmuO/DQiaTF04HtpmDzW1DlTa3Lf3OqHzHEddH
+RnuC3TDiz7dHoTOrXwgWs9144nrxFdxONRhKF4MzUNxP68mhHj/bdchFqfUHnGhjeAFh4CspnBWG
+x/OICwtgWKxaS+95M+bbE/H2XSdGmJM3og6qddhtbFm3qM0Ey3biNsHEaeaduKdcsKHA6yPjvb0/
+3r5SpHFB5DLH9bjScBOVi1VrFOrNj94q36N3UDMDhtOCu/fdE2df92GDm7wvjnco6ciCXZW+RjvS
+W9yLbLxOMOvleUacUzLe0c/1fMhHMY9qNc8ii1P2Tp3gMuYsoS5+WIrsoxwQFZ2yDBY5BD7o8wjn
+a64oyJc0JF646GSUG04YSE4xDh30i8WwZqzGbMnv1guH8EVoeA1eZZcBPptVE8lcLaMY326sKDyD
+yvCVyaVMPhhnRRWn9cphZaXi6m7lhtsXsFJHsjsdOCiBWZqx6h0mG7yf8o7uZ3JnGNrN+hh6Vqg0
+DK+tRMPw1KKc2J7HDNXTVu2I4p2xbEPboP52g4qxk9MrOozt2O6BNCghicrWp93kEPnuC3LcLFqA
+orBDJvJZUYbJbUzoDAvOgpYL3u0rTiC99IgKULBl7e2Gzs4wpPxnDS9SZRk1mDUyjqk5bCnA5DTp
+DYHsu8H9El1z0gM+TPdSUfWqrDeFdEne9I4Kb0u0JngNbW/ofYh4R7uFEu8lYaMdnTDJStognG+d
+w3hzqcm4g8gKd5vDdClOmGgD0rCsllV2BQwjFg6Shd+jzY42RXQLShT8xMJpQCGaZxIznJgqMSoQ
+mg5YbDHkLuFlmS+J0NidrsdwsEGYRSg3gvFW4VMpOpW3x4TzXpKjzGfdOy92uRwygFhzgmCjKbUH
+Xd8LgiYOF7tQai8rTYZuSM2oRMIq+ERu1vEilQGjYu0EtfNNZRiHDUnxLijDG9KyCeEN8agvdj/r
+vi3OUCSXbz9sWwxOs4Oc+CCpGh3hiO4uZON6ukUItUgpdVCh5ST80Z1njfqOod0yTddztviKoDnf
+TfE8XZFTwmon2aYy8JjAnErXI3L4GO9PBcVEpMxJaKZqoW0TtOgP9WT5VHKDD7ryl35pmOUnYBSk
+aWRO9lUs2h6TAoWTsrjhxReE+bdFEKmbYr9gamELgd/UbyQd9+CgWUObPdjbheErr6znG7xH/23U
+VIGNszcKP5NjOKtjWNJ4yYWsofcj3uZCRiR6xHLRq+9Is+GogbgY9ji/PqVm7bzjdw==
+		]]><![CDATA[
+		R1aue81nr5yN7dg0Zg72I6741chOuHULx7w4KoOpKuK17PFq2VdvFa6O92L3uOL1lHwUDkv0ZLkB
+qLBk2LkM63D/2+gzbLqTD8TWgXgyTUQo0jXranTjrpEwUi7zPdf50WiUJGjScXW56G076RPeKxRN
+csq98l2Wd/NogeVz7N3sR/zxy0yX3ePNOp4iWaIbdEUoi7r9iK9FEO+Z3xKFJpJiJlJ24ud6TkUW
+M5wg/8gyTdd0SgBzUtnRlQ1tI69MLu2F21QKziTm+SoBeL+tBDCvAeDmFQCC3YCM5SqyXaZOdx4q
+6LaDqpVC6Fcn70HDF7kAAB/9P+DQzAsjYh1+W7KzEx0gcjxt31TyQZLDIui/FHcNyADAY38yxZv1
+G33hmyOdv9G4d+LqEZyH7VOPAeREGzZmRg/Vn6qp2pjV9yczA8piaY5B37rrW1/a8UJXoiSb66J3
+p9MFOlZBVq5qxHQFNAL/pNpgbVVMBPKzvNkgXTsf5lqdHDKjOhk2V7l0Ay8FkNvs6Q7hIEBgtNbn
+Sme+SB6Rz9vmuu5bXxrR5cp3WZvPUBQjBAFypRAyX6cI6xRqfxddNChHboCb3yhJ9C7fnJN38vJJ
+vKO3+dE0C8sOcRzRp1DHe//Wn4Yr/3rtjh2XBJCcBe9tjYsbPQUBNJmMORJxAREZ2EYJWU6Igwji
+8iX8JPv9QA0FdaKp5ov1SSj7LDRnN1gTt+B2ECreA9Gs/DJF20NDtqpWzC5cRCoFiz2oeRLlgmp6
+XZCET83cpIFFTIt7qYTBJ2xwFnpXMbI9FpqHX7zpKXs8qG2A5q7DXFl8vOAdt90TTxe3Itwvlnfc
+FlQbQ8P5Lea9JhLH0eXohpQ7PsAHlrfJBPQSNLxNPLTAhgQCMaEVdzWcdMSrvl9qSAGLIlEHyyKH
+OACbFd0j+Da9wRCALvvM44JtQheJqvzwpHXvipW9IHFB00XOP+1wYGk+aAyh4IwL6BA9Jki5iQAE
+Y0jMJgDSZbrUR5Zq3AlvgEeJRgvkxmJQLF9Bd7CTdHgOl6ochJbR/GFg4gpxNNsYhuwqrnuG8FKi
+Rs1I9cGX0ZlxEcyxRaEGK8iPiT20ZjgFWBor6VF5Xplvd95jwBDTuJB7XOookWEILSwEL3pli7ol
+qQfLI0D2WQKvAx1rk4HhtS4u8JoVbydLGo9rMS0mY3H9JQoHo2PUMuKoJCF1AJ1r/gbdokxvU4Mb
+gHw7Ms0MyUt6UGcAziFJIgzW5yKrACdcg9aMX+PA8sGxugPKjOjQBImppyK4iqolwqOXw06Ux0s9
+4wmmqjVIKV5DY1CKZDjnHBAuRTxg6UbHs0MXZzX1NnIPeJf2UBl0qcwTqWtdRbZMfJtdOVVEwOG4
+sCDkS1OD6WpqnIPeQ4yFInm4bnWt6AYLYm2jrP6cynSX4OSlqV+9mgG/zjEva1l7lCWZ1yRTtOQP
+yt+UZE5jBILVgHmma8gN+Ac1JIDmZeRBIjVZbtSOPnBisTwLvEjUGSSFl0mTa41HjDHCW/9gO3kg
+DsOjJUuxaq2oTUfMbcBTCX8wNYnAhVLsNNyYKfIGmi0IzKRDwFJQvIB6SzjvRkADCMSr3dC5xQ9j
+HfRC88jiiOK9pGIkr49MRhFFbYqof3kRVYbK4Hk5ZBiJBT1gyNtdzVi1EdX06Cq7FGQUjjP2ogPj
+JHN8f7fKf9gl7DmlCJ/UkwMPe5Rvdj0w1R/Ay9thx1u09KPUf0GebnwaHZ5kaZVQVCQr1uYz3csM
+O03hyBzCIt87D0AsPs+HUmCSIA4RwSCEfWc8v0igBuF0Yp6BnM4acTsUT6d3nMZA41qcZaB7ZILE
+c1jkImwfOPudJqyuxD0WVK64rB4wlDjeMuQc3jhBKixKC7YUYWUihxWR0eWgr0PyIR/1Ig69l9qB
+D3RgBoWpyEeHt0GR2MVNNTBTO6zPU/jBJdu9ws5OmSxozHEuFMiCTEVEYevRyKgLepk7iiVkPetA
+8qaQTkQhc1iHjixVFLqiyuyRYOjBazBIz3V4V0DQXHpHGjl+wy14qDzJ4BofCoRuwEb2AmQXGq6R
+7dbO0blHQppaGW4Rnxhuq5JiDR2RzscTDhZfgxnJoZhFEssY6ByZv0syDxwJe16HwjqG9FD1Thl6
+L78NT5uSxeEcnWudYkBxsyS2COAvgY1+xs2CdR4qg2NmhRVgpBJTL5EzoRcq7kBzaGyDyMjQjmF4
+4VsXEBj5ynTGY+BiwkhxheeGrhI7Trd4ybrD10qIUJVUetsiqWqkhxadWx2+XzJRDhJhcjoCEqUA
+jKwxT3Fg2Fmodi38Afe/jhwznFzhPGkZG9pcAEwmahe7Q94FI0rumI8cIyb5+qfSMCyReS3lNpIC
+aqDUoQJgwa2Uvl8aJkKRvweXFhOhEJg17cphDazMPRSWcDhhsEaHDsDypYHBpsWyHkegozUtbYeC
+zWa96OkXfGf3wnlRkWClQPdQNgJxwk44ZD30QfxBmRzIpPIgSZwyHYNFlwfgH3jkaI3pyBsXU6Hp
+8BLilRtoxP9B8ewrpXYFuqSgCc3CuyUXn7LN/6DcpLU/64Xxnfh2He+Nf1DOFTjswbSXslTCKR4o
+voWhZX7WB9EDqJSDnIfzaBvx/UGeLzySh/EEOnsNixghrl0kHZK8HSBVav5D9/6wQmEQ36KgtrJP
+EhBTyRvKG4k4C2FsRZ+E7Z24D/DauAbidHm327Rt0iujfW2Yr432tUG/Nto/xQHxq7dvX9y9+vLg
+3Nb50CtlPtgJAVYC7g6wnKCToZdsYa8L7DuVM3c6/HYNz3jhRJCKA0M/x+BjP+y22DkswJbB5C3Y
+oWEx8WpVCdUBHNOUgWUJTtXD6VlYXYJQyQ1+Cs+uAQyjiXKSgOBUQ4XgaAXyt9GgIRCX7SVYRiWQ
+gCna1yNfz0VgckXdKjyjcOHXeTQ8CJgwWk3jSlQlaDYtdokTejyeFIwZ77PJUnWJ4EsFPYLgLCYJ
+KN3gJUIezV4GBloQAObIpWKk5+QFjLsiwwIWYWegX7RXWTnsdZFajQSXXkk2y9cJZwij+g+zCejU
+UP7QwzTAqisptjXBw9JoXLA1FXQaMtAtSYAJxSgBietlOaSQOcCD3GpGQBBQjYF01xy/K6IJRkDQ
+2FmbJXhC45HgDW1+Bpamz2LcjGFA7AwrYGH075Pfg+Ae4QhEf0/m0eJVF9Il7g48LS+FEAme+VHH
+xh7DXCMaraiDZ3+YoNCoZuECFBifA3XQKZsgPPCiV1YjbxUemW4qXRYhIHSJEYy80wykLAYCApkW
+HXDDlFYGp9KMARrrazwMkqUEpO2ZOyaViIF4Low7xoFZx+iAJ3BpTGUoYXCrB6BawARc0Fwn4AK2
+gnaASnCWhxPy4K3CndPnuTY5LRE6vBmYecqonTIxNd76rF+63Av2goX8B/woRmcIFOMSFcYTaxhy
+9zYxUCMqYbI5cSbxu2JkGPk+GdaIfRqeHZd8Qh6qPFmSERglNwLQSykDfj/hqvl+pprAidHVPJcM
+vVU4CCvpI6nIgodRXSdgRg+NdIx5zgxsLg4916RgQ0L0NAcskVabdup4tHKVmn1/iYHBwQteMK/O
+c59sXLKcKF6eC0E5D70NTr5OlChAz2uFbB5UpGTmp4ax+iV13nOByBM9zBgRZyBV/yJgxbkIl+as
+sI7ajAeoA8OFmTpS0PlSFSl5afL9JY1LUwpjGzNBFl1GMqBltC0IzbuFxBS+qY4obHjYkeAlx2xD
+qNJtSk2BsB/LWClSa9QNCKKxJTnsRkCfnMCUYoktAwPJurAOiKkIHrUGKvEzi2zsQzco9B1qxzkG
+lTSJlxeledb1RTW/JBkwX/NDwJJkxdjCIVhFfwKtecy6ZTlK7iYgHcFgGKjVSrH4Hfl6Uv6ILvXv
+U3yc2Yku2SNgDF7YI6E7WoAsSpDBQoq9B9nJKC4SveyRaE7zy3zWfdMJeeD0+q7rlBfQR1b0ZSCh
+RciE0hRYcIosufSyWe5ANjJYjFSroFuFMj686Bq0JB04PHPbkYhhDJG/NemzhWQXCvDsdAgUHe3i
++1q3GwoM8n6BwlqGoNuC8sh+HzPlASso6MOLakWLZLjKhhOYRmHCaGXy0JYOXGS+i01toShFZTC7
+0gnYPJHSCPQk9RmWkzEOLuAiO0iIPDMExiJ7CEceGOiaTK3iSr/UHgJTHu7FLukIOr4iL/oWAy8V
+M/HCCJ9me2fKaFLB2lBYMDC6ReQaYLuo5utU2BGXmJobeDNGCUKZbwJcVIII4aCOG1QqLC7n3kMV
+MQrwErwIYthJGeZVWGE1p+CUzV3s4r2gvchDcFE7CLJngXj3IvO3WGDCwXsbgHFJOGIkfPFN7JmG
+11070e/Y1UPAmkWhXTyqnQQri2jDUY8pUL8xkRQAOAjwKM8G3nkqzBLLfzKwFdaIYZpVSkJSDw5j
+5ARPXnqIRg4AzCj4+V1NOgg5jh2ops0qDcASEowTIFn+BATcBQZSmEg6wFVJoiTzxkG9CvcETmKY
+ItHQW1RmDHdkE5i8K0SuzAIEzIswa6ior/CDi2qSWQQvg3lLI6VRVoKL2Il0CQIK3mBZaJfgKbas
+ggQjFgTMRWCB1Gx+0DpwUUwC7phZGOblir6e6Q5h5JqbzN8Q01DfERmdUUEQzDSMYyeGFy84B6FS
+iOFRaySSZqBjOseCkc3m1tiBTVsCXf7CwJJ5p3VSTpuATXoAYOXMK2SWBRWNIGNwkrUpz7N40Mtk
+pGcnai7XhJ/NbiAI76raEVUquBBclBcUihQNIeASbWuKTWEtqPgtZSCJkJxI1UTChEnKi7Zfmq4I
+Bbfl+24giSUs0m9AJ608zBIK97bsbE1NVLeB5TEurmIZPbjysAr7FXCDBEMPCv8oi5fw8MCdEWwJ
+Yh+ASt6UulOT9csUF2cyjPJgqqnPzhm4ea+opAJEbCGg/4OB8F7VVNBFabNrwQk8kM4rPTTRi4ww
+kTmr6PcuiCZLY/CeVgN1sJCTUIrp7RzIYMrObCR5Vq+vO28sTRUjr6RGF12yYoR2MgO9Z0UW/T+S
+Hc5vS1XgOSvfVjbpEKb8slsH0zSwhDbzYuaCZKZrhIU2h4Z3T2YzoRzXF8E9hMMNqlgUhtUshjCl
+bxCwHzVkzaR6hnrxE/gLMWokkiWwhZFe2Y/0f7l7lx5rliQ5bD9A/4feCCAFfc14R6S0ImuWtZIg
+AVwRxEeQIIgiAWK40L/XcTczj8yTWZdDTekuhAa6b/vNihNPDw9/mIUF4ohvLkeahDu4PNfEheH9
+qMjfdaGH+sIbttjydCMJrb6MzQFZsbc+hItv4IG0kt2FflA+7Y10sXdM2KaafZvbOBfDEztwuDP9
+qS4uvfIwj9axfQwVWyfcQr+8446e+UBPdW/rgVAcHu67hQIHoBvQJVNorzroudpODQwj6cS39ran
+kiqdCrtsWW/UJYHi9SbHe8dbnVVCNyGfJuFkxMhBdSCU9hVGyNF5RSDc5MLjSBwcgA==
+		]]><![CDATA[
+		XX169OiySHDL2wRofA2ZE6NVGRE8RZZhnhqFniqJZsWO6nL56l7DNtOYQigTU8xeCINma2jwlU8t
+ZJiqNhedl7UVVhyxyH3+9XEeYoaSXGgDfgxOUHJngYvh33SZ10+7cE1eaCleEtMKT8LGSrbtIC5p
+qIEFtWxC3lr29Gk0BHIpoZCy5td+zHoMYYZSXAOIvg8D+K2RFRjleMS2FiZW4d1pRqfZOpDlnimc
+3JYlbOsK9fehv4c1ZH+vClUX93TQki5auVcbKR3S+LRrbx1Tl8ewxB6bTPn+0WWTV79tTV6wXV0Y
+AQRaLiYsbr8Z+HEp2iqWzt7dizRoL36GfCRFGzIsFxN6p03mhRpPXdMOspp+HJvFXD902qJaq2m7
+VF+siYQPX2zZzVaeuCZ3Rdcj6CW3EvfKdg/ubqsQhdkxARpgssE7Y02cav79CMfsRJ0UhAU+ELOv
+MWdzu7zNnUPvtMvnGHyqe+UchANuLzdwoQFnp6/hJXsdT9kWJi561iP1Bg3ginG7Z6kBd1bBnDJV
+Fy20WeRoPaBlrL8lSSUVvMBMWCcV65SbDoOQ+jpqGdEFaaRh7iN2Fu8XO6ZWjBINMGhjDS+Yj5PZ
+WzCleTkYMiq/zBZGLXshFhVghs33qQUueEWZLeJpTC5c9NVl1LljiyAkYA2Yz+RDO4yXUf4bFd2M
+d40bPUM7rGV1wH1J8fdyrVo2aNNv9ZVk+3tCxEto5tFgV3Ov0nJzP0oyXFqfW944P4VvLmskF70/
+zBUBIVfepv3csKWxYNL5GrWikznjBYTHlRMdjHxay2iAd4Zd3xO3y2L9Im8XnPZlWZ6Je6/s43MY
+4pq2pAVNIFyVG3rMkB1VG7rtzX9Y9EWfrrlnhl4BEl1zsLhXzJRuMS+p8KT3Y43dbMr8VmwXvmgv
+ncYTaMcAX2K2Tf040N2TrgotZmPHI/eUMwb5yrrITGXFOPb9dNTRt7wsXZKhtezhpO75Y/nxF9UX
+WybY2PbiOro0qstTeN1q4/Lx8WDGgR1KCtfKshimToy1MHCBHsxVc2FrfciMwF1978Ppodqn6eBp
+1rJiZnjyWMzA5d19ZHwnmqMQH8sdYZoXonJ+JeIRPV/WrsfM2Kj1wmXbXnzrwGkRX/tHptZiYhu2
+7SqyywoDz9j6dLMn4EpveRyeEqd368EivX37wehKV6TPUk6rJslyMGElLEIrUNh4pXiiGmSZwdn5
+t9K3Kk28qhwqWzfKgSDqRITt4dejW1YNcNBcipRiyIcMPtl2M3yWtpdpa3tZo2QtrKKXuKlZszQ/
+txThym3FmRB624S0ku8dO3X5ZeDJAVKPvLs85JZIq+5f9BI4qC1TslseD6K4i5snlUKmC/72c9ER
+i9DHS8kiQ+xI0dvZLmkr9DehvY710Ikb0uoL5PVeM4WuzXpkeFSh6ONW5dtygAAIE6IayQ1g/r0D
+vlOsx4gX7clhlgb8NtMroot29qkDCdFfbPhDvUVaht03rWcJW6Lw9FhDoZ3kdevJbCmHvLuzrgzz
+0/eqaxMNm7m9dDtaPtxvze4qYZfQvTILwje49XQ5lZNZU0ZYCVaSppea9JL9WqYmDbPotr6x8iNm
+7WVOpXI6zb0xIAcXwtnstJd1W7KXBr05A7XPcZ4VAzV6qxk2LuzOoyNN7bEL0bmkGKR5YvOQ0huH
+4nUmt4g4hOE29hoCypZCJAFUhQaGPHSeQ45fC1/yawYPyeAuW541t7eEHJLm4KK9YipXDup8ZO3K
+tyFocFZ1n/l+8mRNjs3ItOXwgp/mJXy9wPCUNGGHXrFC2EVr7hhVm8LAGPG4sKdf40QUw+inew0B
+ShdOudyUccRvIxrKi8kgF7lwNU6ccZwoZumhQ/59Vr8qI5H8tNLnJ1+m8bEXxaPdAIkGRq6MMlWq
+1rGjuRa8hk08Ml3tHnmqfTewqiJSx34RKjfJpKtqEl9GBAPl0tgGUVm5SwPmEvPFsHz/W6gBg67E
+89EcKjS1/VMen9KyZGvopw7F6n3FE5wPFnw5uOL2fq6cGzm0THioA2kcdbfQl/II5HC2QphZODm1
+Q3dbxUmOJIJejt1CQ+zWI0gIHA3nL+CuOxrn5n3bxn5ukTeCchru54aIOqbiYLt7GmnrGfRmyUw3
+8N6yYz3Ud0eOBoURXNTLvgF+GnNTwq4YEQXsqNZhB4qm0dmwH7of4zKEEzw/rQ5pKXoxsnyDBYlf
+nxJX7r2CMMiWX5v53D9QDgU67Ryf2lcSiZvbuyGtlFsuIb62ouYNtPyUGxFRp+4cq9oKFctgcN9D
+RxLp2BBmdiTYziFugz1pHf4C+7WhfYvkhKcufOzO6Qq0l/tRdufoC3XHI5bNP878+GW+DAqPpJvK
+0+ejd8prubTACO3BOLR6N3l6xor4icFKHJFoovEti10sTsZCdKi7ccuZGDkUhsmnJg6mS4/YkMno
+7zLhVLfkA4ecLzTf09j8VtiYIjDOKLUVUelAlBKa1KqpOITuti0/rYMTZsYdZEoj6oDy5d/3iBaa
+U/jwk2IFl1Nro4vSAE27Wm2lrt0CXYp9cxy5eCcHySy0XythSjAeaF/CjXcM2G+74bEkp8fUCFwZ
+yHoJC/zqDuae+eXLoDq18HpUZsgb7nAHV6fRgqIIyI6D3XKQgN2DI1M+tdXtZlB3D88UcaEU6djA
+Dxgbkk8tpDKiC8xttBdm1ZorYkGWoL0+RQGgPHQlWe0q40/mgcSz19iVF671hWAGhHKNLbD47I1D
+h8yBMhlsx5HVC6fxhFDeuQMOgDg9mVvPwu3cJfZ3cEYvJHXg/OWsyNQML42JGVxj5hAVXYrr0saB
+Xox0irh57A5CLdDFgW+VqnRM2cIVfVunNgl9KiPBusSGTNvEshCCdnWPB5p9ziRD1hWwZ7ybO0nK
+n9Se/OTGBkBLr2G7f0kV6A1ht3JYH/fvP3dLike11+jDeDaOpp0KWWNe79/HBbUYM55Wb2G3MW+o
+hWJ2yJNcDwbu4vajiT26sOXwlxieRB1b/Nb6544ZrIWGJrZQxAyWv2Onp8AmhQfMdHLZGnCuWoGu
+uySmF4tta4euA3xcYf4P+Xj918yt99iFuLkis9+TqcKr5pw7CqL4Fv+U/O37z91Sjc1QIpBntea9
+h0blxvFsTm4x3khmBkiVug/0Q3+/VSxw1tG7WqdszaJGrx04jfHgcR3I1fyS2km9U816eVWMUWHG
+7vXoW3xtJoZukaURubpTr0+rRmL+WQ2D1j5m3yurfVyoWHdFzOFDLejsV+QmU9i1Bh5PeexDDL9G
+vLq7X4+ds+wvvJs6nnSfkuvZ0vHIDvm1mRh9juj7gSgBf8Ac8Rj9EeGdbjniZjVPS9XxvNmX0BwV
+R4HQkXo5esvl7BA3+hsNKqItyPSEBAgoP1wlNGQHnDzEzIsxrDDfJdPSGzLe7gbf4J5e+7KLCMXl
+xfNBTP6aFPWAGf42ro5jd58ETb/Rlcbd1CN+a0yftF8Wk1ddyHe63WOeP+tChAQsuaIOHQyHzmEq
+BbW/VZhzYywmXLuQZSvmqs2RY2fw0JEccTB/pXkdHG9tPS4vwpm7lsegQeMKU5KTFfDzAbLC02V8
+hQwkrXPCV7MAU+MWURDafg5PAMeIUr8aj+SB6sNogNl0p7VoEa+0DBum9pjQTXEs5TH2NPAVZw4/
+6KJ2yId3xLH1ZcQNxdBRLMM2MRQvaUe8ksxUwC614r40OTN9u5hsJ9BxpJxYNEtXmeW5IAh+20qn
+94fXr1ku+Oz78eHvHRMrCBmPBBPqt+wJhTOZq6cfhuWSPNPR6tnk+rKnR/LL0kv/Zzy3EFhQ5Vu0
+cMTHeloN+aJMKPukld1mBKiGMhesXwumsdksnWP1rUiZnxAMqp/sm7wozsxOsReZe5lNqPyYt+mL
+k2tWbqddO1OS5nS8m8kcqLkiWGG7nC6jiQoXym/tfG7VDN/rtJKEY2tmByRwaT3g8uiVhqgJ/WqG
+EFaZCUdqYbVWhGNNrBCX47ukCQNFLgi/BA7KwtncnSqFFlGBP9ZAa5rMIZTRu7A0GBsHAIPj0i61
+sgPxLmr0k/kIZIw7DBK/dFCa6MLr3lucA0ty49XUEluIFX2bwzBBE4vqZiLy7pcuFa8QM3Gja7vL
+7nYhnzt2XjMuBfOIhcOgHXxw+ce8fv3Et07hRHKJq3NMT4ci+i2dsxg041OMP+cGrQlLlx6RMcfn
+clyMSBL0BvSgTXBYmszhKDgJHiv3SchhOt4nR1uyHvHgKUiNxrS5PNNNqoNjwhW1JfCR1oO5KSZr
+Q7NWj1OVlRc+fkpe5L0t1LUm44XDWq/HjoX24+Gt9Wx1Ir3elR9n2ExR9x678mBiu3+pqt20k1sM
+O6U1yuO4uKVEWYmHLjxlLhyXd3X1HZxbOLCd4UyadiFt1WS5cgy9rtOz2tU2FXjVK754iY4rtbXY
+6mkCQnslpZl5ynqWJ9Ow9FjnYK+JiPvfv9eWMFg6L350O8xiMWzJsmkn7atOR4dhjstiWnRutYI7
+1mSzhYe+VXrj3ZabtHaKAxW4DGUnLjsyrbMg0HPxcH+Em43M4bBO5c4fUw7HfQQRyd/laB2Rd0by
+LctFjwldfpboMJOqQZpESY5Cz//50N+Hz+y1qye/beEclsPWgseMadGdDh1haX3hTFOejAFrDnrt
+tIGXbSlVvuUSIcvVWVfZIud5DV708OSpxariQXfQx1+P1cI9x6SFHnn7PVTMS5iYjtPgXo8WlOLd
+caubsEUqtkUUcIusy9Nve7ZWhLzNvcAkcavdWHKUJvj9HMlahTd96Q6xio4eHnpmglntdgQfCrOl
+rACm6C3k6nD3oDIxWr7lVRVuGnDU8pf4phseTNodQK2IiRmfs79Htr754ej4tErsohRsvz6ihdnk
+CVRcZ7mVhIMqA9nBMCtPb2/h47HpGnStyTVn9TN8EZjlBxeary0MTpqeH9qHid5qo+TCE8g2J8pu
+jiNeZp4GMWh2t9RPR6HMOvUxrkY7H1lCv6IoTLKxncwiWhj6Na+NNtkKd+ja/VrhemV2OBs4To8S
+heK83KzQxG7RgI79OtcTeSYgZmHGU3IBFg7mHrPv1766Jpxn0QNkRZmvjreJ9bbLVxej2nVlY59G
+ezA0bcTofvjKc2qa1TdtJj1XHZJXhQmWT81r3WyFxqt2MbXFPkZc2YQLU1M9Y4UX+5EiOlC7IjZk
+VPkMMVe9ADmA8hYhEZ+w1/8nUIOl/h1IwzAssaF8Qq9I4G+Vv0UyHxNWHc+2sq+zQqtVK5QcHNUR
+vqSXmCVoFtOlYW1YZkkhYdaqVStjZey3jHL6eyTtmN8lFf0+wu3uuIE6qWSIcKFXgEb3E5/yjoI1
+9FuoazP9neHyq+UUN609woDWg1D27iD+VMsq4WiRCWIAMFMB6JNQDryO8H70TREd87/Bd+DN6haU
+DrcOrxkaNJI1q/uqwkGEt2WtgS7Qo8zBlvc4RaD59+bh4u3oF15smJTlQFRSZSWeMA==
+		]]><![CDATA[
+		VT4Csi9hj7QMzzT/UAs9arWDsMO3aNJZ00ug7iiLsSj2OA9Rs+5+7g8dntcNx9UA1JsLmfVtuwQp
+CvfTF1ZaZQ6R5c+56+pLthEW1OUsKWyGrFUm8uoSdGarjFS67NjuIXsWuWFoWGR6T4AyDrJMg8mu
+mMxG844btspaAM/sY9Jhs/3cme7nidSPY/jYlqNGkaHlw3LMC57rHE/BBopLl0mdmmwsCs+mY6Eb
+wABfexh5uO7924lHp1PgHPqhOfUCK6hHMbHnjLDNlfTtiL9/G8EHEez9P/8J+8CKJQZNas/N+5Jc
+HtAJ7NPPb77/3I1mNTqkVyfeAaGw/eWBW2doyzV58gYeGnXf0NOrsPaO5UUyESjjn9dD9kSV7Prr
+T8MuAGbErp7Rw4IMBYh7JPjVnc5SN6MG5F1Vz57V+fnc/NMkmSl0sOzKK4K+JGeVWke2euiSnFTn
+lXY2+L2ZeA5nFfkV4BB9qc9JFYWqZTZZ5ady1des2wFJSqHFpb0KEYvwaaQ20Si7/frHqVtMHanw
+srJflj14qChxRSb//fvzAImfwirwGKEK7VrUdtUUFYst6plMWCKBYqzTKFWxyLQmDv0tJaoGDkQ7
+lX3WLK+3vdq7pminOCi6eR+AJinPSJm1ctMI+OUIHZoJSE2TIzZtGW4M9BoCXFEyfDNPDDpncpi6
+ZpkxipG7sCsWw9gUCkzCnzDRQE5Kvm8sLcudOUmW5U2fRW4yPM2yrPXUA39B4uPIDTNxLaoqHLjT
+DCgQcV4TLtzBucFFyUqD8HvYD/LnJtNM7e/3ny/9+cHaoQNP0fjzNVWTSGPGOsUnRNKNaBPAWzJh
+jvfERFGjjkbuoUeTFNxLxiTZsTPUs6V3NBXTxC+1KIRJRX98JBXOeuQi/v5IB1NclZpjiz0EcKRC
+X8NMnSpAbzvL2rZRUyK7Eiey3QNR6EsbNc9IarEi+Ah65YWiFnSYFUUGv1uUvCtXSV64BD1t1mJa
+v9XAiC5UOl+zgty+MIwnmBDILKpEjC5UoXzIzWXdggZZO6RxP2Ef242IXCBzMHoSTLgRw++opGtz
+DaZC36l8FSas8r428zyGH9Gfty5XYqlTO8wq7yuvtQNVJWiWRhfltGF6eJGtWTflXEi30X0QGl6Z
+DIOgiimca8VC8tpArjU/JX/7PvRvOCXNCdbCuVblknD5ivIVM2YP+beCpxpy1lwkwvzR8u1DjQ8J
+334xFq0yRdz+jQf9v2SZL99RLt85fLUptrrCtKmAxoWvj0UYFeEbfMtU2vtvfewZSWHzedlt9GIU
+9KIgD2Zf3vTHnzzTZr0mfuy5aLz+af9eUn3NWmAGCJMgIfTELDd/mR5WG7PBvdV2KE5s8mNBLHgA
+k/mjwbt7NL1bkPvnYws/k61Th38yI8mA48qNpmdcgbfJidvOEyZZpLKqLAJTvqzRJtfFvimSKiJr
+WEK3Vk77FDeLm9x5tr1PU3R9HtuqMxLKIms899P7/60d/UI6VE4xaUARn/NAlpbLHdrgU/IWYJUB
+W/DUzmkMOjsVwLj7rDVs0Irg5O2s8Xu15Pes4Afdn/Ol6RsqVPWUntO1fPn8c69aCQvDwyLRUA1j
+wv3gsT7M2TJ5iUNwbyd+oSqSvBg04y9YmogQCTNLqu3jppKEwtCfCZeMlZM7xGIYSRhVit5nuUe9
+VVQk3btw2rTyBCSE+WL4K66rnsKMkWlRGdW37ZpVblP2gbJv6RVKEb0xYZdtUZmMfu/Bx2mNp/DJ
+dvTXDI+qmlTdFGZk0FrO5CeAPXf68zAxKh0iOSoNzcCJguEVsuvPf+wFlflKfuC9oFEPWnam4f37
+0+bjX3hxXCmnXQwEKTPYRpxdtw0DlME8zyEfhGhJ4BkI+Vv7cRJLaOJ6RsWoqjuajnBLrVvo23ah
+fJQF7xsXumNp+7GK/B49h4+trM7Kx9bl23rrwulxhVpVd6lExo6/U2p4VMLVd8j7UjrsMpMlVlSq
+SgniKT8Nnww1E7rRL5kx9efXnz/1ax2IjVlIsvTTpCVcjC0SNv31DG9IU860DbliyO2chOwuyEIx
+82z97wt/LOemJ+5bDz72guoSvpQtmgeRRtgg4QCEJTFxsbEiwx2TizmKvomicz1aVtVpJU0tfm4l
+7ZO3Ppx6h1eFte1oh9E7e6fhJ/uMfcGo4kQuGH9v4iaY5wqse8Ond/UaTMN0buHtHEmVDbl+jAc6
+UtRdvustbs2c2p8NKQATudSnE5T4F555GQ3NWdXTfJx+4K0d/UI5wpSbCBPRxj2sACiGgIujJmJQ
++VQy0GRCpPUROeRDTgqUbHjDdBTbrx1sVEnz9x58bFtBj34r44xrc2N2W4Qgt75tAjmRS7zuLVE3
+0GA9/4PWxlFpqb90pzpt2b7EDcpmrA1+jGCzC/nkv/ftdNsRXoAJU6FuVbF5bMdBY+qhR80W3ElO
+ylEUYju9GWWoeMt0jCBriz+XejR77UL0LcnKskhjiv3keJrMHT+hBNjnScGrN/m1mc8bD10C8ecJ
+t/31v//uL3839ic/ABr/T2N7vILfF8uVdF6aQLnfotJQH3hCv38QbRY7gsH/h7+QKAjcSfvHLqLP
+f6xIRIZePP8SVvCrscnuINAQH2Q56kCAc2HPJAeid3kLf+vXSG9w/Xhl8M+fmp0wZXYXPv5HRnUb
+AJy+5lQ5NGXfDZLuP+cZNd9NNAnSLBcvUO94zk0ih0Mi9/Vp8BTG4EGwc/52imjTWwXDRRfxFHog
+wvj7lMT4H+bvm5l+XpbHNXxe7Lc5gz/fzKKpeX2fP05rFdu44QDVJbp7S+frQ+zvNX7bE3pd2Hub
+195L+DvmBQQ/54+XpTQuNQt+IOOvdapD9GGKEfw24Z9q+GFxnlbxuxV/3B6PG+l90jiv7WVHaV5v
+ExgTW0Gua5A6rytVvUe58kvcMdbPaGZ0ygE8RoYvX1cDnpipvs03hTHfXhx0/djY6p3Q9dSslRaB
+Ztj7MGK+D7it2eXgs72vT8gfFvNx2b/bI48b6nHr3aaZS9Hna3j/4XlquRLJeQxeYjO9p9hHz2Jy
++risY0SZbBEQ2sy5MADk/OdywUiLp+Gg75709pJtvvrT6Cn8rfmrIPU5fWzpzmBi8lYnSRLdK8we
+8LUJ+ZrqLajlBsOrHBdo3i9CnwM2cNsJe8Vv2+Z5g323Gx+37uMmf181Luw0M/l0jV4mMO6Eh9l+
+WpbvljAhUcOJqj0g9gt0peZWff2sJcCCGNjKQrJzj4+FQHJsglGd/8vgGoyyG/0yD4b/mpv11zFQ
+GJuAFFfnjw/HGGejoAzy4j8nD7v2wGqq0bB3t2jBPR6OgbXV/nAbPWy5x735uJFtrazF+1rl/TT6
+Zk4eJ+/7mbaQkjMwjwnSzU5qPhcm8tVZfnsWK9P+80ZOX/sUqB5Q+qCQcri+t9uYslCvBtN6/dQn
+qb21uWJQhhmydauXRl56aiUMOa/rmL5b56c98bx5nnbav//LfYE4kDAi71PxOGffTS/WzOi+siaX
+etzAC1vbs9vySRjTmw5n0j5/PMF3eW32eX4fl+JpzR6W1/IOtpWUnBWuDKTBxex4pvq78W81z1Z2
+vb8Ps9S98S4HKw3sDidSNNmoMlXdmbeFoT+vYsi8SuDa6K3HH0829duP7IfDQ4ceen4b5rZ9kyvg
+coAuPaalgw2wHOBTljnrdGkmbHW9jZ/CGP9warvzt032hreatR2bZG2U0358m5awax/n8D7ZTwvz
+blPfhv8VhlF3bjbzIFkMLizXjFGZH6elOK6NMhBtnH9cwpiV6sf9/G2VOQxvpS5VcuN5D1K8095n
+K2blYWafluC75Xpc28ddcJuzB5v6Nn8xr3k5d6T5gY8Si3qIk7Iy5rsN1O6XjoX7tnr0gJULQZxz
+mXAKf2u+XrZ7efu4IEh9bTbDQ8g+5LGvLa/uuPX5tkL7IXBfzqd1/26PPO2nx413m+UHk/o2s18y
+GaZ5TJ2/UBHvdzl4byAcblDVw5H2KOt+Y1jlz2TNqP9gdUOtTlQ0ofcgN62vpVugIT2NnsJYME88
+uH6cyfLqjZJV+ZDp5x0gbw3k4H+sR5CeevWWW7OnYV2EPgccwm0nnFb8tm0eN9h3u/Fx6z5u8tu6
+PVjVtykM8vf7dD8sy3dLaAbM9AaaMSaBydVeGvixlsE1jVZ9nl4ike74eJZVPfqf1zVEPl+sssR/
+q0xQm58GQGHsgTrTePvY4tTuITg3axlvrd+6kOT98852LfcBC86GVfDa/W4XPe245635tI/fTerb
+OGOhHiblcfoeJ/oAFe1LXF6XItiijbc0OeOnpyODhLrPmDsrODmOff1jp1hy7ix6EJrP339r9npc
+BylhXGe4H87fVpTTXRstMahrBwqSoq+9dUyqoXHxVfHNSj/uisf987TZTlb1bYjh7r1Px9O0fTfF
+A8SOL3kjNyfMMahzY36vXR2kiSphTDIvlPPHFRBQ12a/m+XHJXlau6d13sa1JZ027/ZMoMwM/3uj
+tyEhsgeFWa3C2/1RY6H6IuQVntXhRezen2rIm5XCl1qWsGN/jAMFFb/VwsTL5EB+AGQOSea98KfQ
+Y5fv1nUtOFyDYEIYVK1Sy9Z5VxbVknMP9qaQL9hTmehsiNq0px+OsT/08nk43w39cZ4eZ/Rt+qNr
+Lz0VL8AUy+LRUn+YTbGbm80DdvMxHXj6Yb7udvX9F2JOebMML/qQu8qykSZ4n7u4uJddkd1Psb0o
+MwfaAMriwtNzq7KgCv2kcrfqqaQnsScpQvhS6A1TlWc8OG7rGF17XPPb3rhPyvfTd5/m24Tdjer7
+0L8kf5inxxm9TX8M/Wiuuwy5MeXYEN1MSe99BqJYyKc/Jg0qMsNDZxUJloDqbaDY3IVH82t0dDC5
+cVqMvaBoKKS2fxlhqzXOy1rFhS2FB2Ptuke0nDsXsaZYrdvihvxhJzzumacN9mZU34f1JfnDHDxN
+1m1iPzQvzrDu9OORoOZTAy+viUuZnK5kRa0Q5qY5tJQvl41jL/BEYvnr9xIZ3/Bj0NqDyKwmJHEg
+t0KVWW4m02icloweWPVPGvToVbps7I46IPJIM41yA/uSn28eDRZ8BVSpC5E64kLDZMBByuGouO+D
+mJn7pnneXk978c2ivo/+K9blPlWPk/rNAlgEpg7IHZwZv8Yzan6yCj1idf7db3sTjv2sSSgHfMkt
+4SDpY7p1HBC0Y1qzI4t6X9eUf84Wi347Idv6smR+a9yGGW8lKy/1MQzDKA0vczMQuSx3YIKPoXUA
+qrsQCUTf7oHH7fKwrx734JtJ/T7Irz1Jt/n4Zuaep9ne3EtyemkdyUDnz084NqpnpWKpR9+jZNyk
+e3q6TsrLjh3YKqNwnivKM72ztqO5UFWeGEMNxvO/deS3uix2Svj0Bq069sDwJz0a4CjPR+HHpUGt
+Wb5Z+cOFftwVj/vnvtW2RX0b35cm6GEuHmftmxluSOXzb3NG9LdZOjfW8whztnUgFA==
+		]]><![CDATA[
+		4adSj7PQQczmPYuX4AAssgtfVvQfz/Hjgjyt3MMib4PagqbV74HXfvSXDuZoJbnI7XxMYNnZ90Z5
+Ifv8sKUNee79bLdDmMaiEKSK/oteLOpCR0D+rZ64rwkvZrtQIRzTT7wdlwKn4L3Pd4vaGGvcmrGT
+kyJXweDeTfG6PMOdb4RCeAM38Q++hO6NHBAqWPz425+SP3b0cUjP43+crG+m9W0N2Lfpa44HWdxP
+0/IOGx+4CpA7CVOHDOy0D1N2t6rff4GTaoxnrm79jIeRZtRHA46ATrA6F3rZl7cx8BA0wgY9wVeb
+Cu1P4jW7HInUL6GhY1S6HFqWLEM72iwdQwb1fRE/tQseVvx5a9ym5LvZ+2aaL/N1N6nvcxdz6lQL
+Lnc4VXbdgImw9mvnL7pcr/FJtFgXluQa0xqnF2IWJDP7qqSdSjCzZc9ztpUTY6wSvXBUaeDmmglG
+vk9LzUVq0dgXkqb7ZKzfl2eP5baUj2v+zf542krf7Lm3Sb67qe/T8qVOPszhN7P9tjQfmtjsCSoW
+ft4pMTa1a1LeCgwysXhASNf9JAcuhDPN3fBonjZmaF2pq4V2wFezdn+T3FF+NXd5z15PlIrJakB+
+NJlD1tGF47efCQ0FZNIhdpRw1N63wh7cfd887rCn7fhmFN+7/6VfeRjr46x8M4UWCOelXYFPZ0Lz
+f/qT2YH2SuO0rOKXs/myalu7hQSXfM+OnQBZgTfFUN8ObOKxlBPSnP1I75rhLliMf3X43odDI9E7
+dygDx/incTT6xvl0uaO2wztHp7DB/HNhKvhZvFWPHmFRUngw74v7qZ497ISHLfO4vd7M5fvwvzR/
+D3P1NKnfLYDl9/tZtCWkO2t0+Tx7AZoShDT/LcFHyCbeQh2uR+zXuN35fDOXPbOqjLgpcbOdgmU2
+q2VSFwx6+oe5RH0AhmC68FxzEzVxCpYhqPD3jVwWemyE3WdsGcP9C24kc1jfbYHH/fK0sZ424TaY
+72P8kvxpPt5n7bv5bSAw8y8nHVgDN6LLSoZpNOzl7YEzhx8M//Ow4jpcLAdrvjFrR2Ffp9dm/MEU
+P67H48o9LfO2l3dWt71RDL7vPQHc5Vn39T9e/tj4/8W8bfPZzsEzHih0Ll94adlxrEW+XOT0vWSe
+gwlZj+3kFYzbl2u8VbgveeGYL9fmzoUvq1YteNENNmQoj3uf//EDfAn/dbikr8O7Z3V/OwUVVc6Y
+grRd/1X700acq5ySafrD3nwJdckdurI7zfyxdXadOmihyydeeVaZxJNmVTJ0uZQwcCbgsD7U5euU
+7eDD0/Q+LsR3q/a0wo9b4W3SPu6u8tsEhi+xp4PRIC+aCd/r0dl70Hu6jLm1dgMMXAsGnzRht1nB
+1pD57IXT0EwLvhsIGxK12oILEkJmWlmUdNRwZt0mPOIHj6vztIzPS/64P77ZSW+z9uAvv81gzOya
+Utfn7hMGHWp8rZOL0RlEocrp7TdszsoRHHLsTyY4mj3Up0x780k3qW/QAbuweZpFR146Ra3Q+iyn
+SFJDKaV/m81h8in52/KE/HEtH1b9uy3yzX66b7zbFN9N+9usbJfqfQafpvq2LB9yL42RtC9Y/Q25
+AxtAvrZrJi1+XOQesmvp4JBqSdFygXaE4nAGOncYvlZhcXMXjt9gKcrCEpSdxFJJ6oP7lZveXPeu
+jiw87Uh63kA7PIXHQq8tXHD1ACWYy0Fz6UJ/RkPYhlrgG8ASQMVUCo9zci3VT8ROT7tsy+8b8mHj
+Pmzyuxf9bVbCO3ufwufJ/m5lnCKJz5WXepW/WukqwxD15O/MQzrK6b+ihdrR/xklOY10dz6oPpC7
+ap5g2IWWTVIiMf4lf+kbTmDiQTBn0vRXgGXiNTqeLVbg6t/5erKWxjxMxe8VpxfC86Al+So9qfO/
+sz0e99LTpnvaoHdX+ttAw1H7MCuP8/fdZA8zPdlCgZVpRnYZ3FSqKzBhh6vnQBQh3KyOKudyPSRa
+Ayad9xdQ5/BZp46xe6JxONPpKuglInKmDOADtCyKzmSwFrPQNvkRGka9lp2jhMw7Q+/rjSsIlNo/
+XO6HvfHNLrpvuZND/X2MXxI/zMfjzH03zcOVrTfgiX6QzYK3uTAAEVoYlQ+7atG232rAy6bxOmR4
+qxHrx4WLIehvp/lxTR5X72Gl9wthGei1guunh+4yhw5886wQp/AozOnPB1wiq0Rs1oh94hpeUdEQ
+uRyrOMyci0sOL+EqzKwZCNtCVLAcHv/Ee/Le1983u/v2E19yV9eqbPljpb4DASNNyjs9Ksbe3CXU
+G90ompeyBk4VXQuEzS5OC5vVCK5RPzY6HBu/GKOYjBKdPAL3+YtZeZzsx2W5z8sfTOLDZF/n7G51
+3+fvFKEoSgmoO/Ay4Z/CoIyLBsKGGKK9xgtdoFPVFR2xioivvFSkf9uQXgIhU4vNizSawhau/l2Y
+w8lwn+5PyR/X5mkRHxf8cXd8t4/eJu3Bo36bwPCoO7sUgsI1qinnS5OuSvlrxLGRCdaPhJgcYaGU
+3IAYnRiOLoSX3xwdKaxur1przLuoFWHGl7A2T5AbxbSIwgy0l0fCey4COqpjsiyeHHvhfYFC/LiY
+D8v+zRb5Zjs9bLzbJD941G8TGx4/h8J1edt1FZa5N1SqA7ozdw+/1G77KyPBiKpUuQwtvGy7IOJF
+uSr27kC/FBZGZRV6n8ZU5eO3gsSdpXhfh4gXPS7aw/J+sxUet83jBrtN2sfdHX4b/5dCGPe5eprU
++wp8yEf7empJFx5RBDGcrWahEc/T+gW/K4yKMbaX3PZNU9LXqmu3jHz20c9hDedIRUIAc2QscID0
+FdvyPVSEQcDi/jOXyJKn33G8PDrvpXFo1el6fW2DyxBRGASLrM67IfF9FqcncZnHATC7+XDlrSrx
+D83626YJPXHfYI878WnbvlnCt+F/RZjlNlVPc/rt/BvKbWxMGnt2+D1QYn7XRq+q4VQVbnWH7Qgf
+uXImKt6A6EFG0Ns+Xk1xjlknsxh8fXasKRUeLs8K5cdtcAmn3MCvnQ+Jyg442u5qyKggGdCw6Him
+TCWqf7ABHnbLN/vqtgdPPvLb+L4kf5iMx2n7bo67dpgTe8caWYmhd/AYLJvo4GPDVJqX6ncEMtJk
+DgtTbJxEMnHYY5T8RzP8sBbfrdptif/9X/7n//aXv8t//fu//N21/qdHKpwRRe/KwQPQoFv+y/33
+noPvIwiX/BZahkwohZO8eE3apdUm2ohzFyREAxamGC1fP26HbLzd6kl26cFJvru7Wz0N7D4LfDT8
+vSbpQEWplS7vitoCUmBmBGF7mg8O/grnWiN4RYrXnJFD7f4x1dtiY3xC2bAQLzRCKJoJ/uSf9L68
+1jbqKxbzwu1lx7xwy2w7cJJe/Vt459tOwN+bEyUcqq7/OlPflLLnlNyVw9LT8DYF2FP/51/+7rSv
+rrVHj1P21PZjL77v8X10T9Pw7ZQ9ze/zSjwu2vP6Pu6ExymLPXVYvtjiAI9ILbGtWtDvtZdkRiao
+WeNRfr0Y4jOivhGVxVWdMbl2UJHW7AssLb+8OIaxadX/sgUbRKVPI6bDEmcmZ/5ULuqECvAWro3A
+Yhm2jR8X7aFDyQRdQIBP8/C0s67FUm8/GXgsD/17HMl3w36co8fZ/G7qH9fpcUWfhv3tHD3O5tPU
+X3QW642coy9HTdmItho0IX5AWRlWKV1UU4q8HifyHsceI6FGvKR/Cv9FEzIjxG2zhAeSlTCmc1WY
+pnSBMeAX6yQdTsesheNQ6TMNAFspMyFii6+a6UqLZW0xIS/bPS+t1Ns0xPaKDfU+zq//v4zzn7zc
+b8hv/y+x3G5Qbv/tL/9DcG6vrhaReTuwbhL0XnLg5XySf17lBoPsJtDntZ3v5Od2DOxtqyCgvvl/
+XtYZ6CuSF1gSxtI5uQi6t4KK5ADk8S/HEF8gD0wbJrDOIHg0rtBNNXSWByboDATThZwNCAd5Jy3J
+dVOFiAHPuT3J0FXX3yQqg4jUBpJxkCzUU/r491ZROtgDJwb65SSDL5NuQhiUfRlPzQbS83aisFmT
+6JwoW37J+gl8slVRDgtKfJ6pwy2jbwhr06GiTdjIHwcq9EECmxzgm8emebAARRO1aCpTBIMOKIyZ
+7SIorCSVXkD9/60GPCrvc9OyaG4moUuP4ID0LO5F9vhZu4DFLQbSi0hbyWjgtOIHPx4ZOMZuuSbi
+eDqwBcbwekwI93PBS/HLkHst0O3b1WwYwKcarZwj/MceRgvGmOfYmUHYC7o8StoAycEyxniHKzfo
+ytdze//5qE00wg2MDvbx4UPI9fXYqRI2sMkaZHEegqedndSjvsd5GsZex4astl8grk2A3m2gG8U0
+ekrZCNxaUnZbquBgC6WDyc+xhbDpmqNOfaiBSYbyaokDIFy1CxTbpiK134SmGgkxP1pMYrc9ehBi
+/mgk81x4cxF3vGYK3b0NSOET56vRzh6CH+7BnBzA5ZBkkFOjoz0I7EwOOtNUg4zdhNy2Fd2TMHFU
+B3NJKSZ0cCXg7mB6tQv99jChVVyXJWGJBpool5xhxCQDq+wiTx01oWheXbiRdi2RsAuP+EiYQH++
+DvZqkQrRhEObYAke6bW9HK57QdmS3smZhYCWu+ibbsk6WESf7OGqD1fy3pzYloHx8BI6egJ5mR0U
+0GVlSB24WmcDXeTZycHsCj8GAZ7vbtuzbCGUp++RaAHsT9BINT4enYry9RaZ0UIm+K5D1v1GC5ZH
+NMhpcVRQ+BiG6+CMOV6ayTL5YB0z+2DuxkuetBGMogw8cYZqnxr3DCpmnIyQ6L+sYOEyLBg1Lu8Z
+jL/OVDLFCsDtZVQZB4CwE7gU0MLRxbaQ4QbxUYF70skWTFthvWoRd5cLYx2F/J1xCX1KzuOc+QrE
+mse3KXPJWtzECblY0fABK8D6Y/4ACEdg9npyAYReLQVhDlV7iHewB5v9JLA4OKsq5st8l6ORCXbo
+BeLqC+DVTia4Jq9Mtx3BUnfgurCyxrT5lYL+x279GQxP224gaHDf17655Mhi+vpJkc9Ux5EhPZlX
+IUN41Ca+swEyXevBmEXCFdRs7cSWLqrNnpEx3JzHVLp6BiP0QqXkb2nKI1XKxRtfRDK1sZAtoXVy
+YZyLlprGIsxDEMlNavVlAhGNWZrOMBAP8qiciKPNFyvg5kUDwZBdQLZwePUYTBFCsGAT2FxzBgye
+IpFbpYtI0Xg2RGji3mIzCUdQhCTkRfyW/UhCXZYqmKwEU3ENbeuEO4O8BZu4NgWNlNEZgJo0McGL
+n8KQ2Hay4W2XIspFA6IvIuv2Klt+PJrowhfMBlf9gxRpIwdla84nAmYoNdAgZU2jc1LYJHjZqM6+
+GYfcipU8SKbVgmQwGywONZV70LEQdUojHS3W4SAvMdhexBSPg+cybc3UebOfjE+jThLc/wSnkSWv
+jLWul7AlUjglsqP3K7fFz4f0r5EmB3K+cOjtnTc5/noQYT8pq/olTgjnUdH3K1+G/w==
+		]]><![CDATA[
+		WMWFaVZkAR57Q/Y0F9FL2TiBmWRidkmVyo+9aArCfCxSKpUR2sAuqVm7+sCfW1KzTp+52IW3h5DH
+xf6nf/Mv/uV//Ye//4+//+E//pf//G//6//91//19Vr8N//slzF1vF65+Z//9V/8H//wX//jf/4P
+f/1n/+pf/cvfv//b1//+X/7h39rH//yv/4t9+r/Zf9m76+9hSTpnChW0u13w3ppG0IU+WZYUnhWz
+B4GPxWfwgJkN7zGc7m2eTPPlSRe4pxgGdQ7W8QNXrbFnTTIyzXki6y6rkBeokSs7i5k+ZYZrn0bw
+oxNlbo1foKNuS1y/NZDql+V9VRLYNhphVjPZghaXFA/Tiq0LFUCRCeTylKaA+DuoH6ZvDuLwF4x+
+bsrUDACs39FAFw4/OdTtx44ifrWEJ4ZFdane8wbf8u6GEjomFyUb74X4gtMQqbdT9UBd1Xxi9T5K
+4uQgaQhrzUkwPRtPotQ7hR5ijSeRKNPNB00W9IoKfvQhJwnfFuL3Ty43NnQl43SGpYmlHkNUemsG
+aZe9YhYI4ybA6ajpQCFv1EN2scTjl4xEgkmrRoTbWxPbDm+mskST7qSFSUtdDIhzkNDGNaMJK/eK
+cXpX6NVi8bSDdIw5xdPzJR+49dfychTIQLUFgitcg/ZhIUeWr9Nv/f3r7E16exrMqeI01ZBRoxUn
++Dp7hajCE9BJL6M1tIAKZqdJfEnMYcx2L1V3mD8bC3vrZhaWhpPoLOpdimkkUu1M2/e/tbzTnwEu
+n+DVMCEZDVO8nU2oM+QW0ocaGCOJr2gcasA51UBOVNCt+076UdXE3TM4RkdwJptwMpc35Z13aiuD
+A/RKfF7dznsHysp+cg685p5y2sxmxIGT1jYvPT8ECcDfm0rjw7aIb+zYJHvmdiGveoZ1+8tfpq1r
+jgU14+I+N4vIHPzW7XowCaaup63HvKDTwjvh4i4rTI/zVwMNlnjh//eNRS0749cti1J6p9PP53Dg
+mb+OTGq4NroYK9184QQmEY0shUn99IsuPqNM+/34D9tMH1rYuoLecgQVNymIEzPEIFtV+mP7qPxb
+EU3V+BYMiuAixVVx20I/rU89/cStzpzgdPqKXdIanXZ9wuwZC4nadPvhWTOdocHdYOXMeT2DezuX
+4NOdQLNxl1niJBn0Np74mYCCv9VA6+4SyBW02hAWfSsVNQnnhg9L6AJL0oBDNSc4WjEwEJqZUIa6
+JdxkdwJlezntszZkq5v8CNclTqu1QNLVl6yCacoYZUa8TEy+9G2lx8dgZGFX25xPOtduC/HTS716
+8PZ0MHl8yRZcfKV0Zt64dny1zkc0iXWH+3RJfexJSx+6e1ciMX2SPmhBNdSBBotjapwW+HuWf0Hc
+pvjq9d4eGWCOLuwTU38RlhJP0LH9CPXcApnr6llRLJHdR+qFv6HTmkVyXDsODNPDUJzUk311WZT7
+9WNy0vZWOHkgq9CpFXm3+rCxUY9wxRyIc7fEW8uDWeLj5hvavOmThqq7TrnRnCRgSM5rwXxinUJU
+zVBIQ9UrecMVc5Dk3Qx5uBys1VarboCsDqxOpf46uGOflaNNfcsHt63BIauYEQXLwaWDpwSFIeSZ
+V0hh/bwL6yF1X2qTsJOyqkAzUOUkj1rAfl1d17yYmyuSh375A0rWevVnzW+Zyj1xf4elvP72siZJ
+RV7pdPbdh4k1Z2NXA4fVA8Se4z18WEQrcXsXx051D+AAcalxg9vTg/5Ouhogt3cEPYOjyCXmPsiX
+0J7Pky2E4/olX3B4+mn2SWjJlA+IPo8Jy9JjgBX2wbFQtfY7YoPYyQveBcj4oSv4S2TRfDbtkMfX
+WgXh50vuOSYQkit+IV4Fmbtu0YBept7VROuCtTM2psmQ2/AZXnIZLx7wvlPrXvIsq/9oBL+px0Hn
+I3JwfAVznjzIjlJEZ63p/yCHT9oChWfWdCFDQjdt+qP6+s9nIKv3qPX/GAVZ9cvwxAwWEjuD9nZm
+LXYDvfX38uDXOrd5pSOz/2QPS7/+0PMRSGrkLucvyS3jkHLCvJqweZKCCQ9WgncEBFyYi1IgvWFJ
+B7KVTTYyOZw83/OxBx8slT8NKsFB/aXBTqDTrETCZ2+GvCUurMcf943FxfaTGTAGxbxk3qo5eDLS
+K+9diM515WYYB9Fcp4kjSqfn9gfgt7kul3fFsKQOEMmYsFaSJsFF+dTy6TdnAnPNpRjS5BW74tgE
+4i4/UCZj31uRS8jf2glWOct/85K8VXFlBG0SMZGMVGxnKpZDH3tpIL/MgzxlK8r37g3HT2bV8ixL
+Qe2R/pfhMnS5kONewkHGs3xO3JoFbF1EW/9QC6NXthC5ftbs0MfkSbr3QVNu/uIu2rVkacUslGMV
+q8tz0Tlsh3Bs/PPZmDHIag4TNuWmvrWrXzRsye5FOCuDlDRKzef0eublPhABUXakSFvtEkGWrPwW
+zEpW5TTXCed0cRGLsFhM1vljUM9PPVDfzKYHVN3sqKyLRDGRCXXA8wT1B7r8Ei8W6ZoMSPHWBmuq
+7w1/7O0hFi6AOsbuUCsDJNgUDl8Uq/9oQwjg1GSTzpTYHe7ehTyvYHYqXUJJAApqbZrN97E7cO6X
+9nNbePP5LDsaFHeMFb4ekicWJ3s17CEhK0JNmCFzGPIPNUACG1++KIZrS9W+q4AemW00rwv2j5n8
+fOtazLJ59aeItwwANkg2yvC0aCt8qVOw8AD2Mg957kKar8BwMYeRPWQ+ooEG/qEW9cnALWULQhW4
+d+GyBVLX+Y46zA6vMMUkt7h8mwMEfn+44bxM3JqUiQZiucb53ug3CoZoZK5LQkXpkszkjn4awsfW
+uNmrf217zahB6ImQPyZmtaqrVsqQl+Gy17Y5Tucg9C11s0PkdeWbE9bNPeZLYPjXDvx3FdGEHQ1l
+KUwIo/LVtB1NwBY5S/8KL53fNs36kBo6Di1Fy9gm3+uhsltOMKt5Ec6/FZonjv0AESsp1kbWLRPP
+UxcGlzz+nsuUUKbHH5tesmMtAMDi3gF1za7CCv7YAsKPMOgIwW7yja5j8pl4eoVAasIeQhRk3RvW
+Txo2IbKZX//m2HaSyYtIRxMpryYKRuzWYqGQ1QrOpau5BYD05c+1W/y3lu49VpHcO/ChKpJfXpqV
+etbBnruMswg9wlH9lkDkFpkyX1ZewPFlXFImU/Te5cRxnsTQijrQBuxUD+GNcZIDuGN2lNGHnNBx
+1k6aqukjKozdSETNsPYW+AmtdwElanpw6Uo7dh1kVxmf6blTZbVhpXR2xA2nkINZszNU5LWJ7r+G
+Ap5LpacH2+3+5GI3hjKDvUI2gMztc+CR+s8R0dRKQEdMRtbqSjF3UHvHVoiJ8xs2ylTTcfB28Psb
+wiCGFK3jtCzWUqSNNgbrISQ4U0hENrPSYIAqeRVn3vXCnXrOa7KiBX8BrA4oT8Gqes4W+mB5dRQC
+McQV3eqnPhyYNaMzZ1XsIa5XL5od6oPhDUE4NsaxPSJg2Zv6yRoxi55tPpibbx8OPgFcJ8ffE+rd
+GihF+1hPDpdXVoq4wkITerlYOfdiXzcVseXAQa9P0ADjywzMW1+cIeHrycAVO2Fsm9HMe37QG+JC
+poMb+i2r2MxO6XzybBgG0wXcdgtlORASjWVulsdVEMpwoWqQ2W6oaZ+AXf4/9ThVgZ4bS4uXdGZl
+7ks4ge+8EnLwo2XAIJlKB2az6TMQ3qK6PVPoiW98nOa6/57wfab/+bRYvNREE2rqtE+aWydOpLsm
+31cBhQsYRk7rnPmlW/L8LMmQfL1V+m52zSnjrp0uGEKvnMxDGyyQfmyGiEJug+Xz3Mpa9zJU0eVY
+W1YZGS3TrGpRaWJeB+BsW4ovS2C2K6JFBhyhGY7toeDCom5y9ShxXAVF/i5srFm2BQAsqTmT0rnR
+XBt/39PeICxgclg96iHtFQWlbRkZ+9qzhxBO3TIdH1hvJh++SW0UA1hvJkx4avVAHfUWsGr9b7sm
+269yP6dra1xfbMpSLcKcIBfT8vzZ+HMCsa62N0hWPbelWfOKN2upLs13YNgZvzXvc7vGcA2sqKVd
+ys52YS3aCJ7BuVvoalh17g4agfkyFOAh0Ijchzpr92ioOlfzcBmMfMIaYTGUnUzLV6cOLdx2rUzB
+aFdoa9uLbZy0uB5B9cyg56pnUl7YO/PMAHTOpypLWEALLHPnQy1UgAy5cROEJgbHkHheF82DKWZh
+28j2hvvOOJK88LxO0lWZMHe+/VD4AQOt6D3fNtSO3QqpT415qQ8OAYTjTuCHAbtioQw2rAUi9ttB
+zLR6DLZUfhA+O8woKLTCndAl/n4UeeFEt2VCVMzamaOvw+58vAHXBU3UfAW4kdcu8NQr24VjHRLK
+FCVQT7RAlZeBEQoZTpT5tszahIH22oP8+7Sh98184tpk6MZAApjH4tykilegWYRdChbZuRAuOWVG
+PlmE21lzaCIbShYwXtBbmKwm9qCv09+nJm/m4KMDUWFupFTDXsY1bxsmZjaut4K6AsiOcBMkeutm
+CVVl7pB4ohn3c/jDaFRtNVw3qn0RUbCdgn0Xzaictj23uWCnKVFdicgmQek+aHLsJByCK1+8HAoy
+az7UwKp6PM4lSOg9LysLOyADwMwu/mPTWx9iEV45gKQMRWPx91E8BOhoLgwz1djAOu1PIYg4fIHe
+tDLLrNU8zi7waEFeA9OSRQAMMN29u9AchkMwdMJmOjdAomfbM41U7wt/x+u/BrAEPeXlTNVr+EaH
+rn9PFPiMloFV7+oHLDrWCEMBF2wIN83xpaGnRMujqmXFDTyZQAZPosPeAZUy58zfOGxhxhVhxyyI
+3gwE+Rh0f4kmQ/zO2DqlCy55RQsnaDLDilpNHwu9eBAF22/CJfhj4idYF1r8fYdFgR7bsfqUnLXA
+bpjiZBhqBwCO1uZmG0E4bCunZpuoo0zBblBlEk6400FI4HKtW2ry5thssWq7TN3obmh8puDANiFe
+MLbNSsDKjcC/tC40mCGGtAyeK3+3FIFZy14giWK0wFvOrnJbHc5NEbaMjeOAPWbYO13bzCvsfrGy
+n1PjIFJsOIffJAOxFMJj1DC3iZhiHvDF6fHXaLRQuUdowpnQMDAUGZoHVJxV6cMjYcuTtq/3ON1q
+mXg8Bk8QZ0iw3la5NQbNk7Yve2thyXVbiURwiOLFru8RVLhZYQW/muLv6e5eSglxjyk5bXyb4lj1
+dbLdHC9kO2JzYcDBbf9Ni4w3vBlIJYthddG4qWGbeMGy7MeUN8XtFCeSP2x6kBpvv5Kl39LRv9xh
+gQv3aGrYL2oaKGFhbPpRP2/q2VF1r548x63fLndDlzl0X6N8CSNLS7FD3mLGnUoDJQFNOFposjoE
+zuyhDrUqd0Efca4tyze0oZNey/br9E5Y2bbmNm1ckwM0oLZvWomwmeGwTV26TWSbfK+7Pg5+bqkb
+2zgBl/6S6y1QkMnIFgC86ecPNlK/WCL72WAtTMXhDt6OVk0OQoHzOjTgivJUxrPBEA==
+		]]><![CDATA[
+		ZvFI8ef90ChI0uJmsXA46lCAyjVONKDQSd6F6R0Pb+gyPgsNfaPoWDuSayyE3j47HG0LkeGGM53V
+FYlKVcKzQ73LhWUqMs8or5/wfBwA7PzlhfiyqRIKL9hCjU2SwvVhH2cFdaTJLE0VURfbucc4tUCS
+aT9RS0rWvs+6jP06h5AozX4sD/2cfNn1b+ee1SmvsMWjo9nE4FTFgTdhQa0KPqY+NkwT2td0Z0fD
+KaJQI/cT3/maNZ4kQ430eI/MYK4HN6bf+Ud0uJyeSdIMhRhYdtRK7u8yNyriz0kt42bOFJG7/EcF
+bjAICSHmB3ieuIYVVSjQctGC4qs1WrBEcp61jcRtwekmlSG0MUPnyHqnFJIzfh+9YqjS1N6GK3Ff
+NTXZUkjrpegUrNgvuJ5PuqGI8zmFxinhfb1H709R/Umt49dLhMEV7vLy7lN4fMX3cqrbxwyYkeDs
+10N8/UMNEAXYt2qQMFg4PRZPoDrOyd70ijnE9F6AtaaAdwRXSTDlu0/uAxPHThGOon8rO1IvKeOY
+WFqOqGB9COZGw54eAGVArdocn0Gjm7Az2hS0kG+UjVn+urSA4mH7lVELlZ1hCxIGa0aqAc2E3UCT
+XbTACdOmUNzd+Cbh/Yh3egFfWTSQ8op52IvRBRfueuPoJ/khg6CL+JM+Z56kJsDg2gpvfnfl8xdf
+GnuuUMK4zUCKIpugcSrNf6jbzJXth/ow1GW55Q1xeHtiWoAeOz/JentEOJuA/Cso3HUhmfnk1ISQ
+bL9+m8UDx4p0dyIAtZcBL+d9TxNqqsVwK9wxbKFFC4zYQUhEd7crhGT9emPLKtgkvYa8zRf3xVtm
+vehh0wpl22C6Jzda3gjXSTeRO7OjYUIye/SAa9EEXOp+cMI/V+VqyOG6u3bQmMtpaw5LDW5MWYqD
+uL2vGbr1l4Ofr852y47ROb0k21Uww6pvi56ghSDAVja6ZF55VgAbSPFsLwRqwY+BfWKVjTuXxMju
+1mCkCxj/YtEzwvnSgixihfIqdKsaXHvR2gfX7+F1VrRoW7CTWDKRXtKtiXw3NvpiaoLJjhrW95lR
+VtdxBlBadIzhIlsMUkTdG8HQ9ATOuPr2kMHPZx8rP8l0e51qYTcbmyQKq4BlX8IskGY3j0+iFncE
+TwiPHRVK4YsyxkCQGXm2/qEO8/qdx3k1YS6YnXrE888GR9MvbXoJw6OQWfwyRjCynXVjWj2y317y
+XOiMsn/g9M7XasmApT/P6ueTbIhWgyGkaOeV1k4MzwS8tlkwYJ9oV9qIexnCLINdeGV/kKDReK5e
++5tZdtbbkjgLlaaFkxlXeltP451KS7OK0VLEoK5dZpW3WYkfOz1jnsY2TqG/zri3ZbuBpvqUy+Ep
+cPKUuAXNFsKJY12bwU2z74qYXmMGVvKJF3GwBav+1G0jeoHatGjbWWOEKJEN0pQQjYaVjkLAXmOG
+X/kt/lmr6Nnsy1WC2rzysWuRkI53Uy1xidIpiA9HvLBOURGjjM/M/3SXocksiJPrab5ewnKEwzuB
+DIMJMUfMVwqu84uQl4TJsI4eZw8ff408pgNYD5CtyFbldVAzCEeQHrv2VkxMI7YwDONCTrCU+EQb
+fMwZFRPQUf2CiCdITUrtNFrWpg7MWZtkxwrhwXD1KfppDWAOievDUcH2msuL8zADzFayEWxXeLVU
+6cHenqK9xVJyD74dD17Y5Yh4nl1/SIgoa6dSn9SS1dKCKGGRu1Hfch1R8kGZfinqXlxO08v0HcHh
+ypQWtaEdynaanEFX/fHnZWl3OXYOBxZsPOY3VHr29Dg7ZZmi75Kw6s4SJ+qqCVfRbFk0DMLGKT/g
+0fitFnbGVi5wkJcRJktCGBPCES72EXZmMbKR0jUz8a4pQ0+xFPeh54yFa4H5rNbdpkUf2xViHx9K
+C1lUzdYq9LWtzzzUXT593Q8x2m6BqWFOM9z0c3g6W2JKT1r1nYhedtaULVvXPveHctC87V6UpD1N
+Z6Klm8ymPboPSk7hpfG9m5lIc8BbYLLCjsn/ZbKlfJm2n2BGhcYE0IWDAr1Aa8OGloIH7LWLqRU8
+KzUUdgavlMUsTZEHgRyf1XaGS4QUXO9mZtrTsjWKMDjSLBY6giKMdQQWNa35dEMwfdfkDFGb8Egc
+dAoNj1egZfjkdKLjUsdGRB/82tFqrtaCP435nPPs3K6sxYGCZAZVrTxs1gAfOTaEJv263etO8KVd
+ovypuvPWVjzUrJwWPpfpF/m+qJnibfy5VfRUpSo5W8StZrvujO3Rz/RUB/NPRdZihidTmkZkL1sD
+sH6dzDnS3qqnCTBvbo1DNnjHQ9Y2GY0NE/JYjw3mBNN+ahkcs/MX3xFKAQOkB2xMuAks1m9Lt18X
+U3tf6ej2vFhcdOlnA0BUDq/fh/H39HB6Clh49lpUK1i7LVxz9vKp/NzjjVuMSgOP7kcGYCvKdLZU
+AGp6Y8RZmnkRnbcGpHwXesu/48mZYkkJr27PRZi71g1mh7fwRFuXLc0lHnYz9rpSZew1jSQCBwFp
+8jfUPrj6TrYer//YVcoRbvaPiZmFo8WDntUqvp6x1Zw1MHHEvkqfkkvJWCNHPDonsjjQznEoO5/h
+UEucPKbS7ec6NG11/+IiMvUkOaFkUaVA36EJEQDwxThOSf8q4dmMsuYFQ2DEhDsT/JbHTXFWiqWI
+1wyueqlfo4eTbwudoT5a2AfXg3kQ7qkJX2eS/8rmd55y0ffF4J6WT8mPmAgloRkT06Ht4/2B8Lsa
+jjgGJfyts6hiwc2wX2e3t63Dpgkxxzev6RGmijmnk2bsaIG6K2NnnCPp1gLNzh4PCnPqJy3mUulS
+RZTCvyzbK2CRG+Dcu/raPvIWM9yR0hPypRTOTjNGydEqW+skg3Ghvzd2ECOpD56UDaHXyqxz+nMn
+VAR6W86xnNG6GhiKfvFybPCU4TtP5HRh31lHPRiqZ9vdNwcjG1DmpoXOmpKWT64rk6/EjztNEovk
+rN0FhdkS2JxsWOX094rvWDi/KKjXkNs3O9xZ/CXEcif54m89sEO99DHdgraTtuxaFRUNkHTBCzmC
+AszCkEgfmz1oPHYo1n6NaX+PtTKQF7zRxZEEIfdCJxKwy8gv5zw354ArHpwGNRjVpRbq5u1kCQwR
+H1pRQdWxt+Nz5qv5BMEcNZBzmoINpJq/PNpNOjtfzMi5G+m0TyMdJitPYoJxGjKGc00Zp80SneNa
+6MhZiXQET2vnBE2lI9SDR7ss3NOjKqhtKe/7cTKKIrr2g/RDurCqVoBGqiUu1MJKhmbpzw8tYG4G
+gyovEZMafyGrgzvKMmnD1LC0jCm5PFejKl1q7jxU/zJx5U83sWWB0DPS4s4cTYFIv9aiD9K7Dchf
+kQmTeDQsaiwuFEVTdzGA4S7GZTl3ku0YABvhjgpGUccxmNxpbsttAvsj7iDR5hziDjYYFOY/zBRJ
++u1cPTcTn27e48jqNTIhpKKY7tm5zca2VFW6MViWMzNz79tmtWJMDlqmRqLrLGD3WW+F2iZHiNtn
+dCq1jmTatisZv72XzXzsYj13fmGmLStgF+tx6Jbm3E/nVNurA8WXKoQqc6damzDKMM8mwPct74oa
+ZdNZ96SuupI+3jr8AR6ev5enjtk89oawqFhUvNZtgY/IaK+mjvWcc5ovNkJDaUZWRB1KCTIDYa2T
+d5E+MJnVbAGuVxOqwPbWt48Lc8JSAYvcgbEUA4afedRzGOJ9nbIIToGXezsqJ7VUp0iSdcftlzTc
+/oWx68lMznhaRkgp5G8pU1t+bT9+ORIszEhMh5bFYcZ7WMvBNrXrcY0bgLKqq2uWcmJH4lEcCEff
+GqVP796D0B5p6B1X6AM11TFkC/KJY8l9S+8hD0dFAzmrcEke8uGcwboHRp7fdgGnUEmjppFSVEe6
+WFa0Es6dUKxwdF6pBiGDGK4b6ylXDAw1bg8WNcBQvT+ea7Q6Vz9NZDTQY3oUorRf45BHpEwcYaSN
+S8rP4RjRPpWTF+J3l/p1Dj52ye6IV4ebPlGyKx+P1VUdkYVmgYqsIz33E+HWzgmpQNej4RMGFYfT
+82T6Ll5qourBhJJVdy0dSg/I4W86ZfqYPI/QJIxIH6d3sZIILcEg5RjNtlHPxbszGtiKJLJ/boPQ
+BBqqEs3UCWzKL1kPTHj1Zrj1i4ofHM+hSphqxGDWOlkwdcq5U6y4Y5tG3OkLhyrkOkMTkG/7ewQt
+zBHZ4TC07slLtWQd3YaiQVpiQejsI8VFZu9xxL1tZdpUooA7xBcANNpmiw7QDmKkUs7w3oqaoTZO
+USm99hqfnhTuoN+I0sS1kRxGRG92+d19FOfxsTh74an7Jb+C7OljJ5BMMUu6z7lLyEC9VzNEFnpj
+ofMkwjo/PeSaUgKU82U0zv3ZrTBFBm6TKfr0KdwI/7GdEXLtVszP29g+z3e6tbW03X2mYugjihXz
+yyzerhbGwP0kcG0cTJy9HFSbbSMKzLMv4A9aluKbsU+dbOMIP1xTosxbny93vfnL6MyZuH++JF9V
+npdZyyllQW6PsamwDcRP7mVAvz61/KEWWuws53SIllf4SCKNqu4qUDmCHxvG1pzhFpowxePoMdvT
+mrEM9HCRyYM494GaogF2TRn78K3l+E1L+ZBD1B8bMYEs/p9z50I1ZXrNFbEWE/KB+jp/vcZ2biJq
+8z0hwu/tqg3P4K0L6lyN8jqFRWiERkqeh0W6XiQ1K5VtOl1FBN9v7ejGMgf6UoTSL+4vmb/yPh94
+k35KTrQkj6+FxXZv53LyLLuiDmU25ECsqcEW5mHXLKc8UwO9gA7xwhq5dx5K3VbzoTC3DZml3Z63
+IQ0s/0Qkn0ziAe8GqtJl5S+ukdJnDYzIXvmuC3rXHzuH4FCSplcHTvWL6fner50WEEyjHgip+ph5
+jKbMssYgbbjOYU9roOjwRXRlRYJkilxzywaJQNCxzuk2rel6c+LgX8ikCLuF2XieNnJoj812Sifp
+WaE6VQNUMhtwFnaqzXUzxCCY6GXh1BbzuGO0dOnWCOp51DQKqH0powGBgJyXUhhXj104adUWhZsJ
+cc4vyRnVseiw8uyakppS2KCtic1MQdmdilZjhFXfMjTtYVlaZi2ungMepmhA5sIRXhn7tYiSHjvN
+7rsusFjexsCccWtWVWECpbpPQujM0GwOMROz02U4emV8OSXwHUkNuZEUqZc7pm74GlscSUyJZMKe
+w6f0oamsuPd+XF7wr3Z6JEilfOrlyNHLvtMMe5QMWzyt5S2/NrPFSvZyKzuupDKU73V6Yz+1cnqx
+m8tfC/iyg4PCr0bhWg7MiF6MN0zZiKyw9eTzSHsd65xVvpS70cqhrHSGpL0YIBLFnRcKwpFOWeXK
+DtiZavZzVZlbZ2barhacJHn3YWgnutseQucBwpCVVW550pnHcoy1G+glknPSdlAUZT86xgPrNare
+up76QIf1bYIvW6XPE6KCe8+DQlEVToDT2D7xGeINenVv5rLK5hosVB6vl7x+ZOyarQ==
+		]]><![CDATA[
+		HEa9QWonlfAy+2IcO4k07fRWA9ZukbKXs6pHlT6W/qYKt/ffv8yB8cVnoVJ4aJmIODVqi9LZ+zkj
+T8G6SNXufsWD+3yVqXJiQt9Yx1MYx+Zs1M8tfrjnjy/Ge7cumtpeb6VznG4oB8wQa8aZF/gZn7M1
+gmN9ftPM58Yx8qQN5D6axzx+INIfBfc4z8VdDmEIYYvydVP+H/r7t3YvBpOqBXHy+yFPjnUvyu6d
+XCBgWTagxrzAtby1o4E5mJQqPD2gHb+goi1irVCYBRWmiKLfFWxgjBOaQt5V5kRl9PtY2YzyEDh0
+jXbQrGHMuJ7heSiCHLJEtkBHYNqjl4AOdrVFOATJfpRuqJ7VdKkofws2p4Y65xkBCNFPrxce0dsi
+NIg0s1rw/FBMe2RO2MwgouOAVIFzQ0Qdz+EufzyHuhkzYYe5YD327gygi+sq6pJ2lRgKoAuNzJ0X
+yjijSWcW3ynVkwdvxRgSHrEfaqBUwZGdgxYrDm8mMwaEMRAvN3jqWTTcouyfoTR7rkzdMyrsMtNX
+Z9jzF+LvdYYNcpGYSQtBJp90V00cwlTtyBl1aSnorCx7diEgPyfz+c0cJj5s2aSj6EOUpes1MtcJ
+DsFTHTmIqGo/hWgIqEy9ErgegTTlhkDTPBwqQGxQ8d9PjVAiMqwDCmuhZlXtuk94oq02j9PaqGY0
+ebCVszVUiq0k1Ke13drad9KUibEVDt2vfhgyt/VoSoFUmbf9dIm07ojeu1G5InW3n7BxctElTdfT
+ClgpT4qGHnrr1fVWTDrg/q6deh9PFXR4FnQSvIOqwlOEYWeS5WGKsUWlnEGbTz1sPJocMb6XSafk
+5kosuxTwPxtHeOaAuUh4u7FlO356OihqYS00oVnJt3Qf3HscSeoVBeA7oqeWlC3alxBbX/0jCkkP
+lBtr/ezHz1EQwdQ6D9mpFiHq+95//t1kY0Hr1Y1p8iJ/obtOIVzqSVJp5YSBAuHG0ugzUF8PZ2Cl
+jLdr2tkoUyX8Ns+1rt2AfJ5H7DGr+67K+FaBijWbtVIeYNhdSIFnVtu49sH9FL38dwbxWt2h2YmK
+ckXTV9Sk3efxsgcs2I5bz/71vkYGQJzgCLPLIVAnKhAi/JpY4Ze/NRMBvfW3odDBKWLikB0KQhxh
+/xIYxx3dOYxaIcrNHUw1cQ5v/cpCHlnE61tAKeIvAXXML6tQeQ5+wgZa/D3Lwye9Jb+IvaK0e78+
+9t8zH852dwtEFQIcbmztP+jBOARhJ1yasYR4M2fknF+EQfiKnysCIjQXZCCqaB48g31t+XUtwgju
+QA1fkWhGLWjZbIpYC67RkMKrgAOF8xPVjJ6Uue+VzivMY3VIvLLAI/X8iMqxew8u2sAIJKa2i0Pi
+cRvJT81oggOryCd78Dk8RpysBbSJCMiy2s02+ba1x1BljFcjZLXBjLdJbkkXslRmOnNTNEtArtM0
+swk6IgdOog8goAmNI5BbTri2jJpGu7RaPcJXNDbah+7aL+rs22z9vryplNNYwvElwF90gwBDFvUl
+LGqHxwTCHUA+gzcNULcuZBoe+rhGfqh7ud5//rrKB/KuV0A0xwtasWXS5X5K7svpv3lOL4BiX5Gf
+9flN877/jZNwTw3c57AcT8/NIVS4EvmsMxJ4HQWLl/Y3qGcbvqMRxc8nMuuBKNy22+9HcHtEsdQF
+E77HZrXq2Sw4iSmUi1VD9A1YCP0QRa8FzxTU0/cYRO+4/Xx0rEcFpMH0HAGl3wPqrUbwxoS959PH
+FH6DQ3JUYQTzkuxRHVc3BEIPOAuSu+y/v/ZM+u5U7ZPxKAko53CyyZFV/GbXEy4nwTN7NIPCWncR
+0OPHQg7N8Js9dkETajU0s8tZa9VQ7JxhuqokS/gVVlijSkalxRTz4Mtamynmw77NAclQhj7e+E7n
+Mp5rF37vmesBIeAowjFzdFGrpPIXy7pk1nrx2x/1bqJ4FR1hqKjME3lHFYHFrQ8RT8snH69HlhiG
+yvJx+lMoq56OwQ9/obw087/Wx7vWOAqQ0/ZZ4N1Y00bIWPG+s18SDvvkDjJZgI5llVTeuvp7BwVb
+U7+8wDyCgnWsIjkiJSVq7VMk/piwqq4y75e9NaD9I79LLQGmkUJt33twCljOLIQ7n6XomyfKYEmY
+71sNFOhQ8Rvr1OvOij9QChKdWyMCIsTAfwnlwElA3viud/x4Y0MSZ9g6HDWm4HJ6GkVEPpLMeIf6
+WJFBkOJAVBJzuZDwAO4FgjJzYZLS2Ta/lft0oSL4en9KzsIrQwA9FYoHAlPe5e5vfYtel4DTMlS7
+CCM3q+aWZ4M4dcaaOuTm0rXjHwpcxHfBRzSQg6zAIqJR2vP2g9KsVgwUpTGeL8CuvJcgRe2QiupG
+wCiacAkbWo+be5XRh1p4+8HoSj3dY/OUbWCXhK4VjxVEgoNUWN25LBVgCt6ItNK95VgJLxuIq2xE
+cpEh6wnBfs4dTuoR4arXENlbMzGoEVg0BcV/O3upCXjJq64jEWXjfjiMfMSx3tqJB1sNNLlyMbXP
+sSqW541y9trSbzHKVozuIosUsA04ITYfS0IP/aUgw70HH/ud4kY9/s0M4ihPVpbrtezpdUx7gXyO
+igQ6AOQL2UDQn7eW/TcvPF3/dMqu/k+i7AJZmzOlGXGmEzqCETJPMtaF/PMqH44MiQfOqZlvxOdW
+jMLrgcTLaescrRDMnpXXlPGC/C05qXtmBBAccWMmUo52w02F0NOhnKuzyt9HRroGzlLUv71kGYiA
+hlxjJHKTjHQOTw5m+syd5h+7oQRWeA+Xg9IuFwrh8/cvl9NTOl29ApIuBw+jyVHZIE6919Z47SRz
+G50nLFVk2MafL7DSF4CCXmRWYsG/N7ytduDv/V3w+y+k1PNkUG8AuBmXKUgItpyHanTxU3fheW5T
+AsgGhOtw0tSUkXDiq+XJ+SH7uC5iop8ZC+4VZN5m6WAKNGHl78vDCLFj1KFfniztjdaW+LEDgUI4
+na36OHbCqIuXgbS4HCg7LnTqc/ASuvXvwgJ2bwl/X/ensyAaHj94CY+uZoGx7EKns9lC9mGgDtlb
+AFqaC/NKojtcpDu0/Qfm0LFhHFzufk/I3R1xEVLpQEgy4k1FxV8rZKL0Gxrkkg1s4m9C0jsapUCN
+hXB4RDFvZs6CvaJTFffzaBT2WbsYvtM8tXB0UiK/LBh0t1piMcmT/ckGoSXKgGRZifPOkHnkRKpq
+t9yuDdhLuTlHZbKK4Uo2TnfIRAtV5J1eeAaZOB4LTBAI0wQbJFuNBvoEyWVGQfD140RH96VZSz1q
+c7eQLCcWxNCLhJYGGjtITO1OTJeR2XoxBYgNZGgIzIK/3rzVTYM7DNUATKOrH+IJHUNMnckLySF2
+nmzIXD+AqtRjYi5MZqvhSwWvjMbrdT7yQdre6YyzJhNrMEIaLuuL9MIe7+afe7IE9+gysBMQqB5U
+AJXo/C9hR443KFjNNccWBvyrp956syXh4+FvJ8jWAGXtRFPRhdO3DoTjvyYi8kFoa6cLPRbWq+8c
+ZO9Ccu7qaBnCBX7biRcpSGATKcMZIGQDBv5QoAQzuZdNExRnyU45CMoP86xAaDBoXczD1h8nanal
+n8HRaytNhSs0Zxd6aoN/6dWfbKG5q8avkkLmYec07QXfFud89S4M8Gzb0RQGPhbNGbXPDZi/NI83
+oSbBhMfoa6+DPu6MvWEW5jpfsNgzkFQhpZynkHUu2HNgZ3VhA+vvYQ7y2XHBN+N9iTXwSmOXDyc+
+cWGx5FwXHmSC3T91ejS4ONsTwM0JYLVcWp2bONjujjIh7DPX0zbgzNhVd8zrDEzCkF+2wWT0EcNN
+fmnZnx9UPfbE9eW2q74sabQGs8W41pXlB4bh7p19yd0BxQuLPOWWevNopP3+A9Jbg+V7qd36j+W8
+TbRc/5P/49/qyZC9GIKWo5Lytg+zFXmTz31mWp9xj7u8EifhoZnPHx9BxgjOhjho1oc9mHzlvLgv
+6NePNLgrHez6+vFAOaMJF4r79qbGAbBwQ5UtCux0p7jGzWNC51M1oUVIRj01yxaM3WK+nQCvB8Ju
+37vaX8vnQWADWmhiQrfs/WuJvTVR6DbK4zR8/HlbaJuc00vsvySuTidu/SxH7KD9tfsY72I08pMb
+iATYCY+FSydlwXonK97w18/Pvby18sO9NOMbTxVumOilxStd7OXFcejcAeVyBzz4fG7l53u5f9ex
+n+7dLJyd98/LN91P7P4Pr/ngdcur7ev93cUT/3n/vgtX46mdn57QuABM1SiyiyNkYLfQNjUd+7Bs
++amj93b+LDVsvFG4KTtqDaCFl2GnyIqQDl2WtFk5/chRczb4ynv9YsSsBSx+lwPtEdTxZoTCI+Dx
+VG/2MIsIttFxRAsWe4N00mIyWq+Fbm0zyqjKltwJnsH7oaFJfuquwbvXcbWEbpPw5+ng7Pxb9W0B
+IN8LwB3x/r229GM7P7rVfTVak13ssxw7ZRatnq//+8eoN3BhZxfbjk243G2n3XUIy0rrbfv0cLG0
+jSz61MKn5GpkG832cfivZF3fR/eTWwBdn2XUU1e+JB8z59OQPiUvRR0C5pELj/Y+HCNSSOdD+aEG
+tvz0sX7tInzr2k+PfYYj77p1plyRpxN+/rZrdbbiOTkSIafTriGH7P1jJPQ/deGHx2iPKWr2ikyR
+r/fHVAVaCoRtjgyhl5u/f3kIHAbyNdpJfhNSkd778KODhNFVj3x6XIf9IDenHt0nd2K4Xy8WDv28
+H/cGMBz4Lg2IuJ2dwvcu/PRCWnbHPHfxS/I15rk3n3e5g6p/3tv5Tq52fngn6vVdXq/oujci75O8
+S/4vvgYjAjhJJ941Lr38fUHF1tNP/fy9+Wy1FAByuUvJ8+G+JDbk3ov/qhgadYOnCoWZLmsZfuq2
++Rde8u64wNs1SBndenIivoRWydzpggtOqJf8dZxHoz8YnDQvYQknXvJ8Pcg6YkTrQPoOGyioZnK5
+Y664bFly13YdQ1i6fK6eFY+nazGIqkHHLZiLX0KLbR8Xj/Rr0qwCGT48Oo7RhbxAKojuukPZhZZl
+v12x5+jXkXb5h7d7LPh45ZBGozVf3Kve11QxBoOb0/vdhpYK3f3LWSx9Zgvdo0wjxTI4mgpciz0s
+x2LlgnDRTsa9XTgsxcWFnsb4tJH+LAcOLgELlPpvO4DJ240xDgHQutDjTOh8xgpehbPkfWO8tfxn
+vSYOY2tc9yFZRghW3/IQGnof3yp447LO+ABPMEdUvaTFxZW6Z386yZXz8Pt/liH/5jw/lBzl8oST
+fhCk5+wRP62wPJn+nXja4dU/bh/bbkVEjAN97MGfpY4vy3YeuxPs9NOYPr/5/ofvwNpRRbeDKehQ
+lW1oasipgky4PL146/KXzPk+MtVrsFS9viXkvcu7I4/4x70d/BgQnP7lUvhrv2kNlWB1Kk0H5YfQ
+gS/877009tKrvAHefQR5LN4wgzeMwUpQke7Ij8FIM0jMm48tMOdmB6BMaKkmQ9Gn6Q==
+		]]><![CDATA[
+		t4bBZr+WCqvkiAFswKhqcMkpRuvCdfTr1XtfhZ+21bx6bJ16GPsutT63vvj85vOfNr327162nQeH
+83GKoT10KB1DOjAj7BkB7KeWf3oqvVCaEb0p1DuXj+jNOHXdaWrfw5VmXUTs3dP4XeiRyz3ID7Vw
+1F6vkUkjQGtvQ7/17IeHPsyqmvUUbcfQhwGAu+n4Mnr8RAwvzrVBr8WwkAu9gvklnJGuBjl8VWO9
+lJwjQL70iKOZQOapaSYz8uAMWaBVvcQTydwu94JzCDMmYxHSwYRIn/cPvWyHDThYne0u85s0qKXe
+zcNbIHQ9AGHP+tLrRKMFR5L3X/OkYAhndVXheZl5/PXaWQrZgjnhXY865dbBb2etlHmCmMs6wvpg
+qY4p8I0TJK/eIMINwzllER5ykFvXPpbtvSOZp14lAMN8qlcNeSpeM7nWlpeKX0zhGuqeD22NOPgB
+7PfuIFyQ1RThayu6y24TO1IQNLlV8nVv1arMVtKiL3+rDy+m2kOOoXgYCyphz2KAZp2n0UtJj9Ok
+cYtYFb+nN2Emq8+EF7JoDGN6JoLqU6IBB6Zyeenad46etb897zsrP0mx8bsVtnhs32tY1uAWey31
+hBBo+v6l75WXsG027MvHRnk8tHNHoQzUs+fd7Niy49QAN7ThCi+umWHn6uNU4Yoxuk+Pv41ZUW/F
+FhqDdSZHMbMLX7d7hRAZUmjWdbuhNxjfPF4xxsTovkcbMEDPX8KEFXkJi3Rek9fGZDOFU9PYB5Fh
+NSsqoE1oFRDYeI3l1P5lstwuTPioeonZxzA9HTMfAUdPZZ2nRYOMD7HrSjZTuPxzfar8iuH0H/Wv
+588mqLT4x03vQKsg4z403rjuCWleFwifnxHBTTYZqEzebM3zvMHR1bZ4/MFeghl0N0TohJjBA+8g
+S0WFonF8x9GofOqSsKZF7eWR2d9qYMIwe+m/zPkztMl2VYmG0+c+IBMGFMNprk2tTrjGDZEOJuhJ
+Abcw/k2Fz7r2CurjfQcYhF7Bx52EfJeu9s2S60MrUvfRBcM+SuyuH3VsTfo5bKxWTxX7WBlXFdg7
+JrR8X89m04BNaA7O0m6zYEeswNchdgWc0Ml+gQPhrA7W2FVUlzvLQkWr8Ng51NL1IrNcIF65TlLC
+MezuOrVJ5xg6cs4WQe0ghHn+kvmtzgbMg+k5cmuRaMi7lZBc6WGtPq4qQo6d35qE5tpgHeSd9lZp
+yivLz7+rvdBZFKxd5zk4eZa8bExZfpXqKO42fcgOyPIwe2rhuTxI8edCFGY/mUM/bG+hHIJTFBVY
+L7kZipU+Mfq+mvGgat62rMMWPucAupxehmVZr1kfrynPVaG1ce/BT5uUI4Zi657CpDzLgSThwtH9
+qWgMunAwOsoxjmh1iBPalI6IfVzMqWF2ubTcQG6bAbcPmV3Oecq/b15S662C/c5lc0Jz1MhVMTR4
+5LBS8/3W79cC64tUFhD65nOhV2JCuMqQMljwrGFgJfd8NWCtorapWamT+xz+ec4cm2eD9PDfLsde
+PWTantSmyboMcl4RhmXNS6qBsOJDf3+Sj6WQgANl8/Y5upwkl5aLlpqOBk0J12TJSA/T13ZF6reF
+mpplWgPvA/3TPEYKMMSm43NTiYojylgQZmiV5vqgdyISEscZDPLkW5P41ynm4qbIyGjVvB+1n8yb
+yCDtVR8DiRFppcUvBoFZ/zrlmoalHV0oHWbiBP5QhH5y0+edTjvZM1dZHQcNn7wNIneUtnV6G0S7
+bGPbVNsZ6HSGQxmr9CWeGcOuc1b07URJ+buQmcPXd497ISXXG2m7p53Kr0caK40X1hzu9GcIG3MI
+KFEd43XT8G8j4xXhVJMfoyrfNNMoLDsJNfovBXj99YLCnOtvnTbiRBFFGJTvqdtObD7+elkrL0q/
+zr7VIrZ5T5o+aeWTMB7JOxVblNRvOc/D0R3bcdlYTszdx/UcWBmW2dYf143p6GBNucX0W3tB2lKj
+3Nleh1xOqedqOCNT7DoFGSksnAQkqd+6wKCPOA4wMH8Q4WOl/Mb5dGrkeDReZsGdAJ+St6WWhwYS
+h9+BmoaENXc+/x16Jlpmwr22Z7ScEFZzLMza//r+cZayOguVYmHyyKO/OiKO9jeM246ZTk43TMLz
+6ceHJVGltPC6HEYyi8crn2T41F3wFyeCfek5UuGb2C1ALs8JfwwRQ1kVXKNx0uOxnFRhcXl54Cpf
+zYz7NfCn3vGyUKqb0V/vVz/En3dxFz3fWyvfydnMD6cpLD456XDb4SY4CGg4viseJR7v0hKvjV2n
+q+Da7p8WO4z9QYUbA9KFcdHjvG+kCa9Dp7Z4L2s5q3Jded+pR/cN7IIOTtXl42NefQu3Efx/kJqS
+NBXnKTr3OzNv+PH7n1/Lb8OhW5eyT1/vOlP4lhdtvD299qWhHd9uiq1LL5fC/rjEdfnWhT/RuqXt
+pC5+PchzVGhJeJqR2EoXj5ZtZYTpzhN13t+nE/LWhZ/ejFt181qNMY7Wbj2UgZQJkH39sKWIWsgU
+O1kyWwNchGryujuYpnTZHM63xz0HiPCn/v/8aX2zaOK0yoY6sTm9yb3e+vPezndytfPnne5WRj9Z
+3F/vp559fTfY8t0AyyAVe399XT+ujLttr++9Dz+9gGfz7jxIFgi+mUZHWW8dPMmy6J0vNt9lMNJf
+l4l768CfqMB4NjnEONv7HPuQ3pII3+Jst2Z+uvzCwOz0u+4YYD6qRavKad4+Jc4IeL3Jb838vLGW
+jnJ6bMRpoVNhJVSDQLgYdU4E1TgZ2ZzHOCv706jq3M+g08vmvQM/fFRmJEla+Z4laH9J7uzclzeH
+AZrPxtcJqG5ewqqcNfO6HE22l8XE/noJZU6CDm8nBoSMwJxxj1zea317jc169idxio1vcs23OWJv
+83p7KTryXWOzB5+290n4yWRCW8ViWamMOjtuRqSXIOvtFGg7CHvm3q0hL1aiU9ApcffrPcmrGyS1
+LkxNwUOwyNfDHOt5soUgk3T5AGgCEPp+eanPcQz1ij63Zbw/eJiuc9V2lACd94mHWiLIrhKI179P
+i5M8T8VCB7Kkrgo0AZQBzsCKKibPxyoPr/zIRzkfvAI8xqsP67YOP73QOq7azF9vN75D45a8LYHr
+5z+tvmSMTqMWqqfMRp4t647t98/nz/9EuyQpFCH/5Jfkzjx9ScGw04DAydnDabwj/ex6iTMi+WmH
+KsfvfPB2qxRGA1s+W1ydBo6R6W0Ox/I+vBFk37lVVwV5ZAUVJI8ELYeHCtdQiGEKn3Sv9QG+iu/G
+cXItJUUbAj3sMojh4BbXs0fGxGhg65UZn85ybdLzzHVJnIa7p3wEFoTJymJXE4JqHn31QIIavWmq
+y3Rd5dSXJ3X3jTCttseVU5/XSbx8e+S30a6/7WePfTnLPGnG6ySsqPLZM3Bxwdu3HtqzWzHFumix
+qKjez0LLO2v8LA+no2Fh6oxXVSrdTtkPmxMWlc2XK/5L8pwmB6mgxutGWGu82QMv4ZxxXDc2h1Wr
+Ls1+tHD7uX/9Z9nZVgyR82nV4onBN4ItvNV8hV8YTw/1/vObZn7a0JZBrd/9CsO5z7deXr9eqnx6
+aOSH74WHy0AbeoE+8ev9kqD87VRGDG0f6RW1ZlfVRvnnuwrYy/D+gw9nc21ImVuX/z/yh1PjJQ3Z
+j0gcMumsS5Tx/v1PmxlxNb0vly6XBZyeixF3XsN9FV4O/a3hH+64ZQ52qelTz/c749TJq5CbYVbB
+IV2zQS/ysdfi0ojyTC/dUL7cvW8/nzjelIXqPYy8cZkfe9KfPv/pMnVL6KnzthaXq0NrcRWmsDz2
+bXCKvi+r0ijX82oNAGftNOWXVvvpkXPr2s8foDmOU8ffU/jf1NXp82/E3sqfBkWRLQR4nBTPl+Tz
+eD+/kNNto9X7/KadP/EBYkC+ugKEB/Im1qRejfp3+bWZP20NSuR+45XyJTExHN/uhPPnHmh+kPOx
+88OuWfqZ9bvbbir0OQzDcH4P1LM7V9np/r21+6Pa0m2gUZTxvnI6eSw1YcyED5tJE982qOdLCDes
+Gnls+afTNpVQYrQolt//JfHh+B9jGN83UFYM/xjZK4OA1BA6XYUL6+qRKB7efUtaQypway8Zvm2R
+92nwlO48Iq4uk7SL0dIThbf3qrTPhno0C8SvSBwtqESyDuzc2mYo7e5AOffW0mR95l/jdcjPX+cU
+05fQq5rYh2o8D7Z8wwitRqTFM2HDCD0PpdpfZ/GHXUfml2vstfNb0RQZwsd8rVLJyLByqOaBYQ9m
+/xrVR9VceEpwuEGBWrnXyCgskYE3epQtbouFH4YfdjT+uUrYtyNXPwUh6sSNesVwPOPvGeMcxqAy
+3py+Y4LhC0KvDvEZaDUcOKfeGgJ+LdcZOEgd8DCDP7lCF5hruz9e4z/jU7/+99/95e/GT6JiH/8k
+VOy5LNfnAMliey0J+RLmUYJ3FeLPN7EteV7BsBmtfCffzfznJ0jsV9PG1FrI/OMkil+SL9OdkGcw
+qjh+6BTlzgHmwuRMb/wyKy3a5Q57hhZ6/D3JnBy9Az90mDME1EMy7FzugQEwFbmb2YXjKBS24uDo
+D0P4IyVt9BtrjvGPPv6vbmdxUdoINy3pS15B4Dmn4OVNduhTMMmlfJ4gFQJCfgwSP4k0OeXTYLxi
+hMLVSaUumGM0sPq6fVuXiJRyjy68jeCnp6gAo4O0W+ItMBDj6Liong0aOYs/SjT0hnUyEiej1iGu
+BINKiZ6LA96a7a1ImNXstQs/vws8SIINmVPbu2CmIZqtAfJyE/b/h70327UsOa4E3xvQP8RLAeqH
+yPZ5eCRDELpQ2YVCTeh6EqQQJVUrghQ0sMG/77PM1jL3c+6NZJJKCeqSCAgULfb149u2DzYsW6a3
+yefTchdjS7H9zrPU6f7te8/2VvbuGpgta596Bz5wPG91xjLutx9SMDsl82t4O55EEChbhy0tohcF
+/PNp2ECA3kquScF1aJmvs/QzNYQQWii4hjacHYB7b/KtnQP6n+MFH9/A++9Z1+lydok5vN6mAizk
+FJbBnkPORmHC5i0zrR1vdG4Gl/9KaoxbvYcfaLCidy0MBcgaWsR3CYf6VoEPLU+1HWajHZDhRdMa
+XQEoGNW0rBcoBxj6HtYiyVvsgUW0T3ZzcVviITxdppEcrEPfqfvu8QYt3tUHlMHqEWu5Ve7z2fgK
+tUf3Uny9aPW+x9KN1SjqaesOKTWrGftgqP4hR8hbDT+zlQWakCcNhDs3Cktp6koU3XwgPzNgS078
+XNqdTYKsushvrMV+Qqb2c2MW9T41nkd/rcQvlrx+772F9NMuVBgc6tU5j0eFXg6gaefRbRXPJqut
+siVkxtr7H/4s4NZDZ7+39oSQzYjPvpuAJ0VLSGs1TH3CkOwcuFkHLMisqpT9Mk1HEOZtPYYtYpTi
+g7Ro27jUv8WE1PLynkQcIemFH97uPCMUHoRoN5wn37iVSaE1xHOVsdMunkw15gAjfQ==
+		]]><![CDATA[
+		cg6l1cKHr1ai3mjuHaX/9F/VVqWro5CFzeRs2LrUXmla8SPfxulIfvAV+65Uv9EsUcj7CntohZKm
+2qVaz60YoaEsjSNsTaF0TcsPj9sSXleDYZdHG1Rv0ufvq2eNl+Y9HfzUZ/xwh9q/92mFBpZatuZd
+Dqadj2/sZy3XxrQzDy1iEtdL7k1HfLaGEmoU27zfdS7eV4NK9i7CmRw21FG/RljqqmtNaFy2YwDj
+lYGQtO0uVGMOk9O2JZO8y6xrigvZgj6j5K7pyR4NxXJzJh8+7GdZRvV61gsn76eUQVGgDrYGv40R
+Su8hXzsenks7Oh3hjmOpLF4zGdCj2aXzojnUWTjhus8cZqxg9nTihEfnCINd5fFqQw9Pt8OgBs5q
+TfKg+5NV/YidxtXHnFtHytj7t0ygpa7jjt2cQZ9/2vhmb6GZm3Wq4VqM5p4ZmVANoAZuuZ/t5nU3
+JutV263sMBrxbNESy6tJX+erX8JvzKCHutS20t5rz5fF+AMrgWb3ig6V9mlqflmN7VrOooLwmWnV
+8F3Dc9vdDZiMgjF5HzudzTj8Bc914UKLL3MEfpaB4+i62j5rACv797fKnCgwXY3vX+qWcHB7TG9I
+ySk8/tfQFObwTnkZtrBsXWeyMKHF32g+HwVEq0uNTGGX5e/IPBd6pzGZ0GcEGgMr8UQC0EK/Nby/
+IGRdt10Ul5m8h3a949JDSFCFG+HsLpy3m2+0zEeMAJCKVK7ZlhOlWARomJC9K6HwEXMoyZOa/hJs
+ql2So+D855An/e962AgX+dnZ7xOo3RTHovsXxdqDtbc/l/2Rc3/5sCsenvRxMbHoFn41DywIq6Tu
+RqIzQboewomjw2c608bZKfq9vvfsu4P+wAzeme67L/ZtLUi/y4LOkD3ut6dHXXYsoiAxMbldYCY3
+5iIOOiNgND3W8AMzeOejvft536yFH144L6vsf+jht0vy3cX7rZWOkftSh27pLAPfKxO7p6PIySet
+dbt/97JQuMRG1t5c7KFDMGsMCtfwe6tlp+MwoSUxfYTG1kwm92LJh3ChCYTNoUfHzp6vNtx2IvsI
+oHJyZwZsQew/PZpXb9rDlQ76NFIfhjYNDOwjgDhoua1ZSBryEC6nYTGh17nOBU/Y7wfGRl2Rq/mv
+q7GqNVSUj0C9ouQnbow+wsVEnelgy0Yn+rbfNo/DnT4Pn2B4tuUsp4z+IZ9us7jblt1cmyXukn36
+v2/rxW0DVHYhekgfznf21sLedRLzmewi7cwX1kKa7ZUbvozMDiNq8r9tYff0osW9WrwRPp5fQ2Bf
+aEu7rlVnd3zIcVV6QKFOeYQLDRg98lC2p0N8hDD/0KraO7M2OdiPDaBLE6WVavBc6R9byeCuZ9sb
+yZXJO81HbNo21eUbBJi+i7b7EyasYXuB6EzttZ2tyu7i5UtKcXNaPo09VIOH12681NRVvclKsPQt
+P/fMSVNY7qiu4iDnz3GHlMqXU4d6XHrsk4u6qcZRC3CKjHMcKxzXNsMkdF8hayuz/WhJHBSslhxz
+i4/ZLZKIyawh22+1qaaobBaf4RNrtZbHWrkMp5iYl9abcLFTMxugunBMdfPddLY+utOgmU3afgVd
+CNQpfDZ5MqVtxT7qeQVEVzdDNWv52Yu+kh5WxrSOh8XLDtqaI2YQdxverdBOSY9Ta/HhIoMIe0yB
+sdojVgPA6OAA5qa5kEdsVCGZkEcs4lI7zC/Qs4NOhhGzpIdnboy5ycuDcMQJgexejNA2T56k6Ni2
+Bj0emmJP8wTEoPqlmxX/WX//9tn3x/zW77872Xdf630dAKBR+HORHxiPERQGswbKHy06aFM0od2Q
+nxQ1pNeynZFAMrfsd2zSRL5WF5YaAwwnOvaB2ULZipe6Rqjewz0dixs8gztCnxY35xzS4AhTdv/2
+LtQuU4ZiH/pZk8sQ3+S8MtUkxQgjers8BkmTbtQzQOtyx5grwzvMLL/aYsV825z5U6mPcdQ4tm68
+pU8J708hiwlOtP+uh2uSlSOjIYLFqApx0+CbKj/Bth1tlZOzKLlupjv26cTv9iH38AHCelvovfHx
+vcDLDwGOf4/IDs69pjjZSZXaKVcV1Sgp3PG2a/iyUw6uzKLn2E7TDXR7gyjF1MeOY7Y/3LMlr7cc
+b7BfYZi2k+4wg2ZwBcSZ/PIWP5SK/13V9BM3nzbxB8pfU+6/W8K9udX0VXYoj6PBlHlIwDALM+T7
+82fviN42mn58Wc7nr9/8xNfXP3x/5G/M4WWyf/EH+cNfvvxDch6N+3couudsrWrLm1G/IT4DWB/z
+M7nuk7t+TKL7zRAjz/vNm31DfAawH5ORbmYLf4hdJc35sPylG+SWVlqOPfBUMg6VyKtbOctnWd8W
+LPM9koqaqGcdcS37STKLo2jdMStZx85bub/GRBtqeqmOGzaZbUP3tpbv3pm9S6IJzXn5rAG0/3u8
+G37NnQUowupU3P1pHqXqB0n0npxTe4w3Fn2r0d22RYlN83wL4ERyoYbDDnC2bpkIRtlb+TUcg/UQ
+5vAwq/KxxrIkiIqVnnOA6knlhzyTo9GEwq0g5eqxRv/m8Nftg/0x1gE2Am+Qjv7iypiO4jTQfAOb
+wajfEW7S3er8aA6TZRP87+tUThiQtDrph5qxASEi9O721gieje1Gsr/Xrgrgwftsngljow7/Cn6/
+j3MvAg21zD8ZTDfFajRrA92YvdGWL93R7Q4bsB98PcMFXIvDtrHWUa2x8JrcrmcXGkEmDD7PmruQ
+6WFMVgg7G5kLN4UrAo+1+lrMpL23L25du02YUvhTCL80239wWEtffGOL1diwffHN0Eu+uMKDCNXU
+axy6viM8v4YPkZcQFY7xs09mhBa++VKEFEbzJtDrDoaPckejsofTO3BCCq1M3nx+CtF1uUIrYPxM
+tWr/ugHXme7z2SJ7HiMIq9T9htfPVW1fn8Lb9fz59Xi1HbCXLqrtkVVTsJfKPkYhuYN/+M4XnvwQ
+xBKHdqanEIb3BePiT6YxW2Qcc3uRMhfZ0CKbSRgnW2SpMzhj5yoXmX+1mTzJxkWW9xkhj6VF5sfY
+2I5V5SJzi/fxAzodPakdr8DjfNCK9Pfdzbdl8uJI01XSxWHhoPNxZuJebzws8HmHIQMADW5J35zf
+oLmTYsfQP6VJ8yH/440aM42rcrmGfZDnYvLvn+UNhVP5vqvfSu6//aXsm/XB52YI9/8MCVhjEpzi
+in9AEubDf4Dckv3/7x8g25ocA7t6YhE8ZwnqBQuQJQaVIMSesmsJ3cd9H06wd27bMcAkBe5pGp9y
+ttkjpmhhHwgdrdG2LqaJgArQInhLoEoiX2w8qfZkAcHVR8eatcHfepxtm/4/QyuIBJQTCUr0z2C8
+lyFoC2OhGVTJRU7MdrOjJL+Cw/el05b3iXgg9GqKgfGeijLCHgrNYBKc+URRcrdPjYwvjR9Ll0GE
+hiThSBg016daIxFZiiv0MbHid/5Hi8dtf91avBP7Q/j4f7Pda2jKUpNUUKun9B7yJoDG4yTFAJAR
+5/PRAn/uxjlRuJzOmpX5Bak44UEVCWU7Nxvb23z0MLUtTLCan/wT+qMgMGbykfwkQ4OUMvnw8vur
+dl0eNtMkw6tVrxd8nKZAD3kUB8aFHQ12PPrZ0sBF6Ik12OYzonnb+WTdklEYqHmzkceoy6uWfxNh
+r2UnJFiuG9M0U3mEXq2tyn9XiGtUO2J79wX4kQ65oRw69koAjKxwwQaYswV6hsnph7w4lhfC+Z0b
+Ix2wvzooM6/1IcQJrfUB7EsfZqG0uIZt43hYs4XpNq2yxlZoHVeczqA23WyyOklBbPPyYxrPzgta
+aFG2yooMDjAVvqv9ht8wb4KH23ZgSFLuGB12Ilo6jYbDLrtaD4Glyc2ZeEiz3iJ5HtmWPtCbOD1g
+/pnCKqp1Ni8lnFVt2FdDb7hsMUycVbF3nbLZZJZafZwp7cJ6YeDklin6g3rEdaLA2tENODTWrh/e
+PUMfU/izbzjs6cP/8e9/+fcf/vBn/z6nD59/9fVvfvUPv/zzD3/3V3/6N7/48PVXf/6Ll6IlHeoP
+HeFczzy1ESG26LnFisPXSw8FZbuJHztX1h6a2CX7GkbY74m/apsk++qFiRkJJAP8PbbW8I/hNjpx
+dyBQSW4ursCNReIGWLkqHxq/sQR4GC0Cd48VUeykGeX0nreEQp5LG4cJooNSacMNzo8WRWIqqQ43
+u7kZQG1ov17awXwBoGF2HyLVeU8uGcS07WKy49GsCAAFi13tKO7PESao0zv32dmY0f3Gdd2yIqa9
+RDysIWLjSp3dtYfSl22Zg5HdzqGqyRXqmtjuuJn+ze15OEudkUoT2vaHc34gCg33mi3nAeiRJ5dw
+fHqQ7fFz/ufVu4xa1KKfc5Xg1b6J/Uc90LI8GZKA3R0TnCHTboDHd7Gdzr/H7vTTzwCr/N6E0Xek
+5xwgit5jdvY9tNd3k9kLsU+zbQE/TdVpU6jo/Fv9f/7Gd/lCSx2RvWaQKWRdEA3/qrzKcLBqhvfH
+u5fQNTsnykntm+3/EFa7auI+1rMjEL/FzFO7pLc3sYDQynh4UhmpyWcl2KzhmB2XpXtSe3NH1EVS
+T0sFm8lih7jhaiNFbMzadnUaZMB/bNp3eyypVYkXaPgzbnq7Mpiha0zstEkWN7Mouh+rbbBKygZN
+3YCArR8uRnv4oezlDw+CwTBCapqCh1LReHKaW4HmKbNr5ZSwLBtQpUlTmMOOo4fQ/DYKm2//5sZD
+jDA8H2vGRuWz9Fda8Ym70FaRmUULx91nKYFJRtx6HkpHu1I/UmGzRPZ+brNeanZKhwPQ4FGD1/Us
+1MNnG26pPQwAWXq525kG1E8OZxRyMzLyhQtqwMBrzVrbrPcW8kHIPcu59HHzOuaqgaZosMmEXdPo
+Vgv5BjycxnTd9sYAK/sNaWkGx2cB7Y24SmSiqjm0iewpbh+nnmlhP1aCUhKt+9ut25Cz7EN2cR1h
+hhEqkLcnBD4SAE+jW71J/dgvy8yaDD5/D+egubQd7khkZQGvs3v1SOZUmQNWrOR3NEJby00SICrs
+wHpcnN7W0OynXdxvmReuweyqTc0uByBC3Y6UN3ULFfvmG3CAN3L7aj+Vn5reFrzlDz/7m9dq53BY
+p8c83nVb0WHF/Sz0Xlfx2yWGy66u7bQF3hHxj79/f0y6rj5Fc2DTw1PF9YsQnfmriGOF1QPvX4Gk
+aTl4hhofV1TejDvvwRbVFm4UNHK4MR/ynel/p1L6EZei5KGZlCFPiknLOMVvCm+3vD1yxMufp2jx
+8n+AcdHwQsCGHNMCoRuPEgEevyJ2ug1+bDaY+YVfXDxlqKKYFRGRL3qccvBjwKr9oohzcTlCvDgc
+Q76rXcn8EF9OuNOz80/iLp8f2VfcRDFKZqgdN9EM+es76VZWSM/itEZl/FU/UNzJneiEo2GKRY3N
+mzMf+Mw9MyiUrskMfaPmmzte6eUnNZnhJUkWsaqIA4fmOQ4TCV8U4JIOcI/EF3mYTg==
+		]]><![CDATA[
+		szO22sG6++VlpSMit99K+3fnjRAqtBdF0A9UGvGxnyfIsyLCW3ahYbe0vtad1Tp7FOFNvRiZG80G
+NBg0NQQT0k7Vx9NmHH2JyHWezHQZ7OjI3b8d7BX+RXHqx8JjTNrutPN8qkxwWj485AIK6VHLb9QX
+Sd+DGRpLmYTcLmNTjoHyzwhuPj727IQdc5YqY/boXxeTRmOaZJNGiDrH+NeXqoa/fBW7ZrWWroMN
+5VLtTmHWJjBaj5+Fwe22DiL5MGs4HcSxbJUZmXfbRz6WF5/huuuXfHZtWCvjDjkj0raRh9TTWbPy
+rlwQM4MWv74v5DXm+fZ9TROPWZrzlOEgxgk3vls6DU7RKarqs8fCkTM4Z4fZW37A4elzFPCkSfd7
+WmKQSw5klXEU8Px5bP51nxBPE4mDYHuK3Y6xjgTb19jyPsXH6CYP5er5dE/9KAUHFu7BN/Jxr9UR
+51t3Bp1Ykjzf+n2ojslXBazuHHtGFvD2xM7f7XekRS+EbBWqD+L2eFEAv+YVTX5+j324kZ/k874I
+h7knwufkpOw19hzTldv1970OKNrKdmTkS9wc4cY1+73Ut/axMW6560+Yr1fbQ7P//uU4/amssJ8g
+XbCYEX4FQlD8kpjHWYRildsSeyu6/vjHQSKe5vA6xPs/9I0pvfcCf/EHNymbXYLuFeO7zrA3Q4wD
+FJ4if9tga/MH5Brm+/dH9xm8vjwMwOr2VbuLm48cILrUA1SwFJb5llzjfP+N8Z+wIriKidmql3WL
+YyPvS+x2jUqrDX/VX4Tjzu9f8qm42D2qEpTX75voQnOP5wdLVFxeAx7h868f+TXVM+h5p9fXV971
+/AP4UtaxG+MVJH96WVwhRPVdQvoobzSTPEnwrJnMTrFPk6PwjXauh88rX8OG8GUOR35NOIa9X+2N
+Hj4fY9b4wV41NFakls8wYwvdfP3gJXya3ZFfr3KGvV76zOFZQ2gg1Pp6ebjJGb+HDeHLHI78mnAM
+e7/aGz281ZCv4q+vc4ss/ZnZWduX8GltX/Kztq9BY21fPx9r+1mR59Gj8WvMI3yewJFfsz2jxlu9
+vP7nN5ffT34Pltd78I5FlB93G076B98E5y2d/P7k8/8azwGG/3x4df7Da0wkP+aRP/w/hmujX9zD
+O9X/foz2X36yYE39/6t62ot61j+Jeto/yopCTVQVEHGoSZhDq5v28VgBqAi5QQ0AE/r+eZxvye9x
+fmnxtj9SLOsmG3zW7Ucr6inMujZz82nqZUSJTfx4oHritQVyqdbv1vCkSptKA9TmzhELgAA/t29S
+H7bQ9AqL1lVtXmaAjEHpNjxr8XA5WokSouJW/EPezwjgNbTik9K9X58LrXDc8m3Rxd7kDy9p+cil
+FKWRioXoyikBashl26lUivMPMLGDqEpl5pYoE+SWcvH4OBi/iWQYTlLl8WP8FEdAQs1SQ3mK2QAJ
+DWYjUSK0HQKGtKM5PxgVdQgEbgDvsf19l9NgIWlgFQGeFhfsIcnNqSwA5wwYBTG5KjCB19iZmZ6l
+8qwqFgYIc1Sy1apywroCvlK7SjeQlysehn9MJ3sZEcj7Ti4Xv+w1bq2SpdWUrqxMDrCX8fuZxpEn
+Efu/fTViuBqJJVzIEgdkX7QgieFB+qbkAEBi4TiwpU2vS/noic/sDzMA4yuXJg/++dgPXVAPJJa4
+drtAnI/hN9Fx7GBub2B1CPHnUvn2FIwLDaVmwsLicvyQVwZB32QMdnlyJ7uuAKJ2kDI4Bqd71fl7
+u/oxwM8fp9IfGRILeSq0b534r5H3QDgY9Rh/rZ8xxkvLdVkqglnm7YV8jtbZnvbA/9v9E3TDDDp6
+pU4AHZgRjb2LQMbgexnmwR/GXzZTeJ3moDFeAUvEN+X05cg385WENQVz9dd6mIBCQ9/4poRuSuH6
+eHy2jYf/+FvlCx+ND/yxVX40jSsSqEC1TWRiAfEa1SLrD426KksVuhUluSPI4Api9pOZ3jk9tw5g
+VbW4QwFUJUuXBWl0k2PhVEeaPfakPWJ6MGolKn4ostZ6IFyBbVqLyUeDMobiycWCgw5QX9c80qkO
+FsNRghgJ5Y/TajroZXjtIr8UMCEmL0sYcWwInyAqOVFm9Gtt5JHj7GP1IDBf5uigyh9nsj+LI89M
+BIhZcGoqzVSp8R79NN/0D39+PfJfgIH5+Zdf/PLPH3bAX/37P9Iz/+Gbz/zX3/zNW7wMal0TKqRs
+h3WLkadc81kdfkNa2fjSPisRUMIyIfClGCqbiyNS8xUU3y4T2MfFhnm2ay8NZtarZxD96uWJj7Ec
+HYVsftOVUVCnO3SmEAX7uDIei4/CWR0kUoEctAByZY+iT1qGRJbjanWKHbvQl5Xl1VPmBE5ZByPb
+TXQXEJema2vt0ePhmSV8nLK/iYenTkZNGJiUbDHcysCiC3m/1Cu0gKS+JV9xMBXfYTiVhnk0yMxn
+r1yAsOiosr3zWTtJx9KMKkJsL553w6PrLnzcY7duY4TaKR70IsFf68iWxzFeU5Wwe202kGfHObX5
+2l1U03d619rMiyjLQ5q8Mx27/fjKpUR9Jq7bTDzJXl6X0gyBrhPJMZ9AhlRD2T1WVD1ABnz/1rlq
+dQBXO62nGzVzxGZPdg+aaXMKvgHqkVlVWwnwilfR42GWquFY2By0JN2vxVNZjqgpXrCDfWGZcmyx
+XGIjTPsq4KYYTpQDzJUF7FAivHCmJ9+8CWnyv9Y5/Pj0PLStOOOrttvyshmc4D1+mSxj2I1680BW
+2CYOBFIx4D2NPKHWgRgZm8YrmbYgtKIO38WBOINOWf8DkI9jpM3y8yhfrd+xzhuIWa8/xNY95fJY
+oWZB1+HYKF8q+nssxCFbeyTuilqEkXZxl3jleLTfwt/Esw7kwmaRNWgcD7rXl66tWvn35g8HYGxy
+t0+/Lvj30yc22MTVWQi2diAIHmKAnTNPLbOkKXSEH+Cj+n3fP0BIISEffy5lNy/BodD3Fcxougow
+S10BxRv6hC2qF0uBcgK6youiShDFwQFhRQW+N1Z1GNTDAQXYrqzGqYaj8lX0MNuWLPLFK8JAlJ9l
+0uvvYa0S5ATHw48GwOebfBWewzBhUqlnuybfmcZXkgN85WlSI1WQrCQCa8Zje5w1z+PqsV+d6tCQ
+YotDDhqYtuuMsxS7DmRX3K4dESmrO6xX5Bx+gtdqYM32qI1pSR6IAdH99x6PLF8GhcBDuDpzEmZl
+tWjUlzWka/7FVLSDU5VH6YpL7qGXkYt8ThQLvGLNsNtrYM2IIsb9nqveuHtsAJQtM/wPfEEeXGzt
+wbteltNkaQIGsO1VUjTH41nqjDWlOsKdL9YnXedKxF5tik7YB92hhRmnz4hS6gp+yhTGX5ETZiTm
+psf7lsuodSPyusvhAvvf5jcTPQLsx165dc3pjM1XxqIJoGogBAAcFYFLdYaj/7IUPn9jiXz5gaLm
+38GC/NlPbUHe5Ns44ll5hmmXgJICguhQUju6tzYdKwLMnHicPGFR+9Ko7q19kcX58Kj5tEWXvuhm
+S8TZm61DadKl/pBbHW3IFYCo/psuZDEFwPPgs/61whpEBGGB0B3Pdz2JgTv4cBfP2ONhxUvARsiH
+s7Ol8eHmxZu2VUUYAA62IRmWI5+FJ+9TvgYeApBUekvxMANHOyqCgXm3So9CuzPUbIWEplCZgzgZ
+bPPU5uU2v/7Gd/1pluPhInjsUNb741wHODHOxFxoW+kWrBa94gku98ovnBXxrQPMMJzwIvr/4FMA
+iPa6nIx6kRyPI1xVWF3UwUEUckJmUcnEo83cDPsORnkwYipNS8o4E/3MQ0TSbtpM8pdfK/z2OMSr
+yxeR8bgBnCkmkYvu14qUba8aTzvohWoEHHMGTly+KUwq951BMEMQKIyvTpm54TEwoXgoyip8Njli
+hQ+3fjS9++z6LG4HW0ivsC5sxsZ4+2V/0rWD9fEBzgRabwLfpRARDudpEUFYLSin+Cp5d85OmDik
+xjznLQw32Og/cRRmto7ZbVQ5XJYAGpBMhhdbDkMA5yHjRHITzFEz/g2EAUFWGupVucqK+ug34/76
+J1U5QKfV3gbBuXXMGp5J8DR3PjsYy+eDh+om3yY7q7c/W2ILw+wuinXKau5aV627i3pCcu7lAYcf
+CEF8SiefaeC3q+MHfw+8SJMVf+ZyUTgqi+uuLdJy/CDL9bmcnBDU/rnv8zBpSdoJhrxR0U/+XVqz
+WB/KWIu+CxmZPdCq9pEWK6XfatVPWRU52RMauFBRaPJrDULecBx5yml0MTLC/sHpd0IdLBjIUeSN
+QEF1y3n6CL/RNFhEWFCyzbKcN3P+zT/LfgTKu6mqITJNeHklIsTOiFC55xYq60IZ5G3e7NRvZkWV
+Xsf959iPPYfJWt1G+KpIqMJLp8y2g96js4DwWsYItDtdRG0Rn0G9EhfJ9AT7byJ98KyTiJJveizV
+6Rp+6BezMwx6RIC0Zx0MaJVpvXSirzjzemI1pKJH08msbMq2p3+t9x4j0ftVce1bJf3knybv+DSK
+uffkHOSukHTtyO4tLezmnuKjdAsIHs+xN5HpYFHNDpPaao8Yz7b6il/HfeJJyuUsLV+kPNYsVaCW
+GRAZoqLDUl3tOgAInkBJImyJiLfPCAqWGnBTlPblzFdcRLK8ee+fVNn/cMPkaBSctnUWfiEVaV1X
+t4omVnUs2tlly5AZtJ7sJ+IzWfGffeLIDexfCviuoQJvFgbBIVXwIwtYUglAicgYKUrqRb1axBWG
+4r/N4v3FyFbj4cIKp6wqHtybPYkvjeU6YA9hgSLqgli2kbyWOeqN6OUz/VtUMwU0TMoK97mHYvUc
+QUiBYKlHAfuhuUbp3tisbkwjqe5+WUypZ+/jEilsdlbwLE1E5rzo3CLqvG1fP6HXomKXmQXoSQy1
+XSz/9v3/lXz/H8LjoFLZK6L+bQH8L7kADEj1E90hqJ1702DvqdHcD9wuL8gBX12IYnniGaFc0laW
+7YzV5qS0meSPIIOUWc++GMIFqwhL1JtnXsJXag6c7iMYxlsX8AeJ8DrDBBjfWR1SK4p5NxCcbRFf
+nPAbwqKeZ9x+n7/7br8mKv1Hnrv/+jTzo0+kf12q+bt/KXuVxPg4nMGM9TWyZh4ThDHLrmGGElmM
+7C6SADR0XWn0Wg0zF5CAsMCVg2nB9FjIjeMaYxmZZVYPz0UW/7ilfklgn5SNzAdmhBGczyID/KY0
+a2vey904VwqzuqCyQM9jOEZhjYOfrBmOs3mphQ9gFFpre+L8o2HuWWiHCnZx3A/R5uTiBNsB8iaT
+LVhk+a5gcHf2FFxfDMmA88MLryJj2If6jSF8Xej/IH7oaZrDbPb2A/6OhuC/ff7/JT//jz51/+37
+/y/3/f+FmIFvYqLBf0QTH2Q1Y6ozxUNRYtOJWAvaYjidLFRO0xk0lh6AwX0PyhM+XERIi4QkA0GI
+uBWxPhklZsTAMjECy8tXP3qohuFa0spF2IiMEM6z+fbVficr8F+hYn7kcfSvTDP/5A==
+		]]><![CDATA[
+		NuBPX6D1pj7rt7DFvF9pA2rEluhjf30RdW9ewYKkqhZn3xBH6dLTmN+rLfrFEtNLx+bMTHg8rihD
+Dk5BBm0AUrMY/dOBf89oeQj5F7nqlBs1xgh8xhbJ5JMYozvSAXySI+rr3/wqy+gtWO6QZEM47nuW
+hXQg1lgjgMh+ixjxRqqvw78jfhrly0ttH7hnEn7egFsrMkNlOZWcTxjv91UuEuX4pRNbx51X21v5
+rFSThgl+gxZNMi95T6LOEsFgfIX3Hn87y9+iVhu/kfLFANmRgW49xi8Xl0We+R35m2He0+tvW4mr
+vVmF4A8f6m17rUKQGHl07Xm5zUMt/iQXF/u1Ap9+7beoyfad18Q/rT5QqPjme15n6oVwi94M8aqi
+n/7UelM2+XudWn2qqw64IyJqGmKcUMBMPjMdvIr0x9+/P+bvc3KNLm7h55ld8uwc//EJkufBRn1f
+PpujWYIZxJub2PDBUfL2Z3/L6rE+e/u5/LSqI531N4+fvORn7Nchfp+9FQrXxj2UEewn8LShrV+3
+c2Wmm4wH1dLF5vEsP8Nnr558FZ/Rf/A4mnIfBtFp0R6hOZbn5ZTV+O+In4b5p99rb2pwf5LdNvJ7
+u63U1832LHkmeXkzou21mxvr3nTfXMSDLMcDzTZGfJnlEFnKA11nj4tiDMV3X94fhQvit271HY3X
+ghVpqNDrXK5HxPshbovWLBVhP7vWvU7qu2Ln7JzwrEsMc0/ix6zk6kq3ut/rM7JhllXdBddJcx7h
+l0+3xMh59/WRiCN///4Pfv9PQ9nTf8KuRfPpzfx/9XdL8p96FL36Vf/sfATz7V7/x/RumuomfD5y
+iJwVbT3t97ciaebpUgjWIqO9A0boEBfd41toKaZCd627Oc8F561HBjYoS1yXyk7Q0GNFIzO0rOCf
+q5H4JRIc6vHXBLHi7EJA6JPWtrffw990dh0BwsgsQISHSGr9dv6fRF2SvArTp4Cqdp5TSRxqoFsa
+0U9oJHGqvpG/jPO9fqF4RzNLglonnLijjtyKSPzk2Q54wU3bHfQPoVfyS/hJx9T0OJlG/uawhwYn
+IxAnBSLP60UR5En8PqbmHOADPR89Kvf8HqcNycvLfTqvzVxy9rKKczM7uYP+IH6SfZr0fMifh3k9
+poIW4mKEAIL0OZiE5bk7uWSMTT7ay5iOjBHOwqP+LWdyJ6JFLRa06Ul7MAUhw/bpZeJo+8M1/BAS
+mDVRv5AlfNhJJL+5P2MhM+Nkd0OfgptvaFxHvLT5MOoAWXK08rx+jF1L+GOZNDUf/MZgOR44alJQ
+MYymqm0MyqJ2sMsN5x5BPfIWTY9nDdH9Cin3T7Juud/uZ7vzeNrDIqEeqK/eFFqvLI4wVMaEdkwM
+444p1LWZuF19kR7uE6kabZN90kVrCOfnh7d2DVj9+BUNw0DKM50Dbrlnj4ZdUwAZqasQfQ1SVRsn
+PVm90OaTHElqh2KXOcbCCMwcTjFraKY4EO6T/PwjVyuQWYOCsup4nVH3DpLPGZ2Vm8rb77dV8GCd
+QgHwHsVXyIfbxNqmVRdbOw1/lqc2KDMJZEWTAn6ZcncUB9Gs9x+7RxCJJNrvNI/xWeuoRlcmau/Q
+6YrfEBTFMxq1OZ2hdbGZYmJbnUZbj9pqtEpNaissBaCpKpk3V/OvCk477+EQpyD+wOleYE3VoaZj
+Uqi/g8u0Upuz48cAevasFGsZtp91h/loD5mK+Peni9/2899faGa1v4weU1vVy5OkU69vD5Lm2dUA
+nJze18mCpTBqRJTu1t67qL0Y39e6x6qRoO6Bp58yHG4M4IGqEf3klzWZZ/c57Ut8SWeP0YHJv88q
+30QPMRY2X7Pt2gE4Pbro+a5NjHNpsnuVkApomjiqegiWWAI88pp3ao4X0G/VIPrHGjcTAxucvDhn
+CYFR9ZSbXz+Wo8k9TqosDjtVKHosCRmQGYuwcv9JzImyax1fvHu387G/O+f/USicK142ODB8N1o7
+s6JW716iC/LWc3atrCPl8WzKfTwtX3QFZHe+s0bAn3ysOCy0YnfAGIE+uR4e0RD7EnYnp3kzQotb
+BEEFCx6OcU6frRLd5wGs6+vgAIOtLZF/dH3Vs61W2DbVaV7i/OHtivtU2w1ZWQ9r1GCnAdetF7cZ
+BXq0BY9zDSypbPrX9fFhJuStjpvMhcq6igOURTjjNIpT68snUwxnuJ9DsvHiEqE5DtOQDa3BV+uX
+OeZAWyLuQT0YF6ksyhKrcGwRUSBby+a8uHL9ZEbI5Bxlw84qfmC1gsdq4Rs/CdlRahBiGOYAT2Pk
+qHjmj66bEB0tvebD+AF3fTuFsEg0sI8qr2RG85QR2SYt/DCKuG5m+CDWcE/08Lbfns3f5TQIxzLf
+7NhnlQ/+LFW+ThvAkO2wnl2sBq4pSGLAX+24AnDAcy09fiityWC1ofpjAly46tP5UWZ9/cCoW8vP
+r4BYOO7dGIGeCAii6Ucdf2Gy3emrsAL4FSNobjW+GaduZ29bSX0LX4zzT27kp5d0+ZvEXXqfEe5N
+LhkftKuFYhl1nsgvOaUk51Lp4i3VaYaDrRMFa/Qzn14GkPx+FitlVC01/dLyWyK2rOQlfsxa1fb1
+LMT92nXr2LBx9fNhyb8pXHqHbw3AC8yPf71Yixe7pkAf6LMOX6IPYX1s7xSC03dnNnCPw2ir+sMu
+0dhxOP+9xgh31JT5MkNmJV9P81rlnsL7D78z6rdmALOmyYAWk+pjgExueNbzP2nhzRTePvzusN+c
+A8jsaEE/9Cl23eW593WgzlCz19Pax5vlvkLEpWzNFX2JWa9mF/L74lPzJdL761FyBdten/erRXZv
+ju1zCcvTVtkxcr73GpfkPlslZOOe2bUt5/n7s//W2X/tNlvxZByrHLjd+1qjno3y9rj49E8THN0/
+aWDw9ImZWV3+HubDUNOxd+Xr3bbujAS+03IgTNeoD4Q9Ti7/dDcymCtamCQvUoio+8N43WeYL+FE
+UdzNgrvTrsOM/y9vZvDldD9pxeJETCScVi+yoB9OYQTmZ3S+8M6vEcefTsuCqE08/WZs/SgigDFM
+ji6BKFz1H0XfkuiWYk0oveVvuxkBXwfR6FaW2PmzM2r+KpvH2fNHKQVh1cEw1CEtaOfbjEupb8bW
+j9a7GUQKoCNau80pPcYrgRCKT3sf9RB7N6xn8Zux9aMoRlli9J5RCJ5WTDJZ004fJuF81+gpvlI6
+37TZIBTv+Ka3GLhIb9gyvbCa4teZaIqpXl8JldxfYxv115V8Sa9lix5haesLnZ98MzITRd9q1uQX
+DWPTOPROG4ESH2lrpI9yuSQONSI5xa8BiiRVw/eusVfSYv/olabRK+YMUkE76nHlfb0TKG98JnAH
+4hOV98X5oQFf0TCNYiY5lu64d2NOmgmCjDGTEpt0eMPNmCC/89PTdWvhAiYTT7d4+afjopfYcu3a
+RP0s83uCvcdnmNpbHy2mesRnJvDOptj+z75984m/qANdV/cZa8s+Y7OoA519ifjVtLT8n8U7+hXt
+M3V0pp3eIQZfuald0Ts/+uW9JiYGWWErq3V6mMA0i4YGV6+pGYGRbqnIWJf6NNthhXFma6mt6wga
+zZkVGKco59vw7BjLk1DxhbkJzWE78qo5Yg2e5bMjEdwRZI/HZxzx910FjDJHIUNRfPsSj09QwcQ7
+qRFBvw4n2FrxLdP5VfWEta7DX95XeRzk/VJjjaQTKhZDfLZJuW++swVB5RW3x1EuaoW4lMt1Bb35
+yVizSMnlIU9AdgPw5ryc74MJ1GvnYIodcTjTMEjoCqj3JavwOjxChRZXLlrI2/lRTGxRBsqH8OEv
+cphJVSmbLeDALd8IkYf89U25T97rTocucx692NZmKPJjnjMYZMnjynqckZ7Ft/j9WGfFebPx6b2K
+voShW+T9X6O8/mSYGjt0O72J91f9anayQwtGx6+CjtjHN58n1jk4wKfkZ2GA6ZbLqF2zTJvsiNiK
+Z5LWZLlwK8beOpcqIEVr5zfiu+tbGrrcnvYnOs4rDGWB0riAShyS9SzEdi2tp2WuT/FYcXiDuCJf
+lCj1rnbmd1nq1r0u9vzpSbKuVY+zjnfjfa0hQH2utXPVtydF2An9bhe7aC8UFp7/6d2PDU4Qz752
+nc+43qjaelv7YC52tVi3Nx1a1we6Bj9Sa2Z07K8tsEq/934LsDrytWcqWzoDqCB+0jqaxePXnXq9
+9NOnsT5rvd+aeG7JhiirvzOaLJ0fKkWf/On527v6ljx7NDEOVKrachgXJQbf40n8NOcvP94x7ZD+
+yX/81S//09/+z1/+/f/85V9+/Ei5Oaz3v/zB//Yf/8b+LSf/x//ym69/9qvHb/3hz7/8wy8+/Nc/
+/eVfvgdfe1vw8jt5s+gX7hjojWOlyKHaU4zj67HHHhbzB3+YRfTreP6Pc9z63diT43THfRgwzft+
+b2vM7g+rOH3Dp5mbpDR7iEltZ2/iAOFW70MMxcAKGp1vMBSNlDyVwEDQJHnUSPAnnAcQuTCLDkGo
+4nrEa5yfFa8DJsGIlWRvwby7d7T205t32i7R/tzON4Mu4s1AH/pZJsf0JohOQ+63AkmFFuj5xqbw
+cfR2F1qm/rOWvLfphfwhzh8kLB4neOz2qmEfa7NT+DDGNEJcQmt4VIqWUFWTRDFgWwvYxi50rY1r
+BJqj2Ea7K5BqfD4eXmItCmL63qwcxmZvIimwXFqjGd16U/unTTA8mBbmh//hzw7vVu8e9PSov2Xv
+HO9a3AXDYkjR7q65YcxVhgORgavUPQ+33czyZHdyTlqY09ERssRkzyJd4Iz1dP1GZ9Ei+N7qZ5Ea
+Eb4pV8nSh7A7Y6g+z6/18MNa5cMrdsqeZvGsGdlSmC9O8IxRW7QMQXtrfnfU6/hy3EgLqc1mt2ja
+TjC7GnPzln+0AXaKZuWIHlbbERAup1/E3nCkEoTWWooh2xUjNE+sO/TDqXnxc9sjjds7lfgAZClD
+92gcBhwgML5Qf8mVDz/eZrnQ2jr5T43YfNZ3PabAfqabxRoQIuttR/duzlf27kH26cmpLwBqP9xy
+kPbdnr39hJNqbKTOhWeGfPKVUml6z+EdFHYTuGOn6n3YTVjVpmOnLHr1XZ3JzD9qaX55oXizlxch
+/K08zwqQfPiO8NfcjAlXCaGQmhxTC1zTNYUxiqC21UBK9lHZYZPL5UnNGKDtphHAtzV5GqRUNldA
+2a3pnMsf3lUitT9wMCQnkUUEar7EVVDX6lQnjz9MI0BiuLadIXAD8eKpux2NyDbiWg5NwJXSzGDG
+WbDiNLWJDL8oZnWg3kNnplHIljLWoFMwc28vT6V9DntvWhZ4H3BGFtfmpkXqB97DseeqSCsIU2DY
+uqOIXkuq8gUOwvMNy9HVz8Lhtk4cxsX7nuF04s/BKPVWL8A+rK3UcOXx9pgNTsTPMstmV+c0I8r1
+G5ClhTiMh5MKWvQhM96wRrvyTEWdyMuIfM7jjmbYWCBIuMVTbRENV8WbeX3n5O8IwQ==
+		]]><![CDATA[
+		sjHeLmrrYMe2j7qbV2kvb6zc6zmjea0iQKR1IOiZKFOvk7z7Coy/JsvwskjT5ElcF0Px3jvAhcPp
+ONbwy+icxP7RFxtXaQTHOa0g68cCbIvmjeFOxHhw8S8b9HDrll+nUXdxrli/HVokf4u34MA1AuwR
+7YfVl+4WnddmbDhAHZXfRORV2Ad89nG2CJjIGxbgK86Tcme/NZt76te2H+4QzhkDDIKy+o7eRGhS
+2Davl5X92rMe6FkOPdlPEacjNnL64aXK9kguTd9MvlzIUrKyF+K/d8N+0sXrbM74iGxgAFlvXVrs
+8fcEt3t7gvh7PqhGX1h/3hNxEYbHZTUXT8ZVg6JpA65RBB8sjut5HEXde1rYEnaWqIXExqBaDCb1
+WTG6x3Vj26BGJb61RdysxSyjCK85I5Nn4BR+hR54yRwXBz5ZmURWGjc9rb2tt8gzXSuJpcP2fWnw
+RevafnAI2ZvT++IA4CBM2cXtgfhcnHKjsYCi+5VqsZeVueQGgGuxFNNSy+fJg8sWOHetGGyGwGKQ
+9SCIB7Yae8jl5IGF0Nm6sMXylHBMWd24J44x7tRYZqQPTUCmNOINS8b49M4GuL/zOl/B6lLoQVFf
+U2ccrMk9Am/kPcnMI4n9vCo75eC6SmymsRj8sisoLefOh9e0XFjdTQnrmE0XzH3xS2wDBWIvvFls
+6YecUJ/bEVyfdPh534e1HH1Gw8T7KzyEBsnkdgrhganhnnTyz7Wj3xoufd9RuKSJ1dmZAKBdLDcS
+t0d2vgm754kTbZrAvnGTxM3ueWN0ceoZoM2O8a52vzRszfqualNK5uBd/VQNdFVKtnl3cV4zP+iY
+399I9fgURpAdw7pr+yLcmI06HDu12I6LS3GUrR3ycjV8ZszkyZm2g/VrnFbdsPQbzMZTd9NlJun7
+gP8t00zqD7Ps3G7eWgQmOvHKuL0MI/XwnrztoGtS5sy6AXAAZFhECKu0Nqe1eyggm5vw8HLUMAdf
+PTWufXMy44b2UwwLmkhIvILzrWPhJh25Lzr49MPMpCk/tlb/HQju3ziJoWSCrGscRVhNgWqXp/0Q
+skgIxn+KF8QKWjKtKnG6S+0uxvblRh1nxv5zCpw1MNCRULU8vn+kNDsDzubpuY5XU2/rUs9XHqpd
+R4pxLE338bt0G+yf39PBb1PywzZv88dz7f5lqJSFAsOzM19hKVGxxJRv50v8KiXKtipCW8PDWV6T
+Bp+9JDmYxU/5PfxdwxulyYZdU+n7IiNmeRV3LiqFactFvUfAZWiHGVagwzrhI9Enh46by4a4Eg1D
+fwYYcgotQVc0BZkMye0cuppLECQ79zjC8fbDq/cFNlhIIMg/VExjcCAtcswjQpvwko5MxdnghVS4
+F9PU6shOtIRP1Os+B8Yqsv2aYXbhgGaeZldgQnky7IacwyuNjDQirN6/cicC9IdfBuZ8n0hHKv18
+AQbvVvGcnP+Q4hc4Qdp4/izz6m4GcfXKHzvk6lD0odor4cJMNWsZhV9vnmnMn+3gdlPbVouA9KyF
+mMrksGZEe5xin6BG8VCTj1xypwqLl23s8p0uWrbt9HBpvmNDezdeNCnTfZoiCMTR4svond30iXRA
+l0cCxEiavOFaSvLBcXdu+apmX/rDLW0qW31zJrq0Vn4W9PA42LhBK6wp3GSIu7AU1PHp7Rxe4V//
+8Ac1pQ8/+9tziCATuixFDgMbTQM57xx7uhhFxkePSmYeHm3KZx7eN9GiCSUMtxWxqAMghxVQyvVT
+bsztNbmWHgbxZTHwaN9JPcgQXfbdhHjG3FEu5b0td7mCktdcA7+e2Z5pl6jvfPv6n1QHuGRwTEdg
+BzKLJGewiZNA6QQHw87OS2GO6mh7OCk1XHnLbCq8/HCJVV2lw2dGFQqEjQfK1YQYWXbHU9NU5trp
+NNSNxt5lhDFDGBGxa7Ln9wGy8PYuFgvPYlV61oCpZnEB+VDZEZPbgoLr6IiwecmpOFrMOPeJpZeJ
+Y18ZnnvkEVgauIGbrVp+zHvk8KeAPerjkn3W6mUc5X4WZ0LhklJLsyOEbR2+1yVG+2U/zU3zJ17B
+mgY46Z1qsmRefKbEgyQzyjaLWGVwupRV3wjtM8cMKN9kePEf8yajl2LffgUZvG+1G1wG1peLIRZW
+bi6vHfLfYzewI3zSziVeTtDqvzZb5bq0CuP7+0gW30chmevZLE4tcwx7/UH15vAMZ/imhtdsjPbu
+yrK70I+EEVpM2od6FqAbb5Vmqaa9XoRPX+iS79j2OLfG5DJXI6d3l/lfBGtGujLc+HuPpMLj3e3m
+n6B8OVaDe6rSvbZIir+uYtMUhsrJJHQ/XNyNeRr1EnIKsSIpV2TuaVg4Tzn15zlIGCr3+V7Pnhe7
+Rn2rhc9+5f6llDG90y2cxHDkLvFpO2r4sUqhWpBhrea+LmEcjsVpX66HH8LhwfFr2EvoU4gBjthi
+DE+j7uThm6cpSBg64nzvh+8X1rBvtPD5LV/OOysMwDyiWh42H+zq4HjKU1QmShlC6J/XkFRZ0H4r
+lvCyiXbC3NNtT3Oc4mFER71KA314ugpFWpHwat1rURzJJ+M9OAIqwTyrJ61R+m1AgLUr3zCmHbuw
+hR7/mz/G5sEoEthVFW5mw5jnt873GzqD5qm8OCCzHAVyb5RoO/offkS2xmqDXctW0PdV0p4mq0gj
+XIDWbSuQmiotZnN1BH1zeKeofl1DHETMwiJlvCtLKKy/LnW3gpMJNVTn0qQ/CbcoqSpC2asUPczx
+JEtpt3eYObZN3cyUGOupazoV5adLXxIyEAJoajsjBC6sRvEWHH6iwkBntU+F9aXFH/KwEx557Obf
+oZnNbdnn8IwYmxGpixu8Di5VBM24W6fPtWr/I/jdtxZQKmex2Xp22C6bGRjKdvPhovon31UPgxAN
+wiKpxIbx+NHCz+U93z3TxBakFsXYBA9eBLj4pRxhjqK0VqmkZNj0jGeLMHK6Cx4xAW+rgx2irz3V
+0xifmKQOliJL/NplpDtM7ysRu4gdKTBzz+H4ztR2ZVc4q3Hu57xY3oRqNiEEZhA6wuuvXcv45SP+
+8IJ5qLnnHx2R+Rbh1jdpuHICpkngpHfxSv/wZ3/25RfvgZX+3Z/g/9x2+Hd/YsClx39FveFfu/S5
+ABGS9yBMkAPE9O/+5KOFU2U4YIk/ywzr3HimkEyq2789RM5Y5v/zM/9yO97+eswiNyqA8MGOyLtn
+4y+PDK77VJ7JBhtpfScQUz//U7+pqV2PxQucwe73tL/85jr4+U/VRPYPf/b99+8+93/96d9//qv/
++quf/+IvfvW3Lx1n7Ss+f9Ly/E1lUTX6NBYB/frmXwycRG8HsZLFIFdiga5RdJV2CaVPy0eN9vz4
+2uIJvwY+Qs0jxjj/Mjzxcw+MeLf6a8c8QhjfVdO+H79e/Qz8Vh8//IV/sjbBv+0L/+wv/v4Xf/v6
+gUEP/Iad7tru+Ykl8kYnvtYX/yA+8WVj/77b+vfd1L/vlv59N/S/zO3Mz4u24eX5SzZwnTyXfdfv
+pkelEEs+gNIjF0EDdWTXJVgDqoe6VlNTTgnj+z0u+vn0MOKuLEE+o15CTSEit5TvpaR0jIrPlFnC
+rBlIdj7oGE9Pnpc6I75VgPt/8Pnbi/aOPk/RvOFqPRk9Djgk5JYZmlr2JTnR5/Ae1j55I9s/wgtF
+M9rTw4hQ79Lr07CXUHOI2Dvle4nuI0Z9GEbfzf40AYpCeT7X8+B5pzPe2/eX8lDr/qw8YJRelVdJ
+BjsdZvH1RW7MYDRsUXRNWpVZqj58aeUWHgxRWU/PQhsPo648DXoJNYNQHeUbnClTaDYbFRoRPk0T
+kOwor5enJ887XSO+VYC0l9p60d5ZjEd7JyM9wXry9UV+IXLMG+2sqLCWnB8dAbZ2vYSBiWF7iPOw
+JWLazk/DXkLN4WRtXA6M3iToQcMiS72pgphDCI8KbcL3w+fVrmHf6oFKrHHUSYct9Tc63DkHFCQq
+PY4cvvLS2Verl4B4maDPftZRj+yAimra96OWRBqWNoshL5l+/iScXA6UrLCoGhQaGSXnpwmEMNTn
+k70fPm91DftWBVJfn6/6O3ta+kP8oDE1lPa4OEMoNzLwGgpc5kBZHsV9a4CbSOZIYSBhHkrqTw8j
+fewQsDPqkWkGVKHEgOgIi6sxoRS9f0wghEeDNtv74fNe17BvlSAN1lpfNIikwqsG21Qc0bgFv77I
+4fqOrgukkek+BTJlRbmAhKHBVFt5ehhZy71aexr2EmoO1GHILYHpXzGGHUisjlWe5hDCUKJP+H74
+vNo17Fs9SIm4hZ6VeA7Ho0T210UodQT16pGDEqsPXSTNuZ4QbyLicEVjewmpxIBunocte74VOeSw
+l1BzCCUqHj+j4UgMC700MhnGHEJ4lGgTvh8+r3YN+1YPVGJ5TPVZiXWzSfdR4lCOwnoYRaBbYkRP
+CYUEV1FOLG7NzJgC9FL6uIRUYfaUx9PDG/HZ+TLsEWoKHCHkewqFcYaFVjLt05hDCEOFPuH74Xiz
+a9Q3SpACocxnBb4xpMPetdD9ykeBkiNEK/111Z7uIMxrniijLLT38CyfHzU81873iJeIPx5QJsr3
+DCs+xhxWM0EzXr8fwqO63l4ePu90DftWAVLem5sYhVWvyiOcwBASUQR6yZNHyzmlPSNIu/TpS97z
+ElIDyNOl+vww9gwT5mfYS8g5HACNy4HOIIA/hoVaquinNIcQHh3ahO+Hz6tdw77Vg3SY28tdct3P
+R4mPefEFDCb59VV+OBehjSauXqNl+2gFeNsj8BKGEssuz88ChNTq86BHxgmEBl0MBBvcgGvIAdiR
+ShL08yE8qRab6/3weatr1Lcq+CxO+fRyjTws71dnDggqgW+QkPn6KrY+UbpFDOvtsQiCYoB2JxMm
+hT7/Zenq+fwwIkneVO4a9hL6FMKXphhYXlZQxajQyiDnYEwhhEeFNt/74fNm17BvtCANjvF6hxz7
+5miw9S6EAygqv77KUSLYdYtMBt8fxsGqIi59XFztEoYKczCi6mEgTMeoz8NeQs4hnELKtwH4pEMf
+Fmox/OU9hxCGDn3C98Pn1a5h3+pBSmzl9R5BBemrEq1IznP9uJi+vsqLwmaY0tiMM7CPGOrE0j4i
+KnCpOVQ8aA7ZnE8DXjL++OUTOkYL4QjPVmtMgIYX2Qv16yE7uhseTzjPnje6Bn37+tLdmyv4mIZS
+HVBf3P27BIvGERf3Nn1Ci31UZnApgwcoWNFMGMpjudz1MGDnAcfVsJeQUwhrnHIEIwdNdw0LpViT
+qXsOIQwN+oTvh+PNrlHfKIH6e2jrJRpY9nx16JazcFtMOx8O+CM3f4nQiyquONSZb81+OqRAQmpw
+CqZxPYzq05Tz86hHqCmEBiVHAZDnG2NYw62zdjjmEMKjwT6en71e+Iz6VgtS4cwvIcHLsj4q7F4n
+ZFfchalxqdXdlSA634vMfIIbOCvhvIShwZTK87OGOKzPg4bMfz78GAphYCzpzgZEsQ==
+		]]><![CDATA[
+		/VSyRD8ewqM6m+n98PWmZ9TX15fm2nyJBxa0fXnV3BqbX96wvl9f5IhVilcRtXuZtD6dwGhkYR0i
+KiF1B8Ye5Zr1MOB6pe3nYY9Qcwg7XPJxtqqGhVZqDwJQn0MIQ4U+4fvh65XHvalf9CAllvoSFrz8
+EikRuGFh+awh19cXOYgCSJeAOS0VutXgVDdcfcioQmBrRJTPR4Ew8/DXNeYRagJhQ0o+PCN3j4ps
+22aVW8wghEeDq7fnh6/3PcO+VcLnd0FwbxKdH7+R5nyS/15Jzo//6BTns/z3SXDeE/790pv/IpOb
+/42EoPnDNyiQ//Bnf/6rP/sFGEX/6oON9Xf/uz388D/+7//0GKOhuLm0x/WS4j8rtfTJ/jP/KDeX
+5ZF+9vMMPqPz3OPP03v/Kf5fLb/7r+mP+Z93/ryVt4+v9PM/fv1TzIp//i7t88nn/uCCN4YIR3lt
+su9/ldwSFQ4vbU0lDhfmdBcFJITBdH7GCD60pUo849Ljs2SIeJiEaYgloXilqBHOxHq3Qpmiwr+e
+olDGG7buA9yDdZ/9KE7eBOdTZJFb44VWSjDVLI9E2+s0FXRsJo7ZuSyC8Y+7y9TTvEiWJSxeUL2z
+KpTfUeQP7ZiPiGQ+nIT84wve8LOJzqExQn2VlDA9BA1K8GvsWVWersjPUnWlYXDP7bacsMcxsD2i
+IawEkV2EzzGzyo9Xu/68JkNngeSiUkVFnZZRk+zdkyEkRxBqirEOImGUlhgVvMe7ZUFY1ZW+c8fq
+jQJ+SMHAYj+u6PSPRVb9KAzVp7/91d/93Yf/E2fUe3zFr+zrvwt/cfVUl5mtPUdYgpUWbs12D38g
+heM8DXufLhXRoQRm2toX4cbOWUU2BCCjmIklGwDGJ9npzDsg0H9Vgp6FV70ayoXkzUSjId5yL8Lo
+aGOB8Kmfm1WGWXFkIYgE1KxjOx+G3/M1Cs9VHuEp/VxUq5/98isq2DI9WnGW6TFgHxAbYjfU+67O
+f/2NbxEkadUDY3b+9FPDgxhK2gwPNLY0QFFQEsp7s6ZhRzcqi2Kf8GOJsGSJ1iUobXZQMiiAshcY
+mXBQWPaKGsKsI3dF4n4d6PeICiu8BOK29hLW1OHoyF7C5D0r56MEGbnB3lXDGeFZHoor6s7q1ExB
+MdfVVnpHNwvLUIZr2Cjc3iPTlpB97BN0m6LRSk22aWOvb6QPyF+1ghwj+cr6FBETMtolz9NTuGUd
+s6ARQiNBc+GMoBWKZPzqwKpXv6XpFB72NcT5v4bw9ZvXV5iMjO9gGfAKtXL6wttSfEoWAZMj0SON
+iffcMu30Do9Hq5yOPkv8/fN34ABv5PpywNh7oGkzxxwcy5PTy2EigHWjq5GqsLpg9/CgiLWxiXAn
+qmS84GaS4ZPnnX+7SdJrF3Y2/1zeLvuT1ht78MK304dG1XRY1VQmfiENvl/dJ2CF82YuKS5aRvAg
+NPKZXj68q4cY4UUuze2otB1u8geHEtn6RngCVnE6WUKnb2UFrrlfwk8xADsdPz9cg2NOw77OIA70
+Z3HMGLWjm7UmAzCErzpaqKWLoQNBVWeVMZLtFECPlCk8LclMPOoR+1pJNXGPJTfPIPRu6MsiWfPs
+8l5L1PB73QL2Xe+EpcjVtvivf3vL2X6KqHBV5Rt36HbeHH/XTQakNwo4UKNneaisRMQv3/f2LjKs
+QLRLosYcTuDDlMpL3nX0H/Do6HllX/M42OrMsZU6Y7m0tpbiGn7c7RaHArM4Lp9LD7MNNcKZ0YRL
+xOg4wUq/wnkKczbnc/Y3K4zcDrj1MijE3QHfoJ1bjSD7nSM1byrrFKo93ls9nnvxWX5pPpXBOm7D
+tsVdbEerTSVi2FMcccYTfVqisUdIcwskDkNiByTneZclXEQlGctGpnCXvM+Bzq7bONrZeMmq5FQS
+a61H/VKRPbCtwfEJAfgA2xn/PzIZ2VlAPfcKEqY6WA9vOc7QW/LehEbgFUFDbjkIP7yrxPPnz/K4
+yXd4gajZDDgf5Emhs+jyt7gbjYOzSwu8Naw3YdwF0s0OciQsYGoX/U+GUkcrmB0uvpKlWmy7ZKs+
+cPJ6EkSQawiLgKA9WCTsjnGXdzklv09fPmgLkB2+kzM4blY4ntyVl0sZYx05cW5tTTYVfavCs+Wf
+5aH0ETAIqC16iMMC3jKLDZhJm8p7DcIeL4GZMJYc33Q1Xx0fzZx+tsLLtdLMnf61lrVoAdsxKYIT
+AwiL3OIa77Qa7Q4+Sk6KmibuQjBidMqM6OzdFz42w7P8sjBVS7qcMy96slRn0INpvrWGineNw8Wg
+utPHubGdyAZ0LkFVh7pBuiTNOeg/Wvg38UZ5nIwkhUVMmIpvvkFjaernUIkULLidI6xj5ZZgrdz+
+veJEkkm8o/rculx0Lpd9Ghu+qCFGeJGHgXdcq3LzEiBJ4F7mulyu7T3p7U4hNw0cf+eIMrbCHr0Q
+m/sAS50yXDYIGcSdncNqZIfe6edmXD+0U+IMhPnQa6BPooCRtjaos04uCeVoTowAJi6xKCwRI+N1
+ybnzVgcc4Y08tAYIgsjrrNYtzGJvLGl8buyd1UXkgro4abKFpUQ2wbi1OTDKztaS2uhAo6SdZH0G
+6fZyu+xZhdA7z27oWPs/e1WrZ4FF6DDUXQ8X1sUUMLwjBOM3W1V0VpLnb6xK2jdqiBFe5KG47mWY
+piErv/+qbcaLDCuLtsaqogVADZ+2GSjAm7/25UHjz/wkm/k0KM2sQTEVpcicux+HAa4bpES9a42I
+o5xCB5RLFWwQ7RDVHrc2lgsbeexw2ZCJJ9tKduJQ10JSo+cet651GU4kEZ0pi9pFYKHqGaN3tcgR
+3sjjfOwC6FnY4FwhIKNT1+pJ+j6rlV7MkFswiavFyyANmLuu1eIHmZUJq7GxQB8rrEyUdmc6cUaw
+EkobviEn+6K52hm4QIqD1Cp2xQ91ZDsXb1XMyPo4x6Ekt74cp3w4+azHXqLtuImrxEkup5ZjEaPy
+Ozo8WbNn+X0rkay525TjbGXsa/GucUXowM3OB+0fVHGh7Fv0kz70csYkk4unjBvf+J5C68VbuGNu
+JQ5XqJ2si/VsrRR+VvfglYxckVaVq08vev4NmlyF3dVNhVnErnJbXrVw7qQncWgtx8jbL4Q4I05g
+m7cPKn5J0OoNIHwfdZFPnpMV0iT7W38Nd6jIbNzR69uLqGGn53FdJyxEhr/ZojPvINkKWq93XcIC
+kCerDPj0csCYuEs3DNMYIUq0i35RQJxxL/J3ux789kD2H3/506+/+LtvxbAB3Vig5eZ/jbROYmnV
+Hx/VBhfXTqTwyuhC8FX+NONrMDBJHYLIDB038LYkCR0PYdwV/YJ5rS4UZ/B4Pzz6tejS51qCe88b
+3RjX1qm8ahGd3Qew3K6PYdxZHy1cQv5dBBZrVKsD7LPF/qOoyK7KI+EL8eSzCLrWyLgD6x6rtngA
+jSGULzSRJImbAMKprWYp+JgCVWa+eJEvLn7qh/K4qBGMXik264GMZN+69nOqzzfSzyJ4mBATs3b6
+DyMI1T29oFYMi6EdYzCl39fX0ABsaLLZMT6ip2OQ1K8KJb1FpWGc0pHgGFnoFgs9fpLXRF8Fx1+R
+2zXoF+FCXBLWKuK3i0naHLekmbHxJczLTmeABhsI0twPqDfngrGtJsof/s5x6xt5PTOrSjECgXCI
+DtUzgAXWTRwY9xUB2XxCwocWMd9MHfCph+hgRK+MOHmLHK4SAkONVBAJy7GWVyefOL7ziWCvwWCB
+SGbxsksJhfoE3BRr2zqBqa0tthnl8GFXjxwBSjfjHViYCwxOUazA7FpPxOwIBrtqgc9sO5bBdEvM
+oYclXtfuOAwapZiDHYMsV3xHINxiNcLU6SkccTa5i9VDyOYSe119FZZFIQX17moUDLyZcttRh4LG
+lIOg5t5PmBO+ZCLgfs4S4T0nmd7odS9ZrZv+de0H/tm+YyFODhIsuGE9VSlmKrQyHGXIEy/+fhAo
+2z31qx/r24UWRXOjqy9V7vW2n/xMlpka3TyN8MSaayvxoMxak48MMpUVdyTyLYlVvuN0jEnJX3d5
+esCFuzrWeToVR8zALFanyT02jMeK8Q6lRSQIa8rx5vlKhTi1yl5xHwOrNCoX4mTXHIsuqZbCag4+
+6ZJ2gx3yTBJhs/03Kwksbs73mo3weGOz/iwlGE5iGABhSWFOBT2s08PLn2dvUhhWQl7qp1C2zIzC
+xW2mCc0R9gHZTmtykkmibNammTvW9uCNMHFsbpUv7isfonN+i0jUvCjvT4X2Qbxs8eQWRbHZ+J8i
+J9MnF7dVWtDOys44jVzA0mdRttiCp/vYtrOqsrKNLSIbPbwsruCyZPvARj3pMONO2opT9SVTLw2W
+J4jsHQ9WrQHT4acrcMBPqEZNMFUncYSL4f+pZiz2sdYKV3Ko0SRmm4MmK0edj6giF9MYuOnGnZYS
+Nq4FAGdF3yME5sV4nyI1BuxMvpxZ2W4pCPavYcthMVwRIas+h0/Soi5WBus4bBZymmWBRg2UmRh5
+LJl89oG1MXDzhi0xsL0GKeirTpik6KYx5pcrdqeq4aq2Ku5nbWY7CmOyllgk5uUi7Z9bl6jlaJPW
+YmYXro5SFn2H3tTSwS6oWEqM5Nu9QUz1lG7NyJtiYBVd73JDItRYN0NeRVMY3y0xI1Yiwm3JyJfp
+KZofTAbEfbpOrmtsV+F7qcgUH4ytadjX52yHokSJrJkZDTRXDcqPGc2YioPe3wyQD4vaUjR53bxU
+3i4IIb9cLmdV/Se2R4v9varbWFagGX3ECD2yw6FcvE5+33gDxy7OsBxd20X3bkxymV60rfsTWmmM
+rCiqZiRSRNuqYQpkXb69NRc7f59I6aoiWXjssWgsBccHOSsAfU5MrQv2bKki3kyqImtLdGGPs5NO
+Sd03DVrKgxZey01RpLkF3csl6PXSVNeCkiMHCg2mzOD/ID0/wmrMU42YkzVUDUp5hPK4kJN65Fgb
+XfJoFQZfLNG0Oaj5MjYt80n870FwWJWrUMbZkOg8e0QGOKaij5vJCX8F9HnIkxOzzh0utHJbv8da
+VpWjOsztOxlgTSbdOthOR/LRi+s9hYseZyKEbOcSTjs6L4zBsh1YF7Prx6iCEVYb+glRse3GSmIC
+cVrXVtQ5Zk7xaBqh20cWuS4uo3bK7K7KG/T+JD4iSQnruGHjHMvl6mFm36EoG5/r1sNs2LRSEF0D
+XRx5/1oiOwmS58VQYCtFZLxsTmL9kBmLAcmgOs6PY6MYL+tmVVlnWgccv0WMh+yMZtS0VS3IT5UX
+OC/YumUER8zyGL8HzqdWR/cLwGj0TicUdR/AG5DdeOjwmuvosHu03UvxA3WEzzv0stYFxwcgkTPO
+1sYeMxGjx3l3OkCNCCtDAyx2wMNOXY3A1iRM3lYVufIMaBsjsKcAaIiJ97Im0V6sgjLXKlLlUrNC
+68Fg4Rt9s+v7pmUPdly3C+3/qyIsZcDHiJjD2Aan9ZgkIYnoM6BFNjF8pRbEHBZhRQ==
+		]]><![CDATA[
+		1c56ovf0bWLVPFkXg7GamzCJVWEeZhmzH+Nm6VVkRyLpx9XhzRLH6Sm4zitQGD6TxVopjyy3kV77
+z9GdNaBY4hxyK1fVyXaa+jEdxfPRAjbULb70HgHo8VWL2R6W2R14AzQ2ZobRmgp4L4t1Ojau76it
+kmcg2MxSZ0vh6i7i1T0AD3uPMYNPcwLTfVgbwfrqeWwVx4tjEwzaa6vGXiupL6L69S6Pl3IAeF2F
+k7XIvQurdzR/nCN+61ufO/atSu4VxgDsDmFcwf5jWYOCrdFzEyasSpuNXut5BWGUigMh+WskNXic
+rZoAo3aTfkBMwIMVts0KOyZE81BjJS3qj+EmsHGW6op2cSJ3EfuJ2ASaEmCrilBmqU2bwXj5942B
+sMnCNvZbYFIMfsKOMR2GaOnUuzMhW4IhP7GSdHha70ZnQvRKlel2msIZcLsX1Zq2ITQ3vTFLxfgr
+POaalHOxn+IAA50RmAEjTgfC5XS7hqY5rTjCSjqmprfNbESFjbomH85ZROBs2+nMWTKsnxm1mLwy
+quipXozT46QWu+fEvJGzyU5/Besw4VW4BuPpIqGiq2nIrqV2GMKZgmb19Pis10uwj40VACTR9Nc9
+1ZKDpy2MfhjBoUj5KE3wTPvw3mce4ZseW3q6ba1k7zkU2DdpetWFih+qyoU8Sma9Nru6RBioIT4F
+A9Go98jkpinfFYW4WlkzltOWAYUa20/aUgyibp2LvnizYmTBuqTo4/A2KKHG4obK7t4K4ulDbA96
+8jtUtRDNUU9vDFeTUVw3CGw/RNEZo3zQIXt6Wk1IVBTvE8guQupvg76c2hgupaSQefMeCpxAUqMu
+IG4Okw99N2saxu6LW7c5HP7T+Be0Km5pWHO8podnwF7L2mpjq5DDuBhxIS5iUKludT+m4Cas4sr2
+t43EZxbbOL/OHrQk8/9oRSduU1kIWG2P5KVaq+jT98NchaIgFyv/EJHOKgiemymKxoC1xfPgln+K
+JFTIU0mqin8YYQwX1xHlRc4hbVCk0/Zuk0PaYjSMY++oqwVOpkSnKX/VswusbIZph+VtOzjiJigp
+8cIfEnVvycY/n3J9jZmuqoHMYGSli/UQ0bqiNTxPSSd+lemFhl5u6k1UmM6pJ9G1LAvraZuLUgGF
+qo6gKj4wT4cmEGe0X5yRESvexije4WFeqERMS8ZaQ1f/uaIueF1pe5g6uV5fwDpWeDKihBLVp+Kx
+ionvwUsO4bENvRf5Pq96sCKzFqk9uXPduYMo7JUHRE3hc2BGfjdtMoz7sGWr71DYbo3uDRR5ahXw
+XQj/R6FEUn/VtfSw2Pnf5k0//0AJ1B/9VFWZIhZ9LBjwEIKXAf/1MFrHlf+db0oLkzrYwA4tKXo1
+J8dH3jFI66jE9YzTb1NGJwu8Y61frFonXlk0QPY2YZ4Zk0mjdIJlwIJVy8v9VOfNhoAIQRdd+24n
+eU+nTGalfZo9W8Wi39mVfV5xFw3Vjkcj82XoAZuT9X+Lv9fFlINLBIPyBssB/tjW1KW6sI6oJsaW
+6mrKGAfoEqAMlVU7h3ApEbvGvLd/p26DZXApCtG84Twf5H5EwqeeCSjo0hQ2R+4vL17sfQl4P9np
+uz8xnOL0rSqpJ6/ZDkpP62fWtXPZVQFTQSfSOL9pcOMsZBAXI4wpnogVww6eM8PXS5weSkSiQfQW
+WmBNmQF0lY2Bp/Nl7UEOEK4UokyMntnxk3iq0dK0gz3zg5vfFwPkaDVUdIaGt46FwO4/qCLxJgCG
+9z6J9iGnGMuuHcpj75gMCIKcxLtp6ONojx68M3hIty5yu0nCAm3McCIOtQfj8dZ+MuZw4BGJ+Vio
+YQlIMQn8tutVVZ3lQGFxOmfaSSnpUfaDwKUx04ujC91etVY1rJzr4he8wjtuSdQEV2gnhgo5rSHg
+WvjoUWwwNDVxWSW/LGL6jCxYIUncOFmokx1LuQx1lL+YEnEOTn2aIo47dmwzbc9UpBXGCsB3Ose1
+nRj4Ok7Acow+EUubtNZePkTZPFW8VSUZxgzSQoPBUNu7rkGe3ghDz0DLbZUPeg+/LtJNtaqfp0Vz
+ib4J42Z4sELUwgqSKAAB42SmkxfvUMU0xi6jnzTAWnIIW4ru5Ty/Fns4MLRCJEvz8E6EXIR6HOdD
+gDGvRJlqCaqQaJWbLrsMaSjdOKkOdfxtozbdDVVomqQsmN1BHODxxNJeEPet1UBHjzxWIezYS9Xz
+HMwz74DkFHmUBp2hkXKQVUBnuMeTPYn1WQNQ2Bkz9rpwP6SYaUKuQfFmA4zE3yYV2dn24aNbPnLr
+IasHCndQM5spfSv4YJ9Uy3tR1Y1EI0h6dT2YD8XFOik0IMFZ+jCVxVsBvjLyIMoMrUHtjUBbAmq/
+NAG5K9kgAS5bWxmGNIO7GPP2TBN2dYu37bLBt5BAdMRxuYxT4TMvzsao7yLL53K+zyTEzCGV7qeo
+bc3gWFjOz+1CD3PCvfbGqV5yoyLg9IRXqcrpF/ZvB+4ov3gb2OcycS/CTmuRTDGT0QDxNCUtVMUz
+IiPV7vwyog1SlVrGGcmJTG+R9VhHy0yEVz0heEBUx5BZwA+IzkzifIgl3N3aNs/M7qoYwMMOlqPp
+AdY379OhNTsoyOWxGpblKpm22l4vQZ+BdrWiUUctEce4CiMMcEKRteM3hF2r+n4rzPtIXOykdxtp
++hpPwrJI9xSGnFNBK1DkNuR2b/ZBvoTL02oxgjX5c9+qCpkyI0wToKEq2Dv0eG2lEnwECOJ3lbKM
+HULeCHgzj7bj85R5YW4epi03g4GNKdwyEou42B8jlM5Fu+YFJfaTw7zKU95Pz6qf73DeoTl3Tigh
++zFh9sBSnVAWQ4G1tjaZP7NT3OoG11HlUK1iaCx5C1QoVGAOy7/5a3KAHE3OL9h1IDPhhrL3GdLi
+8aTFkz+dKVTKq07DrJ6+5jQnFTSoWOaxqHMgale6CFBSjeoHAU5aoNfm6Y/aHI4cWInGdTQOLUXy
+et3l1WFZ0CFmfSzkcEDtWwfNPPnhHf7LCAcIIBK+7rjPZIDas3yYoX6aK2JT9X4Jho9xTx42G1SB
+FeWehfyxLlW6BKMtQaIbaYnYG3wlyzOFr7FO4HU7iJzf8vicI12glXOJ0QaA7Bj6LRi0CBXGJQwb
+8ZO0UJoC2Nbrgl+nC2OjKJj1s1I3abuFYzF0sVWp0vQsUgMPFq1HRm5Rb5JOJcz+LooL8sF7CIld
+A4Rm0I3FUa29WQxQnGTVKhGC7qqwAOTEMoE+YkfQ7imz0AKvgsvKNKH6ebZTdzHETnJBEYHHWTLB
+rbDioyN3inp/zoMCm+qV2w/cYSrvigKTlfSowEf9VPNMNS/EpTjuArZThxXdzCIjDZN2Zg1LELIV
+vuwLeMOkOr7PnCqZ6ExFVMXl7R3cz0fBy1MNXVJJUprRK9qabVr6ZxIyYVknoQJO/0QEO8SLvQ5S
+6RTyKHBn+fkc1T0XcIVl8CkcPhS/ZGWUFDNDo78p7JExyMUAm9AG0A8R5DLC/KyB/ocwCyw2zlIc
+QjTaXTvi15bKwQuBICasxAPN02RALQjxdVmKNIfiF2iaTPICPEjAxXzCM/ZjwmrrIp/orqi5Z6GD
+JJv4in2iB5/CWNcLLHkqylrjOfeKEJCo+cqy9xQ4oUEVlkCzI0bZ1SpPeCCktk6LAJAhlqzrtQrn
+w54GcOvF1JHDxa5eh/NJI6yqGCHhJWiYSDQ6ssJdPZEjMJ1WPdijqaBhYrgaXaV9GV34xBEHDxzd
+fANGuJMs5DuFGGEvYbt2hyAUjL/gchpnhKlOoIivlCZwhix+nMBsYj2UoLVMzIwW5lP8ShYnZyvg
+yzpXCNtQHEPlB+GzIrufebcxC2pAGGfRsHCq2qr3megGPf356HL6RrBYKvPlritlpP/aV4bdhk3q
+DczEl001Up0yvMaBBg4PxscIqlYZcQ3ireKUlMWOL7Pp93c0EaEGt0zVi8sKNbWD/LSVhQ5YL2T8
+eMroGbhgkSBzsWYHQBfWEuGfo7c948TGb1L7WYnJlWvdZ68RKBtlRnfyKe5TI0KIKTDcbuCVpJa2
+anw5nzaYh1knCfJiNx6a7U3fy5qhL5ct8gACpzUr4Qf5oIuxSYRKaDU0vg+iipV4WF2qI03tgqBt
+SWXZYm07RBxIHTI5jSFgGxBR2B2xEYhRRFUu7X2M4NsZb7D9QLJhl0jZD5kdUH8EYDVnX3WhgBE1
+vDEbobC1QDoFKyOud8ORFO0cNwqnUeaoNTSLt/DlgEaP7+genTW/UWvUJJtuEL/q3yt5Y1agpPL5
+ijx8oE/SY1h/Owf9TEcU+PktKM98grl3ncpQR4vLmQHCMSNUDfuiJcKkDubEAPTeyRUoJXVY10c3
+7FqSdUBj11BukRr0xiDN5Yr+WvWvbX/AHUdUsDOPacLIsWCDezZ8sCb2owdSPLFnB2wW/w4tDEx2
+rSseqQ8x3Hj66OHPgHWZjfvRQ71uZuHJw7tvMNPKtxMQzpjiA3LWxNcoENm8LITtkbgxVfdraTLP
+K0IomEIWxgkft59GXFnlboZwHQJ70EAwrKKwSyw8ws8PxXQNb1KEC/NciP29J1Ows3cT/oPBHECy
+wsJwFtFCqFZAXkrsHDiXR+gJrem5uRiAUWWcxs5u6b/mmC6s9RzkkrULp7Xmhb+avmiwT3uAtWjR
+oDVCahqBywvNg/s9h+whXcAKU6nxEk603+UQ2m95l7R+1bAZHogn81D9luk8hNtzkPZTvk3hUOQD
+/MmKClo9wVRys7Pf9XbAGNFirnH44+VWgxBUoB4N0I1czaTKcEPHbDFAg6+GA7S4vfNB7SBxoSvy
+As1smcC9HR1w4a52EFxVF45RSItcVZxn3cH38QLKcAwR8plwqIUfEy/2HadYLO1Y+6QRumL7uwZE
+SNPCzm36tuy5jkrZdIEZD30pG3kYOG7IiievvAMU5YsZ/VEoQaUYxV17Aq1Yh1EC9YxkdBO55p2m
+WZGm6TIWLctNKolo7eY90GTd9wsIV7yvghlxLCTeVi4oK5rtaN7J338iE7k3nu/T/ms/TPQDA0B0
+/IlRG6EcZh5oGX2NHDpDiSisnEo2y9lDOUaSkIUu2726k0QPHs1gakP+QLakSrws0jiYsjqI9720
+HqaOIYPqRGmREDgz0pvDHfJIe4pLYpwE3RRpxAxGFsTXCYtkAOukj5uYA4IybUSdyIGAGwthDq9u
+Xvnjou9OULYFw6e0EhllptDXU4jXSNPVLSKPJMBRUyXWlVBWhOVhnJ5wjIVVB8380oNBT8iiFKxE
+hn1Rtfw6dYFWxsAQmhBLVZi37NBFl1nFiMffVr4q3QUvgLUebTiU7wcbUVEicYuJ7iKxbeFrpmCm
+ZOLGfRfGQfBSJzGV2w2xPnRIu8keqIyOrIPvaCoaxnq7aBfbVQmmGlSkWZzoZF1IiM7y3qh7O3Pw
+sKfVmAXjISPiyLRQMphKJSL9k/6cwWNEyoSGGU6P4t5TLxpB79U9zXlewfNjiF6xtA==
+		]]><![CDATA[
+		FErImm3QGjbjgvHj9qKgRgSli696BeCKVv7iZejCqHq7KpzNKY/g6GuW+IkxQXt5PiE5qrPH+kcg
+Gw+QMQzPEjP2NIHhcz4IAo9+22GgF2CRB9720Cn3+ApWZ3MgDF2cDUXU6E2mBxQ7NQDj7Ih2rnm9
+gi5IsAgFBmKQVrRFjMf4mBNv6Hn4apCALyLtXlVMgEu3sZUGuIwMY7iEcp4n/66v2KNWfsetC77K
+FbKoy7xBSSU2U3OoIR/26iwLqeUSQkXvbG3EFOqOezMr0W7gX5MpwGIpb0XvRq1Xw0KVGrbTmzC8
+aLww/UoDZFV9yD6vso0Wp31hasP4NLT5BwvidrqQ5nnvq2udLCjccVElwnpcO8O5wpK301mOROux
+pcHiUHlnKudip1kP+E4SioBmqPEb1ot0UFH5JXvRctu0SpbTd7mQfG4IQ54tZXh2IUq0fa+H50ls
+7tgS845zI93v6T9oklVAxi87uFMjKbYu6MhaJ+uyonRhOE+nC+msXBkAHCdLVCoG/zvZdGKeppMz
++cNaUeCsCuVIvduDREcPfrTcLBxbSDskjoteQjlM0DkfnsAVoc8SmFrDPwgJGsweS6h0c/HiDfZQ
+GbaAjYYeqvytTaiMCaeQI4eQBnLmJ4vF/fj7SWjF4F44Ic7sFAcxgMCsKWwawxTJdlBab0WpMYTr
+kA+MAGhlFQ05O+hmPFJV2JZUaQz+1mspDN48dgXEAAylWVi6hTAQCDUygBZZZDJXJbl2X24GXgXZ
+VLmER2P7vAISenicxG2EYGBN9ipaP2dAcMaQmy6Z7gNynjNofmmYWB+m4EtWzrV7eiXmsDwGAwND
+TZDbVVN6dVffEbG/spCXHIGXJRCCksTF82Af7wDMc/k/TvGpOofakh4WFPNU5C+tzxL8BzjVi3BM
+Y0QfbKJ5y2EnqWJfB2QnHVaddhU8lzWkAXrSWHUKLDXHlrltG73cjPYk0T6+mMwEaVveLseFTNhu
+v3YCkzADFhl5YLHCAytYQ1jkOOUnerR95rWifTALYo2MKrrK9qFuXBan+6QRBFHCw0kYjNkEXFNm
+dcXlvZ+UWCIOf7XfyqpdNWRa8LkImJnueuWVA9mRDpVTCcfh5JOMUFTJHAtnfXodoSj2YLlzgrKA
+w9tispg6Oi7/EXEQr8HbF6InfdfCyu+nL2DtSsif6kpEHrNIR4PH+NgP6xzWWaeXsOUxwm4qVrsW
+A2FJOAwZO0WWPYgz54WXS4p6Wb6wRUkqrYLj2SKaQw716ajlT4q0hjlqEVyXKYs5wpS0/gibVl8+
+YVLkNnyVWY6Z53hS5wGzw/YZgSbX1WbbsBWLUSQB1i4yjaoazYuufz2VgVgiJKmZG6tuLCi2KexK
+8O4AQXenNI+k/myiCwwSv6VQiQmDWIWwEYAgUJ8SI5zokLGLuLAFkyE9KyTEaVl1B2dfuIKwlJXO
+jdpzHN0lK5CeItU/nvhtRN7RIqQyo85HnSP4WwxdNGcsPml5wQJEOXCRklRHunLULqbS0fbF2qn5
+sqU033iz+rNwn1jdqRqbXI0eDUPQhCEg7acx5GyyWlb2f0XuqvNBMyROWt6vPpw9UsIQABcHJXsY
+I6NBnw/o/XURo/A2sMaUU3StLC+xGsk6Q6j1eBWGQd6IaAlmlRPCaVE8DiF9BdQo9PP3DMcZtXbW
+j7Ulj3zOYJEND7XmemVwWJhgBCJJ8AgdTYcV0GhNdARd9WWIYHs6EuanWEW6OPRxuCVxnTBKuEi3
+EuAApqFkDn+c3op90rwzf/mjZeaZCDPr8HCzFLnPkJM4AcF939XmPU2RhajwJHlg5JNGmILldyF1
+qpKfVgZR1dD5RHcK3JJAFzC+/Zx1q7LzRUWG/FzVT1k3h5PM67qO9GRuKoZrZHAa4RbB3IlUos3l
+w5PhPhZnZKC1EZluYhCqBzUiq63quBLIqrEDYJz9GOc06Q1vDwGdtHag3KvYaVDstSPkRZ1Y+NBX
+y9mLOTb5jMz+PA2J5jmQckQ9QVc0rxFUzt3P18qxZttZGDngWii/zhfEhFuc8Ec8uIPyWr0wc5z/
++SZtAw2N814YxHILSqKgSg6uqZm/u5rV53XrIHqXBOVXiv2ZwqucAeJcyVutBTJApCY7WkwYLUoV
+NGA0CWkaAtZ3UQRl4flwS7EkCRNmu1S6ZxQy0TSfdnPmiTbH+WZJN6HxFVE3SdXoEK5Dc5RUXm00
+HL6SwBjjqQ8IuRaRQYzEmGExYjewlgRycewET4ehtJogB4RYGJopgkPAlGy1Fy8XpsSdW6NiiD62
+hRNrfqd+1giErc0a5haGdRPKgEdFc8jOjzCLc+/ECIyKQn1qBBuMmBMm0hLiiBwRRmBz+IaT0uiA
+h27BUhj/GCvKls9CtwTyaW5UhDED38ie6ogdyXkhrQ8zMgAX7caNTTf/wSEjeuRIciAxngJjy+od
+kBmldMH/6DCOfsgEF+MXV8J+svJkdAcBhb1HZqXRI04Iq9cDQyDXUbwp67VMdrnBRB30qNtb4ubr
+RsaUVfsjHT7xBFmkUowrpV2h4UUYQNQSo3xx8cl6aKPhmC/Jgw13ysYGlCV6OYqvZXrDiAAHsFDI
+oCikIUhy/CE8OeHiFLWGFOsXsQcVPpWlsPSgM4PYQhiiC/FSNuBBgnjLc7qd4+4s6gom4LA1y8l1
+u5+DNbtS5JRLvNoWBagJHa8DIJ4jjmxa3KU34bPJuW9Iu+WDEmvDunpPtieSu1jEOv6csF3s0rkD
+zODXJiyTMaUXIhkmu3+evDqZXKq8H2e4qTwmlrgRiq4YwAtyvZLCRL3jVPKQqKM0MqFYxCE5bw3P
+27MQHAcweTivPJQTFp5iqhbYniTGbF5cxZYr7qKtIuO0/dpUd7VyUAviy1veiOp8SYKstldw8CW8
+0MBc6JMwr2qafK+FrLRjEYGZLVza/eXQ1GSCUsyUPzQ5d7s9uvPPwiVulBQ45+a1cJ80wsyLFkT0
+ek2X3R8MSDX81VqvCcguLCo0dLYkuj7MzNkeZVqIBsilgUKzIojOt/rUqF2MHwnyUMrdqtGqduU0
+D7Y82PtyJoZ6we6g7xmOUouXII2SBXijLFwW23aY48f38vpCB+Drwwqw/zLX8aAD+nyFB4yTTrNg
+1teT2I4IhKN2TJjkebOjEGThuD9u7zheh84m87JPZTWx4AHasSenMmQXA/oQFMeig1VZYCKPsBpo
+zFlJXEQlaruqgrczP5mTHclxlc82B1W4MFVxQ/bayj1CQGlmVQFvdCezNocuEwoFsY5Tmd1EYAP/
+csWNpG3ZAhDp3BUuu6znfeDkPXD+ECqAcZK9XRW5lhWLP1dg5plII3ibiLmxRCUjEt2ndxK7hCj0
+wAEjhM+YRj+5sKpaeoTq67wKk3PS+heC1Wo2G99LzCOVORnLXh4d1mv/KBJlKRa1mNwt3kE5xXYH
+Rayxorz86CmA2mplKhfTAafo3JrNlju3WyWnH2Nx+ejLm051N9P29YlxooUSip+6FI6lA4vF2S3a
++BX3bj/Fl6QbU04StUVUshyulhZRqOK5+JPjn2pxKx5000JnGMiAJdR4WlTNc2MEZdjwTeJLsBAM
+W5JJEWStR1d861jfO2jmLOEQKe4R4ZpZybdQAixRnRg2Eswj5tDZ+21HwcHV3mkrzl/vNJTlyOPy
+YGs2CFmrVA8KpQRYrLqXebL0rAapDn6mFnqorBEKFFbPIivC0QKRAuUgp4rBFvzrrOjeSLBEeeI9
+AryNH1Kup5XLLY5p3BAuZH5tEXsZShS6RT+UeKyWg3kqsZQx+6AZRT6Hx2pRUMUSprG2atTtC1hT
+3CP5FAMEyVwcwVk15iWcS8MfKch5f4HMuIzNtgtkIBbeGj1nd1RaetrpgghkHfeVnrc6YfrhQZpR
+u1p1Ks/TFTpFWrurZQ0CarwrLvKDFK1EmIsMfICXfgvAwWeZ1O4q0zf6kK0IeBkXQoFBLKvCXsIX
+6BbrAdU3Ou9oHXQoM6yXhwI7aR0wAo+0Lh4QC0jpCrtu17UDL9OiAuw0+FhkO3OhWqe0mzTkghfg
+lossvthQmhGzuozfuznv6KcAF8RkGV00/g7pYAfXAdMeiELnff88G7rY2cw/J0HIjGVoPUcm0zkz
+cMneulqgp6S2Dqdv9WGbPfwF+GdoIN5AZZoEf7hQWL91Ol6sCBAud1JiDsoEXmQDK279GaHfACwY
+w0GsJPO6I/6cRHfAyvMVvouBEJrgmhf/9qFBuDjT1xSU2xqmbOEjsiLaLcgp2RloRdWm9dtVW558
+ZIw4bidLC1CAAuJkyXPhIYrcbQhVIObodNNnw1bJMqPVArmrqkIFvC7sXYXFZZwuZV2UmTgsxDPb
+gwMieTjThSIGSR7g+KwRtMP26cfSI+uzfdU+C5fzB5wRlkK6Yp82rnh15Uq0GGwOiZDVxyrI5y3Y
+x8HIzYdaiJJGfQY1+uqRyZkXPHyxVZgvmdNPhS2/8elVXn2Ew+E4Z4AiT0R8PwZz3EyZCElq/Ng6
+KNeVze1X37IqPbZAd7fzEmyzEkDyCEuxgwx01wKboGBzP/CdFjnX7oC3M0IQ4wQMg/yz1nmtaAIX
+kPPYynCIl5KbKgW0fJVseybfzJDV8X3QvAKr+5spd12jLLcHGTMc1LhZ2rnazHnXzRJoqYNiZH2N
+Cw8s2wKhnzQCC+lUJPjR0Q1ZeXJB6tSUxnFgp71E8UaTy6sJh57N+mRLK7xcxei9iJ/U+7zpem7q
+sP3/sfd2vZYlx3XguwD+h3ohQBmodn5/YJ7YJcsjuwQbksmRMBgQVLEta8QibZq0Rv9+TqxYKzLP
+vbcpNosS9GACUpPR++bZO3fuyMiIFWuVqDt15TJQ649ichm3WE3UjbUPxs22Q4yTQ2CweWIucAWt
+R8m3KRN6ehICbpUFx+1O+vRBJf3KCk87jDspkg7NyxM0xnkDGPgDCiDjbw0cvmVoiWatoeBiBZAW
+fdjjlDB3gCOLV9TcqC+EiuQ0dkE5L1W8uaMns7p4B438SKvymxext63rGv2EBkKg9EbzhiEas2rn
+F42CAiLIIp0BtEbtXBV57h2VYGkrz2hMJbz34BK4GddoWJtLOVoceYLvQK6qutJRpNrvA0sW38E5
+3UgB24xq/29XCfOEGYeQEwT9mb8mMbnQnFlMq56S/ojofoSqSYsoXodPwCUkmHmR1doITSOop9Ia
+WhkrldNdO0NhvTw1ms9o6Smh2DXndZ6MjtkZ7qM+VaOniqmLAn8yckHLWc0ZZNfViRjOAEnJnOB9
+OK0hzZMObqRA8XqiG5whGobEzRSEgP1tiLqLijHH6bd9IRvk2Xowv1iNzMmVVhfqG72+arYCRuXg
+CryegnhmBj1BgG9DM6ZfINurgQm8DUI38ZRj+XAucmObiIKUFDQN1nJK0kBaKLTTS6sXWkF9/AAb
+aICrnFrDC80QsLM8fZL8ezDE1PA286tDMzfV5YfolN9OEUPkir5MdOKqQalf6tE5Yg==
+		]]><![CDATA[
+		nR2yHChfL0WYxNOeui1OO6dBN13QwBRVecl+BxO51wpL0Dnsu6QcAOZ5avCKgGZoNs5o1kTHxrzA
+GSzIYIXEO1M3XbdVmWmcinUOwqWpU9sCJLkwUL1kfQxbTcrHYd90ONBSF23MUMFSPrBEyGkX+mHk
+CZNs5hA4lpKv/Zh3VNs+cUaVcfnffNAITE2CKoYcRlUOSNpoPlkk/0Ef/7mHohMzhKGnyrZ8kYDh
+DRkVcyYXWf4Qa8l3KOjUJ0EhuMJt2AO7mCGd3I/cx8w6XToGTiQeKkif2N30dzyNaXiscWMDlhr8
+BUCG1rbkVUSDkomgRqk+X/3uXoWE7FBwHPAEBHmkIEOQDooFoofMJmmTNeciroxNuT+rtokHcOx4
+Y83J/T4IWkCOmllDUOyQGdSoZ1uh3hM6szjfdGATyNNQot/LSp1cCTlwkQZiYGXwEXq1gEeYfUqm
+IvW4mKggu8E9DlQHuUJIHNUzCRJHmUEbOYMrzAq3PRYC2bitxnw5VguRB6v9TaJTVS2KVtIWJ1Bw
+U4/+hBYaLmnk5Xp2WxiXgyMAejTozcg7jP5EYbFUGTB7msHuNFmrL0eIfDQ1/V/Cbghc+ffpgG+Z
+IB6HGAnYQEcAPGXWUCzyRvzmuaj3niZhUd0Yd8xkDQec2e6i8JEa5bHGQAw9RUOjV2HG0fiyiklQ
+JKQnSmCROgx/0+9R2ONOZAQDJNnaQYEG8oV5ketrFsdXO+qQh6iBz3VKrrClq9OaueQnhoCVZIOM
+nWQQNuv/OTpOoEjhUKwRvLG4uEq9h+8GxkzYCpRcoiROwo0RcHoYPXgBF08OYyJXRp+3QAMTzwMS
+nXGtc+/NaFZ1aIOgN8icnREaP96QiCnSD5tRoL2RCflqzUXx2wt9toWOJRwC1y2UY4rmVp65uKbj
+qalXIQtGCG2IzKR5xyJL6th1Z3tB/8C2UKMoCJUbwqotQFtJreISd6ISYAxAeRTz4jtYB7g+51A6
+AEYvp9kecDXtZ3VbgNJFveauzAaamqZyNJvVDbhWYpPf0RlmXzwRjHsLUTNP0m1vaXqAymBfKBl1
+yF2CDFvH3nSoilcE3ckroEyVx8EsRWfHFgjTbGlIJWEI5jdumnXKDtjPjxBbEpI3ndLyCiR/8mxt
+PIAQ68khVO4PdrA5iPDIqF0z4YP7sOqAEHN6/CNSNvMnU5UNVFPcqJpmdV7+gypgdasdrvlxATNH
+CrGO52K+QwLe2RH/XRYMID8jAOwkwUNf8grvZ9n5miGxFWnUIKeIZK+084AAq1dCj+rXaOqoSnxR
+4GKVOIRZAMnDe7kRh6h0ZpU3xTSaBba17EsXZSMrAeVC9iC1MVUoaym2rlO2VW+Fh2Ruww9F+qBH
++YwkOCBs1M2q+mTGILkbK7jdQYIYVTlFo9G6h5Ns0qlVrITtrnXNQQg1OnWL9DH17i27SdHdFsxY
+/eaEmtHuBWjA0nGpqw28ieKoiFxyeso+Tls9av2Bm6+RW24OQ2Kc/u5V9qJffQZTzF7DxWj8nCDk
+6gyAPrnm4tzuxAHgQ2kh1EqM6hZxCow+wKQy2hlgCWgb54SA6kwQIQfhY5N3xinyQ5zbE6NpNbid
+cA1xe9a8KtViB8N+jrzMhCGcpv7fDPhuDq6NGa1DRiV0EUZGZzbipa1Z8NsaTmvoS56tKaP5e1OZ
+x03Svd5dWQuLcjwVaHsuT/GGN90RTrTYx7LkOV3siADdcgSEhK015sz2RNSRCX8OsOZJ7RsqLvQJ
+SAtmzvJ8yRARLQStSaPZYkCmY1LQiqO23rk5geUvis7HG0kc2CqTkVOKLqk7T7QDeICyFJ1wnju6
+ZZmayyDnfNOdfvotGjH/7g+tEfPOxF1MDsb+H1LKf+/PH9wVALE34bxapBfYnc45pOTnPliTyt3N
+8pGWAvygN0M8FQ4P44gk8u+VIgJGg+/l8tFGDuAQVNDuJbX2iyBve4/Xe5S3hQQEAjsaEXewHuTT
+17tEzAvF46BBV5tn8ZX+QSVMdQMU5wymcWlTSVEYVbkxexUjBlBCOB0deledmk7yz4XlzTeWmjgK
+xBCH6HRmwZg+rnkJFvjwm8iY92urJSQDkxuc63zYU9hsrlrk91nzxbLNO1iXbECNMmryGXbjCZ2A
+9okRyHCaApdnm+5Q5DS3+mRJTGef4UlLrki6gB07yitnq6dOHDobmWHO3jkfNRPxzOZIaCMSU/Jp
+kGAHTaqFCwaV7BiBpx77OXEIb+2/bNp1mzCE5S7DQsFcLTBNctgz2DXr2WtHAEiqP/hJELNFrB4d
+93YhLUSJYdt9PT04wTxhm3DgZetUAk1Z4xKZEDt/MLmaneH0JBFYzcnOguBGteAmTxhw+yn6StEm
+H/utdtHltRReHJSRIak91eoPifNrw2YGH3n0HOTEZIdjDduNFwvclWOWthwo41ZTFjDyX4/QVXk9
+EhLaDa4zQBGMY9ZouLEsk5/TDBlfTuZZeH0Q5J2wy4Eoo2lrsAMXD/YH/baO1G678xDY6ByG3+I9
+LOqejhbKsQg4932dYBVKIZpdNE75YnAEt45vDT1SRPvIokU/rDVOKAmQI74Y4ulB3BDZEbSpR+Dg
+JdOZFTa58lchHWArQRDGmsJ8ouY1bnrH5aF4s4Q4ZuAwDwHAq+3tk04+j8DM3Nc7qtL+vSIS0bIu
+l4f7HLukx2/2LbNFE8T7Q1sf9asN/RkC0qXuaz90GB9qaSNAltoiQ+aqxtneHl7R9o6eSzCwd701
+Ks2gvJZllFL2dLJYjmDHX4WlInLYKtU5j612SKICkpdR6QVX5FP20UohrnbuQ5IRzdnoYD97oT13
+Z1Ze4EYDmyRNgQL+FVxvCOejmzyUYawvjr3CrpUezXJFA7APcc4n1pkhNk8bmOBgoGw6J2YL1GSq
+IosPUU6H1WHZELf9e0JJVuzfIvroEeocenbbaNnpZsfFKpoM5iyxcLeMBMGhBNGvLVlUuhQr9W+d
+KvOOEJADIP4qeX05QBCtKEURUJLizfVMh3Q5FcpMg+E9cBw5QLG+pOisWKbLUqTG6VvN4ff5P0Ww
+UUKUa0YFYJXD+r6CJd+QG+naTyWiWxxyxT0jByhW1LZDGXE7ZdZTvj892/lm0lWpz6K12JHvQk69
+2tmnQmHpNl3704q4xLZIVmfW7cfN3hZXOakd8WtVXZpRIQqWQHjBdo3AJ7Y9OzrBiaeZT3kBnb/a
+TTA3Axc/LyBGDhLXFq4OzbIcFeXlqHJN7vTptO+n4JadDgx9z3pFY6q9nRrT8BXwMEMXJwRLPEId
+9UDcznZWAaGKz4FpRJrdxr6rQfk4hrLOzmbGCyK3BJgajLjoWKMPkQoxphQ4dTJO494OmUkckqhA
+k1fUS0j1jN3QgcRW3zFwQeyGPAAlLUXvAGQ5qxOJYtJAXpxB5fSQ/C3FYPbyieq03CA3w+ntN2/u
+brEbmmLo4yO1/5bb1G441XNgS82yvNEEpE11RGMtGmi4nKMfpOmRJ2WJPuh0yXB2EkPgO5+y+Cv4
+LMDKp08K1cTYD0Wnu5yKT5uk6o1rCoFO9LR9BSUCuX1a7oZTwHGP9IQj4s4qlDFjcnuyfcBYW0AI
+C+WFu9rXCJUaCWCm7AxnURyIERTmHjEBUKNp0ru2xNA2MSd12oDM7uqT8GhDOzDrT7g4dNnYBWfD
+PoWDpy98zCVYrefRbfGkyOaSmgQvOHTHRWJPhIphVfzTQfgRgFFW38x4kGAALhYGO5k8+mgBi6zQ
+YYIiL5rFT/vekFXWX5FGtGRyUfk+EYEEJFCcpi1y/yAPwk9tB2LedmQHvtyH7KoGSTMyi+529aTv
+aAZbN4Nz3MLN9fxMN8TDBmiDojwqsGKK+r9t2Vt5xJl6vvdUFTkkj7IjZ2aBbg15psa0DlJckY9W
+Km87MbIbU6TneE6/0qPrard16ZvFj4R84NiS4wvRJMyhtIytztmvDZUdR7YpMC6B7ktn4rWRvhMn
+1ElHeNGt4qsXtKAf3RX2xM8j+Awe8UkMQT8SjTMaa5gIxx7n/1O0ilbQ56LPN2bfdkCey9aBveWL
+1z5RsmQGVNqOgOk+3mrXqeHTjqzYuETNglvOjCcosa+BO6cxl3Wx1jGfPC4SuFNPL0hmfpJHIv/6
+qKGaAtHioa78FnTIgT8wNcHYi/iNQF9gqbtZDfFdxSHshk0N8blcm+HylWxAES8uPZdyCcdBD7KX
+mI3yIcQykICmfENTozsOkkTe9NNa9Gp703ZoJNoFe+EjJv57nR0YYpv/XDoYostQpwdJpZtHiAyZ
+0HgrGpF0hIxgdvAI1NUr7xpGCsKWihs1RjCk2yG/mKIlNBqMI5JC3tvBzlMGqJQDqDd80HyUozBH
+ic/snEBG8bjWp4GprFFurrAdLGa2niS/UBXpgw5iqK13eevTIDPaqad6SVqoCbx5xmBtjVg1BDCg
+HvdJq0bBHTG85LunGEoSraozAFAE5IhOYTF56Q1pnRnC47y4Rvp3r8vJ3Lc/lQAxNyRRii4sm3lL
+HpAtQ9AV9/e7lbS7UYRG1ju4FQUifeJGLfvi5aWTICArQHWPxyDHmUsNgbCXes8uCoN0956x/R6O
+tKh3jKVW87VdDWktkmjIuJ1whhFCC/Ay2kY6S1zBR/ryY/ptpZAf/uFLIe+sYvgc6wL6pAyY3fBn
+VXql62GJsa4DCvlYDc40D8VhVYWtzqtjgA2+o57jdhXlxKhBwY3WkMxjD8D7EeORT39UYWbQgMjv
+rZ9ex6rz8hg3s6U1wnuEAuBRFiE+2wZu8BOEnsgoUoPEATgQh9Eaz5X6CpfSx0AAMmCfKqPjzJjv
+78NdjNVC+1DbPrnIUMdMal52LUJ8iv0q9ZFJ086SPGuChDQz1M3EHWzpQ8mhRkVJaenu+QifR+K8
+7Q7EsS4FaLvVFjs8SDl5Y5nt8XY4KEIormgWTOe0bF3wkQFTJqB5HZpGPz7OK/cbepmGewxiF3xM
+WZopoRA6FQxMdh8xWm9d3/jNsso2LyieZAW2TblNZM0Zkg5xmgBe80nfw1raXddoivNEb2XZbQU5
+zI8UJ3n/pIwBd2cDi42oQ3jXqy3bGj0Lz9/jtTeXF1lb1GJ8zU4rWX+Osk3RebtLClGSpVZGZ8Hd
+QmEqEg3nuI2wXHxMLToLkEdS+h1aqIy7MFmjPTELD0KUht4q/aZhNrUbaFENJidjsZLgDWDQ+qKZ
+3LZOIuTBTy9kwNV/aWdvFu0NjypiAbLpQ0vvtPqTgyc5Cdkn7Sj6OE+ODE3eTN2jnvT+LqFbJeU8
+PujSK/l6xAlswPipnNNinz1ULqTkczIb+Az4aRDJZKdjLuAcsvNITVeyCG1T0T4pZz9vWTifisr4
+SqPUSD+uwJhY9aEHlPzKJNdQW8CRWQpjXO7rVh2DumKgA9j4POvpJh4RotZoKXeaFD4tpLzjk+25
+R1YjYjPuCZPag740WeIzwqIZjFaQReYzIObhd8yXa91HXQc+bnaz3PvHDOEQA2hSJg==
+		]]><![CDATA[
+		zQ53LHpBJ1B4qacv8fpoHw7xCXhwwX+3U419jrslXZjlAVPcLlOgKcQr7dAbileQk4xols0VY0R6
+GJXiLrxzipxAC76yeSREV5wk7dh2kZI7umowCPb3HlW+W+RsXlpvaTdVVnh4RzksaPNdxBRTdo5h
+JL0fTyT/TAiY65Tk9WIrC/C0fd0xA6eLsrkrNCbxmQetu+ihsgtxn1ILF12ObRGyCYW7dZx1znG+
+XA12YC/K2tlZ77IGXm9KhO4omZ2HioTgMgzxzAMzFDCe7yDrgB56951SGPZTJzmNTNRsuoUZ6Sn2
+KhTxsMHoBI+ITeo1AtF7uLjpYoISgfTSCbvIp12svaeb1z4ygU0st6SYHC/UjSTesOg9Hy6Ccvml
+LBL5QxBZgkT2qFOjMyi8uGESeLzM4SlQwXPPnA5H96sP8kN8vQ4R5Q0x4CqO7/qsJJiqGSVwX1cR
+rIRkESZF0nNlP/G/Fx73pK7ozZn8OqS2A/jI5DYKME989opdhzY880eeTMV+P8OZsLZvbqlfUyW8
+zeFPgYxytJC0yO69mIXfdoD58Ac+wPzoe47VzcTqArP7s+/90Xj3gz9+91f/l13w/R/+WU4/+Xe/
++Nlf/uPnv/nlzx9/B8PX3/zt3/1Cph/8+29++qs/tj//of2/v/qH7/3Rb773m+/9m9/Y//pPLwHB
+6d1/ePy3//dh+4d37d2fv/u//5/07mePG/mrv7B/97eeiKhaVuDCf3z0vjiAL1TFT5Gz4RWzwDaM
+zswLBwcdip7+IYJNtBN7ghX/UXYXGLBwleSY1pLThFNBLt6NLCNYUGdBBQfe0aSZguzJYiMhy4WU
+STrFTZITR9JPrQs7MhxT3HLoSK5i95UzWp67+aDcjRRTBzAWHyOls1RhCTrhEYedHvQb4wQjzPNF
+UohAN3Mz4nVdl6NingRzw5NZc+hAFPdUYrHX8tiuPipJeiRal7oBi/qRIPYdaGDVN7pXSKLuSPLO
+SYq296wQbp6OIBbAk4F38tvZZl1gppOBUIlgRuPOPMRdqFcmBXYB6bJoTv4Pp+d4NHbMwjNEqxVp
+ZM1hpfl8s+B9PuLlwf9gfK8tyq9NDTaqD8xQKIEXDEDxjDxldmz8R9kJYrMMqJDddkQqwt+SWQjL
+y2O47KQhHyKR0faLrje0IcoYicoUvXTZ63wf5F+7bk1kaQtpCM6jODAs2+a3lbwRJf7+MW+MDtHi
+8jH89uTpbx5OhJGYm9g7nK7iH1K0HkSEN2Kg5etkWHjQG/qIQSxQlD20PooPEWFPvWD07348h+Wy
+tUsWlbLUZpOCtRHN3KqDjwsz05XKsKNQCQKXMbjGZoqEmCROk6Mr4wQpyFwQqSK2muqXUo+ugUXF
+wwoWiTjAXLTG7NyDxNNk4kbAIzsXdb02AHEjq/dYIiznA1fxMWLUqjxucIMlEdIOTzu4jTB7O+K2
+k1PKKqRc1MY7OD7MM9Zo6tt7qrWynjJyPsncx8FF783MLBrlOxWKuMoPqVz/oDIrXRFtancyVedG
+QdCLWnsmOVXfzyXNeY/8jmi4ZeKIfq4RpxqtX90K5ggVfxi1dMpNMGFyk3Py4waJ1Efl0R7fPMP4
+RnTFtopvFk+1wNZWEG1cOxd8z/bHSVcSnU/G7c15iPLIuhJu6RTJDM3vLYeTvDPXnak3WLklMzYm
+eoGG4wCBZ7lo8S/MgmFjtnoHtsrpImMMMdI5HVX9QcWnxyFfqIK8VflhDmGpGx3Eq4EzEPkd2itL
+UQ7ehv0ou6pP1rFVQkzXe6/sHLyp1moVRtXD9+mabM5763t/ZuNm87eKKGHkkPitabJGjYa/D6pp
++QAQrJlLd5acppPh0gp12CbIE8V6YPQS3ioXtBkj+GqCF03iwX38tCjztvpUj1bfDpD9Bdu0uH4E
+eqVIUnjMIkiMIi0SC0TB7/GmybSDSJvP1kPOyfAAZJseoQbZPcFAY5VEwdH7g518H/MQD9uSnSRY
+SKvzVXSKCxGO+EFFIRFjuqrGR5m5Odkpu+SQ+i6LRipFYXJKlUqDlShj0lYXe4S3wGPSRxUP2Y5Z
+R9+oE46Ndq2H4VQ3xlioMmvSzg9sy1DtFQRbMK56MYT3kShXge/yYyxVn3UrR40uMWnmsMxZdSqL
+2+tulFhDYSQWO78BA0ztqa8lNxe2GiIIRcvslBF0Gx/koOg7NzsFP8rOSrjZjwYxI1qD6E55Q9y6
+C72tCNZNrxgnZPs9przMc1YXPhm32DD2WhixtYWD6r5dWOn4CAujWxZGAII4QvV7XU++c7vHXANk
+1RHfGbar29cx8KlX+SlfPsPgYDuMIBkdRnA+2l14x+F3GNG7wM/2HFlGojrMI8PL2gj4LD6oSJSQ
+8rFbgDrwR+WR0T+LO6Y4pe1kMx6jBVTLW9ExgJX/Yi/kTSQ/+bgt4Yw0ABzn/gqZG5hQGYi9GLGK
+mbsS4XYo17WCNGxV2vBgPYDHaDDaZrbQ7bHxf5R5j9LcLroZiKIWPK31Vypw8GmZHmdGcnsPtwZO
+IrFea38shSN84q24EbobkZu28wxeDaLPjzJXpHHMrnrjIim8v0fuYmBb3LwSrjsiPo8FzK6+ZEja
+Dq4E9UVaMi3pwn3oMzsjJdyCenYEgMf9UhXBOnkRYZjxas0GUWpqnEVD3UZA7X0ONmuSsbKovDTc
+2joqgdY/s2XM5RK48xys2SkDDlJ2jSpyCvRh+Vsfnmr8oOxyT5odQO4+yu6Jfjx0nEJy9VVegpLM
+G6GqG+dpCXYRGV48clSbVvLFWyLhORWADZEG8IS2mD0xuzJN6MX3hwPhj0i+QNmJn1pRXwTNS8a1
+zbkaP8ruuBFb6YL4oURQufxF7GjH15bddnj35vmwe4TOk0gM+y1JnFtSAeAQm8SrE2+KLt1cAD6M
+j6eusGmPvqhGnK0Z00FxEUBoleh6j1zp/ndEw7OqpGokA5LIqiJ32hBHijwAEbEQnV+SEaLErmF7
+d1E7D2HzhiXqUWOyI+OO2zVP/1F2x53CG5LS3pICk7600W2N6B1EkX2uk8Bh/48hY5g8tmzP5k0I
+ZGKKNojWbP+p7cKjEdiMXTDpxqYKjrZhtixxIKaA9oUaF2eLVRIPB6GN6yADqyby8DjYi+Caoqyt
+W3LNqW/2k4OxhJOXMa3EeEntDAnJS4jZkitkRi1e8OIIPX6OWhMfZScc1tnHMUYLDbJzmBtH3pUt
+fZ8igykxen0UVufljyUf3n/pEuYy+orI56mHcLl+ZmQqD0/vZAnNTrMhVBlURiukvZYXuU8OlHLb
+0/HtMhY157N0PtatMH8qKuPQW4wgp0DpTFyZkwV5e4oIvpGqiXmX7HnzTeKjErziAWwhwjdqcLqz
+weX9Wyni35I5/7cvDf/Hux/88Ge//JtvfvLDP9s/efzBX/76H3/+zU/OVc958vzuh//d/v+faFt7
+nOmYLAYQ57O2FHfcSA2rk8Ng3OrN3FE0OUrUcAunwlImeYklS2gZLD9lW1hS1GXLWYIC8ilcTDGA
+gtx+S4ia7QaGEBCgLgW9wnMjvVU8F+dfFFFG7KyO+a1N/MUUPP7867+xOfrBj37xi59+/uZn7/72
+Vz/92d9984tfvyt//O69waQe16d37x8RoCVh0oZ0yEAtd9lOwH/S+vAsNocP+2OFWjq2vfv6b7/3
+R90Ou9YfN6ygYwuvGqjD7qqYllDwwqPU+FgkdnB6nBv/6vGKatqErlUwaFmA/fqvV5H8zLYTv0lH
+ff3p9//hr3/nH34smOl6AZ7fsgDma5a9v/4aq/gPv7L/zY9+54G/6+v6t3/xzU9//uc//fWv/u7/
+sz9/94MPP/yzf8818V/+6y9/9dn/ne7nu902Skt/cgpGr9fzZ+UWXy/+tz+Tb/um3vj+3vxQf8tX
+/coDvOkq3vyo3vz83vxK3/yk/9kc4p8oq/zYS5lzfEzzZ8Wf7MVydU3yBTLNlkLJsAZn9FWoNrR2
+4f7PxAxw+uj+wcnvtFZ0D4vy1cYFyN5m9Cx8hwVa2QXfh4jFcP71FJmEkCKtubc60fMOLrcknE2m
+hODLh/8nXaClz+UBwcP0+3jAmhhsVWSlHo9SQKv/uM1i99ZEH46q0xrZYqvHEcA8YLGWbXNDzYA8
+Ruz1+m9XBqegvb5HOOTYaHNDv+/vfv07/u58xG/RK7M8Xv/f7u93d3/V04Pkxv8scxrSZkerIr3f
+qnR08wAsakVJzVvfLsQXJMlgF6H3JbG9g+ANrUyN1GBXWyQ4umewU1SdygsFZrKzO9L/cYTsR7Dw
+f7w3x6vIBT6ODaSt0nH21TT8C3jAblkFpbivjccabzzwJfiYuYEmFfMpsYEcHGLDz4MHbEdBpxWI
+EyXdne6XpKfQMelM7qLWe2p+AJOiYz9oax6HOaaMddy2GW6aOMiTxMz3nMkm/YhilC5KQ3QjgUV6
+NQ2/gzfMwJ5Uc4doLP193OH7bAvh4TUy+lu7/bPOR6CWbb/PYrpJIxHDjPqgOcP3pRsW8LH31mSw
+z8ce+/pvR7GUhyX3yqCIizml3+9Xv/5df9W596bOc/Y5/m9X+Lu6wi1+s7WckP+z8trsBbf8PDva
+UMtNTUnwLCynKw4PqGZGf+qk8J2nmgnRAbHwYJ1jjaTOPhF8dSfr+6SMx2kAliqTulu9jNqjjK86
+7DMS2voNO/FiS1Wy9BXlwlLc1+tp+BfxhSs6pB9PV67Wl7VEytxP2i+IP0NNuIQuUPcaNieuSN4I
+BfVDTueC7Ctog4GJxEeH5Ny6zrW1oPwLbtGszsO0JhNQ4gK3T88rTJYsP12lVqghoVI+vCvFi+R4
+4iHOtlfT8E/6wmZsiPKFy3igHTHn/x9+rtoZ8hGu6p/F0CiPLU7/1EpCbrNbUfkR+8LPZXSSt3f6
+5xt/2ZcaFGpz3Cm83O/1m1//br+5M/sm8OVgB//X5OO+28A/+t7+jpDJ//Onv/703wyk+Ze//uXf
+f/MaPJmQcqJn+wv2mj3Ww3/8NjilER6/gajEelQxb0WqigiPPR6h1+N2/vJ73/0JPv7d3/63X//N
+b37+N69v3m7/P517fsUJ+9sgoL6mhsjH8WF/fmEeUZiEmnFTxmQKqptnq5fxk46lr6+NMZET2M+2
+5V2nn178/MU5FkPukIq8fp7GD3JBFkRc9gAZefn7GsP8SnShttCrDNt1W8d8nuAMeZ70+vmnWXnz
+2hjzzPSx8aW8/HnrUAulRA5pZDC9vPh5Gl/+/HVtjGmAyfZiRlya8uWvZ99NnkZMDlx9/nUaA8uo
+d0X7xxdL5Yxx3v/5rWO77+pYz/2fEc9zXr/+NCdvXhtjnnl+9Z3Af2Z6jhdgeyLlqzNifX5lfpzC
+pWKljpES9QVIt6Z6GQPSV5rj6WgPSN/j3DmfB8Fp1FtZzs89GXFr8bW8sH98aW8hG339XPuKlajr
+1tqF172exM0fZdZTnxFidq5fejmRH96e34/2JvwVz6XPa8XEP5lRDXzvcFlHIdpnxw==
+		]]><![CDATA[
+		OM5oOMTqD1tMfI22IjPHvK+mBsgIBQ2FqW5B/diTcd3T/mz++NI8XRr9+cemdxw+3RhtUdTmY9Ac
+iF098hnimpzzY68m8sPriVyaeN88a3r881ePT8GaaJtIGAzBWGd8GRv8jnYCyIZRTtohN1jqm+MD
+vK/FifGLStX9ydQBvKn5IL5S8frf8nb6ANqt4nXFIAuChPwcLJBmil+B1p6lzZIu2E/ayscAI/Le
+MTCtMzQ92tG0AbjeLhAM1z+SlmsdEIuw+9kF0tyVPuIyInkbUf4uQnnZjivdaV/2cKXsrbvGmIds
+7/wamJLUPIVbCzTC7n1cj/Lxhf08tsU0yfFsZ34MsNx6eTmXTrE5n6cd+i+RKiabE4ReHMbFtxl1
+0J1wTNfb//hs94WiO3ucz8a9oBxK4NlSLr44aXY0Az4OKs5v5dPjDdOWWoXUh39AzZqCH8buAjKR
+PNrF0jxmX/pgJUg+8uGQgRr87pfxU3iYlOrzxRapNzc2Z11/8xPCPrT0+Z0okK56eJ8h9ao+K9X0
+OK/a8ulGrNxDlDXj4m7ApZafbjiMn5RxY9fZfbER/Prx5BrW0oTa3i/NrNf39tHPzL95/J+8iaU/
+vs2ffP8nPkc7+4veLsT+Wf/GZEcnEWAUGzBUMhYxkE9s5byMyUk6PmgIQwXweLv5kelfkD7A+BG4
+WwGhhzZaAzpS3XAPbYyGzLQO6g/n/kpD35sh7SQhb7mORAwu2jmejCCrcT5WH+P0bNhBuvVzh5Yy
+K2ILCZq0lIJFN4egdK79Nmpw8zGjjuvfaHA0HEs1RQN5tWk8/SJ443u97i8Gn5oXPdPHV//mmgJT
+9gJq7p4sMzJP8WJuJ6TJ2vOrQNOEZ2jPSzM3mYQP2nSwPoaVYHq5lsXH1/+meprLf3JOL4XFcjOY
+kzsRLc5PGmJ4+7B9xIO9Zl7Iw+deghTf8GkdwLdsTc+upYEhAIkDoi1b39QUVZnveKgIldDMzdZN
+fIwxhgFGVnu+fBspKB4vUyvize8MY3xr8+TXf+Dmye//xCPt7/9kPbmG7XxP4MjPBpU/rgHEYUUw
+WoOof379b5Lz07mRvYYG6BLFxdCeLOOns0y9mfe+evNDtXGjD83aVmsXkNZdvs++4OBeVFW/e84O
+qyxB43kZq+vAXotA/4YSk9ymiNuzjgi21C5GDGG8niQRPHtdbgxuTVhQsdB1NqMBFEvJOc3o48eJ
+NdRGfk1zC3bq12/lty+kPzSN0Pd/8qPHT0X6RZmfK6MSkSyyKt+6/XynJMub29QXb1LfskV9+Qb1
+5dvTt21OX7w1fdvG9MXb0rdtSl++JX35hvRt29EXb0ZfvBV9+Ub05dvQv9gmtO4z7nKnYPvPshpJ
+ZH+W94xicYG6I8BRj+OAVIc6uyesnLd48RTTTu2bbXKgW4vPqY4idnSWhyGi0ti03tR7Z0YJk4Cq
+LkYgU5z1ZqnRrjvnJlbszqEg4LdqSJx2kqpWyyvCJrMdYZuWROIqFjWHLehdeVJ/dldplyV7U98O
+l4Xhq+s8HYje75KcEjFGOL0LBFkYX99oaiU4PZ5leAfI9tb2KE7NYfUxW1dVzJzTGTKxhiWMZy1z
+/DSq49ijm2FgB8smDpDVzeBoQjOKxBQJl8pRH+fyS38bRGVY2RIAsc8QaH0710mSwwBnk9/svNm4
+1GE0Tx+99XlzXsRnAFFFn8HggZ/QnQ/zcUUOtrZe+XzO0HyFUCSOv3/4Nb3vWUIZFZOKlaEsbKGK
+K/irDmlt4aygiCso+wxIQ4tOKjOKwx3KMeGmQYJJew1d1EmNgKDjnCEnMp2LNwboeREiV9LZKNhd
+PaLhCW+q86PtOZiGQHG8XzTITkkWSriVIeEQI0TadyrtET+xOzVTkddcR98kdRb5w2t/8gFZNwuj
+MnzQMnTvsvzT5YPEGjBdBj180GMvZEm8qjXGKiFHyqVE/xPbjZdXiePUDhF3t88mLwR38qRNYMYS
+qoztoqskkZhVblUbNg4MLRXxdcHoxf7mtFYcoTvdmTcEUvhlD0LhOrrnklxT2ajrW4LRWElPbMO6
+9Y4IZHirJz6L0YMt16E6MI7jSYdDnyywhbae3xZCYv8oo44y8uZ2hUAjfFABHZp5AOH/odOX6C0u
+TtoRLgRfW/ig5g2FOXSBFqh1aVOfI1AK2kbXGWBGQJmLs47JCU06oSzZ9kZ9BTxEKpdkeQJpBh74
+KKQ/zlObU5OTUoJO4jXU+nxcSa708UHzk6RuYC+nhy9Cu4cb2z0CC+LWRUOqBkN2pM60b6htF+/3
+9m7YuS71+cKm0XZ8wXDpWUJKAgGB5OkKRdHjjppYvFsKbkUROBjd5hT4hKkwGWMEyMB43Fmj2OVp
+aoieVGUl2UCDalS+3VEpIqelvPcSp4mkkNwIlAWN5coni7jY7DvQaytI8amP9Nq1HHfU3R3ZP5Yh
+2cIdzeCNXU5iG2nIxy0Sg6oFvwOLs6NrDaQV5FTHOzh1mVaW7NGB8fiKmJ+XtrMZs8Qox9MIYNED
+HBCqwe54kuuEG6cpJwPG7g1Y8gLNqEO7r7NGhj60Z00CZdjLtI0jcEdq4URDXchyCPaWCMiq+nGX
+sr7dCTTcaPCNGKGX4l8bSHzfE7W0GPxDjNmjaRAT4CN+nGXGSTw72aN98Qii3k9ngRt0OonVV8tn
+46uCsfWL6wwS7W6/RMLnkNdZQVsDBmWEPfNJEBRYMTjD1E84hAfOKYipoTK/6YnaURiybzhtZjBE
+3WSuoWxmHxI1+6YE5DCPl6SK6aCoxU8ayHYxgkK8HvpTGDNDpbGDe+QwpNp7z0yYGDVeY698xFrF
+2UqxvPbhmQVrbVbn3ujyyKu5oKNxyvQQrJmSz0RHQvgRRtewt5B1GzoNiHrTjFuEFS1E966D8XaK
+RXqiwg8y7QjXHgu3yJPVS3GeZItzhQKKER6toFAfUaJfK6S5RuhyAu486COxUN2BzDQYdaiJ7rVX
+OZ7IWaKXxUd2XL8ckShMLL5p8ziitAZZPWz+6em6s65bCaMthWirSCK07IuydFVaQz5kiUDHyGeT
+eB/3XpRAmudcBLaeSdILkC2+9/pPj6SBDktVbUvmPa5So9EQ49ho5AfiWQYCkIsy1NlMuIbduyDJ
+jAGG3I5EH7aolADCJBv9FhmxGUF9HAMI3nl6iy0NggAan2YRZgSFZnzG4KQJX8Qu8ZxDWskolqB1
+Zt5B0kqG9wZiF0Yylrov8tJYObKdRsyQGef0sVX0xltm8HNU/iaV2eANaz9BEXKbOZ1gwGY20RXh
+3YQrqp0nM6zj90z+dDppeafM7QQza/DV40ZWpqN/vMUcAzTGq7uXY0xMTYPHOUZAFzreea26g7GK
+mDG4PkGOWXhmq2dPAe1mY9y9S0g8uw6eYdZT1JUfjq74Ym49XV4kNZLWNLWoz+hXzbFLIK82sozp
+OuCRYgQaaCGCII315GRTfGFFAmjYO84Je+noGAJV1q0r1j/ATt04CZfdTsP+QSMgv+R2sUqafAEH
+pa7Ia5cSXqgCtW2nPByZ13FDw9kQ/blt1/gs9zTSkJ20/eabpho1+kjipCaZE6a+5+OHqiMeQLe5
+NQI1BgDYjS6ER8jCHgKkk2IEloZtLB4RvXOPTicooYsfaWDc5/WjbN0Zk9fDVo0qgkOFZ2gQs8hu
+oOoU7x/24CnJO/QXymS1pKY+w9gWjaVd9wAf6L5I5COzVx5XEudxk/cNn3Fu+eqCOViBkkN85TEf
+9Dp1bDUXPk4gMl6aLpmMtWaPQo6J0EzmniRDihXqR7nsHE3HGYEMHu5wxHeYcqczklqN+FrtIaAW
+Fb7I2aOsXLMrHVfmwQTeaMgWXC3ozTuehBm0HMJckxuc56HTSf9sMULkQ91jJzHnKBf7ghtXSWQ+
+yMy12b0yFO6H8AjKPkXmIgLFIak7MKxMndgoeVz9MHXgLMtJreqZRCuESLVQjO6Tjo3Gch3vqrb2
+x7ghAlx0xgCrphuhoOxtVuMKiRyttlKIV+KYJ+HmFZQhSDzSdvuhGlSnPXhhHmuZR9F9aJpfeJXj
+iYZ7IitkPSKReXuixoNu8Z6j8ESkqzN7SIKQb9Filxn9bXNLcn3kUCUBQ3UlQ5kSgnxdyPEJ6Anc
+fyU3Ab7Z8EO5+DvaUZW0U4xnBPdJse3s7I8eZJeIJA1k5dgpVMOGiAr3VCJBKTawTogs6RIShz3L
+vov07vzGwGxUQvMlu79I2eO3a4TJdAh4QfweTIDcP8sdWf/EA97yk1o4IsYDdg4imz8IrutQ+ii6
+nOGZ3Tjm1VQ42mKs8wg0lBUaDQ9hPocLCBtdYfYHHfHhiOaYvDjvIclLiCHixgqDLeN7AZGHPcUy
+gqnwRKPpkRfze3Y48hEQLx79oz44u3Cbx5PYOcUdvUDCmcwYSGWfuAg9K2RruXlx+xzcgTYpw6BG
+sH2JiHu6KB26ydEfroit0t3jBJ+EJiIQKMa7DT0l3i6+g08LmtvqIl+HjB90R3ffohlx+nZjMHoi
+MzPptRbxAkgdFdIG9roile2kmfh681POr4nQuYRaq5f1IOHKvhyoWyXpulreO7zREWaNxOVwdQEf
+lumn154lvJGX0y0qGpY+uXxRqiIe6aHhbMmIsI4lr5NcSm4dbQQLzlxOAlSF52w2XbTP7TvEitUc
+GlKfLiexmfbbjxDkjDB8D0D2OukUk7fS0JJNgiB3ZaANFQT6ASP19fYb9hO4H4AwhCc1R3Ck+VMg
+E3FofMGnpi12HU9Ss6dg7bzCQKmIai47x/81wKArCjm4/BXDpxGarwAVZ2InwUkbVdreAGSxc9AQ
+h3+amy5jplAlRnLGjRaphycSItJa/YoI8EGNBJ8j0ifTn1fkgxj0OKLssVYK/jh3RKpri/SlUUTM
+nuGSdjHuf84uBRDcCUymj47Ajx2ZWpab3+sKaUZVXyIOJDQOQXxOTIQSqSe3H2eQM8B0p7GPFvUE
+fpYxs8oq5nHIqDj87YYnmqSOGifHPh6r3IOi7fl6+qI6ucp7aNe6vvJgEaanCGqSq75ak3efyjjn
+LIqg2vsTVCLxs4wbnuLXt01/jeib6NGsfPqlJzW+3c2Ri8/yR069DGmFFGRqKRxiiiqMp55kF+ne
+I3xMmcbaAtr67FqOL3JnNFxH9/FlhzfqIdlJ4tNwRwTRSKDRjX2QjEkkFhBjFeXGxRC8UF2UXTLH
+Q2rma96ifbsNGW3nDncErg24o52LAggqqprn4clvh6QKarXjeKPUC8Py7iStyMoscbWBOM6NbekE
+kG935s4ddrkz28+T2B07q4CZ7w7G1e8RRucxRPVyNNR3hQksLUOYvtMdjUuhbRJqY84ADus9ECZo
+i3TPMdVjk4dsSMKGO3qsGaWbxL6UmL+xv08hvtrGoBHMd7GCH3640SFSxQzuqKpkLw9jqbFGd4SP
+M9zRdgajNKKjFazw4ujT6ReHJmEFLzVjsMVP7QD0ymYMrNCVL3KhOxhLuUbYPKMFow==
+		]]><![CDATA[
+		MXLUXqmyJNKIM9qcjgiYzuke/miJoFVgI3wlvkKVuYR0mfP1jpsOHE7K62fj1qBNrOL0OOdOFhzd
+dpfzM09Oj88vFbmdOhO9GUWO7dgWMRgqHMcVManLngf3LunivKiRys7Bm2w7U7iix9trHEHyYqZc
+3Rh4hCT0K79yfNF0X2Rpo2EEOJcvomaTOTLT3VZjKVvSzNyild15ECwAy0muiBS85jrSrfbzmG5m
+9R7h61bg5usBKtWhLN1qI31PjsdewZwAutUq6MDsWibq/TfjECARx9iAA7Bb3aLyMYUG7GRkTadF
+J5E+HycA06+IEcbs9DCqsWxy9ANGC85bGRMJOC9MEuv97op4qLT7bUWksCLjMJ7plPUZn7TzsP9V
+3BGgB91dkYMP4DWagLw7TzmSebFepaHzlbQELbsyGW0hFnVPVMfiD819rV9UaOAJSYkLP+QPcNHG
+PJacF/asLeYaoBKlYk+rgy5iEmeqbUEhbEaiHKgzEj4gkaA1O40njaU3JZbKGUHZJoCizghs+9mh
+JGQ56kk3NHsLzZJJNucbvEnpZEZLLXL3NdMRbYE0H/++ZLIvgtIyHBH16BDqRgi1XcoJm3yWI2FO
+ZzwNMJ2uCnYAPOiIHAmAQ0UU8qWM0x1geSJcJnauU+Zizg/RGvl3LYXk/JhmPDkL80RdXOtDPMLN
+JD85gubxtVcJT9QdWGQcgl/ZvhaOyIh0OsksAXsKR+SLFXa1sRqPmJ9XZ1T3TV6yiwbsHE7MPiuz
+zmXHDUJDmSmgiO+opmPGHmE14rItvtAduAH04bvXOb2qyVUTbG8rI1JWW0k90H3HxTgCeTZhh21q
+z0UdIQZYk45Izd1m24e2O40wVrIDg8LwDNAKgyLpwaOMuOmJQkvETqqNQRHi/k+aR1a7Esd6j2oZ
+i9s5eWLAfc5wfm0zGiaBIyQXxHO7GCiTV9A90pmRty48iyHNHCsYbK30hesERYVBUYRVjXsmSKF3
+iJEbuS9RQeMoFBbXf/LTa8ky5j1EP7f25QqyR4Hpyu+az+8kmolkUSGU0DePcQYoOKMhya12huIs
+Mp46ZEe1eZ2ZVfbf/Srm783EUtpD7RNEgWQXZvKZ8ZwbxAoOZeskA7fbmXJAammSdPARkV5YJX1m
+467C5VRor6xpAwyw+AFDYeA9c0hehhtPyPB5wotVAlK5K22zRwKptCHbCU1XOIsR4kcWNs2i3+pq
+inzhVY4jckgR/tGNmf/yRMV1F1DdyvMIu6Py6/NGGAakKJSng4YcfRYZHK37+HSXG0WwX2xxvwK5
+ucgvDHFkNzZSHCU/aMbfP07tsNcjoWjeerJDORykuZ9EqP865S878fSABWmSdqQ50vmyDbbVtRvn
+fYv/zLS0G+cYYYsXPSjONll5YGzzEgX3jdO+N75ocBu5gyNjqvtdsYwv518ITwTpRY8/lLerrufK
+SCU0i6Fd457kYqKzLNOWnVRNhlfJ8mWRpLA2Yh3E8gFqT2lluzfcOoaknOmLknS9mjoQkqGRTg2u
+uug1HlmMpqhVbQaMQQ9ffM9wR79uR4BSodupuTB5iZ/aCDtDrMMICh/3KcdnIQJQ0HAjJcP3DkFf
+RHFaZIhfPkR0R9D9BHmn+6I5Mlu3G6W6wETPrRVAz/BFOJvCLg46AJO6ct8651oWsWQZ8w1M6kNf
+60l+lzypvRIARcMv6vvNrd58MCVx5ERNYDu3OWzdqkg1zm2Cac5bhNtS2s5ULqopbY1DPzei5/mF
+bzn+yIFFiI96srKa/BGFvTFHYF0Nf6TWof1VKGmSKdyyyYT/g5h705tcPDZm76I2J4jNojmHHFjO
+ZseobATLTlkS3ugxLMFmwX1r52BhFKdoCadS/paXnAHXt9kKpnypli5qsntlOHxcma292o0R6UkL
+oRBUg1cuI5Q2ZMwUaYC2/RmhJDqj6K+fzmPo3kg4T4sCK/vp9tWj9Pi77snv7YGEvzOvvpjbCElp
+UmS6L0kRmVueejbFNTwrT8A2YwSd0Rzgjnx0KtchDdyC7hDXKaL5g63TCmGw0k1fhKpS+CK2XtaI
+aB5+NSuHFjhnx9TaHPZ15Yx7rzz79nOlIEjUPvLrmnaUtK/zneuaIXt0COTmUnfsFt6wimze6DNO
+QFMpMWeRuJJaXTJWO9Q7rLjfeiz4dvmgssi6CbAfg6QtQaYR+Tellc14l/HByu/OLQfPj6epEALs
+AGnTqWzHmZzNpFdKB0gGDjV/jRrR7mItF8Zyncwk+7V9lfoabC5rvni2f9OZhAMa3u/crPusjbvt
+zNoAdNA9Gq6G+HH0Jw7A5O1ragOBBnwSmXBxjCVyOZcoDPoV3SxfVdvU3rFasOS7SuMud7eGB3dE
+mUnVYzl9DCPp3cK2Kf8x+5XsLuocKPJerSrPLG6opToojlR9n79m6taWfTqq8atQKScFsgsyUm5b
+6x4gCUW8lcxCcE6Vms7+D1RYJpvQLjLE1QJws6PrzhAUTAjvQJUYlqOEcQWnuaWCkHdFGJMCTD3K
+pDsR2BHw/kFk5UjtiuRBBuznL0Ky0OK9VSPTJ9UIIoHWz9FNmtAHYWoeoL33zMQsHsooXQanIJWb
+qwo7KbvjduESi7dlMSMXLgj/nqe3cY/QGg9waHdwozLoyTUd/WaxqtlCUi8fRCJ4q8KupFMZRHmx
+Q0ptywr7a1B/DeKX4YYEIrA6YA5spItfQl3qlN68NwHGU8Uf/r9gny16z3Ie2v1nVPEdVAWi4THX
+vZEMxg+ITumIHL1kxhQHu92Kzi2nlRStIXKmVZgi07GsS/dQ5YmevcpxRA4pQv2sWcnkYj/bniq2
++vY4vWc2+VMcS3x9i3JEzjRaFZONLcrsq+3bXFltzPBsUbfWrzxlh37rpE6FNdSZfbUbLcJMHLCo
+U5E14w6uFfSCyLij2foQgY2oWuUDvBkER0LvbUYHxUzchR8RwpVxH+xULf6J6+LJFm60bujKRSdV
+L3ymJWgXN32gBd337CnVLKkeNC+h4UtGy8unmMblsdvyZJy/ND+KwkEczSzUrWFEvSX80ePgy6Nd
+4y1YkWwV+iNVQKxCO+dW3mde0XxdnR5NdEfuj5icrjNaPvCm8BRGoxHuyIS1/Ynxqtz4OM/RV48y
+dVjbPFZZqmZcKR7PI8IulDP+a9UuEv5oO5xBlBxnhJzpj3oLLa00BEmSTDBOkZOnNWwi4Y/q7Dqv
+SWDaD5zoPRpR20d9Eit/jAvb2L3D0sxKc5FYEsY0r0Bp8krwiR9n5KctA6iolzcox23Hl8x31Pt3
+vlcTzmubF/dagj6xIKmF+nEPRi0nsDPjUZ1DR0fpGmEFhGRMHnEuXsQXniW8kVfO4ItSzrcvkm+v
+TnscVIwQVXZ712kg1U3bYNuUHRFWbA7z5Iqrcl7Wd6GoxlSF1TaP8iKN54WmenuzonaNFHkqJIyW
+a6iVyDPVdYNLTso8CeejPklLmbfJMEiUK8AtKwWxT5Koq9nBQp4egJ41M+MgCWviysIr+2kZsVtw
+OLNpNFIsbVEb3p2RMEVGADPojNoolzMqrauiNpM4cLSnG6FO0Ig9vgEeqyACxgW4XePP7Zx0q5PV
+QWeU9lZiQKQY249dxxnxYusFiFRrSovBkUJUE77z9FUiBCO80a6JqKJIKdU49rYj3wfwKKcXdclz
+Okpdoo5H+y6nQRcVWaIatIjFgZ0nyTMF1Viq2FfC0bBf7aZ7eLg2HuXgl2IE7/NFKVanWXubmch/
+sXYb1mhKhnasdUVHzbG8ZmfV1RySpQVhlPqEOaTuy79e9WQoNWcOkFK4oywSRm6vIAbIjCWe6qC1
+FzqIGd1rncJ5xXdURktO7G7GeZgFbBFODaCKU3aRTI87tOO+8izHF3nbB3yStWTetLBtsb9vmEJl
+OKNaJn1JMHsWb6SHce2lH308gQh86sEnFkmGAyVPnYoiIJTRY0h5pAgyZcYDkazh3aeHu++Zkhoi
+imALRPPTiid+DqgNpA3zefEh697pi9TPaMYxyVOB7yNcCRrpPdypKcfFnTGQurtx5eCV1zmxsbP5
+VrtcTUDpNIKrwmJOckNOrzV+iln0irt98noPmaxgcA5UhLdu4xVpmxQyhBMdoZv2GrTDYZvi6lhE
+9sFoCbhYwB4jm/362lzfADmtrPQtiOPxYPvkKCgDhEnQaR/fdWUvzFRVuno85vM909MRKd6DTopm
+HIxaI1NUrWmEgRXEHM8ILaAX3Eft51pWnW3FMa0HXdrVgmT2Ie4YZZZ7tF8b2rjoBItqjO+tOV1n
+LJQI+UU1efS+ihKhAQ+Yfh5s92IE61sv2t2XXBYlEEFnEnX8LP0sHEmu99ilU7GiEfdxeBDvSQ+Y
+kqP23bivtg/nd3BanhCvccQ87ktp11du5XgiD4vQh1br3YCWXZYTbgCZs8+yL2Z2WEjmD5AYbzgI
+0I25C23RDtDZusGdbsvs7DaGAFuncZVonJJm+fBW4OPMuDWcWoGBTNnKlBwUIKOQJON07ICkq3Df
+jJx3o5In1rCAUc0XGAObfTkTB0zB8QiR05hVcKatHSN0qTHv03dk98CDXg8RNMR8iaX8UPixqFZK
+1blcrax5JlWkSpTKKPhlR6RdxDroRRePoaK1305kW8DJAPluMhX7xTWoIlal52v5CoywycAc3Wrw
+RuxwDWJ/fJ3+XGJJdHfkB26wE7In2TJJxEW3OAKbj9piBQTE5cQkdOBWOhzKMKOTy/eQExc9lhtH
+yFcp3xKsmb7rHmHpwC4HNZT2Llfhym5W2YFRhFsgIshq+yUy+YWrtntvaLgShUrdU350RaBgQudt
+4LVQ9KPtCQgwowOuRxfgdhiiJVVnVMOo8NE9FX3eYl78sXQATDjlu7FGbR9T78Z25a39sA4zg2mD
+rNXFOwhcyyu3Eq5oOaIIjfnF0PSXK8oOgABS4nSgZULdADYdqs1o3i5CEkvQaQDwm30IH7cbq55K
++FsPH8OczTK+ALSOvM8XyXwZjbWNKp9le54AbRGlVC+X+YYXdNXgy1h0OBG81EhTW6qnyS2g+wNG
+FNPPCEEESVif25j+yUUJM5KXmW3H2sPRs9IFrdOuOhZr+KVF65g2fdvkrsYxNnNZUDgES0TSEj4h
+VtOOQtRyarvwQGoLJZWML6e1NwOiPKIJCVGBG0u6NtK8eOBCEC4PNOiBGnHmJv5T+ATd1K3DAzmZ
+HjxQLvrWIV+N+VpVQdKYky8GncqXA1BuTvQDx1nY22jBLl628nVrXQM4i4QXOudFRS4kqkKc6mE6
+FheCwhhhduEiBQR93HhW49pcTROTueLZH3p8EKW0x81qgL3CN+oZrK8jq6fpuYvWeSAA8V7Rcuv5
+AxhL1O9TOt1z6TqagU/K7TVA3pVpmHEIYiddvhvnVb+vdd99eb4cHVdgPVj7UOg+e5TjhRxOBKKi
+Yjqx4YVSlN8X+l0/y0yaE4tFDojXUa1I25HtbGUvCsM4S3TamH25GznJBXQeNOYDeQ==
+		]]><![CDATA[
+		zBVxiNsMwh0DTHoXEy5IYtd0Xo8b9Q/jkMM58A07NTbtoUgo0Lgy13XfEYqA5Awfxt1wUkRCZg6m
+xwl4NLXY11al2DGqNndkgWOE3ngugYYXvQ5ZwYZPkry5TmyH8VB8CMsJTYParPbEyGmKuHh/xb83
+UH+91b4VTa0eENrZm4wtskSPCKtogLt8n1v8WE2nhCZ2EyFUzRWNqVL92lc05MRUNgmRV21iWjVf
+tKKEvqh9Vx1MHZ5g8RRVHUFKI7v369H7BacDjUi/HF/StKVIWhcORlnv6NKv3n3ou9oY9y2o/V+l
+I+u2YyPj+ircS66D2/c8aBKLk8bgxzlPONPYwT0dBMkgaVZu1qhHHSTAGsR/C+Fnvkit3qK9mGif
+Uh+C6aLFm/Rub9gjHiqF7vSmcJvCcAKCFY7Ioaiws1sENZFwyGoyfelVjiNy9thi1fxS77azxGAC
+5ShrggxPJLThvvUo2MZl3Qr6SXThw7ZOgwpqOY2Ywk0eKbu/GlRApNg141bTez6EKBCnXSx3oLWA
+0VNlDqAcidVVRUUKSH8MIFzLw+WoEJ5NrVP0xS087BopXMu6nOnqmf5J/FY4s1Z1kokfJX/FNs9z
+JqYzJXVR9yXhRmSk3Q+V8C1bDRGjXCAgwP3xvV8Un7srt12ZqjN/Iw42VOQ+ae2Q68zK6/UwPySB
+D6OHe3nM5sbDlQyOr6SR57zY2pUOEmuQgfJ1KgO1RfghRHOYBAmy21Gtaca2JK9u5wRdzA+RZmJf
+h7HiDVXqdDCsoQhimfG15LHOIX8yqeEhlErmlXh/x2V0FdQCKo+Y6QxQVWbj8docLKFD2ynWODVz
+agO2IthxRNlPNSsqTDitZXYjDQWsIzhI1lOyePiH6PYWF0PE1I15y5URk2TG1C9YhtNtwm8KWDn9
+q3PjCpU8ZVCWBzrHFzX92iiCyFKMFNFF01f9wq98uOTLvlVIge/1lYzCs/33EVHwh/oCCQU5u99b
+QOHZ/vvIJ/AVfoF4gk/Zl0gn/IsJJ/zoe654kEPx4PHPn33vj4akFFzC85399TuM8z//GBc/VtZf
+/efHGHZGfbjcnHKK/6zU0gf8Z/7JI7x6+k+r578//jy99Z/CS/Ob/zb9Kf9jf15ejF5eX77S13/6
+CL2f/tTuir/+xjNLPuI/PWkAJqtDX+IQ70FbXpbwaXihIQDhokvIKJBpf1fic2EUR/IpW2TPMPn6
+MXvphJpsEiaasclD5x40N3VUpuOQPYwRRF7DDtv3pIsw047cATBAlRDYElGpFeObzI9vN0gCo5ii
+VW3MKUk4lavRZKuvBbUb9XsaZo3xp452r2fxt30BJvX7cLYjX6v8669/+OnTbz7/xS9//VO7+HmJ
++y/UKSoguPfPss8U+hspxAhaFt5+V9EDKeaz/Gt0m1uZkJ958s6I92QjmmydPm/paKJJ0Jhvbyo7
+N3rQXvuM4sBeD/k+idfnk3roVPPyXkdpdAS8Ox/9z1ez8Nvm2cLER2SYftdpflK//a5CuH/+059/
+8/5Pv/n8+MdbUrimUJ5dxxfqLcswIYYI+ar9PrIttheLAdY2GC6G/sIcH5G+2TZfGqsb7y9O52Fd
+fAqb0/kY+S6fjRxhv74YOoit8Tsqe700VjdihNuedTF0EF892ctJ+C1rIb37t3/2i1+/+4G9uHef
+fvn5v//yN7/42bv/aVvLu8+//Nk3r743NA10tnBYLj6I6lUcyodnyND2qtpLJiLp761+Fskiw1bS
+3L86mrzHpj/P8efj/vMcl664tFw2DVlf2D5pfeyspI8ubThHPJlG/PjTX1vk3+bzpevFpS5k+Wz7
+oPf6+tLy6nl2qm89uplfztLbtvZi4rmq2qt3tC3dwXe8wzZevHf++YhLR1w6w9be+PO3f33V1zd/
+DVlf/Dqfvbxxo2/b9Ozp+c+BSsOiZXJlowFvEc1Kei0zdjKMZ0e8xLurtXMExtTPFzeXxjDj/LZb
+KGw38hOUTT/v1uLox6V//WKd0PzzF+ZhpcLy7tnm0/W/Xl46rkW5vW49ejAp25HDCRtlPCvdewvu
+i+N1x6i3bd5fyjFvh6o+GdH+l14MMP0DeDnA3F8d4ZnZCllir5tqu43LGAOUty4ub4xa3r6BEjeL
+ytCTcRi0/5XxxRQccyEDxw6ogs0ri3NGF+2PICNHaEjvPV9br/k+0c6b7yDMM792i1xa/yin/mwO
+MVzSg6MFJlTJiWJNDn/6sX4tsUffao1Zd8tGQvuazgAieuR3F9HqcFExi1vTVrDrTawdPPlN9Gzn
+K79eWXx567jnt23Hx1x/nogVhDtqKfShn9yZz9YbLg6Em68ujUUA0PfpxnvhYP8wu/a/+ZH98w8w
+zm/8/JuiGpcABfQIYKwXZrMNVr0s/Bdi9TI2N/pEXfajzj0s5d9ZfEwM2U1c5NnIk3l56+IWBVBC
+RJ+NzY1xtpe9nIvL6yd7NQl/yBhrFF/T5Bjo6sg49n1key4jq0jPxuYjfHg5grXteSJwFJYIUBek
+T7yunE8jVE+he7Jqec5utMuonozRXxr5nq26X9eLi8GDXV8Yd9zD0wjGgLVE/KGLDd2vXGIIGbQX
+Nibh+huXWiVVDdqSSrvwqUbq0S6wFznErTmyBhVeCcakKV6tY2zOoRV5ZdlLcK9dxhSAxmNcgJiN
+VyNYI14/GjJli/1PBachERoZP2kaWusvL+5fNfLOhPKDTPOuc4bVGtRajwsbN4aAD4XRHGx9/vvG
+OEvwfZP2bgq+QlWsO9XqMUZWG7W254tboP7K0ZQ8xuysvtcIlbHiPYKvOtvNe3lhwxd53IXMh462
+ufodwqEodwkzFsZYyd7n93Rxkk7GmAc0dozrzgUd+0yHnDtdShtJBYrbuN4cYbudLnZKwUeIp+R1
+jbDF35c3Lq1vjVm/5QZkN9BI6FLVeK5QDwjjq0moMWNzeonQQkyUTWxuRQUxlkuyHWM4pfz64sHO
+CAzL3qDLuLz4ENsX7eCFyHEx6WWTnzWejfkmMrnsJ9IZktPAemZ/xxCiJoy8h+6tnE/Xdm6KgMhz
+Ii9j9qruNcBp5t77+WI7oxDgeRmni96+HMH6SihTNixpssgZHt69vTR+0h61Xl98tkRmN97cJ//V
+xUxXvix5lusvXme5/qOlwP7Du/LuH773XpAzChHgUaMf0+2P3cKpPB4HwL/83nfPyP3nn/7d4wH+
+5Kd/8zofdyfGv+rfOf0GurrTJFXmKT3VJuQR7O9ZEVQschnF6UVjlMOdwgWp2+yypxYos290Bs3E
+bv5NeeL3SM1YW0adrED2EdpdQovlW2E5jUXQYF9RvTJcYVN/BPuvLTMByRTPcI+tbAdaD16MsBO5
+Oe+f28YusQWmQKMwTl/bGCpS20/zY0ZQJiKzQ7Ki+0q8AP3aDihTczyEJ2fQbPFtxup9Chzh2KOh
+yYynQecyooR8jB80guxMlTzdGMRL8nieBhk/vZiGpW6KbQodQ6x7y4U9NuQSm9vQxsC/b07RCHeS
+B/zfNY2TChz+dsDv6btm2uvMAp8Bsnozv7h4uBTKs7FflCz3CF2Urdc8Qg+krqeVA0nsoIV5tsfF
+TdgcQwPwIawrEn1ItH1SnsnTTPefGxnN6JeRaSIjnnDRwuvi20i8wW18ft5/4uJvMeK3YoTu6mzz
+bCPgmUA/+Lmx81U+z9iz/c2L3zSWINIwR0Nhs4OwQFnpnl73F0QLPD3Ds/2ta1/b6k3hsoORf57+
+hXBO32oEU0DU6Y69SFHjnzAWh7VFZtwdpNklsipP+jTAMfqFH569boz7Oxjr3cJvpZftynXXr2Xn
+nn0eITnpetxCJGA8EWgNcF0Ei9WJsywHJqq9TQqA5z83TLQHYGcGLH7taGe87um68Ok1Pl2sN2b4
+6ZbaK2OqpVzGwCwUl4e4L55OovS0PCd3imM8MbprjAEE4wedUZ0U7mmEPh2Xbd/dhWTsy2Grt7t7
+TBybfDpUexxIOLLaR/VTjG5v+xsXW1/VYlTndS7ZGBYaGtPN9M4etjvd7PHMFuIPd/hS6OEA25s8
+b59vxuZAQlBmJolOOnw2jB9ezOJ18dhSEnyyvRg1buHYhXW5jNSY+0edDRPV37PL5Hh8BEU6GOcI
+bTuGXdaElA+c/7aTGfSyVS8f/y8dxzslKmn/udsHxSVAW0slR/tqVlnXXvs0EbwwnjnM3Kov23B0
+zwsbUGWxcvUuaP/5SzsJTH+uNGTetV12Py9J8fcyxvKX8YMWGjqvny9uX7kw9W0zuvBeXg9w25le
+umzL3QTPSlVZ6KuJ6bqD6+L4LK5Rk/N1v4iZrg/TyGgJHr0u3sF6cz5AMGWelVrIKhv2pxm7jZqZ
+FwNcZgAcf/7i0faRS3z6MSElzvPqyk8v/MiJKO8RSnA2jUJpIpQ2DZUTz6aRS6B1rmGfjMWjrqeo
+9nlkNfpfj3aNEO9dV55jclU1NpGL5CxTw46syKHLaLK40QJ+FrpVb8gnFR8RDwJPbsTiiZGuJCo1
+rDe5Ed48fr15qgMU8fc5eP73b3717uNPf/Hrb371i7fAIMSAoHvaWIreQTsZZ+Xy3Q+j7P95nJep
+tPQ5NvSMx3lsapfsBYKDh3E7F6IHe9mx2Rohang549w5motVfjy/6LXU1/anO/m55yl+8/i/eNy8
+Ho6bMM7v/8S+4vGVI8gtXDHu1c8v/8U8uh22uxUE0qNECzWoB/S/P/lfI+R2adBz5c7Vie6vIY9N
+v68R4l/sUFQ5o7p6s8gDrv/Nvz53el8Zj3SGfP38GOFbUU1f/6Hwkz/44cePb1735z/99af/9l9+
++fU3//WXv3qR5/n+TxyZe96nNQqs623O5vzNCEvKLvE2r39RgijYgkYvcI7lbLvv0aPMPVpGzan5
+XjR/3JcbPokBzxn4MvptxBDxL6zruXnr3hnX6FZ7tFArVKBRY5y7vi4/z3cN/Go2fvu7/YNhY/+p
+d/vD//rwTS9f7cO9/WS/RJBeruvZbd3f8XdyWG9971/ytX/pt/4lX/qXfuf/Or/y846HbUq73mp4
+qkZ5dnBruxmbEiIy+yGL2RzbuwnlO0br+Q2FgGOeRztSg/ZhUIomqheWw2SMNZBS3U8XW7JMp+oY
+9TLed3CZz92eUe/nej0Hn9hAxWkzZuXkx4B73ooky8Gw9PmUpUS5LUWYvplAFY/Qk03SyhEE026i
+ARR5iVFtMtRaG7cQxkj4Uo3iXIzUIXWmY9jL+HQPl/3cb4x6P9jrWXgxc4bRsnu/KawbVZfRj1EC
+i2lCdrvXy+6hrHLEOcj9jxGcSdF8eeyzhD7aGXa0IDY49yBjIMWSa8+ei5EejVQKh72MT/dw2a8b
+PsNej/Z6Hl7MnbPvTutzveeuCbMJDuvPgpA4l/A+FOfmOkO+bb4ygnEoXYcL2ufhMolRLS5kMvPc
+gYwnuEyI98/FlitOWsoc9NiebuCYr5s9Y16P9XoKnqctbVSphoGy7mnzz8eOAjVWnA==
+		]]><![CDATA[
+		WBJk9uNQWYOkykBAPRvzrXl77FY87UE8wlFHD+HFcwcyRqrTmVauiw1JCY3xe9jL+HQPt/3c8Bn2
+PNmrSXgxb7bMDOVf72lj9szwuCs4M6wuFhq1sPvR0HXTnZOfZ9ljTHdH2rGb7ECNfBCHHRQrerqH
+8aRgBEISJBfPxRssOqM9DXsZn+7htp8bPsNej/Z6Hl5MnTErpK+61QrvuXOBELRvVFFCAhVSLvN7
+pAPJk2uou+GwwMtoO1CABo4douVJABQfdRhr+wqqf78DGaOiWLwWcC62ooqS+THqZXy6hdt+7vcM
+ez3Z61l4MXMN/YDN/MU1c8ODQkhGzDgAD5eAPHaPKKhFPlzM5LYhNR6V1GMuIVh1xjQYHz/gcwMy
+flJKv3ii/ly8UxIY+wx7G+9buOzX7Z5hr+d6PQkvJg40W6agt58mjh2dJryZIiR5uNaa6mVnRNE2
+E6QSyT1GZBuOtvyxUyv2adgxg0f33IOMnLvibGpPFxvZRU/ledjL+HQPx37d8Bn2erTX8/Bi7jwM
+rrbf3XOXM7OMcBIxd1SCl933RZIy2vomuc0xTmrIfdLWLHvx0OBp2DFdv/npHmTkk+cLJqSLQbFS
+2vOwl/HpHo79uuEz7PVor+fh01P/7sscwbdkCL48P/DF2YEvzw18cWbgX2Ve4J+9vzb98J+1v7Y+
+/6tv7a+tz39qd/Xt/bWGEfcMyd3UZ0Cnio0dh8DH8ehVbsRDZ8RogPwhv84TtNE/eUS8Y1M2tKPz
+GeJbrpUNBxYQdRXoQYr7UQVMlyjv86hNdqsawvNCFySpAkrVWminhexoHwzirUnEYpePMpPOzOxk
+iexW8/VTgEE/DuhuOtaBqjeB+wM3moNurUTzUQdYaU7OgHbaLedEASTtvueWIUUWUsHdumASQ9rH
+Ljg18nTwt9tJCmNFoyYFO03zGFKptlLduiqhTjUGijkTD/moOB6EGgiNO6kM7PBMzn9jB5tRS6pC
+PdU69ql9DTYvLvS5xMCDckkrdPAeEwq+BR+DFZeZA5s9nKL2QxQys6O6rLRQIjk/g7h3O1fqR7nd
+zqPmPHLnJZScumsr/1jB6FydrMtx6rN10shWKoFU83T7MhGj0J2s/PnSEVK7LQp2EFPZXTOfgzSK
+iuN47FCdHNTlBVjf+Mn/WheLtnk7HaE/s62emjS4SZB9VMAmJcXu5Ml+qExboL5cvVpl4Pm92Qx9
+iahDRChJw5OyHyJrxSt5vKi/1mYTsmp9VHYdof11ibCnpVlkN7y1OHuo8AFkFEVwlth9HC6lNbQC
+6IODX5PKCBKVH2Uv1K8wbSqeHdF5CxM5mtEx2PTMIDMK1BdEt5cLPepBDLzWqWGEj8ht1euXVpv1
+HRoXZqLpoanwQX+P2AXfKRwjx836cmyLLZ6syqpg2S3socQBVHj8m45Oq8sOIMrIZ2BCek0+a0XC
+mLUuY94ZfcnIlEgISZnR2T8RwxvR50fZKXINKQq/N8s1OqvmXOcUcG5s+Ky/uuHhWC2+uEJZso72
+IVknJXxse4FilGeZwDgHI1UlNhjkfa9I6BSJdQLdPB/WNclsUTk8Aoj0x3/7sc7EG+oa2J4yQZLp
+iktBtPRjRZV0suY/zfPGZ6d4tbok9Ed9Ic6qaUV2UjCBR8uzv8M15n4coZsP3YPkB9otSqzg6PEe
+7WsAmWBUJIY+yCckb/kkzy9dxSCg0BJeRsT4UZ6luiiN7do8u07PK5yRf6whILfm9jSlRjCXEoch
+qdsi2m3Q06DXTA5Hd7O4Z0b0ZPSjYS2mIpudy2sayAm0Rki2UVjPqGNceNAS5hbu/7Uuzs5IjR1t
+xE6RKbGN3oEZfZK2eKaOv+CO+qjEAwSr/AiXTtbHQ/QZIi9Dcg3o4FynUaDGD25pfb4Onn6Ms5pF
+Yf4Ohitdg+B6hfzq8J4it9csGncxGlWnYLo3LpoirmfQcF1q7ML+XZqHV09KJpMWsAnzgKqoDeWg
+h6muPynUTk8M+rRNv9A2xtEuYRinA7PwKZF4BITtXkyxTWZKJYhzZMYUHbVox6y0iyVM+pJ+cSYF
+4nZyAzceMQckviSzm6j4bet+K8+S11Lr54sXATCFQ3ydGsqGMNKyz3JmeRT+pPQQLPHoIbF1BZD3
+eweoedUbKWL21pkprpQjQwdhJ8BW2kpmdEJhoy7qIXBrW70Xi6Ijw+5LC25QlO08Ajq5Dxw4zMbM
+u54vtYl0Za/XMxBTkxRqGOqli/7c7C3pwEuaSkCH3aXbaXdved7in9xy1beAGTPgMdTgUJhQa+YJ
+gsql8P1Z6MXUW+zx2TkncfEY0UAAdkvgNeucMbd5MfVz0e9bspn9RGTVDOdPSNMgbsdfRPGRx5Te
+0Ruzw3nDEd3vDlJah8KIMRpO63wf2eU3HafXyE/SA0c2XQk0dkIJ3D9CEJcFthHalgLGdAoiTLB6
+GABzCmy1SySA+5qeG43tDJcFMTX8Wtn0DkdTa3t7pH9ZVMIzcdYe3+CS7WkCNDE2gJ9f7FOxO/ms
+75hNXKtEX7ntaQ6qXadXE76ksuK3r6bMEVdKzqF4VRu/JeEq9AtuTjfi2g/aG5p3nIJWPy7OhQfS
+x94lGytCJEILbzq9h2xeGbWpJQYm5RWyHETYV4DGPmlDUExVD/X/1FswIzfq7colDkrul5I1mzXt
+TNQkZM2gzjgppWzy6hXEy4leYNusDVIXL6f7okHqc8ohu83OfbtHJ35WhhqBRZyRXP4QqT5SwtoD
+J1aeRI+PuUmst4EKPF6voMklVCChPe/NHfWk06eaD8EiO+VJLXLkrBVvOPaXptrV8my1GxU1mZDp
+YRDsVNmGX+hBIThdWdVihi1pqZymSCVKtB7b7kmf16OkNV3k3Ke8NYkGv3gPeEPWGvecxnwDqceY
+qw6WtMHsG/g7OHecoaS6ZR/qktwsKlruqDztGCNEFtbdj5MW9wOzEwPuK/PTffz8KYt933zN182z
+16v5R/v5pd2CsFCwdn8Ppje2A1hFf416GSMJXSiheS7eR9qzhoDJZezYYc/TJ1GdRkh/Rn0sITE+
+n1ugMZax7vdcfD3ZOD3tr6bBKwBvv377x8xXqRhteLl5GubzCUTBVCa7f7Aru7GcVHIYTTD1oDIu
++zwKuYr3wCefuxy31kl3X3ZyJbRPj4Li8LJLJ/292qbN69TMScTp5dn4fG9hfxya0XzoH9yCmqA9
+XYhmxvTQxgEK9c2frlWI/DRqGF/cwrEv11N240pZTzZDW8pl4jENR8PjsnfXvfmokUVAZuQRW/ok
+u26upSS5jmN8urdjv98zm52fV8TL1fPpFeT4u6KP//Kb//GbX/7dT7+t6fWxlKxsX95B+KI+Porv
+it9DBzjzC6D2+xxmol5StK6acXce1zoZee3kDuVhMyKYDLh5JeZhe3Pre0eW567ytRDky8l1YQRh
+RZRs51IE4LkhXDvZvFNmFNArlBKQELdMV6SoH0dituhLm8OSFV6PmxfogzKQZFIKeAdVeO3ITloJ
+bCqe3zrUQAMIc0LQ6mFztyzKqgyixEWNux1EDlK+awxXO0dghfaAT3oCpjfsc/SQFb9GyIc1EPsZ
+zw6fnb0TYx9ZluQk2k/wEDv6V3UuQALcA4LcWEodBiqPc2rJksPNYm0v4BmHrUvvr0Suu3gJ45P2
+nj7UMzCoRz4pKuvHZ2I97EhHfgCL1y5K/JIE50Rl971X7slI2T3txVGpLUxUzKeoRTbp2LR2SJjb
+InueROVNRDAzjd/OSrCDoVjRk4jjl+s7MRvd5ULmWExRXxorxnAyM/mG4fL91x4xQyHfcC2aBOcS
+cUjdvvh71xjS4Uxn9+vOdX5OFAh2ZYSacrwIT1yBJJsx8hQKzYVegs6EyifNSxWfohZRSeh9VDQ8
+6QQlOOk8oU7TtNVfgtIPh0LHHZzLzF07gWsuSmUdyXAkuWMEB+Jgk1hLt4DTxXL9qaDjfgSW9O/Q
+PY1H8JUAwlkpLY0Q19qeQqJxUuL8Ur4zB4hxc/L3yx+DMLftD1KKV2vfw1hdzOLMQofSsGWYd9da
+cpcwkIuOWfC1hN1k7XW2o1L855oLdrtRW7h9WlulHIoPZ2Pi3ddm61XIkcfBYT/28Axd5Gx1uRra
+Z91/a90cr5BMxKaa99FlMqlY7JMleVLfo5O+Ie9Tkvd9R8zh+Qqz58x0cBYD9+PGUA97j7wvV0Me
+npP/oJB0uthGHoc8OFtdZboxU1LNwkzOWL+lvq8R+k0J5yKVNpNrJuWeGY0/jBcTjuXAW2aQFDds
+H64bjXsm6x46zvlmzKfBFERxmXKxgd8zZubFZapcqyUaWuLqxx7BEdpXhexhhSTgRpLQpAYpSiaj
+ctqJISF6JQO62bJkZRWZWjKE6gojsJfWIebvDMzOI5rWq4t0wmEE6bDtUomHg1mzYCvSrbbnPky1
+8Nc8M0lg3XrMZpP8DMuThukR/+2lcW0rZ4u7gpz+u36VJGnDWg/4UXdh8a7lkDm2Gdvy5ptbxCYp
+OowseoGOOSQy2tX3bmk30XtVRrBmZK3XCKeKOFpzbCcoJsUk+NrFjiRMj5VkJDmiqglqcWyOu7Sa
+bXYLy7l4Pf52RVDYwj1aNbo4d397uoPD/2raC+QvWCZYpmZANq2blnwmxuoitB3Is8Bae3APPGIz
+Vu0fpwDVfYI1A8WCSGw6o7Slsef09GrV9r9CDMOMKlKauMQIhF0Njo5GLTNkUROZNMAG/p4ZSSbf
+AUw4Cb4taM+ifg/2/Ml+5CZuVhNcUnLogAQ3RJg9YAsFSbBbzEWwxR5Jyd2eNhFDOBB/UOa8N3WM
+N4d7gXGWBKAzMP2mqzEbC4l1tYv54/F5M7tbyCtlizWLS6OJv509lAiwyxHqtWr3ShGQRwcAH83y
+U3WroaJVYfhmdOAkEcMDMz+Yzl5fFaaLuEtuKs7h6AAmhw9Rh8wiM0MOz+fAlT9QP9qVtlyIsRmh
+HALeEefKe9izOG9sp/Kq2ZLUHlodhlJIhmzSCOaMhwqTQsmaulNm0ptO0Z6q1UI8LbIZHOFhH2JU
+g44JjazcWcarxbx08age2Qh7j6VmNnjsTQaX4usdFwcLTZZQtRkvouKk94jO3RbruRVl0ohx3oua
+N6hq9ujJNjqRxDqqF6nACZw6i6hMeoG/eBU2i8I/xpukLKT1Ly+RvQx/gnSgD9XP5uhkvSGz1bXD
+0fbKFBPuoOFcaPgo78THSkSwY0bovcX2tiEa3fvR5DKVcWdJ6RaiejoSPc2YmG5udZ5IZUHPwMzS
+ezHuQT8uGYqJlJSmfpLwjdmV8z7BVGyFD5f4eA2RYGfSvgenymO1spG5ExD2SfnXhY2hj1DDsoNw
+4mMlddYvuUVhqM451Mvs/RBWjLipFUJLZvQz+8NYYgpsZfsh0NqTGHjbsvZigJ3066FHc53LQXxJ
+AKQewYnWB/dX9E8sIgWkKWEjED7QbvZK2Cspn6Fn40bsEyzSM8fQBLOWMUaYWa1Aaw==
+		]]><![CDATA[
+		eH+Q9eB3Vrszdzezrc7SeD60MA97rovFrcEjH1rwh4xBZErsiVVGDkOC0ROqXK4CcTfHvINa2acR
+IDosWhugRqJtJO8/ZE4lC6nmim/uRUlw8DKt88GBvIa2f0oWKXCHOEMpXuCJrGcDm/wo2Qvm7z3n
+DTA4Qv/JpG8m/NXOCZj8K2eJQDb3+Ew2KB2Wh8LgtfaPz0tIyO5aDwY/360RLK2n+lrCBuBxaK9i
+gxbB1/a4PQLsmSQ631Ik7oc0laTWa0U7R5gbSsogV1F54Gqw8Kb5mc+20ymAvoK97ZkXpkpW9IRZ
+BnKLeZrto5aOcfp9KwbNooi3tMxi4BgX0b+ubSFLbUYcMMHW4lhNCzJXIRYK8pCfVPncM5FIRzyR
+FkU6u+dsoQ6K3E0mxxA+rU8K8RkKW4Ms22IBjGzcUYfy/yu2h3Xp3oNfntv3dA/PAjU/lCqhMlSn
+uci7V+siMqK4p8EwG1FWlqbmZlS0oVoNL3OHQaYhpoFqgcahoMJ5sGIYlJSALpCMIcLuz0Ts27BQ
+2qbaCbFb5c6jLhJTXfAnM0+6oo5lB5DBfeOG4gOe2S/d8sf68LqyufLDqmTZfqcxN7ctFNRQE5jx
+QNRozpzutEe6iOEgiDl9zrNjWN97/qCA+cTQQ6EnxrQsKFQOjHZQChL2SSeUBTy1/0Y9MdsDSuXu
+Xyw+iMwq1ykYTJn+SxTRxQIZqlKirdQTzgFgMLunjYCKWwGs5YNZZm27X7EfIDDfKngRFgD45liU
+5Egcv4W2GXpLYmj6edIRg+20BpTgAa0ncWVcwZ318cLcLhKjlXAEHMsiH/c47QUPqK4VMClh4/Dr
+Ht+IaIBzvmh8Z5Axt7wk2ZrrJPJAOjvWouofta2+FixF1oIZurZauE5fxcyqaO4hGy41TAjpfYhs
+VpW83ePgNXkPPNmYUYrSlh9JzGtetDZ2w4Oluk43CDlmz9KVSB1YVrJIvnpbs/KHKMyWykzFIkZ3
+OobG039Hh5W937k40isGYBKonsbmze/fNzkCsV5tk49H+NMgROnWyjafuFBQmsssEm3fV522AmV/
+z+8MadJuZQZNwplefu0gLzKEoG9KPrYhcJo6VZNcelcn/JRHNwVWkjt2kmT6PVTXHqT31iYqhgb7
+dLNGXS6J3E07yJOhPkSolvQSstXIEnhgmx1E4Bsu47/ukpefzhQtBvgp8hPWUbCxu/YU8SbgYUAx
+d6qDxxjR422DkzgKiEqNEW1v01XCcMNahU4CorysPWSfLajtsObciY/ApXQS2o7yNEKcRWseYucr
+abB/o2dPmlsfKpMUxNvGgxTpw2ZBlqHY7BUzJKGyvujhqfzpxblrKig9esVWELmvzKAG3MTabVEk
+z9Pb/WOMIfXQvDxt7NFRSSkSq1tYQa3vGqfG7//kT//ZaTCC5OT+7B6+93x5xVe9xZ2IK/XlWWJn
+s5CfA/MwChKruQTN4MPY1mKQ2liT9BEs35qkxVgDtDA8N1u/kixv88nz8k6/13xjKyqEYQg3Nt29
+QR8NvAeNfTChtljQ0mPwpLjOVmXAOAfr2fajlx9FMdsGxkW/Y7kvP/NbnxvriBZKDFGYIgKRsQWb
+ZL6XCttWxo7AEnvfYppESrVmRHEAAcas7b4N9URlUd2a0ZPVFtGkskkVwxeFU7vlUa4xmBWxE/aY
+Vz3iHQ7Y9G8YFkjY/th9nz490P/RMwjKbH7IQ+Sej5wxBNSKGxXg6r12z1+a2+K2s5Tt6IxgfHXO
+Wun00IV+eQCeBu3fFFVmmJU0Ww5sxPTA14w3nZHxLrrPOpq10I3vdIaDXS92inKgthntq/hwhkhb
+j9h48IOcvEe0BgwOkIf39TxsCLmuu+Ba7BWJCtocvNebhwhu9MKmvTps+9dcPOKjrFg5CXfBIvG4
+5riw5GmLK62n6WQDj+UMW3xVw88R83QXrDiyrxIZZY1Ri76qRbrOhQMvU9WKW2wyGsJwKATtpx2q
+N5WrE/koF04s6tTJRLHXr4rqE/DC1+JS6aSG/oeFWtOrws1RQDRS3PYkD/Qo3cDqiIsk+QT+Ii9D
+byFgQdteEYLl7OQll+fBk6DitR3/gF/04laNAtAS/sNcLTpofvvm8IdWkv2dGbCeA7fvBJ55K8D7
+4vDuC4O7Lw7tvjiw+/Kw7suDui8N6b44oPvScO7Lg7kvD+X+xQK5pzAu1VWVmQTp8vK7wsxGZvLx
+yqvHd0LjIgtSiGAQ4MxjLUIKGmMGfzdDAeIYsbfoIIi0E3en1Vm2R5/teTVrs0LfyAiLUiAL7Gm1
+MCWCNtMBkpi9VWJslihb7Jy+xbpGbBlGkEjuVVTA4ugEO4EFgwvJ8+GWplWq0bKljcXS8qRrjmKC
+exTyfBnVS5nMd1TCHwzW5PU0A81dCjbbK7KEoW9pmLMvySDgcwnhQnVJywRZuuRTAKO8uGr1obF0
+UmcDMFxVwGFGUmVhXsWVhWYyZuSSoM3DY495AO/LNZQ8RFz5+nvebrcQtYWmFdlWm/NyuzEzyGx3
+Qs1cSvfsWw0NHeugd7EH86CkbLPZ86RR92pYZFGmJ64ejlXRgVWFa2GAh9qavx0/OZit7CuRU1ae
+iuSaNmWP+3s6ifMqOCAGODWuLlrebnmnaCBxT2U2xRZb8V72fD73i6RMsMXEvFlLsg9eG0rShlhd
+9NVoJv2kHbMr9g5s+GNddp9V7WGZEDJ7A3MFwM/sfuljFxPGIat5yt4ri25m9GxgN523faktaquY
+rpn8bFziJTZPXpRaRvUjBli18XgjOLCVAURopTbNzXxXVwIyNlwuuJmFwwMp9IoGmMAysTAN7bfo
+gDHgk6exj56V5RB3Yd0gzeiYpXCWsTetXk7IQayLrcEkdUcWrPZFnsfedIStvd+IrmMfM/oRHcKN
+sy45I2EUtcI+clZrCXKeToABjWZnQOgBKrGaiUN7rDx0l2pBqkHIedevKQ6tXqDnxtLRTGCFqenN
+2X/6ved9yMC/sQ95CQdpA0MSRyMq6RnycR6LtXbfctoQb507CWDNDJAf+5B/+0CWKVCyLO4morDO
+ohOKamkWDezz7W8q2KNKrNg7uSDklHILbHOwVeIixrIf60rBjqIDFdGPR53RrivKZ7QD8F1Z7N1X
+gQ4fJNHE0ou1BHqqBDOjpTz2IU+1IHxqZENCUydJHtVIuBA2kmRptWAbXSn6qUwAvQgSKVDE8kXi
+xkeYzP2mriMHtx0Y7PuTSvQmbtxYXEpscNom4qMC96nMWgFlMV+htAmKKk1l950UQSbvVu0WeeRL
+W1H+vkeFzR7TrzV9qKaNbC6drEHpFwMAywm7ikDYSj0lUQL2Y9nxyjgelbYPGsBFoTziJtuRTVjT
+NkSaPHs55eQYgqTLXlXsOWNsLeZ7hK7NaXdtWPtUt5rjen3P4S0YWZq7PDs2DOaplss1+E60T3f9
+tr42PpxAcOCs8H2DQthuxKHbjw39UAsmyX7ZPBa/2Iy7Eq2RKP6AGo1OT+jdixGal71sl6FA406C
+8uO9t/zKCHT2NUIhkEOHfbuHThBGES1r3MJIF9ba2nZ95Y1Ds297rwP50IMXFPIHVQXZgNhPgrtT
+TP+2oTtYYh60Be4gEZoGaHvcAs91SItEy1Ta6kRn07u9Sc+n2X87urhG4bBIWzdHCu20PsREk8Ut
+Q82G5b2Zp1Cap9hDe3SEZnz9EKhPp020CvT/CJGu34dTcVXdfroLM7vbohnTmDecEWb7XnNGAKDI
+tiPSKRmmovgWVR//jV1R1rHcs28O+XGceGM3ssJfwDVyrtyMsKF9lv2xyJmMYLxi17auPHhS/mtt
+tS6Vw+EaqTVkcVpkmJye0J4h/DAq8XxgoBVjhETc8jrN0AI6AfdPeD2SQ42gY8CWY4Q2enRDxrnM
+ITa+HUV66bFVLN+OumWIz37oOVvTBa46xXXnrrDwa28ZU1YbDXJnsZkMh0+CmWHrFAZhZZyVJP6y
+0H7lBDM7nz/f/kVaw8VmuJGCPGMFjNeC+S0A1eNz7GcENU7ZM1ZdTMH7coKYxOjD96d1HexaJnhB
+bbXmObFzAgF2+m+HJ4C70vrcthyd21t0taLBwJOxtui6BuBuajG6xQkxAmD85lkXfTDoHJVgf3xC
+2iGVjcku03pqsllZczls9OF15qvnCSqUwUrO7XPSRynS40MJV4JVezofbyBe7Mp5lkHThp5i40QT
+cuf+prU1PX+AR4Aaa3z8NU0eibpKTUt6zTgA7giHK7fox5FxnJ1MZ6rToY0ovXEfaouZeZvazaPt
+qP3eC0uh3b4oXewnmD7OLZwRLIkyrkNB3l1okzE0ggogPEvwSh5s8i0ZjZFF0HO1unuvCfAfe8TB
+pHnlKfkWGyM8YiByU4vzY21pXM8gfsCNUZuQhHLxKsZKJDioJd4bcUqgjqjaSw4pJrqsTh5NarTq
+v5cMqOUWg3BATKvW0RjxAOyNZF+LWE8Y1X8mcJ0ZmxrNrqPVjBC9nGqfnc+pEJ/F32kVycqD0Xji
+ioHgFbw4ij7+DJB3NHc/coviVvWm3e5sNm/sRKZgFe3Sjr+0rQTH4c+yI8LEDqNTXzMuQ550EBH6
+XkTpejucRafXqh59oON2ZJ1/at1qq2lTO1FZTX3D14mgOCOy7TkzRYnnNLqoCW+V6InuHtOcc5l3
+XxnGnC004HyI9pU0tJWNudnGB1dzNsM2yCoYX5+xw7HvMbfI8DlRBmLX48GiPGduh2zBiLAXOU0H
++x5RV8tsOoCY4DmZlU3M/yDMyvan3QnaEzgne18zNpLnrmyyCdkONbOqXILXFqe0o9GBWtif6uWG
+S5tMz60RFz/Caka36qtZgcS3oLnkazMjOr63U55K4ZcuNY9glLE83Gl3s32DdcTHqxLSajMBi9Ju
+FwhO6D7eduxGp9Z68qStKpGm2qT66jwNN6/0HLtC///2vvW5rRvZcz+nSv/DubuVW07VmD54nQNM
+araK1CPJnWTitTMzmTs15aIp2taYFrUk5Uzmw/7t279uPA5fEvW07JhKZLEPgNNoNPqFBgC4zWtm
+Vrc6uUAub8KT0+1dvFMsKyPSw1HxpBMqsejtk2Nlklhp2BYRbRQKM7ZxgYCDcYkV2qTitGTMR7Ho
+0srPcmymlmvUnWzOjTDlok0QkrGGglG7dGwaQJWA06oLV2/jcn4+/YCT0WMDre2IUN7CxYrI2Yyp
+HKxSc/6kwOSUBbAhx2lK9bhq7MrmRp/2IWA3UpthPh6s573q+CKS+iVHyYSQUfXxdsl09gTMgTad
+G+jLVnBI5mDi2Vf5WoBGRDifB15OdqljzocEe3OENgYY+cBwn1Y8aqViAl+6bt5jj2sjOqSTeAqw
+rHojSzgtBQEoiwihXFCdt81jiUp3dKDoRj5EJL/L8JYziFTrcw/SmaVBzowqDWgf82xSyjOY2Pm0
+9bWoirqRcJsTP2KDFsJVMm+TtpC0aYmhlfx12E2csIc1rZSdaJNbBwcsiS8THQRWOA==
+		]]><![CDATA[
+		HRssbT7j5Z9WpeyNGHALcvte0i0xCKdMV4vEVHf4PnXOViCf1kTfR+VFe+Fm6CE+G61owrhB2sgK
+sQCjp7eshwJHqzjfqCTbcoZlTN3Mi67I/Exn3cXIFqSyJKWEmKlSHJp4uFPLfkXULBKnQZaxyeZ1
+OntOLYk/HfdHw1YzdV7yTMcohnwrI4c4o2ZheVI0qdYuqaeQs2JEILH31AH6tCcl+I5rG3fg8XnB
+OchZN3XML8lRThXj8y7i2vHqnEi6xoakb2IwAiLRl6Qam6x2thuKV6nEaNZ55waUSJt8B3Zekm4L
+aUW95Nr6OieqI+jmktYMKeDWapfsidQqX4TSjRRn9yfufWctZJLKKuugsrgpBYtfadJeUmihuNE9
+RyPEJ/JJNcWYCmtS1xFCcRciOpzDezH+43S+qxURYhGjjqegLg34uIqHFYlYlJPXZMgSAsgFDnHT
+li2HSQg85tq3MW2bgSZu/MqmeJN2IWBJqENFPkw/CCvxQU+xX5JSXxdTD0otbYnr3OhbjjduOiEk
+LPwnqywvnrTiE/OiEKdyZV3i8m3pWWY2+V7kNh0rUvRL3V22xejULh5jqFNM16Z4GVRYOjmSjzjl
+YAqiJcUhsXGrPx9w15bzx+Jm53hGqgDjOTLYltPYzgkCOp+UwVwVgXwTPURYPAyPYSHGeVQ51QzJ
+JOlIq/R6Cac0sickpR3a2sQ0Tr4hs9Rum6iLchqZjYHmnG0gTC8HkrEuks1kK6pIZ3doQ9apNHH9
+nNNo/V074zTWv36+aYTfINtU6H2DXNMEvn6maRRUN8gzjfBrZ5lG+A1yTBPNr51hmuyUa+eXRuVy
+/exSKXyD3NJou1w/szQaStfPK43gG2SVCvwmOaWxx9fPKBVWukk+aYTfIJs0wq+fS3pvmaR3f2eK
+u8s7U/IdKJfcmbL6AVbb70yJybMei4s40UatnkH3DAduLm83/uOG+1N4W56O483mX7mdT9l4NmId
+szd9OmaA1WaSNE5ygcT5guWyn9We1XrZ+Wrj3l5Zoop+B1YudTzZihcWiqgyJmZM6HQsUyPHFbHv
+ZW2MJrm49ZePpbHdzC4yx+KxNE4VjZEtmhAPcIIrHw8/a+X4tNyJKMix8877lAYbz5TlWz7Sbk1v
+5IhuJ7owB6/SHRaOg8uRjJJwhkNhitZrJcbEh+Hk6BdjZuL+Q7Y7o8BO987nZIWQEhAALMnEOAFO
+jh/njCZxUvjO9kpiniHd5dZKJjF0vc8LuThjvrExPSRfFohjgCR3UeXDz7G2JuckEN35mvjYAh85
+m+KgOl1N6E1cpatjZJMPy6vTwSnF6cC30EbRnm9saVNaA+ecuHy8ZbwdAmcHuY7F7VU0dNjCjXQV
+r5Yvsw2JrnEFQ4mpNkp8ZIL0QAkxBS0li0l8ykkE1jg1TosjwfclRBq0KRetlYuQH8u5hyqetGDz
+CRK1mCh8/K7Phzm2nUhwvPYCpxTIXILOdCpfXBhkWyuAJQIIHK1kgNZyhaEwbXQZSMHGc2KY3CbF
++njBp/BRTPNr8/HxTbwKiAunMCqr5RxE7JxjEcTnY7hKeZLJb+AwZJ2t0HigNOKNre34n3GDLpIw
+mmzM8/kXcUd1vnkg+lON6pxxJH5WWg+L22u9T/mbOLsirk+HHBzgSynymZBY1m5j3MPLzU28uV7i
+HgizCwZ8dYh4qrgZt3N8vEs3X8IBTXvQ03GvzAx1PDIMDnUbU3mt9p3TALxK26+tS1v5Od7rO/dd
+4fiWmMfC+6XbvBNfx2TDNp/ljoMD5Jwm3FgRWSE0yS3mAx/LdbOwq2T6tr24+oaDIOMlLEGuFBBM
+5SxDF8+MyMkpTSuXC5iSk+BkyUzyoZM7olMwFHYUfKr9NKOjVIRfIRYrn8MjJzLxXaO2HBUVTcDi
+hAOczrVyWSriXK34Nlxx0eRLSXUCcqB6PzFCE8/A1DmkjAMcJAlTSToPcA3R/OKDNRGe2E8rq5KE
+xdee2nKXXhN3pORNHibaipwio0rWq86FQ0lrQFZoWsTMefStsLBs/zaFjHyORtSbcTk7GNmNAfWY
+zhbk2zdC1Lq6HM6B1VefwqNtzIvgU01VTCJJcSrQw/tkT4S81IjsIhdiiDYeO8BXPMUzR8gTTJzE
+Nz6w4dCxgnEonrxM1dkRDzmoTajErSO8NiFBbS2pEPuJF10TE2ziQlRIKpfNHO9S5m88XNhJZCqz
+slw8pZqSPIntQ/E0FpduBgkx2ikHMYbOyoyccotDXvhMEwHWNZNVR9NdZJ+c/ov9791wkk1ruFrn
+o0n5rhK27XU5lAaTrZEwu5c9SGWBzMg2j7bIZc6iS4sAJh/cvGItUgsv9+I5yHb1ZBuEEJp0bJpq
+Ore0x8QIxMpiBgNuCvdx4SYtZvGlFzpG0Phc1qiKnGSJs/mRTyiIBwnwSRHpFgaVDkKD/GlVJyYe
+T9oDXNV5f5RETX0MVkV9ke+z7eY623RPW9y9JCQjwzKe/8KBi2gAilHkZfJnk8JJ9JvPiok0gHLS
+6cRkna47XabhKN540IS0UsXnk9W6UDdKQT6zqU3UlZUizkiMq9m4BCed/tLZN8UGY6OSOox5szaf
+hmZLhq2TE/l8vksptgAdGaI2SwqGV5hNbIGPgRWgE7ffsFrNRnNcoebjzGIqLKJnsQcpAoUXpQCB
+8uVsD06eSOemJasdUiXdPpVSYcqJH42WqFRsQUWnRvKMo8GGNGIVk49T7KQRF0DCzC6fiInLl0JG
+rUlnhsUUG1AgbmvBoWM2UoAtPnatRQiILcrHTNem7L2KOhnwcuYHH8Mii0TJp7HCxXL0YycbhXVM
+3N3ok+ncprxoSK+4CQRySJazfTTpRkltxCNoGB73J+LsRR+disa2SXnaaABE/2k/mTBxOxE0bTkW
+qhRum5yztUyG0QUnaWlJ05bUf4TAcz5MLWoKW+5cXiCguRaTM/PSHsf204lZruncAqJ03PCWF9Bd
+jhfbbkRTkpD42OCyJxTxqXhCsClXhmSdYiS4lORu3nOnQze/vHWp4Tpnh/uU08PB+Shw+GZCzmYt
+awZ1Os6VFVgUC8g1lJOPYeDZlF4uyYoAdqQur2JEVcdbFFMPJLTUZMdkfRhGawfx73T6/l/fjMeT
+0Zvhyazqj0bj+Xz9HP54qUg8jR9BAs6+bDnGcdX9xDi6UPw8dhry7SMF7kKyd5uS7uLzAeQQIr7t
+wKLJD9vDdMDxcsGQzrItTfCNjDIz8rs6sISXtJvhYtM0vnOrY51SkePFkPllPP7a6qqDWIZF4RW7
+kcHxDrrU5U4ThTblXV1YxGt/C32/B2Ocp7tBqtcStEJMiwN+GDNiDPfi6GQy/n38m3nk2XC+GM+I
+RxDq+/mbvS/+HgdajulkNjXVPypy9mnS0Ai/2VoEICkmv30FQ0Z5eUA/CMN9yW89GC6Gv68U2Ylm
+74ufv9sWHNzxc6Xqg6PVf3P1wdHmKrf49t9C9XUKb/t3jfJXG4EH2Pf7rb47pVf//Uz5K3yWafSZ
+8ndX/WLyfab87VffjXyfKX971a9Gvtum/A2R/yirX498t0X5GyL/8VW/YL7fA+U/atJds/oOkvYO
+KX9D5D/K6lfQcXdA+Rsi/1FWv4Z1cQuUvyXkP+rq90P5O0L+o65+B5S/wtu3fz7d6jfwZXYTHQ+4
+7x+m+i14kbuJkAfY9w9T/bP/ft/Vb9F//2zbXKn6Z8rfa/Vb8N8/U/5Knxt4kfdD+d0/Hwnlr8F1
+90v5q38eGOVvcb7fD+Wv//ntxmmv8fblz0dE+fvVcbdA+Ys/D5jyn62L+6r+MKyLT17OP5i+f/KU
+f7B9/2Qp/+D7/slQ/g76vr3pj5Ty8rktyt9i31c/nxzPy+dalL+bvl/+trt8+z1QfvnzoXyZK7z9
+t0z5hzHut1D9w1D+Gsh/2Ldf/vnIbNodkL+Ft+/2+W1R/gJJe4tv3+1zV5R/mHJ+A+Vv8e1X+3wE
+3sQdSJvbffv1Pg/Qm7gHDfvRUv4W5vv9UH474jd+++eVkY2PLkf8xm//6FZGlpu+6/l+P+N+vc+H
+Wo+7Qd9XkL/8LR9qxj2M+b75s1PU6JLqF30+rJZ58DPuDqt/cpQvn8+Uv1bVnd++/fOZ8tequvXt
+u38+U/5aVXdC/uLPA6/+sCh/ReQv/jzw6h+G8reE/CdV/bdkXVyvuoo/t/x2VZu6rQ/op6W/1K0i
+r3EcvHbGG6+dwns23Jewvfr2j64HWlnTeB98aLw1Wtf7tbkV5FXdauVcqAfhwByYQT8o19ee2r8x
+8qo+NPt+sL9/ODhqjprDwYEOhy5oeuVNKa+pujJ20G8P3VH/6JB+9o/UQe33zX59eFO2IWK7un9I
+aB/EGy0Gh67f2IHSQpXrI89NU/WLWr8+8jrSpDnCpRxbaHI95GUwDw4wcEea2m+Xx3PXdja/Xbhw
+0LcH+4cHBweD/W1ceB3kabLow1YP9g+Y8r45slZm0FVb2vx2q4Jr+81AtcYYZbfP+6sjT+xij8Jh
+37oDxRq22Z3Sl78d7NIPoU+467b2Fzd9NeTBLge+P9C+bw7AfbcqaVXtddv0gTtNG1vbWi/9rCmO
+q7zd0HC6vuprN9CNapRVFtLGxh9NvWl2m6ib3s4j2lcD663bt0f2MP8cWG+c8utDvLOa4Nmv9vcH
+R30fDsN+GOCHqtM/fX/UDIwirr8iA6W36/rIHPqj/f0DNaC5mVq/rOnLkGeFrGq9T/rBDjyRYNCh
+ygFV30aWSz7QxqwmjnSrD0i26L5xB7qVEd1tMLchb0iiUG3XJ2QJYZqgtWvVoHbLXIjqV0MaDeMW
+Lx8GHlzntOsH0slN//IJehnyaDu4/WAHNbXWWmv7fsAT9FDh6fIUAum2zaaVj2akqeH+YfBNMEda
+aQxcM+gPwpGDMdSlefkxRP0twjIhD8Wgnee2HQ3fAVWiuUkT1A5gZg2WptAS2wQzoKYHW0fX0HSh
+3g/q4KnhQCahYVg/7FP1/XpglrgcP/v8c0Acj4sqtuk9Hnevm6btt6RtBvqA2xah2LYtDWhNjewv
+NXxAvbL9pn80AOWpwzSbNyoooGg9TRZ/iIPcYxlVNyqY1gZ7iL4vkcPVzjc46/rI2/5Bv23ozw3M
+BFK7poWK3O8frqgETdPkUOmVAXRqYIyjqetaGn9NI8JvtxtQF4VwuF/3cb9lu/QcDLbGdZqKHBlc
+ma0b4tnmsO+3oC5yj8QPv90c1keXimdVHxjvdZ/MU3vktD8C6pbl/CrqENg0v4ki+5fNwcK0WT05
+bUITiA8K6qUBbppGHtr9oHa7yXmnDtxB34R9EjatbYgTgDpNMVQP9AYX33Al7S7IC+IDYE56lWQD
+sbAn6XNgCHmaxjZK4WXtzuS+DHmoj1xFKeo5mNiTJPJN4/pUXR/RNFEd8vXJulQrrLLpYxSY1imi
+JE0gpnLg2Xe47wZNn8SEOVLp3jvR7nZ5OLcjX3A5iLiI2AgkHQ5DaLVx9UGR85kVAw==
+		]]><![CDATA[
+		7i62F6JuIg14vic6YhLW9rA5aMhMMK0KWe+JAd4fHPSPOiJlC/KmJlFJA4kpQwMXBZUm0Uk6QGP+
+Zb3XdQNDoPkQQhaH6yICDdNzKlf7PmQUqqdeQkgAYcMdKZ+kIFwW4pYob5KKrHn6m9orS4r6gItZ
+Uht6Rb5utS6yZsOQNAMSMC318Ijngq+PVIub05pB8NzwfvErdplxqXFSNf0j4qt9mtKH9AIyJSBt
+iC2avifhRHoEbYfd/Ypl5P3gcJ8kaN95Yk1Hg0cT77BPE6bfegIy0ma9+uXI4+6lPlkqZl+R9CVf
+ghvFjAuHvt805AupqztDBXlliCTNvoeQrFk50ix0yhxcFATZBXmMPw+eObB9VmV9s487oWt2hdoN
+DHol5CPXkV4z2Rzxa8x7TeTrekmvdeX+FZwRKvrl4ekxDu/f++Lnb/fkGgGCpEsEjvbO+RKCZ3LR
+Jn7W7srEXVveVr/syVUndbwjy8od8e/SvShN4+SysmCcqybpAsPWhHjdGV8INUn34cn94G280WaS
+7kvULsR7EMnSMYA/X7rpIuKF+y1wrZYRtHBzeLwjy/UCLuPIV8YkuCFM4sXeAVdJ23j3l9zmwZdx
+qQLK182FEJYLOrm0eqnFDjC+Pl8SluC+p41Nt4xJo6qWe1a6r0+wfNtMxLRTttOn0ug6AeR6KqYc
+boqqVR5AUpnxrl++t0wohUvwZAAbuWJLboqLtxnKTbx+GYiLKEO6N6gLr8uFaE28Vx03/uk2ZPrz
+RTEZmK+mAgssF8YFlKq1y812gF0cunCfrlRDCd/G67XylVttuq8KV7vgys99MNrma33r6sl3p4vq
+Ea5pqUbTd2fT89Pjao67e6t30+OVO3uXZovqmYYvvwxGrm57l+6TcXzLWYYzny9dE7Ppzy9fnBOO
+26YhP9k0EfnBxqnITzZNRnmwaTp++QJ0kikJ2vwo/+RpSV/SxBSENk3N1SdXnpxChZtMT2nhJhM0
+0fsmU/TLFy/3QD6hZp6oaZDXp6o8udFkRRM3na7S95tNWGHLG01ZYcabT9ovX+RpKwTeNHGlz5um
+rqDxZ1JUj/58ejp8Nz6uWr9hIm+6+onV8Ys/TU+fzk5OFyenrx8/3uvc9tN9svfFn874mZdnTyfn
+9PvHl/8cjxb5LvDB7Hz+pvpheDp8PZ5VP86Ox7OvLntYydP94WRy8no2PHtzMopFf5pOJ08qU50t
+qmeg4JMLin5VEeaPuEKDCkeT4aK6qAIXpeGhsj++H066RaWtzRV0qnB549pRWWlL8L+8iqsT7qno
+89FwQcYSl5K2UtkBEfJ0WH0/Hr7aVDgVezY8PhkSMz5fDGedctLWWulvz98NT6uj8XgjAqnU0eRX
+XCE/oGKT8ZNK2tpe/LvTt9XzM4Zf1CqKHUhbs+lZKknT68dTuWO+U/bp+HR0Mrm4zH6k13A2mg4v
+KXt0fjy+sEQcxwOa4oTnxY19M5wM//Xr9jKRV6nk89FsOpmgN9VfhrOT4cvJmAb09PXiTar9lOl0
+uuEtNHMfL2Jbj+lLdTCcv6HJ/3wxm74dX17/x+HblULS1iZqTye/no7nxEeXN7s/Gc7nJyNpq5B9
+e4Xnw3dTavirqhfFC/VlWbjcgaBa5z+Ios6UwldVPUkSVcrFTlSKZmpFlgb935DOcrg8jXw9ZwNN
+cTJFekZuUwPcRM5R2a1RuK0aV4HiGuDQanlwcf+v3pelOXpxb6x0hzS9NvxHY9u6wY1+RhkyvKRP
+TQ0t2+0N1ahIV+E+yMeqRzXol+YvnnqJ/1HqtjtWRFTs1Z/Gv+S+NDX3hX+eVBGDDu3rKvB/9V1g
+xgKMRNeF1G4jgrjrOGi+MrH8+UTIGiJ9G6G2JcI2SqjcYFyIeWDZqIrsuDuhcUdir3TGCVUF0QZ8
+HpiBe7aJv6rHzBiEJV/nV0d2AJLMOreObFfDrWCrtPCu9pinibyRulr+ALoRmnjkEhRvWxhtMQe4
+L9lAkZ7RDzGH4/9Mzf/rXVC+7uuLuSPvp7neVtbhP7z1Lt/N5lM0nGLn68pSn2v5/67fX+zORHqX
+3w2G1nf7+mIKyuup502dLs2k/3bi1Gu+u1jQ8d2VB/FVkp479fu2Z8kmWwvo7UcDL079Ks1986RK
+PyKxeLaLOrgh6bahEq3DVUx0FxMoUpL2+l4Qglm7ik24f7qIQbyKiFL3j4n4DQmTruXwIbDZbv5v
+wlB3+KjYOJW5Cpa3PSm3mfU8McUTWJ+ZSwbRFjCPx9qT6LV2xwu6u2FDddmmssEq5WUY69sZxos6
+K97Yuh92Yd9hTT3Z+hDGS+eJ9L373Kxx6o0V0kVdJIdx48SxT1YhrjM0MgzkByXvQtVwNKIxeF/D
+UzzYiwckXDAcdemVLo5dS84S28L4tPfWIfGaL+6M3vbArj8o8aDTpDkdG/Twb5f8XB6+K/fzOoIn
+yDOSns8Xv07G870vnvzxdPrLKX9DpPWRegzz9HwxPzkepwlHDiH1DBHWJ/3R4uT9OBd/sh9DsUcn
+E7gRvxfr4eS0kiIC/koEayzzu83VyNcYvb16tV3eNhiS0OzUoT8nl1Tpxp+p+9PFs/FoOjum4cVT
+NBBpUK2tYy4tttbVf9Ff/yTYL2Tz/VD9/R91dbxHz55JyZ+P8bLxq+rrau+L6lFumOPZhNKAmLN6
+9Of5+PD9+PTH42OGf10xftXXVOXJ0+FssbGXg8n49PhG3eQWSj/rHfvV6U9pYTviF/dCWPDibmj+
+MvlxFgtf3jMpWLqW18vV+nq5oq4q6qre0FWUWxnCTtNXGKz96enx+cliWw+vQLBbH/YkkG5/2KnO
+4b/Go3PgIg+5iXWhNJicj6tvptOHI4k+DJvuLlk+AFvei5i9qmwdvCzCefAGY5CX9MhRPz4Zny4q
+575CyMqoWuNfHbSvHjvdQ/BZ9VSwbXyt/B68RpODwW0J7ouJKHYLYqDV8zfD4+kvXzEaHSI+6jzs
+DU/OaJKIrUBFxmm6PFpq4clPJ4vJDgxIxtez8ZD68WY6+/dXS5D349mCISquzL6cnB4vF3k5OZ9J
+kbpOsOPh7G2qJpDp2XCUIEK0s+HJ7Ao8KhSSqNb+dHY6ns3XabT0eDuVVlrZlU7Kpd6Ap7Cs+OG0
+9K4z5A7F9f5Qyvw0PHtAxuOHsyx6NTtsPDRr5kUaoyaNkdLVXVgYH96QytxYPxRL6q5V1g309Z0p
+lE9R4Hw7PR3/Opq+e1k9P5m8fTgi55b8VdFwP756NR8vEHF4s67fOg+3a7elFnbVbY911tSv5qLy
+bYK8m5y8+yoKDjYC/nm6OHuQMqmnsbCq7cUyeBPbXlcwPZie25iCULuAtWWL38Y1YQdV9MHl84MN
++BSR81VUd521btLhxV/4R3X26QaF/B1K/4/As9zkTSr9FS+bIJOD3UhlHRI5ApKFP5wf+Smq/adv
+hqeL4fzd8PV0hvy4h6L2PweHPiJJfisxpb+cTCdkWR3+OuZQkqtD/se6nnY083u2bsOdCoC7nvNK
+3Y+0/7RZZV1hMMvUTdtw9NFh00TAMm+NLEVEDj5qprlLTfFxmghfVSlE8tkcuE1z4BnJiGOEufd/
++NsfP1sDn62BexXxSjc9FxRcbaOD3irudbif+X/XU959NgbuwBjQ7WfueFBa/9H+8N30/NVk+Hr8
+oCM9v0F1fz5fnIyQ6vtwdP0tSauHs1Z3p6HguK5xvpicnJZkw+stbaw0suvqxhVTDF6/AbdtSC7A
+gwvTCqTmrmiZtMIyP/n3eHnN5XgxnCTxEHMOwHGn4/l8ObFi+HI+nZwvxvlJbpR69+/rSpLPy6u/
+PUn7fDQ7efly8mt1NPzlLoTtB59ubm26qXrTfBMmmb/D+ukVhUek4bgaEnv89Mt4+Ha9Y+tltvcx
+l/3P1NqVO5uTutympC7p6/B09GYZcnK68n2eUFmGT88XFxDpo/KlJYenbrFHQfNGBV5RrbGis1Vz
+2rvUnPdsIFywZN4+mLXie3D5erVuebOKbIhy3pq4RepDZv7/BhXSyYREVfWMxM70XhXSR5Fiekuy
+9eI9zWvd31JwOyHWK3SpcZvSq6cvkNN1j0h7LRnW3VBe4fU4HeTRwcn8bDL8Vb5yuSff/Pjyn8+o
+md9XS1Uuo/CT7pYvwuFRJNIVLY9PYQQvGj77efge7vD1AjLNcHKcYuvJeexcVcaYi4a0/VSH9CEZ
+NJ+953syVqavFsRS80XZfvNAopWfVyY/jBcRGgv3ITjNubit5kVDAD/k/uEHvNImQeqHtLlaFMXR
+bDyuSL0spoibrCrk7tPtWni5jZ3dgdrnmNVsVIsOMtp2ge8lIOPrDlBtKqliyaU2tZTUTneBm9o0
+m0oaKRl0z7Uqt3s8X0RctQk9ZY3uPomNB0NzQqnOE7W1zjrqBFxHHcA11Am4jjqA76/ACE+f94+H
+Z/TtxRmP7YtvXk6erfPCN8PzOc7KqAaT81nPv3y1mRmWil2BGxIvv55Kf2zcj3E8XAyfp5jmk8FJ
+qt9/vv/dd94dUBvH3P6X/0Gf//n1d/988/bffT/68/90/2d/NATwP/7f/wYtuKkPmEbG58nd/Yry
+b9A8WQxn1eB8hr099xRIec7HNh++ekVW9IZACj+WpxfEv9/I5tIdZ8ijQzLpz+bjC92CtIsptv27
+zhpbPy6mifRsOuC/nhzH5YAl8Lfjk9dvFsuNPBtPSukutFM4JLBEiJ7dU7DnRjbSve+kJQeRvUov
++2rvJwZ/q1Pgp9nwdP5qOnu3zv75UXU4HF2w5N1pYtdZkG2eRaobzy+aL7Pku+n78bcvni42gP/S
+BfNsOT1/tz89OxnP0zo1Q89OTp9OT07zDJD30muPp++SQuqsYC+Gi/GLg/FrMobmG5/JkaTxWa8s
+2I2GE0L1aDgi+0kWs+qVZ0/Hs9F4FRF+9v3J6Xhzi3+5oMW/bG5xNn41IYn180bo365sWj49P33L
+64CDyXS4wbh8ej56S3/mEtv5JJb8z9TSzhs/venVdV0soxevCk1268qd+AI9XbcsA7SDRfBgFl4+
+y4fP8uGzfLiSfPjM65nXm4uYXfVq2+oLOF5t5/fO4TtXYHi1nd1XG7xrfr8bJdI0zGyftccnO6PM
+heqj53Tx1z7rkI9Xh9xNvPnTlQ0f6hiZzPy3f4yMdOy/T17/e/h6vU8Er/57+Hp7f2KBKwm6TZnX
+GbyWeZ35G3tJ4qQu6nw86RewKkLp5Pj1+CpHyX2SKy+/8ehs9/65z8vGv9ll44eYq/FBTybN/klO
+Ys+Q7SeT5iL5ZNI2a6V8MClnH11+NundCcv5aDJbwn80n40+3Mqb9EV/WDH4d4IPzyeLf3Sl4POT
+d2eTIgXXD2Lf6TDKjUsEcVCekgxdLCHGZ+gfnh53TtC//Cj+p2TRkyMk2Dx9KS/Az6O/P6Pnc/KX
+QIF/YJx+nqO7K+Cno6WePfrrmxMsRRUwcx1RnYT3Uume5we+/rLa8LDhh83mh5Yf2g==
+		]]><![CDATA[
+		zQ81P9SrD1Wymx89I1b64Q8IFfwNv3PtHufPtzFw+6h1X1ZSlEB/o1+loIsrvm85rS8Vc2jQddrj
+3BmdCurcnkZ7OrXXS8evotA35AWeVvt/8MvI9ZqqXsUtFW3qLnY9vitqCbtU0C7h19NVvYpeKqnr
+DoJleVvG8XxMJUC9HzqNMelMW8oBw1iWoD/8wbS9jGImS8ExFnU1kyejyDeIdIrq0qpGq0r3loYl
+kfFHcrdfj9OYLA2yWR/lXBpIrgy1Xh3rXJhHsTvcan28c2EgujToKBpyv+IZTZEAIZNVkG1W6JpL
+M74//KHp0JZxsMvEzeWZZvQwFY4YrxA4F2ekqaOFyMyrqWz/3+ezMfPqEpd2EE0lmnqJOzuopRJ2
+mS072KQSulA6D/PfxpMJNHOe/svjuv64O5DrT5eGrvs4HpbDou13Sawk6bb5KISVwqmVJCnjGQv8
+9HcVl5W7eyeXNryxTgfL/enZWdKrFzSTinVq4pCal+jzJVVzuS296p44dklT3aIdTH4iuwt3SVXP
+z0/Jn7+0mbXyaOvRD+NjotGM5uB4eFr9RIbdfKdzEjZX5Caf/jobvjs53rGdUporX+1czm5xrv5f
+56evJ7yN/ORs156s1uGGZEo9I1tgx1aWKnATVzx5Yqk8Gng6KMZJNkGudkHQ92SFLJlfe6vHLO2t
+HPe+nFG0t7pXa291N/He2unNe537PvY2pE/vbb6kaG/tPMi9pTMi1m036dw1b1JStTyUq9/R1P9I
+iP9E+oh7cc67YkGh2XQ+r74dLkZv5CJhMmHnfI3fWC5Y5UfISnq+iH35HhlBL88nL/HlBxq9x0fj
+d0NpTszSg+FL+UIipvqeeo77pkGw8f89n54Mv2L5OB5PRm/IZ6n6oxGiUQn3fGl9xPzaF9mJQ/fN
+bHp+9t3pq+le56atNxW7AfO8r0K+VlKFoN+fvE9Adg8vb3Kx8fKuarlAuoErvSbfFbjLSzZeLFiV
+hzdqfOvGku3P84su2t5zyWs3XPJbbXyUX7Ze4+L3gACvSCxQlefn7JukHsUQUxVz6rjkUafkLviT
+9MGCVaE5Qw9P348n07NxgWcIViz+Opyd7UQcngYn83eFJh1I/nuXpmhezzro8Nf0b6m/bZ5F0Xsw
+HZ2/G58uDoaLIcFfPEkA+Lj42nHdGfDzD9//CVm8/O3R/zqOxTuZjv96NzmlEo/xC+FE9sm/fLG5
+wPshybBYIsQIRPf54tez9PhJn9T3ZjTejRdDyRi+ORbq2li8j1eAPh9jVfGBYPIwELlvenxdSpGm
+mxzPxqep1CpHd4qSFCJj4XwR10Hw7HebOvX7+RCxIMyZDzDWV+jbCuKotgO2j/7zdP5iRLbM9N3X
+W0p3UdcfYFhSVzYNDz/6/fsd+0kcOn/Yvfz9+2XARZx6fd4gOhAv/4mpcynhXpJKpQLqodKt25lN
+LDKZjt6Oj3fo6Ck5Cw+1k6kTd88bV5EbD38+7U6xFTLMX/3yYbXpfHIy+rRUKffo+fR8NhoPYLg/
+4M6tYP7r5Ziqxve0UnmPzYOaCr9uUZ6Xd6v1D7JD/9rcoV9kC9RlnbLO9ZT19kF27Ze8jWute2/i
+Xq7L+2d7rffqQfbvTdmQttbBl9MF2aHfj18tfpydsKd76bRLq+cPqo/r/XhYepuU26eitm9XY91e
+NzrBEgY1zhkX6dn/LlTD2eLldDg7rkbTyXRWqWqWzbtLiyLX+HTXwi/LeDpttd9eVndwuLRoF4dL
+C79c19fr5VaYDgU42/tsSKMw+pXeeHJc5VM0v3yR841Q8oxD1fOTd+cTzmyIZUzZUIBSP54vzs4X
+1bPhfDGenfybS1bPxpxSWSopt1Tph/H8zWVV1rgjDQn1LHWsTT07PjvprfZhODmZr8LeDedvUz9y
+6ubZ8LjjBvS/q/rni2lGL1O5rjMZVV29miDmekoUmnHBx+/HSIWuXg4nw9PRBoIu1ZnGA5AX438t
+diw654WTeRnzjaVHk5MzGnuEV/5FvPeaCLhGhJUqZ7PxfDx7P66m78ezM0Q5117ytv/d0+GMJB51
+dH747uX4uD+ZHE2p5B/Hv15Y+Pn5y/l4wUUHY149LsQU6m8r/gx8UZpPxF9H5els+upkMr6k6F/f
+nIzerBXdjPTTgyNEwgmBlyeTk8XFhVGSKDi/gHNXpPrz8eTb4eJgOvp+OhpO4GXPucBmHZBLf4c1
+o+8Olsp2n/+EQCFenZ896eaJreC1lke2xFOhOp0WfqhOTpmnpvOTxaoie/6XbzBcMnCLtDe/CKX4
+HF3tyoPylMdQJluameXh09l4dNIhbeeth6ej6XF5ny1PeLnwp6JUc7/oGYf+meRnw9GmAj+Nae4M
+F5sePX39anUqEfTn4dmGss/JMSvIfb2B2p30tJVFhC+x3DdenMuiXVzQ+37463hWctHSYjIuKSNF
+IZtrHaDfv8R6JErjrqrvTyNLLTbZOn/+7gCHqnHpF1T6axEOL6g4PfqqIPoCeQV9/Pr5F+zVoS+z
+lMPXC9Xr3fL1FOfrmdr1TCDx22hTvdv7Ishfk70vfNOrnZev5CU1yvaCVZb/rl012vuC/lJUir3C
+iXxt6WurXJUqZ68xdP6mqk7Bgm9VAVIDpGZ7rfauAJ3RsVhquEDSm9FaAgKxSfd7Qjo3jd7kl+PL
+aIUGk/Xvr/acbnutRf9MrzaNAqVcrXumIaWngu+ZNkgXNgNNT+PYIBVCT9e+AiA4pStd1z3VhpYg
+tte01Btdq55ygpcjPDS9VVOjXN/VRFYTFEGoRVtrhjjs6dbUgCGw1Gt6oW0aAjp5Sr+o1cYQpOlZ
+T1QCxFpjCdL2msZLPfpTo5DveddYLtTixVoRnt5LtRbXrRHpe04LH6wDJ6Ux54knVZNAXM61oVfX
+3mQgd84jn6ypSkXVa2tfMHVe93xT2/RK7pDzNv6ROu08Ob+apmKmjQOr1D6RhinofEtjjLcJjZ33
+PVtbU0bC+cD4jGQAebxcqHuWRrHKQ+qC6mlvMRJx5F3QPaXSCK4Cmc2FmRpFHQtab4cRSoZI16iG
+Seg0kY1QxHfVYPQJIFytqBfaKpkMOGQ7yIy1RlNfjerVmijYKCP8R4CG8CKAovnhdZpEdeNRqu41
+YEGeRk7TrKL3GkLKGSMnNjdE/kQbgnGsgeZeD5OmA6D3a5C0QHSvCY3J9ZSi3hDHc6MZ4mjueMyd
+XNGFhjpa66UXZuCkA8QJWL72zcVAT3gqGjnqbkSYITTiDiKkVCQu8aa8VkoR9VvnhRptQ3OdeLBp
+rGKChcZDLJoyiwnYYI4rYmgHAgOiavJqaOr3gre2DIhqfc9ZE6VaHDbVtjK389CyOLRdDiCMeqY2
+LVeMfKJaG3k6cRLkV8O0WxVoo8KDGTaRfDe16eJFuz3njZBsvTL8/bG19GpHjeWp0KggLP4zCVFv
+Qi3g5dKPW0+kDyG4Un4w2r3twQVtF3bstvxqT3L1tujnDd4xWy8vYDWkrKgXpdSyuiZ2sK1qmbQk
+dRz0h2Ipi0Ehdm+t8PEWYAvx07L+YA4CRBtWFzXxC30nUWdbUR9OKWYDRRPSN0b0B8kpGlmC1DhS
+DvqjqWt6Dc3RVnFDVriUK1pStsGz/vANiQcFAQi5B/3hmQMJ0rYusLKotTdS0WBvMIABB71LMasa
+ViCMIAPQF+gKnuSx3jJwEhsLrmVFoFtSR5NOSagQA9QSEPKRNEhrSLxkPKAyaiFYRNfRUOgoSXKv
+oESI6KrKPYcSsd6bQiAoEaZ9pCzTEVqkdS5UmdbQI4SrLkMCPcJYjWQkedygSFpfmyqPLRRJY4Fp
+5ACoDNvqiOkqcFKYCjrDO622wqIUJxCTkb4rqD6oEYITdW3gKg6n8uN1oCPPJiu987iwgboC/UH6
+m+zBwEUbRfPOWkaxZZkTWHuQHlZkJ7KChfIwQfN3ZomGFb7Qg21JEmWBXsJ/wzCj9qgs07ehEapd
+Iy8gmHEN6wvTWFMlgINVhamSarnQ4oIJlWotwSYFpgLZDmT6bAeheUUk555lAA0os02uRGNOpWzH
+JnaGKUB/E6doa3PvoRnSBI0Ugl4Ium2rREIFS8gSM0UyQykEyHEZGh4K6ASer3GsoBF4RqfhhEJg
+pTRiDuARh0IgDmiqyBL4XsNCWpNPow0y6yJ1EK/ewwmR6wrhsYnMDoCIYZAxi7pWyQugEB7T7G+E
+dXGzL2HXreMxz9raqFipdSy7d33B4NIXyJCaTpW7Vg3QuqHRgeengyCNvgVpJyV2I6TIZCuQrGSG
+GRx0Asu07nk2FgjSNl5VluaHty1EDNkD6Dj1yUK/sC0eyFw2NMVsgCyD7CNI0B6QRngMlpbGegtX
+JDHRWFfML0vNEu2aMscsjiEVs7fNdqllrLki2biQEJaEYESsZUa3NLPEOwEAvUG9NSBEvsY8sNIW
+pgbDaB4F1a4VbLQUJAueeJ6UPu4YzYWU8jI7GNlGXChFstFjCgJIX1CPJHzLIpj6HQCw/G+XOAoC
+sraFhAp7VFiJJTKThRsRKoOhoB1bRiGOmSKp2UJe5HFlbvZMrDj6SS8sAUUHsNuTGWobzDIJGxWd
+bfruxW8gcQO/gWQX60zYSckoZS0IVUB0NWS2V9CARAV898RONFi1g+SmwYBOpiqwwjDKAAUYYKTp
+QgNktGZqURdBEXxl6Y86JDYbyw44kde1rpW/vRi5KMr0RVGSxgF6AbAG4rOGrxWWIFGtd+utA6M3
+SlPM7gIkvaYaW95CYp2sbFisBWJYm3Rfi+CD11bHSESDC5FC/NLKdOgSwsFGZScwEotYplcr7m8k
+p6MnJLxUl+Zk/cjUxbgEBScQERDH3cWWKuIsTQoiOCPDW4sF5/gmXlCbmMDL+8j5cOyFevGU1wTW
+aJMU20FbhM07ZpIwj0IZj+A5sSef2JxVBYtvsmfg3rWGzODVGoTG4xb2goPKHIx2bX2wU+ttZ2Dv
+RU004jMSOopGNqoJjTGFY6Cg/SdbgSp6gDSFNE5Nh56wsFwhQS1JUKgJMXkh4NBAVBO2hiAjIAcw
+LEvcGk41mcjgcqgJdk9hPIUmKQnNahq6AdoCSkKB2wBhaw1Kgo0PEDh44SMyXWh4jC4uO5RERIs6
+jvNuoBAU9CAgycRZB0L4K3jH7OsbEedRTTRG+eWSmBSNactbFEtB1RRMyGojeRiWEYaisB4yJvUL
+ioItvNx3xYEYbioRCIpCW35fpCI0hTawEBOloSkiTmVAoCo0hp/HDWoRqkLsVBpZxpyUArGLMEAN
+BKKmWAaKVmB+zzy1HSZkRGSA/oKq4EABmf8kRqAobLSz2jqanBJyA6iG60lqIkYgamEospkbsqIr
+1dAYwf5HJYRDgCPBjPasKchdCBwQhsFKhBeK0HemGuS/hUUo4WVmQ+hjNrUzgGQTBj8DRGs0xklL
+BrFOBUOKp02BRPewW28dOJGoIjPtpTDiKUiQ/A7oDDaZOhAd2a3zVigNC/GagY64jA==
+		]]><![CDATA[
+		w50dSBsnSoc4UB88YkxBNihgECFgCiLzRIb+qAPTIuRoF+kPmdMYL7a+tI3zHkPqYNKQAmHl1R13
+KBDNPnhiDkACoiyZe9Zl2WiTgNsh/KTbzSokOwSPs2Vfc6xM3pAEI7QIi3nyBbycnd9srkIzHI43
+0Vu0yI4vGOz8gjyMd65JzvdoRInPX0NoWrHEaMB6itQflIol5eZNEwioJbRt4WvWNHkBsSR9CKJl
+IqKia8VUsQ1xvK9RkaYkFmtsQ03V1GXT1rzIQAYv2beo12I7s1SzCOkQ99A7SeKSP2YR5qwbvE9J
+4MqqjEGEoCKHZrxnoNfktSHgBxMFrbeK/yDLjetFBBBCJJQDTWAGETcSk9IU5P6SjsRNlcaQQaSs
+vI0cbeZPQ2zMbMlA6A9DMjy0dcuII02FbItoARqeSWKja0SEjLX8Qg7ba/jq5NAXCusGRiGQIQg2
+1Y/4YgURFoA5LKaR1QjHlZqnCac0wnGG/lBAufRPw8GpUS/SGDE76g2wIhvdQSFBM/FXE6J6wNqK
+YwJDv/DsVSSC6bsXw07xWPqG+1aT58TVHHUY62sAivYD7XSQnvAqAjWzTk1FsoNtKZIf2BQPC5X/
+DDawi2Y0CSJGuE4aMwENmRtxRYmrGRJD1GppEgBI3vxiA/3pRX9m/AypS4Poeu6DjYNQukqQxkSM
+M0UI6CzQzDSjF7JHKGQ1kMyOkS6kN428toyOpUqWxGIZQwudKWK0DLWF+4NFucwOhDivxRWmMa14
+AqiYeYuAviGHs/BfemNhU+tkOQv8nbmZgNq01GzmeNCPCNeZGB2KlvlDb+R1gzzDbLRkyjTsdDFP
+1gQr85kaslhuK9OeIKQXZNpn6ZCARYLYaHoVOUMQb5yIpySM8EIavyKvLLWILLMi1nBbipMYZZF+
+RHheqCoSMtG4CFLj5b620SbpymvJuiWUEFoiXUBgYjwSuvi7JfZA5+ras6G6EUbTUcxiSzTSRho3
+QMbSZCEh1PKsqcFrFgK1ll6QbYFzOohYLULzNKGNo3FudMvd0R7j5loRUBaeP5kEUjHqMhjipG8J
+b2rKKrbgcR8TZg7kEZgOrkAIrYwvcgCUbmWtVDWxI+AU+LAGnGsxlxyiUGSDEC0k4OPIVJViNAmQ
+eQeI8kGWn0mwAOJkMOHt1CqGppxhjmIsHBQJDSzzHfwR1t5AQZkaTgsW4yRGbBFMQtTPkpXKk8ci
+rsIIkulLFKAuUpu8zGGxQhfXAdaBE+gzLXTF+AUamu1ASDLmZKIfO+kWC3UgLSsQT0YWpkDWHlHC
+Wyx1a+e5XotrdWGdMEENFjws5lDrhTUZEkxUfTTkLaY2Qs78Hld3FGSUJa0NXQVtYOclLW6IE0nz
+uV6D8TAepYhzkDEh74fP0ojwg7fDEotQINeDZJh3Ufj5WsyG9cnAMmwVyBPHgj0hTC0Jvpq4iq0V
+mrKQWhkG3pX5QF0jru5CDIlzJQkEBUh+nkGgI7dEfVFIACjvSxC2VhBN6MAwZAHCpzSUId33ZWBG
+K7WUMV/rH9U72tN15gCsTZBcxeJhQGwOaoxIRESXhQW2JMnsoBGE/mvj8qeBu4YMCtbYrSwyGE5v
+IPVnkDhCQ2G4SfgPQBUK0SKSoMUaITEuRgimBgk16Fv4G4iLwH9AToUi4Wdg9QDigmRcKBskeEbS
+isSMFrykfWVEc8MwhrIDUa2oIw0Wg7wyAekgSpH1E91hg1mqabZoBOmFMSP7MfOsAol5dAMZzpYT
+IQEbgyYjjTZbSVrCYBpizUJztlg9tMKKLq63gPgYLSjmGhILLGxJhpL+NpFbfS2Yoh4H19AY1mcc
+EnRUm1rCEj+vnK4OLFsMq0Dh/axLiLQk28Oypc6Bv7ZjqBOAQ/JFoyGmWIuNUBQfDQkriKIbyR/x
+te5qUIIYLzZQUbTIMGgw9lkZa9wqgTdmnZ0gS6Y6wpEk1rLy13FtopgICYOuqY4sB9Wx1OHDGii/
+bJAgHA33eclSB1CRH1JsG2JtD5e1mEDoiRJVVywlAhKzFFsq0rdYXJrDi37ZTkdgKVjTsdNNLVK/
+2Hid3hVTMJG4mIsKkZBgkkmpotG6ZKnzQkbwHVtde1HDxYDVMHKdXbbVoWQ0DX+xhTUYSamOydyh
+ZzGsEUzAaVxsdiNA7BEFyoY5kLbWLFnrGstFOi7eY86iQ6rumOuAUJ99eTnqeKQSde11HVpZ8C/9
+4KysttNbXuTXbtlcr01Kv4mEY72knY/Exds47ahrrzPaMAnKINWYgaE7llB6oMCSvY5EADLOir0O
+xHndPXMPIHUUj5nHAFSQhoULMWlM6LqVSNKopYOFpwno6uCLvc70q1VnenQpmmeRRqBR22Kuoz9Y
+ACpzsdPDPGMhownZYq6jHQf5n6c+IAYj0jXXM7BIEXTHkn4pwiYRecleT1hkuaVTqDqLN43gZ1gy
+1zNBs5jUbJ2GYq2jiJc0tnUBy3KXT5SLp8q9Rak6xSFaLH62YoLAFAdpGnhFRAesmHM8ooGxxxqd
+PDQJDHjRAtxBTYwfJH6AW51hAJDBaVl1KaSDIVJE1RxrA69kIhMrRDGI/C5E1qxG6p13/ELl0BTi
+y8xECcJSGJO6bhhokXFAdaImwBuRDAd12JqEAyDRB2hMLMbhXEPuR4y9wMpvxAlWFqiSkclsy6JY
+y+IRgCwbqZVIQUJeI0bDs6FlL5EskRBE79JwiO2ClAUN2dsmExdcAK9AN3WUS4nMPBF9ZKUGzgzU
+s5eVfODuHISxFr+q20ONVTmYUeV9tUohGSeynkSrJP4hvpX8beRmxAhIDHoperGIo2RHwObKlkWj
+4vIjeaEB5hOAPFsVURAShOpreNuKxTk3XSiK1YsYmEE8lp5iBaJJaEl0XMkosFnHwtixjxtqJwvl
+uYaB9kXaYW7VQPEgKpJfblUJfkcMSdhJoCb3wUKDIcSeu8pmX5D3Z4oAiHXdQrXkehfiEoSlCYvj
+NAbAHglpeZjILuNVqzyYBGiT45GHnFSFhglSuMIiKtXqDvNYBHZFNBYes1qytwsfulpWyQu7WpBK
+PJbC1RYxLC9iRDjfxuy1MkE6FC3zCN5AwJTMc83hZE0YOXlKdvpYZi78CVXDeE6z2ypZoihCwCLV
+VQz5IisSsMgTlwIHWey42CZ710k6JTSKAEPkDLq5yDkLrVtHiZzEoYWChwbIEhN0RuAly1WqZ6J9
+tC5so0gOkMn8izxY3GsI0Qy7nxee2eJWdZCwCjAk8sIVc02Q9P6NQJo8bGdY4png4QE7L2YC2QOk
+8G3LEZOmURDwMFlak9Qp+xsIFZBvHUcE7Acf01tmHi2RnBRC4XpW1DxWRtn4YsXMC7EwmbRIcw8j
+Cqu3HCbhgVdCFcRC6GnL0l9iIRpxSMTdabpwbBNrL00j1KT3MUNiocXWCJs5Iw4fFqEIA8d959nL
+qfOtTEIwA3MaryHDULOId3LzdZy0QIHnl2WbQnwgCxeOw0kBK9JoH6aKlThLgAVqsNwL6wrEUzrE
+qMoqkGMl1FtmSU5wc+oCIHLaWdpG15hYjQmbFQw7nhwc6agAeLtOGQnRaMTwDFliNTxjTnpRooWB
+PwDJsUdUW2ZPLoU4q7hwLvra5CJaCdgUNQ6ju26NqDjPsRcs+LbMwijG1mSdQihOskY4rlJLQgPe
+yBk7mlheHEHsfcCy5vpsGG2aIjGuomWAaVKIcIRRg0VEIlwBwoySKJlzcf5kiEFMsZXgVAZyFgwW
+fXJTSGpC/8obE2Qkg0kuhOkUo3HjMFNpKkO6b8zAjFhuKiO/1scYW0HmMOZeC6NbYrHYGCCqAVtX
+LCfgB6QKycCQiMeqa5PCKD4t6WOSs9vJyQZY/Da1SGV2k4Al3AZE71ofVHKT2D/LoRCNjCGOBDZi
+rSA+w/k+ZLDlPQWKBG4A3gC2vKAc1xcQhYqbErzsLbCKRKQL0cxR0QZHjhQ8aG2a6E5ikmpeVmik
+IgJJ7Cyj4hqQoyomkqWNCp54XKYcuxDIrYAbFFeoYPnG1qxLy4Ah+lsmhT1gh4OlySfmdQ9maRJv
+ElVRKaLlZIC1Sp4DZEXd2mp9SNmQWAXGqErSMLoR923JnIembBGhywpMY0HDdfWcRs5gdCGyOoSD
+3cBhySoTQTbkLBfNSiKBTCi9bNAbZMK1HXue/uDcwqLKE2TJntfIyUTsL1sFeKFqbcd4SJAle56A
+WsPsz3aIjkeHFHOFGNe3K+Y8YBoCNBs+hLqxvunYRwRxJoqsbEYhWOYwTNnUSlQuFhlRuW7FPiqG
+m24k9lyMO0RXPXgnmYCdHhZDMb8w25KYiJaTgpLJCf3gfVi251NsrFiv2MgDfVaM3LhBasmcxx4g
+QyRNxjIQtzy1k0VdCFrsbnobh2iLbQ5IUFqseQ0fX1I6+Htdy2TqWvPwilmh5FYZol3Xmq8jkTvW
+PBGGl91LF5ArBJ+udLRGZNcuG/M18gE5nhtJpksGWaQsIMkMLANQ85nuTcear4MEOPJQEsAnVzAP
+OFKfGt+15tGkX3IFCdK4FAlOLFYr2ddV2DC/MHNrHSTPd8mar2MOWGH8OqYvlenRoWiZRTV2ovBa
+WZpp6JF4hWlCdvpY5m0ClrmNDaF4UREByPBu09JVkhQJWIQJ9uBA42WRQwBnJNBVJBNeiJyAIr1q
+WEvBd4RcjZQkWfEvsjBRushLtg9b37HmqaI10bxak7Usgv+8tznJ5RGnzdS4GSEf4zIY9Eej83fP
+cONg2YVuYXd1z7P47t3ZFIcN8xFc1U/TtCMccaQLCg74TJt8RIa9qCxOvslnEbUXlXzWOQwoJuCE
+6tFX1c9/3fvi+84h47zrm0+z/fLp8PX4p9nwZIIt5q/nw/c4lPeUr1k8o0c4mWS+mM7G1fzN9BdA
+UClX+PLLwx+P9r74/1OZYok=
+		]]></i:pgf>
+</svg>
diff --git a/src/main/webapp/img/theater.png b/src/main/webapp/img/theater.png
new file mode 100644
index 0000000000000000000000000000000000000000..475461df425b3a2887e1646c362e493aeb2bf48a
Binary files /dev/null and b/src/main/webapp/img/theater.png differ
diff --git a/src/main/webapp/img/train.png b/src/main/webapp/img/train.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a85265e2fe8b5e4c04964f63bb366c29571b620
Binary files /dev/null and b/src/main/webapp/img/train.png differ
diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp
index e0f610e2491cb3a4bd0dade3524d6275d3197f8d..e305b903e6ef053975ebfa5638f43be882575d63 100644
--- a/src/main/webapp/index.jsp
+++ b/src/main/webapp/index.jsp
@@ -1,65 +1,50 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!DOCTYPE html PUBLIC>
+
 <html>
- <head>
-  <meta name="generator" content="HTML Tidy, see www.w3.org">
-  <!--  script data-main="main"  src="require.js"></script-->
-  <script type="text/javascript" src="./lib/org/cometd.js"></script>
-  <script type="text/javascript" src="./lib/org/cometd/AckExtension.js"></script>
-  <script type="text/javascript" src="./lib/org/cometd/ReloadExtension.js"></script>
-  <script type="text/javascript" src="./lib/jquery/jquery-1.8.2.js"></script>
-  <script type="text/javascript" src="./lib/jquery/jquery.cookie.js"></script>
-  <script type="text/javascript" src="./lib/jquery/jquery.cometd.js"></script>
-  <script type="text/javascript" src="./lib/jquery/jquery.cometd-reload.js"></script>
-   <script type="text/javascript" src="./lib/jquery/jquery.json-2.2.js"></script>
-  <script type="text/javascript" src="./lib/jquery/jquery-ui-1.8.6.custom.min.js"></script>
-  <!-- ###### included javascript libraries ######--><!--###### jQuery ######-->
-  <link rel="stylesheet" type="text/css" href="./lib/jquery/css/ui-lightness/jquery-ui-1.8.6.custom.css" />
-  
-  <!--###### Google ######-->
-  <script src="http://maps.google.com/maps/api/js?v=3.6&amp;sensor=false"></script>
-  <!--###### Ext ######-->
+<head>
+	<script type="text/javascript" src="./lib/org/cometd.js"></script>
+	<script type="text/javascript" src="./lib/org/cometd/AckExtension.js"></script>
+	<script type="text/javascript" src="./lib/org/cometd/ReloadExtension.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery-1.8.2.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery.cookie.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery.cometd.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery.cometd-reload.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery.json-2.2.js"></script>
+	<script type="text/javascript" src="./lib/jquery/jquery-ui-1.8.6.custom.min.js"></script>
+	<!--###### jQuery ######-->
+	<link rel="stylesheet" type="text/css" href="./lib/jquery/css/ui-lightness/jquery-ui-1.8.6.custom.css" />
+
+	<!--###### Google ######-->
+	<script src="http://maps.google.com/maps/api/js?v=3.6&amp;sensor=false"></script>
+	<!--###### Ext ######-->
 	<script type="text/javascript" src="./lib/ext-3.4.0/ext-jquery-adapter.js"></script>
-	<!--script type="text/javascript" src="./lib/ext-3.4.0/ext-base.js"></script-->
-	<!-- script type="text/javascript" src="./lib/ext-3.4.0/ext-all-debug.js"></script-->
-	<script type="text/javascript" src="./lib/ext-3.4.0/ext-all-debug.js"></script>
+	<script type="text/javascript" src="./lib/ext-3.4.0/ext-all.js"></script>
 	<link rel="stylesheet" type="text/css" href="./lib/ext-3.4.0/css/ext-all.css" />
 
-  <!--###### Firebug console ######-->
-  <!-- script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script-->
-  <script src="./lib/firebug/firebug.js" type="text/javascript"></script>
-  <!--###### Openlayers ######-->
-  <script src="./lib/openlayers/OpenLayers.js" type="text/javascript"></script>
-  <link rel="stylesheet" href="./lib/openlayers/theme/default/style.css" type="text/css"/>
-  <script src="./lib/openlayers/LoadingPanel.js" type="text/javascript"></script>
+	<!--###### Firebug console ######-->
+	<!-- script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script-->
+	<script src="./lib/firebug/firebug.js" type="text/javascript"></script>
+	<!--###### Openlayers ######-->
+	<script src="./lib/openlayers/OpenLayers.js" type="text/javascript"></script>
+	<link rel="stylesheet" href="./lib/openlayers/theme/default/style.css" type="text/css" />
+	<script src="./lib/openlayers/LoadingPanel.js" type="text/javascript"></script>
 	<!--###### GeoExt ######-->
 	<script type="text/javascript" src="./lib/geoext-1.1/GeoExt.js"></script>
 	<link rel="stylesheet" type="text/css" href="./lib/geoext-1.1/css/geoext-all-debug.css"></link>
-  
-  <!--###### Isochrones ######-->
-  <script src="main.js" type="text/javascript"></script>
-  <script src="./lib/isochrones/iso_main.js" type="text/javascript"></script>
-  <link rel="stylesheet" type="text/css" href="./css/styles.css"></link>
-  <script type="text/javascript">
-   var config = {
-     contextPath: "${pageContext.request.contextPath}"
-   };
-
-   // Begin Google analytics part
-   var _gaq = _gaq || [];
-   _gaq.push(['_setAccount', 'UA-35566285-2']);
-   _gaq.push(['_trackPageview']);
 
-   (function() {
-     var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
-     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
-     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
-   })();
-   // End Google analytics part
-  </script>
-  <title>ISOGA: Using Isochrones for Geospatial Analysis</title>
- </head>
- <body>
- 	<div id="pbar"></div>
- 	<div id="featureInfoDiv" style="position:absolute; text-align:center; opacity:0.9;"></div>
- </body>
+	<!--###### Isochrones ######-->
+	<script src="main.js" type="text/javascript"></script>
+	<script src="./lib/isochrones/iso_main.js" type="text/javascript"></script>
+	<link rel="stylesheet" type="text/css" href="./css/styles.css"></link>
+	<script type="text/javascript">
+		var config = {
+			contextPath : "${pageContext.request.contextPath}"
+		};
+	</script>
+	<title>ISOGA: Using Isochrones for Geospatial Analysis</title>
+</head>
+<body>
+	<div id="pbar"></div>
+	<div id="featureInfoDiv" style="position: absolute; text-align: center; opacity: 0.9;"></div>
+</body>
 </html>
diff --git a/src/main/webapp/lib/ext-3.4.0/css/README.txt b/src/main/webapp/lib/ext-3.4.0/css/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..84ec2e7f89e7cd1170c6c368426c1536f65ee81a
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/README.txt
@@ -0,0 +1,6 @@
+2010-03-16 jwr:
+The CSS file, yourtheme.css, is an exact copy of xtheme-blue.css. Feel free to edit the images inside the yourtheme image directory to build your custom theme--just remember to update your background-image file paths in yourtheme.css.
+
+2006-11-21 jvs:
+ext-all.css contains all of the other css files combined and stripped of comments (except themes).
+
diff --git a/src/main/webapp/lib/ext-3.4.0/css/debug.css b/src/main/webapp/lib/ext-3.4.0/css/debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..23a7cfe1137d4c1554e49b8717465d4a2d170524
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/debug.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+#x-debug-browser .x-tree .x-tree-node a span {
+    padding-top:2px;
+    line-height:18px;
+}
+
+#x-debug-browser  .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+#x-debug-browser  .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+#x-debug-browser.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -60px;
+}
+
+#x-debug-browser.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -60px;
+}#x-debug-browser .x-tree .x-tree-node a span {
+    color:#222297;
+    font-size:11px;
+    font-family:"monotype","courier new",sans-serif;
+}
+
+#x-debug-browser .x-tree a i {
+    color:#ff4545;
+    font-style:normal;
+}
+
+#x-debug-browser .x-tree a em {
+    color:#999;
+}
+
+#x-debug-browser .x-tree .x-tree-node .x-tree-selected a span{
+    background-color:#c3daf9;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/ext-all-notheme.css b/src/main/webapp/lib/ext-3.4.0/css/ext-all-notheme.css
new file mode 100644
index 0000000000000000000000000000000000000000..6bc676568990c10a408c5bf5ba473ae7a8262881
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/ext-all-notheme.css
@@ -0,0 +1,5326 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
+
+.ext-forced-border-box, .ext-forced-border-box * {
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+}
+.ext-el-mask {
+    z-index: 100;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width: 100%;
+    height: 100%;
+    zoom: 1;
+}
+
+.ext-el-mask-msg {
+    z-index: 20001;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border:1px solid;
+    background:repeat-x 0 -16px;
+    padding:2px;
+}
+
+.ext-el-mask-msg div {
+    padding:5px 10px 5px 10px;
+    border:1px solid;
+    cursor:wait;
+}
+
+.ext-shim {
+    position:absolute;
+    visibility:hidden;
+    left:0;
+    top:0;
+    overflow:hidden;
+}
+
+.ext-ie .ext-shim {
+    filter: alpha(opacity=0);
+}
+
+.ext-ie6 .ext-shim {
+    margin-left: 5px;
+    margin-top: 3px;
+}
+
+.x-mask-loading div {
+    padding:5px 10px 5px 25px;
+    background:no-repeat 5px 5px;
+    line-height:16px;
+}
+
+/* class for hiding elements without using display:none */
+.x-hidden, .x-hide-offsets {
+    position:absolute !important;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+}
+
+.x-hide-display {
+    display:none !important;
+}
+
+.x-hide-nosize,
+.x-hide-nosize *    /* Emulate display:none for children */
+ {
+   height:0px!important;
+   width:0px!important;
+   visibility:hidden!important;
+   border:none!important;
+   zoom:1;
+}
+
+.x-hide-visibility {
+    visibility:hidden !important;
+}
+
+.x-masked {
+    overflow: hidden !important;
+}
+.x-masked-relative {
+    position: relative !important;
+}
+
+.x-masked select, .x-masked object, .x-masked embed {
+    visibility: hidden;
+}
+
+.x-layer {
+    visibility: hidden;
+}
+
+.x-unselectable, .x-unselectable * {
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-repaint {
+    zoom: 1;
+    background-color: transparent;
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-item-disabled {
+    cursor: default;
+    opacity: .6;
+    -moz-opacity: .6;
+    filter: alpha(opacity=60);
+}
+
+.x-item-disabled * {
+    cursor: default !important;
+}
+
+.x-form-radio-group .x-item-disabled {
+    filter: none;
+}
+
+.x-splitbar-proxy {
+    position: absolute;
+    visibility: hidden;
+    z-index: 20001;
+    zoom: 1;
+    line-height: 1px;
+    font-size: 1px;
+    overflow: hidden;
+}
+
+.x-splitbar-h, .x-splitbar-proxy-h {
+    cursor: e-resize;
+    cursor: col-resize;
+}
+
+.x-splitbar-v, .x-splitbar-proxy-v {
+    cursor: s-resize;
+    cursor: row-resize;
+}
+
+.x-color-palette {
+    width: 150px;
+    height: 92px;
+    cursor: pointer;
+}
+
+.x-color-palette a {
+    border: 1px solid;
+    float: left;
+    padding: 2px;
+    text-decoration: none;
+    -moz-outline: 0 none;
+    outline: 0 none;
+    cursor: pointer;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border: 1px solid;
+}
+
+.x-color-palette em {
+    display: block;
+    border: 1px solid;
+}
+
+.x-color-palette em span {
+    cursor: pointer;
+    display: block;
+    height: 10px;
+    line-height: 10px;
+    width: 10px;
+}
+
+.x-ie-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+    zoom:1;
+}
+
+.x-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+}
+
+.x-shadow * {
+    overflow: hidden;
+}
+
+.x-shadow * {
+    padding: 0;
+    border: 0;
+    margin: 0;
+    clear: none;
+    zoom: 1;
+}
+
+/* top  bottom */
+.x-shadow .xstc, .x-shadow .xsbc {
+    height: 6px;
+    float: left;
+}
+
+/* corners */
+.x-shadow .xstl, .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbr {
+    width: 6px;
+    height: 6px;
+    float: left;
+}
+
+/* sides */
+.x-shadow .xsc {
+    width: 100%;
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    width: 6px;
+    float: left;
+    height: 100%;
+}
+
+.x-shadow .xsmc {
+    float: left;
+    height: 100%;
+    background-color: transparent;
+}
+
+.x-shadow .xst, .x-shadow .xsb {
+    height: 6px;
+    overflow: hidden;
+    width: 100%;
+}
+
+.x-shadow .xsml {
+    background: transparent repeat-y 0 0;
+}
+
+.x-shadow .xsmr {
+    background: transparent repeat-y -6px 0;
+}
+
+.x-shadow .xstl {
+    background: transparent no-repeat 0 0;
+}
+
+.x-shadow .xstc {
+    background: transparent repeat-x 0 -30px;
+}
+
+.x-shadow .xstr {
+    background: transparent repeat-x 0 -18px;
+}
+
+.x-shadow .xsbl {
+    background: transparent no-repeat 0 -12px;
+}
+
+.x-shadow .xsbc {
+    background: transparent repeat-x 0 -36px;
+}
+
+.x-shadow .xsbr {
+    background: transparent repeat-x 0 -6px;
+}
+
+.loading-indicator {
+    background: no-repeat left;
+    padding-left: 20px;
+    line-height: 16px;
+    margin: 3px;
+}
+
+.x-text-resize {
+    position: absolute;
+    left: -1000px;
+    top: -1000px;
+    visibility: hidden;
+    zoom: 1;
+}
+
+.x-drag-overlay {
+    width: 100%;
+    height: 100%;
+    display: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    background-image:url(../images/default/s.gif);
+    z-index: 20000;
+}
+
+.x-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.x-spotlight {
+    z-index: 8999;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width:0;
+    height:0;
+    zoom: 1;
+}
+
+#x-history-frame {
+    position:absolute;
+    top:-1px;
+    left:0;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+
+#x-history-field {
+    position:absolute;
+    top:0;
+    left:-1px;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+.x-resizable-handle {
+    position:absolute;
+    z-index:100;
+    /* ie needs these */
+    font-size:1px;
+    line-height:6px;
+    overflow:hidden;
+	filter:alpha(opacity=0);
+	opacity:0;
+	zoom:1;
+}
+
+.x-resizable-handle-east{
+    width:6px;
+    cursor:e-resize;
+    right:0;
+    top:0;
+    height:100%;
+}
+
+.ext-ie .x-resizable-handle-east {
+    margin-right:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-south{
+    width:100%;
+    cursor:s-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+}
+
+.ext-ie .x-resizable-handle-south {
+    margin-bottom:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-west{
+    width:6px;
+    cursor:w-resize;
+    left:0;
+    top:0;
+    height:100%;
+}
+
+.x-resizable-handle-north{
+    width:100%;
+    cursor:n-resize;
+    left:0;
+    top:0;
+    height:6px;
+}
+
+.x-resizable-handle-southeast{
+    width:6px;
+    cursor:se-resize;
+    right:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northwest{
+    width:6px;
+    cursor:nw-resize;
+    left:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northeast{
+    width:6px;
+    cursor:ne-resize;
+    right:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-southwest{
+    width:6px;
+    cursor:sw-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle{
+    filter:alpha(opacity=100);
+	opacity:1;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+	background-position: left;
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-position: top;
+}
+
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-position: top left;
+}
+
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-position:bottom right;
+}
+
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-position: bottom left;
+}
+
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-position: top right;
+}
+
+.x-resizable-proxy{
+    border: 1px dashed;
+    position:absolute;
+    overflow:hidden;
+    display:none;
+	left:0;
+    top:0;
+    z-index:50000;
+}
+
+.x-resizable-overlay{
+    width:100%;
+	height:100%;
+	display:none;
+	position:absolute;
+	left:0;
+	top:0;
+	z-index:200000;
+	-moz-opacity: 0;
+    opacity:0;
+    filter: alpha(opacity=0);
+}
+.x-tab-panel {
+    overflow:hidden;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border: 1px solid;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header {
+	border: 1px solid;
+	padding-bottom: 2px;
+}
+
+.x-tab-panel-footer {
+	border: 1px solid;
+	padding-top: 2px;
+}
+
+.x-tab-strip-wrap {
+	width:100%;
+    overflow:hidden;
+    position:relative;
+    zoom:1;
+}
+
+ul.x-tab-strip {
+	display:block;
+    width:5000px;
+    zoom:1;
+}
+
+ul.x-tab-strip-top{
+	padding-top: 1px;
+	background: repeat-x bottom;
+	border-bottom: 1px solid;
+}
+
+ul.x-tab-strip-bottom{
+	padding-bottom: 1px;
+	background: repeat-x top;
+	border-top: 1px solid;
+	border-bottom: 0 none;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-top {
+    background:transparent !important;
+    padding-top:0 !important;
+}
+
+.x-tab-panel-header-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border:1px solid;
+    height:2px;
+    font-size:1px;
+    line-height:1px;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer {
+    border-top: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-bottom: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-bottom {
+    background:transparent !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-footer-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-top:0 !important;
+}
+
+.ext-border-box .x-tab-panel-header-plain .x-tab-strip-spacer,
+.ext-border-box .x-tab-panel-footer-plain .x-tab-strip-spacer {
+    height:3px;
+}
+
+ul.x-tab-strip li {
+    float:left;
+    margin-left:2px;
+}
+
+ul.x-tab-strip li.x-tab-edge {
+    float:left;
+    margin:0 !important;
+    padding:0 !important;
+    border:0 none !important;
+    font-size:1px !important;
+    line-height:1px !important;
+    overflow:hidden;
+    zoom:1;
+    background:transparent !important;
+    width:1px;
+}
+
+.x-tab-strip a, .x-tab-strip span, .x-tab-strip em {
+	display:block;
+}
+
+.x-tab-strip a {
+	text-decoration:none !important;
+	-moz-outline: none;
+	outline: none;
+	cursor:pointer;
+}
+
+.x-tab-strip-inner {
+    overflow:hidden;
+	text-overflow: ellipsis;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	white-space: nowrap;
+	cursor:pointer;
+    padding:4px 0;
+}
+
+.x-tab-strip-top .x-tab-with-icon .x-tab-right {
+    padding-left:6px;
+}
+
+.x-tab-strip .x-tab-with-icon span.x-tab-strip-text {
+	padding-left:20px;
+    background-position: 0 3px;
+    background-repeat: no-repeat;
+}
+
+.x-tab-strip-active, .x-tab-strip-active a.x-tab-right {
+    cursor:default;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	cursor:default;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	cursor:default;
+}
+
+.x-tab-panel-body {
+    overflow:hidden;
+}
+
+.x-tab-panel-bwrap {
+    overflow:hidden;
+}
+
+.ext-ie .x-tab-strip .x-tab-right {
+    position:relative;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+    margin-bottom:-1px;
+}
+
+/*
+ * Horrible hack for IE8 in quirks mode
+ */
+.ext-ie8 .x-tab-strip li {
+    position: relative;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top .x-tab-right {
+    top: 1px;
+}
+.ext-ie8 .x-tab-strip-top {
+    padding-top: 1;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top {
+    padding-top: 0;
+}
+.ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:3px;
+}
+.ext-border-box .ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:4px;
+}
+.ext-ie8 .x-tab-strip-bottom .x-tab-right{
+    top:0;
+}
+
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-bottom:5px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+    margin-top:-1px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-top:5px;
+}
+
+.x-tab-strip-top .x-tab-right {
+	background: transparent no-repeat 0 -51px;
+    padding-left:10px;
+}
+
+.x-tab-strip-top .x-tab-left {
+	background: transparent no-repeat right -351px;
+    padding-right:10px;
+}
+
+.x-tab-strip-top .x-tab-strip-inner {
+	background: transparent repeat-x 0 -201px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-right {
+	 background-position:0 -101px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-left {
+	 background-position:right -401px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-strip-inner {
+	 background-position:0 -251px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+	background-position: 0 0;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-left {
+	background-position: right -301px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-strip-inner {
+	background-position: 0 -151px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+    margin-right: 3px;
+    padding:0 10px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+    padding:0;
+}
+
+.x-tab-strip .x-tab-strip-close {
+    display:none;
+}
+
+.x-tab-strip-closable {
+    position:relative;
+}
+
+.x-tab-strip-closable .x-tab-left {
+    padding-right:19px;
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    opacity:.6;
+    -moz-opacity:.6;
+    background-repeat:no-repeat;
+    display:block;
+	width:11px;
+    height:11px;
+    position:absolute;
+    top:3px;
+    right:3px;
+    cursor:pointer;
+    z-index:2;
+}
+
+.x-tab-strip .x-tab-strip-active a.x-tab-strip-close {
+    opacity:.8;
+    -moz-opacity:.8;
+}
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+    opacity:1;
+    -moz-opacity:1;
+}
+
+.x-tab-panel-body {
+    border: 1px solid;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background: transparent no-repeat -18px 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    left:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background: transparent no-repeat 0 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    right:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+
+.x-tab-scroller-right-over {
+    background-position: -18px 0;
+}
+
+.x-tab-scroller-right-disabled {
+    background-position: 0 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scrolling-bottom .x-tab-scroller-left, .x-tab-scrolling-bottom .x-tab-scroller-right{
+    margin-top: 1px;
+}
+
+.x-tab-scrolling .x-tab-strip-wrap {
+    margin-left:18px;
+    margin-right:18px;
+}
+
+.x-tab-scrolling {
+    position:relative;    
+}
+
+.x-tab-panel-bbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-tab-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}/* all fields */
+.x-form-field{
+    margin: 0 0 0 0;
+}
+
+.ext-webkit *:focus{
+    outline: none !important;
+}
+
+/* ---- text fields ---- */
+.x-form-text, textarea.x-form-field{
+    padding:1px 3px;
+    background:repeat-x 0 0;
+    border:1px solid;
+}
+
+textarea.x-form-field {
+    padding:2px 3px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:22px;
+    line-height:18px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-form-text, .ext-ie7 .x-form-text {
+    margin:-1px 0; /* ie bogus margin bug */
+    height:22px; /* ie quirks */
+    line-height:18px;
+}
+
+.x-quirks .ext-ie9 .x-form-text {
+    height: 22px;
+    padding-top: 3px;
+    padding-bottom: 0px;
+}
+
+/* Ugly hacks for the bogus 1px margin bug in IE9 quirks */
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-text,
+.x-quirks .ext-ie9 .x-form-field-trigger-wrap .x-form-text {
+    margin-top: -1px;
+    margin-bottom: -1px;
+}
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-element {
+    margin-bottom: -1px;
+}
+
+.ext-ie6 .x-form-field-wrap .x-form-file-btn, .ext-ie7 .x-form-field-wrap .x-form-file-btn {
+    top: -1px; /* because of all these margin hacks, these buttons are off by one pixel in IE6,7 */
+}
+
+.ext-ie6 textarea.x-form-field, .ext-ie7 textarea.x-form-field {
+    margin:-1px 0; /* ie bogus margin bug */
+}
+
+.ext-strict .x-form-text {
+    height:18px;
+}
+
+.ext-safari.ext-mac textarea.x-form-field {
+    margin-bottom:-2px; /* another bogus margin bug, safari/mac only */
+}
+
+/*
+.ext-strict .ext-ie8 .x-form-text, .ext-strict .ext-ie8 textarea.x-form-field {
+    margin-bottom: 1px;
+}
+*/
+
+.ext-gecko .x-form-text , .ext-ie8 .x-form-text {
+    padding-top:2px; /* FF won't center the text vertically */
+    padding-bottom:0;
+}
+
+.ext-ie6 .x-form-composite .x-form-text.x-box-item, .ext-ie7 .x-form-composite .x-form-text.x-box-item {
+    margin: 0 !important; /* clear ie bogus margin bug fix */
+}
+
+textarea {
+    resize: none;  /* Disable browser resizable textarea */
+}
+
+/* select boxes */
+.x-form-select-one {
+    height:20px;
+    line-height:18px;
+    vertical-align:middle;
+    border: 1px solid;
+}
+
+/* multi select boxes */
+
+/* --- TODO --- */
+
+/* 2.0.2 style */
+.x-form-check-wrap {
+    line-height:18px;
+    height: auto;
+}
+
+.ext-ie .x-form-check-wrap input {
+    width:15px;
+    height:15px;
+}
+
+.x-form-check-wrap input{
+    vertical-align: bottom;
+}
+
+.x-editor .x-form-check-wrap {
+    padding:3px;
+}
+
+.x-editor .x-form-checkbox {
+    height:13px;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid;
+    margin-bottom: 5px;
+    padding-left: 3px !important;
+    float: none !important;
+}
+
+/* wrapped fields and triggers */
+.x-form-field-wrap .x-form-trigger{
+    width:17px;
+    height:21px;
+    border:0;
+    background:transparent no-repeat 0 0;
+    cursor:pointer;
+    border-bottom: 1px solid;
+    position:absolute;
+    top:0;
+}
+
+.x-form-field-wrap .x-form-date-trigger, .x-form-field-wrap .x-form-clear-trigger, .x-form-field-wrap .x-form-search-trigger{
+    cursor:pointer;
+}
+
+.x-form-field-wrap .x-form-twin-triggers .x-form-trigger{
+    position:static;
+    top:auto;
+    vertical-align:top;
+}
+
+.x-form-field-wrap {
+    position:relative;
+    left:0;top:0;
+    text-align: left;
+    zoom:1;
+    white-space: nowrap;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {
+    right: 0; /* IE8 Strict mode trigger bug */
+}
+
+.x-form-field-wrap .x-form-trigger-over{
+    background-position:-17px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click{
+    background-position:-34px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    background-position:-51px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over{
+    background-position:-68px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click{
+    background-position:-85px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-trigger-noedit{
+    cursor:pointer;
+}
+
+/* field focus style */
+.x-form-focus, textarea.x-form-focus{
+    border: 1px solid;
+}
+
+/* invalid fields */
+.x-form-invalid, textarea.x-form-invalid{
+    background:repeat-x bottom;
+    border: 1px solid;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background:repeat-x bottom;
+}
+
+/* editors */
+.x-editor {
+    visibility:hidden;
+    padding:0;
+    margin:0;
+}
+
+.x-form-grow-sizer {
+    left: -10000px;
+    padding: 8px 3px;
+    position: absolute;
+    visibility:hidden;
+    top: -10000px;
+    white-space: pre-wrap;
+    white-space: -moz-pre-wrap;
+    white-space: -pre-wrap;
+    white-space: -o-pre-wrap;
+    word-wrap: break-word;
+    zoom:1;
+}
+
+.x-form-grow-sizer p {
+    margin:0 !important;
+    border:0 none !important;
+    padding:0 !important;
+}
+
+/* Form Items CSS */
+
+.x-form-item {
+    display:block;
+    margin-bottom:4px;
+    zoom:1;
+}
+
+.x-form-item label.x-form-item-label {
+    display:block;
+    float:left;
+    width:100px;
+    padding:3px;
+    padding-left:0;
+    clear:left;
+    z-index:2;
+    position:relative;
+}
+
+.x-form-element {
+    padding-left:105px;
+    position:relative;
+}
+
+.x-form-invalid-msg {
+    padding:2px;
+    padding-left:18px;
+    background: transparent no-repeat 0 2px;
+    line-height:16px;
+    width:200px;
+}
+
+.x-form-label-left label.x-form-item-label {
+   text-align:left;
+}
+
+.x-form-label-right label.x-form-item-label {
+   text-align:right;
+}
+
+.x-form-label-top .x-form-item label.x-form-item-label {
+    width:auto;
+    float:none;
+    clear:none;
+    display:inline;
+    margin-bottom:4px;
+    position:static;
+}
+
+.x-form-label-top .x-form-element {
+    padding-left:0;
+    padding-top:4px;
+}
+
+.x-form-label-top .x-form-item {
+    padding-bottom:4px;
+}
+
+/* Editor small font for grid, toolbar and tree */
+.x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    margin-top:-1px !important; /* ie bogus margin bug */
+    margin-bottom:-1px !important;
+    height:20px !important; /* ie quirks */
+    line-height:16px !important;
+}
+
+.ext-strict .x-small-editor .x-form-text {
+    height:16px !important;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+}
+
+.ext-border-box .x-small-editor .x-form-text {
+    height:20px;
+}
+
+.x-small-editor .x-form-select-one {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.x-small-editor .x-form-num-field {
+    text-align:right;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger{
+    height:19px;
+}
+
+.ext-webkit .x-small-editor .x-form-text{padding-top:3px;font-size:100%;}
+
+.ext-strict .ext-webkit .x-small-editor .x-form-text{
+    height:14px !important;
+}
+
+.x-form-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+.x-form-clear-left {
+    clear:left;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.ext-ie6 .x-form-check-wrap input, .ext-border-box .x-form-check-wrap input{
+   margin-top: 3px;
+}
+
+.x-form-cb-label {
+    position: relative;
+    margin-left:4px;
+    top: 2px;
+}
+
+.ext-ie .x-form-cb-label{
+    top: 1px;
+}
+
+.ext-ie6 .x-form-cb-label, .ext-border-box .x-form-cb-label{
+    top: 3px;
+}
+
+.x-form-display-field{
+    padding-top: 2px;
+}
+
+.ext-gecko .x-form-display-field, .ext-strict .ext-ie7 .x-form-display-field{
+    padding-top: 1px;
+}
+
+.ext-ie .x-form-display-field{
+    padding-top: 3px;
+}
+
+.ext-strict .ext-ie8 .x-form-display-field{
+    padding-top: 0;
+}
+
+.x-form-column {
+    float:left;
+    padding:0;
+    margin:0;
+    width:48%;
+    overflow:hidden;
+    zoom:1;
+}
+
+/* buttons */
+.x-form .x-form-btns-ct .x-btn{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns td {
+    border:0;
+    padding:0;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-right table{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-left table{
+    float:left;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center{
+    text-align:center; /*ie*/
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center table{
+    margin:0 auto; /*everyone else*/
+}
+
+.x-form .x-form-btns-ct table td.x-form-btn-td{
+    padding:3px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-left{
+    background-position:0 -147px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-right{
+    background-position:0 -168px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-center{
+    background-position:0 -189px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-center{
+    background-position:0 -126px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click  .x-btn-right{
+    background-position:0 -84px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-left{
+    background-position:0 -63px;
+}
+
+.x-form-invalid-icon {
+    width:16px;
+    height:18px;
+    visibility:hidden;
+    position:absolute;
+    left:0;
+    top:0;
+    display:block;
+    background:transparent no-repeat 0 2px;
+}
+
+/* fieldsets */
+.x-fieldset {
+    border:1px solid;
+    padding:10px;
+    margin-bottom:10px;
+    display:block; /* preserve margins in IE */
+}
+
+/* make top of checkbox/tools visible in webkit */
+.ext-webkit .x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset legend {
+    margin-bottom:10px;
+}
+
+.ext-strict .ext-ie9 .x-fieldset legend.x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset {
+    padding-top: 0;
+    padding-bottom:10px;
+}
+
+.x-fieldset legend .x-tool-toggle {
+    margin-right:3px;
+    margin-left:0;
+    float:left !important;
+}
+
+.x-fieldset legend input {
+    margin-right:3px;
+    float:left !important;
+    height:13px;
+    width:13px;
+}
+
+fieldset.x-panel-collapsed {
+    padding-bottom:0 !important;
+    border-width: 1px 1px 0 1px !important;
+    border-left-color: transparent;
+    border-right-color: transparent;
+}
+
+.ext-ie6 fieldset.x-panel-collapsed{
+    padding-bottom:0 !important;
+    border-width: 1px 0 0 0 !important;
+    margin-left: 1px;
+    margin-right: 1px;
+}
+
+fieldset.x-panel-collapsed .x-fieldset-bwrap {
+    visibility:hidden;
+    position:absolute;
+    left:-1000px;
+    top:-1000px;
+}
+
+.ext-ie .x-fieldset-bwrap {
+    zoom:1;
+}
+
+.x-fieldset-noborder {
+    border:0px none transparent;
+}
+
+.x-fieldset-noborder legend {
+    margin-left:-3px;
+}
+
+/* IE legend positioning bug */
+.ext-ie .x-fieldset-noborder legend {
+    position: relative;
+    margin-bottom:23px;
+}
+.ext-ie .x-fieldset-noborder legend span {
+    position: absolute;
+    left:16px;
+}
+
+.ext-gecko .x-window-body .x-form-item {
+    -moz-outline: none;
+    outline: none;
+    overflow: auto;
+}
+
+.ext-mac.ext-gecko .x-window-body .x-form-item {
+    overflow:hidden;
+}
+
+.ext-gecko .x-form-item {
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-hide-label label.x-form-item-label {
+     display:none;
+}
+
+.x-hide-label .x-form-element {
+     padding-left: 0 !important;
+}
+
+.x-form-label-top .x-hide-label label.x-form-item-label{
+    display: none;
+}
+
+.x-fieldset {
+    overflow:hidden;
+}
+
+.x-fieldset-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-fieldset-body {
+    overflow:hidden;
+}
+.x-btn{
+	cursor:pointer;
+	white-space: nowrap;
+}
+
+.x-btn button{
+    border:0 none;
+    background-color:transparent;
+    padding-left:3px;
+    padding-right:3px;
+    cursor:pointer;
+    margin:0;
+    overflow:visible;
+    width:auto;
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+* html .ext-ie .x-btn button {
+    width:1px;
+}
+
+.ext-gecko .x-btn button, .ext-webkit .x-btn button {
+    padding-left:0;
+    padding-right:0;
+}
+
+.ext-gecko .x-btn button::-moz-focus-inner {
+    padding:0;
+}
+
+.ext-ie .x-btn button {
+    padding-top:2px;
+}
+
+.x-btn td {
+    padding:0 !important;
+}
+
+.x-btn-text {
+    cursor:pointer;
+	white-space: nowrap;
+    padding:0;
+}
+
+/* icon placement and sizing styles */
+
+/* Only text */
+.x-btn-noicon .x-btn-small .x-btn-text{
+	height: 16px;
+}
+
+.x-btn-noicon .x-btn-medium .x-btn-text{
+    height: 24px;
+}
+
+.x-btn-noicon .x-btn-large .x-btn-text{
+    height: 32px;
+}
+
+/* Only icons */
+.x-btn-icon .x-btn-text{
+    background-position: center;
+	background-repeat: no-repeat;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 16px;
+}
+
+.x-btn-icon .x-btn-medium .x-btn-text{
+    height: 24px;
+	width: 24px;
+}
+
+.x-btn-icon .x-btn-large .x-btn-text{
+    height: 32px;
+	width: 32px;
+}
+
+/* Icons and text */
+/* left */
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:34px;
+    height:32px;
+}
+
+/* top */
+.x-btn-text-icon .x-btn-icon-small-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:34px;
+}
+
+/* right */
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:34px;
+    height:32px;
+}
+
+/* bottom */
+.x-btn-text-icon .x-btn-icon-small-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:34px;
+}
+
+/* background positioning */
+.x-btn-tr i, .x-btn-tl i, .x-btn-mr i, .x-btn-ml i, .x-btn-br i, .x-btn-bl i{
+	font-size:1px;
+    line-height:1px;
+    width:3px;
+    display:block;
+    overflow:hidden;
+}
+
+.x-btn-tr i, .x-btn-tl i, .x-btn-br i, .x-btn-bl i{
+	height:3px;
+}
+
+.x-btn-tl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 0;
+}
+.x-btn-tr{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px 0;
+}
+.x-btn-tc{
+	height:3px;
+	background:repeat-x 0 -6px;
+}
+
+.x-btn-ml{
+	width:3px;
+	background:no-repeat 0 -24px;
+}
+.x-btn-mr{
+	width:3px;
+	background:no-repeat -3px -24px;
+}
+
+.x-btn-mc{
+	background:repeat-x 0 -1096px;
+    vertical-align: middle;
+	text-align:center;
+	padding:0 5px;
+	cursor:pointer;
+	white-space:nowrap;
+}
+
+/* Fixes an issue with the button height */
+.ext-strict .ext-ie6 .x-btn-mc, .ext-strict .ext-ie7 .x-btn-mc {
+    height: 100%;
+}
+
+.x-btn-bl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 -3px;
+}
+
+.x-btn-br{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px -3px;
+}
+
+.x-btn-bc{
+	height:3px;
+	background:repeat-x 0 -15px;
+}
+
+.x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-btn-click .x-btn-tl, .x-btn-menu-active .x-btn-tl, .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-btn-click .x-btn-tr, .x-btn-menu-active .x-btn-tr, .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-btn-click .x-btn-tc, .x-btn-menu-active .x-btn-tc, .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-btn-click .x-btn-ml, .x-btn-menu-active .x-btn-ml, .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-btn-click .x-btn-mr, .x-btn-menu-active .x-btn-mr, .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-btn-click .x-btn-mc, .x-btn-menu-active .x-btn-mc, .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-btn-click .x-btn-bl, .x-btn-menu-active .x-btn-bl, .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-btn-click .x-btn-br, .x-btn-menu-active .x-btn-br, .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-btn-click .x-btn-bc, .x-btn-menu-active .x-btn-bc, .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-btn-disabled *{
+	cursor:default !important;
+}
+
+
+/* With a menu arrow */
+/* right */
+.x-btn-mc em.x-btn-arrow {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:10px;
+}
+
+.x-btn-mc em.x-btn-split {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:14px;
+}
+
+/* bottom */
+.x-btn-mc em.x-btn-arrow-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+/* height adjustment class */
+.x-btn-as-arrow .x-btn-mc em {
+    display:block;
+    background-color:transparent;
+	padding-bottom:14px;
+}
+
+/* groups */
+.x-btn-group {
+    padding:1px;
+}
+
+.x-btn-group-header {
+    padding:2px;
+    text-align:center;
+}
+
+.x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+.x-btn-group-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:3px;
+}
+
+.x-btn-group-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-btn-group-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-br {
+	background: transparent no-repeat right bottom;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-mc {
+    border:0 none;
+    padding:1px 0 0 0;
+    margin:0;
+}
+
+.x-btn-group-mc .x-btn-group-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-btn-group-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-mr {
+	background: transparent repeat-y right 0;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-btn-group-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-btn-group-bc {
+	height:3px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-btn-group-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    height:2px;
+}.x-toolbar{
+    border-style:solid;
+    border-width:0 0 1px 0;
+    display: block;
+	padding:2px;
+    background:repeat-x top left;
+    position:relative;
+    left:0;
+    top:0;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-toolbar-left {
+    width: 100%;
+}
+
+.x-toolbar .x-item-disabled .x-btn-icon {
+    opacity: .35;
+    -moz-opacity: .35;
+    filter: alpha(opacity=35);
+}
+
+.x-toolbar td {
+	vertical-align:middle;
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+	white-space: nowrap;
+}
+
+.x-toolbar .x-item-disabled {
+	cursor:default;
+	opacity:.6;
+	-moz-opacity:.6;
+	filter:alpha(opacity=60);
+}
+
+.x-toolbar .x-item-disabled * {
+	cursor:default;
+}
+
+.x-toolbar .x-toolbar-cell {
+    vertical-align:middle;
+}
+
+.x-toolbar .x-btn-tl, .x-toolbar .x-btn-tr, .x-toolbar .x-btn-tc, .x-toolbar .x-btn-ml, .x-toolbar .x-btn-mr,
+.x-toolbar .x-btn-mc, .x-toolbar .x-btn-bl, .x-toolbar .x-btn-br, .x-toolbar .x-btn-bc
+{
+	background-position: 500px 500px;
+}
+
+/* These rules are duplicated from button.css to give priority of x-toolbar rules above */
+.x-toolbar .x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-toolbar .x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-toolbar .x-btn-click .x-btn-tl, .x-toolbar .x-btn-menu-active .x-btn-tl, .x-toolbar .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tr, .x-toolbar .x-btn-menu-active .x-btn-tr, .x-toolbar .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tc, .x-toolbar .x-btn-menu-active .x-btn-tc, .x-toolbar .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-menu-active .x-btn-ml, .x-toolbar .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mr, .x-toolbar .x-btn-menu-active .x-btn-mr, .x-toolbar .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mc, .x-toolbar .x-btn-menu-active .x-btn-mc, .x-toolbar .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bl, .x-toolbar .x-btn-menu-active .x-btn-bl, .x-toolbar .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-br, .x-toolbar .x-btn-menu-active .x-btn-br, .x-toolbar .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-toolbar div.xtb-text{
+    padding:2px 2px 0;
+    line-height:16px;
+    display:block;
+}
+
+.x-toolbar .xtb-sep {
+	background-position: center;
+	background-repeat: no-repeat;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	width:4px;
+	overflow: hidden;
+	cursor:default;
+	margin: 0 2px 0;
+	border:0;
+}
+
+.x-toolbar .xtb-spacer {
+    width:2px;
+}
+
+/* Paging Toolbar */
+.x-tbar-page-number{
+	width:30px;
+	height:14px;
+}
+
+.ext-ie .x-tbar-page-number{
+    margin-top: 2px;
+}
+
+.x-paging-info {
+    position:absolute;
+    top:5px;
+    right: 8px;
+}
+
+/* floating */
+.x-toolbar-ct {
+    width:100%;
+}
+
+.x-toolbar-right td {
+    text-align: center;
+}
+
+.x-panel-tbar, .x-panel-bbar, .x-window-tbar, .x-window-bbar, .x-tab-panel-tbar, .x-tab-panel-bbar, .x-plain-tbar, .x-plain-bbar {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-toolbar-more .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 12px;
+}
+
+.x-toolbar-more em.x-btn-arrow {
+    display:inline;
+    background-color:transparent;
+	padding-right:0;
+}
+
+.x-toolbar-more .x-btn-mc em.x-btn-arrow {
+    background-image: none;
+}
+
+div.x-toolbar-no-items {
+    color:gray !important;
+    padding:5px 10px !important;
+}
+
+/* fix ie toolbar form items */
+.ext-border-box .x-toolbar-cell .x-form-text {
+    margin-bottom:-1px !important;
+}
+
+.ext-border-box .x-toolbar-cell .x-form-field-wrap .x-form-text {
+    margin:0 !important;
+}
+
+.ext-ie .x-toolbar-cell .x-form-field-wrap {
+    height:21px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-text, .ext-strict .ext-ie .x-toolbar-cell .x-form-text {
+    top: 0px;
+}
+
+.x-toolbar-right td .x-form-field-trigger-wrap{
+    text-align: left;
+}
+
+.x-toolbar-cell .x-form-checkbox, .x-toolbar-cell .x-form-radio{
+    margin-top: 5px;
+}
+
+.x-toolbar-cell .x-form-cb-label{
+    vertical-align: bottom;
+    top: 1px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-checkbox, .ext-ie .x-toolbar-cell .x-form-radio{
+    margin-top: 4px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-cb-label{
+    top: 0;
+}
+/* Grid3 styles */
+.x-grid3 {
+	position:relative;
+	overflow:hidden;
+}
+
+.x-grid-panel .x-panel-body {
+    overflow:hidden !important;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border:1px solid;
+}
+
+.x-grid3 table {
+    table-layout:fixed;
+}
+
+.x-grid3-viewport{
+	overflow:hidden;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+    -moz-outline: none;
+    outline: none;
+	-moz-user-focus: normal;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td {
+    line-height:13px;
+    vertical-align: top;
+	padding-left:1px;
+    padding-right:1px;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-cell{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-row td {
+    line-height:15px;
+    vertical-align:middle;
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+.x-grid3-hd-row .x-grid3-marker-hd {
+    padding:3px;
+}
+
+.x-grid3-row .x-grid3-marker {
+    padding:3px;
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner{
+	overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    padding:3px 3px 3px 5px;
+    white-space: nowrap;
+}
+
+/* ActionColumn, reduce padding to accommodate 16x16 icons in normal row height */
+.x-action-col-cell .x-grid3-cell-inner {
+    padding-top: 1px;
+    padding-bottom: 1px;
+}
+
+.x-action-col-icon {
+    cursor: pointer;
+}
+
+.x-grid3-hd-inner {
+    position:relative;
+	cursor:inherit;
+	padding:4px 3px 4px 5px;
+}
+
+.x-grid3-row-body {
+    white-space:normal;
+}
+
+.x-grid3-body-cell {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+/* IE Quirks to clip */
+.ext-ie .x-grid3-cell-inner, .ext-ie .x-grid3-hd-inner{
+	width:100%;
+}
+
+/* reverse above in strict mode */
+.ext-strict .x-grid3-cell-inner, .ext-strict .x-grid3-hd-inner{
+	width:auto;
+}
+
+.x-grid-row-loading {
+    background: no-repeat center center;
+}
+
+.x-grid-page {
+    overflow:hidden;
+}
+
+.x-grid3-row {
+	cursor: default;
+    border: 1px solid;
+    width:100%;
+}
+
+.x-grid3-row-over {
+	border:1px solid;
+    background: repeat-x left top;
+}
+
+.x-grid3-resize-proxy {
+	width:1px;
+    left:0;
+	cursor: e-resize;
+	cursor: col-resize;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-resize-marker {
+	width:1px;
+	left:0;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: text;
+    -khtml-user-select: text;
+    -webkit-user-select:ignore;
+}
+
+/* header styles */
+.x-grid3-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    padding:1px 0 0 0;
+}
+
+.x-grid3-header-pop {
+    border-left:1px solid;
+    float:right;
+    clear:none;
+}
+
+.x-grid3-header-pop-inner {
+    border-left:1px solid;
+    width:14px;
+    height:19px;
+    background: transparent no-repeat center center;
+}
+
+.ext-ie .x-grid3-header-pop-inner {
+    width:15px;
+}
+
+.ext-strict .x-grid3-header-pop-inner {
+    width:14px; 
+}
+
+.x-grid3-header-inner {
+    overflow:hidden;
+    zoom:1;
+    float:left;
+}
+
+.x-grid3-header-offset {
+    padding-left:1px;
+    text-align: left;
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background: repeat-x left bottom;
+
+}
+
+.x-grid3-sort-icon{
+	background-repeat: no-repeat;
+	display: none;
+	height: 4px;
+	width: 13px;
+	margin-left:3px;
+	vertical-align: middle;
+}
+
+.sort-asc .x-grid3-sort-icon, .sort-desc .x-grid3-sort-icon {
+	display: inline;
+}
+
+/* Header position fixes for IE strict mode */
+.ext-strict .ext-ie .x-grid3-header-inner, .ext-strict .ext-ie6 .x-grid3-hd {
+    position:relative;
+}
+
+.ext-strict .ext-ie6 .x-grid3-hd-inner{
+    position:static;
+}
+
+/* Body Styles */
+.x-grid3-body {
+	zoom:1;
+}
+
+.x-grid3-scroller {
+	overflow:auto;
+    zoom:1;
+    position:relative;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	display: block;
+	padding: 3px 5px 3px 5px;
+	-moz-user-select: none;
+	-khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-split {
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor: e-resize;
+	cursor: col-resize;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	overflow: hidden;
+	position: absolute;
+	top: 2px;
+	width: 6px;
+	z-index: 3;
+}
+
+/* Column Reorder DD */
+.x-dd-drag-proxy .x-grid3-hd-inner{
+	background: repeat-x left bottom;
+	width:120px;
+	padding:3px;
+	border:1px solid;
+	overflow:hidden;
+}
+
+.col-move-top, .col-move-bottom{
+	width:9px;
+	height:9px;
+	position:absolute;
+	top:0;
+	line-height:1px;
+	font-size:1px;
+	overflow:hidden;
+	visibility:hidden;
+	z-index:20000;
+    background:transparent no-repeat left top;
+}
+
+/* Selection Styles */
+.x-grid3-row-selected {
+	border:1px dotted;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background: repeat-x 0 bottom !important;
+    vertical-align:middle !important;
+    padding:0;
+    border-top:1px solid;
+    border-bottom:none !important;
+    border-right:1px solid !important;
+    text-align:center;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    padding:0 4px;
+    text-align:center;
+}
+
+/* dirty cells */
+.x-grid3-dirty-cell {
+    background: transparent no-repeat 0 0;
+}
+
+/* Grid Toolbars */
+.x-grid3-topbar, .x-grid3-bottombar{
+    overflow:hidden;
+	display:none;
+	zoom:1;
+    position:relative;
+}
+
+.x-grid3-topbar .x-toolbar{
+	border-right:0 none;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-right:0 none;
+	border-bottom:0 none;
+	border-top:1px solid;
+}
+
+/* Props Grid Styles */
+.x-props-grid .x-grid3-cell{
+	padding:1px;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background:transparent repeat-y -16px !important;
+    padding-left:12px;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    padding:1px;
+    padding-right:0;
+    border:0 none;
+    border-right:1px solid;
+}
+
+/* dd */
+.x-grid3-col-dd {
+    border:0 none;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-dd-drag-ghost .x-grid3-dd-wrap {
+    padding:1px 3px 3px 1px;
+}
+
+.x-grid3-hd {
+    -moz-user-select:none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-btn {
+    display:none;
+    position:absolute;
+    width:14px;
+    background:no-repeat left center;
+    right:0;
+    top:0;
+    z-index:2;
+	cursor:pointer;
+}
+
+.x-grid3-hd-over .x-grid3-hd-btn, .x-grid3-hd-menu-open .x-grid3-hd-btn {
+    display:block;
+}
+
+a.x-grid3-hd-btn:hover {
+    background-position:-14px center;
+}
+
+/* Expanders */
+.x-grid3-body .x-grid3-td-expander {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-expander .x-grid3-cell-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-expander {
+    width:100%;
+    height:18px;
+    background-position:4px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-expander {
+    background-position:4px 2px;
+}
+
+.x-grid3-row-expanded .x-grid3-row-expander {
+    background-position:-21px 2px;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-body {
+    display:none !important;
+}
+
+.x-grid3-row-expanded .x-grid3-row-body {
+    display:block !important;
+}
+
+/* Checkers */
+.x-grid3-body .x-grid3-td-checker {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-checker .x-grid3-cell-inner, .x-grid3-header .x-grid3-td-checker .x-grid3-hd-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    width:100%;
+    height:18px;
+    background-position:2px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row .x-grid3-row-checker {
+    background-position:2px 2px;
+}
+
+.x-grid3-row-selected .x-grid3-row-checker, .x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker {
+    background-position:-23px 2px;
+}
+
+.x-grid3-hd-checker {
+    background-position:2px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker {
+    background-position:2px 3px;
+}
+
+.x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 3px;
+}
+
+/* Numberer */
+.x-grid3-body .x-grid3-td-numberer {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+    padding:3px 5px 0 0 !important;
+    text-align:right;
+}
+
+/* Row Icon */
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background:transparent repeat-y right;
+    vertical-align:top;
+    text-align:center;
+}
+
+.x-grid3-body .x-grid3-td-row-icon .x-grid3-cell-inner {
+    padding:0 !important;
+    background-position:center center;
+    background-repeat:no-repeat;
+    width:16px;
+    height:16px;
+    margin-left:2px;
+    margin-top:3px;
+}
+
+/* All specials */
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-check-col-td .x-grid3-cell-inner {
+    padding: 1px 0 0 0 !important;
+}
+
+.x-grid3-check-col {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-check-col-on {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+/* Grouping classes */
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom: 2px solid;
+    cursor:pointer;
+    padding-top:6px;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background:transparent no-repeat 3px 3px;
+    padding:4px 4px 4px 17px;
+}
+
+.x-grid-group-collapsed .x-grid-group-body {
+    display:none;
+}
+
+.ext-ie6 .x-grid3 .x-editor .x-form-text, .ext-ie7 .x-grid3 .x-editor .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-ie .x-props-grid .x-editor .x-form-text {
+    position:static;
+    top:0;
+}
+
+.x-grid-empty {
+    padding:10px;
+}
+
+/* fix floating toolbar issue */
+.ext-ie7 .x-grid-panel .x-panel-bbar {
+    position:relative;
+}
+
+
+/* Reset position to static when Grid Panel has been framed */
+/* to resolve 'snapping' from top to bottom behavior. */
+/* @forumThread 86656 */
+.ext-ie7 .x-grid-panel .x-panel-mc .x-panel-bbar {
+    position: static;
+}
+
+.ext-ie6 .x-grid3-header {
+    position: relative;
+}
+
+/* Fix WebKit bug in Grids */
+.ext-webkit .x-grid-panel .x-panel-bwrap{
+    -webkit-user-select:none;
+}
+.ext-webkit .x-tbar-page-number{
+    -webkit-user-select:ignore;
+}
+/* end*/
+
+/* column lines */
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    padding-right:0;
+    border-right:1px solid;
+}
+.x-pivotgrid .x-grid3-header-offset table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-header-offset table td {
+    padding: 4px 3px 4px 5px;
+    text-align: center;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    line-height: 13px;
+    font-family: tahoma;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    display: block;
+    float: left;
+}
+
+.x-pivotgrid .x-grid3-row-headers table {
+    height: 100%;
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    height: 18px;
+    padding: 2px 7px 0 0;
+    text-align: right;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    font-family: tahoma;
+}
+
+.ext-gecko .x-pivotgrid .x-grid3-row-headers table td {
+    height: 21px;
+}
+
+.x-grid3-header-title {
+    top: 0%;
+    left: 0%;
+    position: absolute;
+    text-align: center;
+    vertical-align: middle;
+    font-family: tahoma;
+    font-size: 11px;
+    padding: auto 1px;
+    display: table-cell;
+}
+
+.x-grid3-header-title span {
+    position: absolute;
+    top: 50%;
+    left: 0%;
+    width: 100%;
+    margin-top: -6px;
+}.x-dd-drag-proxy{
+	position:absolute;
+	left:0;
+    top:0;
+	visibility:hidden;
+	z-index:15000;
+}
+
+.x-dd-drag-ghost{
+	-moz-opacity: 0.85;
+    opacity:.85;
+    filter: alpha(opacity=85);
+    border: 1px solid;
+	padding:3px;
+	padding-left:20px;
+	white-space:nowrap;
+}
+
+.x-dd-drag-repair .x-dd-drag-ghost{
+	-moz-opacity: 0.4;
+    opacity:.4;
+    filter: alpha(opacity=40);
+	border:0 none;
+	padding:0;
+	background-color:transparent;
+}
+
+.x-dd-drag-repair .x-dd-drop-icon{
+	visibility:hidden;
+}
+
+.x-dd-drop-icon{
+    position:absolute;
+	top:3px;
+	left:3px;
+	display:block;
+	width:16px;
+	height:16px;
+	background-color:transparent;
+	background-position: center;
+	background-repeat: no-repeat;
+	z-index:1;
+}
+
+.x-view-selector {
+    position:absolute;
+    left:0;
+    top:0;
+    width:0;
+    border:1px dotted;
+	opacity: .5;
+    -moz-opacity: .5;
+    filter:alpha(opacity=50);
+    zoom:1;
+}.ext-strict .ext-ie .x-tree .x-panel-bwrap{
+    position:relative;
+    overflow:hidden;
+}
+
+.x-tree-icon, .x-tree-ec-icon, .x-tree-elbow-line, .x-tree-elbow, .x-tree-elbow-end, .x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+    background-repeat: no-repeat;
+}
+
+.x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .x-tree-node-icon{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	background-position:center;
+    background-repeat: no-repeat;
+}
+
+.ext-ie .x-tree-node-indent img, .ext-ie .x-tree-node-icon, .ext-ie .x-tree-ec-icon {
+    vertical-align: middle !important;
+}
+
+.ext-strict .ext-ie8 .x-tree-node-indent img, .ext-strict .ext-ie8 .x-tree-node-icon, .ext-strict .ext-ie8 .x-tree-ec-icon {
+    vertical-align: top !important;
+}
+
+/* checkboxes */
+
+input.x-tree-node-cb {
+    margin-left:1px;
+    height: 19px;
+	vertical-align: bottom;
+}
+
+.ext-ie input.x-tree-node-cb {
+    margin-left:0;
+    margin-top: 1px;
+    width: 16px;
+    height: 16px;
+    vertical-align: middle;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb{
+    margin: 1px 1px;
+    height: 14px;
+    vertical-align: bottom;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb + a{
+    vertical-align: bottom;
+}
+
+.ext-opera input.x-tree-node-cb {
+    height: 14px;
+    vertical-align: middle;
+}
+
+.x-tree-noicon .x-tree-node-icon{
+	width:0; height:0;
+}
+
+/* No line styles */
+.x-tree-no-lines .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+/* Arrows */
+.x-tree-arrows .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	cursor:pointer;
+}
+
+.ext-ie ul.x-tree-node-ct{
+    font-size:0;
+    line-height:0;
+    zoom:1;
+}
+
+.x-tree-node{
+	white-space: nowrap;
+}
+
+.x-tree-node-el {
+    line-height:18px;
+    cursor:pointer;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	text-decoration:none;
+	-khtml-user-select:none;
+	-moz-user-select:none;
+    -webkit-user-select:ignore;
+    -kthml-user-focus:normal;
+    -moz-user-focus:normal;
+    -moz-outline: 0 none;
+    outline:0 none;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	text-decoration:none;
+	padding:1px 3px 1px 2px;
+}
+
+.x-tree-node .x-tree-node-disabled .x-tree-node-icon{
+	-moz-opacity: 0.5;
+   opacity:.5;
+   filter: alpha(opacity=50);
+}
+
+.x-tree-node .x-tree-node-inline-icon{
+	background-color:transparent;
+}
+
+.x-tree-node a:hover, .x-dd-drag-ghost a:hover{
+	text-decoration:none;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:1px dotted;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top:1px dotted;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above{
+	 border-top:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom:2px solid;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top:2px solid;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 border:1px dotted;
+}
+
+.x-dd-drag-ghost .x-tree-node-indent, .x-dd-drag-ghost .x-tree-ec-icon{
+	display:none !important;
+}
+
+/* Fix for ie rootVisible:false issue */
+.x-tree-root-ct {
+    zoom:1;
+}
+.x-date-picker {
+    border: 1px solid;
+    border-top:0 none;
+	position:relative;
+}
+
+.x-date-picker a {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+.x-date-inner, .x-date-inner td, .x-date-inner th{
+    border-collapse:separate;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background: repeat-x 0 -83px;
+	overflow:hidden;
+}
+
+.x-date-middle .x-btn-tc,.x-date-middle .x-btn-tl,.x-date-middle .x-btn-tr,
+.x-date-middle .x-btn-mc,.x-date-middle .x-btn-ml,.x-date-middle .x-btn-mr,
+.x-date-middle .x-btn-bc,.x-date-middle .x-btn-bl,.x-date-middle .x-btn-br{
+	background:transparent !important;
+    vertical-align:middle;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background:transparent no-repeat right 0;
+}
+
+.x-date-right, .x-date-left {
+    width:18px;
+}
+
+.x-date-right{
+    text-align:right;
+}
+
+.x-date-middle {
+    padding-top:2px;
+    padding-bottom:2px;
+    width:130px; /* FF3 */
+}
+
+.x-date-right a, .x-date-left a{
+    display:block;
+    width:16px;
+	height:16px;
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor:pointer;
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a:hover, .x-date-left a:hover{
+    -moz-opacity: 1;
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+
+.x-item-disabled .x-date-right a:hover, .x-item-disabled .x-date-left a:hover{
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a {
+    margin-right:2px;
+    text-decoration:none !important;
+}
+
+.x-date-left a{
+    margin-left:2px;
+    text-decoration:none !important;
+}
+
+table.x-date-inner {
+    width: 100%;
+    table-layout:fixed;
+}
+
+.ext-webkit table.x-date-inner{
+    /* Fix for webkit browsers */
+    width: 175px;
+}
+
+
+.x-date-inner th {
+    width:25px;
+}
+
+.x-date-inner th {
+    background: repeat-x left top;
+    text-align:right !important;
+	border-bottom: 1px solid;
+	cursor:default;
+    padding:0;
+    border-collapse:separate;
+}
+
+.x-date-inner th span {
+    display:block;
+    padding:2px;
+    padding-right:7px;
+}
+
+.x-date-inner td {
+    border: 1px solid;
+	text-align:right;
+    padding:0;
+}
+
+.x-date-inner a {
+    padding:2px 5px;
+    display:block;
+	text-decoration:none;
+    text-align:right;
+    zoom:1;
+}
+
+.x-date-inner .x-date-active{
+	cursor:pointer;
+	color:black;
+}
+
+.x-date-inner .x-date-selected a{
+	background: repeat-x left top;
+	border:1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-today a{
+	border: 1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+    text-decoration:none !important;
+}
+
+.x-date-bottom {
+    padding:4px;
+    border-top: 1px solid;
+    background: repeat-x left top;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    text-decoration:none !important;
+}
+
+.x-item-disabled .x-date-inner a:hover{
+    background: none;
+}
+
+.x-date-inner .x-date-disabled a {
+	cursor:default;
+}
+
+.x-date-menu .x-menu-item {
+	padding:1px 24px 1px 4px;
+	white-space: nowrap;
+}
+
+.x-date-menu .x-menu-item .x-menu-item-icon {
+    width:10px;
+    height:10px;
+    margin-right:5px;
+    background-position:center -4px !important;
+}
+
+.x-date-mp {
+	position:absolute;
+	left:0;
+	top:0;
+	display:none;
+}
+
+.x-date-mp td {
+    padding:2px;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+td.x-date-mp-month,td.x-date-mp-year,td.x-date-mp-ybtn {
+    border: 0 none;
+	text-align:center;
+	vertical-align: middle;
+	width:25%;
+}
+
+.x-date-mp-ok {
+	margin-right:3px;
+}
+
+.x-date-mp-btns button {
+	text-decoration:none;
+	text-align:center;
+	text-decoration:none !important;
+	border:1px solid;
+	padding:1px 3px 1px;
+	cursor:pointer;
+}
+
+.x-date-mp-btns {
+	background: repeat-x left top;
+}
+
+.x-date-mp-btns td {
+	border-top: 1px solid;
+    text-align:center;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	display:block;
+	padding:2px 4px;
+	text-decoration:none;
+	text-align:center;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	text-decoration:none;
+	cursor:pointer;
+}
+
+td.x-date-mp-sel a {
+	padding:1px 3px;
+	background: repeat-x left top;
+	border:1px solid;
+}
+
+.x-date-mp-ybtn a {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    cursor:pointer;
+    background:transparent no-repeat;
+    display:block;
+    margin:0 auto;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next {
+    background-position:0 -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next:hover {
+    background-position:-15px -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev {
+    background-position:0 -105px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev:hover {
+    background-position:-15px -105px;
+}
+
+.x-date-mp-ybtn {
+   text-align:center;
+}
+
+td.x-date-mp-sep {
+   border-right:1px solid;
+}.x-tip{
+	position: absolute;
+	top: 0;
+    left:0;
+    visibility: hidden;
+	z-index: 20002;
+    border:0 none;
+}
+
+.x-tip .x-tip-close{
+	height: 15px;
+	float:right;
+	width: 15px;
+    margin:0 0 2px 2px;
+    cursor:pointer;
+    display:none;
+}
+
+.x-tip .x-tip-tc {
+	background: transparent no-repeat 0 -62px;
+	padding-top:3px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-bc {
+	background: transparent no-repeat 0 -121px;
+	height:3px;
+    overflow:hidden;
+}
+
+.x-tip .x-tip-bl {
+	background: transparent no-repeat 0 -59px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-br {
+	background: transparent no-repeat right -59px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mc {
+    border:0 none;
+}
+
+.x-tip .x-tip-ml {
+	background: no-repeat 0 -124px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mr {
+	background: transparent no-repeat right -124px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.ext-ie .x-tip .x-tip-header,.ext-ie .x-tip .x-tip-tc {
+    font-size:0;
+    line-height:0;
+}
+
+.ext-border-box .x-tip .x-tip-header, .ext-border-box .x-tip .x-tip-tc{
+    line-height: 1px;
+}
+
+.x-tip .x-tip-header-text {
+    padding:0;
+    margin:0 0 2px 0;
+}
+
+.x-tip .x-tip-body {
+    margin:0 !important;
+    line-height:14px;
+    padding:0;
+}
+
+.x-tip .x-tip-body .loading-indicator {
+    margin:0;
+}
+
+.x-tip-draggable .x-tip-header,.x-tip-draggable .x-tip-header-text {
+    cursor:move;
+}
+
+.x-form-invalid-tip .x-tip-tc {
+	background: repeat-x 0 -12px;
+    padding-top:6px;
+}
+
+.x-form-invalid-tip .x-tip-bc {
+	background: repeat-x 0 -18px;
+    height:6px;
+}
+
+.x-form-invalid-tip .x-tip-bl {
+	background: no-repeat 0 -6px;
+}
+
+.x-form-invalid-tip .x-tip-br {
+	background: no-repeat right -6px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding:2px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding-left:24px;
+    background:transparent no-repeat 2px 2px;
+}
+
+.x-tip-anchor {
+    position: absolute;
+    width: 9px;
+    height: 10px;
+    overflow:hidden;
+    background: transparent no-repeat 0 0;
+    zoom:1;
+}
+.x-tip-anchor-bottom {
+    background-position: -9px 0;
+}
+.x-tip-anchor-right {
+    background-position: -18px 0;
+    width: 10px;
+}
+.x-tip-anchor-left {
+    background-position: -28px 0;
+    width: 10px;
+}.x-menu {
+	z-index: 15000;
+	zoom: 1;
+	background: repeat-y;
+}
+
+.x-menu-floating{
+    border: 1px solid;
+}
+
+.x-menu a {
+    text-decoration: none !important;
+}
+
+.ext-ie .x-menu {
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-menu-list{
+    padding: 2px;
+	background-color:transparent;
+	border:0 none;
+    overflow:hidden;
+    overflow-y: hidden;
+}
+
+.ext-strict .ext-ie .x-menu-list{
+    position: relative;
+}
+
+.x-menu li{
+	line-height:100%;
+}
+
+.x-menu li.x-menu-sep-li{
+	font-size:1px;
+	line-height:1px;
+}
+
+.x-menu-list-item{
+    white-space: nowrap;
+	display:block;
+	padding:1px;
+}
+
+.x-menu-item{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-menu-item-arrow{
+	background:transparent no-repeat right;
+}
+
+.x-menu-sep {
+	display:block;
+	font-size:1px;
+	line-height:1px;
+	margin: 2px 3px;
+	border-bottom:1px solid;
+    overflow:hidden;
+}
+
+.x-menu-focus {
+	position:absolute;
+	left:-1px;
+	top:-1px;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+    overflow:hidden;
+    display:block;
+}
+
+a.x-menu-item {
+    cursor: pointer;
+    display: block;
+    line-height: 16px;
+    outline-color: -moz-use-text-color;
+    outline-style: none;
+    outline-width: 0;
+    padding: 3px 21px 3px 27px;
+    position: relative;
+    text-decoration: none;
+    white-space: nowrap;
+}
+
+.x-menu-item-active {
+    background-repeat: repeat-x;
+    background-position: left bottom;
+    border-style:solid;
+    border-width: 1px 0;
+    margin:0 1px;
+	padding: 0;
+}
+
+.x-menu-item-active a.x-menu-item {
+    border-style:solid;
+    border-width:0 1px;
+    margin:0 -1px;
+}
+
+.x-menu-item-icon {
+	border: 0 none;
+	height: 16px;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	position: absolute;
+    left: 3px;
+    top: 3px;
+    margin: 0;
+    background-position:center;
+}
+
+.ext-ie .x-menu-item-icon {
+    left: -24px;
+}
+.ext-strict .x-menu-item-icon {
+    left: 3px;
+}
+
+.ext-ie6 .x-menu-item-icon {
+    left: -24px;
+}
+
+.ext-ie .x-menu-item-icon {
+    vertical-align: middle;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background: transparent no-repeat center;
+}
+
+.x-menu-group-item .x-menu-item-icon{
+	background-color: transparent;
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background: transparent no-repeat center;
+}
+
+.x-date-menu .x-menu-list{
+    padding: 0;
+}
+
+.x-menu-date-item{
+	padding:0;
+}
+
+.x-menu .x-color-palette, .x-menu .x-date-picker{
+    margin-left: 26px;
+	margin-right:4px;
+}
+
+.x-menu .x-date-picker{
+    border:1px solid;
+    margin-top:2px;
+    margin-bottom:2px;
+}
+
+.x-menu-plain .x-color-palette, .x-menu-plain .x-date-picker{
+	 margin: 0;
+	 border: 0 none;
+}
+
+.x-date-menu {
+   padding:0 !important;
+}
+
+/*
+ * fixes separator visibility problem in IE 6
+ */
+.ext-strict .ext-ie6 .x-menu-sep-li {
+    padding: 3px 4px;
+}
+.ext-strict .ext-ie6 .x-menu-sep {
+    margin: 0;
+    height: 1px;
+}
+
+/*
+ * Fixes an issue with "fat" separators in webkit
+ */
+.ext-webkit .x-menu-sep{
+    height: 1px;
+}
+
+/*
+ * Ugly mess to remove the white border under the picker
+ */
+.ext-ie .x-date-menu{
+    height: 199px;
+}
+
+.ext-strict .ext-ie .x-date-menu, .ext-border-box .ext-ie8 .x-date-menu{
+    height: 197px;
+}
+
+.ext-strict .ext-ie7 .x-date-menu{
+    height: 195px;
+}
+
+.ext-strict .ext-ie8 .x-date-menu{
+    height: auto;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border:1px dotted !important;
+	padding:0;
+}
+
+.x-menu .x-menu-scroller {
+    width: 100%;
+	background-repeat:no-repeat;
+	background-position:center;
+	height:8px;
+    line-height: 8px;
+	cursor:pointer;
+    margin: 0;
+    padding: 0;
+}
+
+.x-menu .x-menu-scroller-active{
+    height: 6px;
+    line-height: 6px;
+}
+
+.x-menu-list-item-indent{
+    padding-left: 27px;
+}/*
+ Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:
+  <div class="x-box-blue">
+        <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>
+        <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">
+            <h3>YOUR TITLE HERE (optional)</h3>
+            <div>YOUR CONTENT HERE</div>
+        </div></div></div>
+        <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
+    </div>
+ */
+
+.x-box-tl {
+	background: transparent no-repeat 0 0;
+    zoom:1;
+}
+
+.x-box-tc {
+	height: 8px;
+	background: transparent repeat-x 0 0;
+	overflow: hidden;
+}
+
+.x-box-tr {
+	background: transparent no-repeat right -8px;
+}
+
+.x-box-ml {
+	background: transparent repeat-y 0;
+	padding-left: 4px;
+	overflow: hidden;
+    zoom:1;
+}
+
+.x-box-mc {
+	background: repeat-x 0 -16px;
+	padding: 4px 10px;
+}
+
+.x-box-mc h3 {
+	margin: 0 0 4px 0;
+    zoom:1;
+}
+
+.x-box-mr {
+	background: transparent repeat-y right;
+	padding-right: 4px;
+	overflow: hidden;
+}
+
+.x-box-bl {
+	background: transparent no-repeat 0 -16px;
+    zoom:1;
+}
+
+.x-box-bc {
+	background: transparent repeat-x 0 -8px;
+	height: 8px;
+	overflow: hidden;
+}
+
+.x-box-br {
+	background: transparent no-repeat right -24px;
+}
+
+.x-box-tl, .x-box-bl {
+	padding-left: 8px;
+	overflow: hidden;
+}
+
+.x-box-tr, .x-box-br {
+	padding-right: 8px;
+	overflow: hidden;
+}.x-combo-list {
+    border:1px solid;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-combo-list-inner {
+    overflow:auto;
+    position:relative; /* for calculating scroll offsets */
+    zoom:1;
+    overflow-x:hidden;
+}
+
+.x-combo-list-hd {
+    border-bottom:1px solid;
+    padding:3px;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom:1px solid;
+}
+
+.x-combo-list-item {
+    padding:2px;
+    border:1px solid;
+    white-space: nowrap;
+    overflow:hidden;
+    text-overflow: ellipsis;
+}
+
+.x-combo-list .x-combo-selected{
+	border:1px dotted !important;
+    cursor:pointer;
+}
+
+.x-combo-list .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}.x-panel {
+    border-style: solid;
+    border-width:0;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+    padding:5px 3px 4px 5px;
+    border:1px solid;
+    line-height: 15px;
+    background: transparent repeat-x 0 -1px;
+}
+
+.x-panel-body {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    position: relative; /* added for item scroll positioning */
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom: 0 none;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top:1px solid;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-tl .x-panel-header {
+    padding:5px 0 4px 0;
+    border:0 none;
+    background:transparent no-repeat;
+}
+
+.x-panel-tl .x-panel-icon, .x-window-tl .x-panel-icon {
+    padding-left:20px !important;
+    background-repeat:no-repeat;
+    background-position:0 4px;
+    zoom:1;
+}
+
+.x-panel-inline-icon {
+    width:16px;
+	height:16px;
+    background-repeat:no-repeat;
+    background-position:0 0;
+	vertical-align:middle;
+	margin-right:4px;
+	margin-top:-1px;
+	margin-bottom:-1px;
+}
+
+.x-panel-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+/* fix ie7 strict mode bug */
+.ext-strict .ext-ie7 .x-panel-tc {
+    overflow: visible;
+}
+
+.x-panel-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    border-bottom:1px solid;
+}
+
+.x-panel-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:6px;
+}
+
+.x-panel-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-panel-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-mc {
+    border:0 none;
+    padding:0;
+    margin:0;
+    padding-top:6px;
+}
+
+.x-panel-mc .x-panel-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-panel-ml {
+	background: repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-panel-bc, .x-panel-nofooter .x-window-bc {
+	height:6px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-panel-bwrap {
+    overflow:hidden;
+    zoom:1;
+    left:0;
+    top:0;
+}
+.x-panel-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-collapsed .x-resizable-handle{
+    display:none;
+}
+
+.ext-gecko .x-panel-animated div {
+    overflow:hidden !important;
+}
+
+/* Plain */
+.x-plain-body {
+    overflow:hidden;
+}
+
+.x-plain-bbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-tbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-plain {
+    overflow:hidden;
+}
+
+/* Tools */
+.x-tool {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    float:right;
+    cursor:pointer;
+    background:transparent no-repeat;
+    margin-left:2px;
+}
+
+/* expand / collapse tools */
+.x-tool-toggle {
+    background-position:0 -60px;
+}
+
+.x-tool-toggle-over {
+    background-position:-15px -60px;
+}
+
+.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+
+.x-tool-close {
+    background-position:0 -0;
+}
+
+.x-tool-close-over {
+    background-position:-15px 0;
+}
+
+.x-tool-minimize {
+    background-position:0 -15px;
+}
+
+.x-tool-minimize-over {
+    background-position:-15px -15px;
+}
+
+.x-tool-maximize {
+    background-position:0 -30px;
+}
+
+.x-tool-maximize-over {
+    background-position:-15px -30px;
+}
+
+.x-tool-restore {
+    background-position:0 -45px;
+}
+
+.x-tool-restore-over {
+    background-position:-15px -45px;
+}
+
+.x-tool-gear {
+    background-position:0 -90px;
+}
+
+.x-tool-gear-over {
+    background-position:-15px -90px;
+}
+
+.x-tool-prev {
+    background-position:0 -105px;
+}
+
+.x-tool-prev-over {
+    background-position:-15px -105px;
+}
+
+.x-tool-next {
+    background-position:0 -120px;
+}
+
+.x-tool-next-over {
+    background-position:-15px -120px;
+}
+
+.x-tool-pin {
+    background-position:0 -135px;
+}
+
+.x-tool-pin-over {
+    background-position:-15px -135px;
+}
+
+.x-tool-unpin {
+    background-position:0 -150px;
+}
+
+.x-tool-unpin-over {
+    background-position:-15px -150px;
+}
+
+.x-tool-right {
+    background-position:0 -165px;
+}
+
+.x-tool-right-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-left {
+    background-position:0 -180px;
+}
+
+.x-tool-left-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-down {
+    background-position:0 -195px;
+}
+
+.x-tool-down-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-up {
+    background-position:0 -210px;
+}
+
+.x-tool-up-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-refresh {
+    background-position:0 -225px;
+}
+
+.x-tool-refresh-over {
+    background-position:-15px -225px;
+}
+
+.x-tool-plus {
+    background-position:0 -240px;
+}
+
+.x-tool-plus-over {
+    background-position:-15px -240px;
+}
+
+.x-tool-minus {
+    background-position:0 -255px;
+}
+
+.x-tool-minus-over {
+    background-position:-15px -255px;
+}
+
+.x-tool-search {
+    background-position:0 -270px;
+}
+
+.x-tool-search-over {
+    background-position:-15px -270px;
+}
+
+.x-tool-save {
+    background-position:0 -285px;
+}
+
+.x-tool-save-over {
+    background-position:-15px -285px;
+}
+
+.x-tool-help {
+    background-position:0 -300px;
+}
+
+.x-tool-help-over {
+    background-position:-15px -300px;
+}
+
+.x-tool-print {
+    background-position:0 -315px;
+}
+
+.x-tool-print-over {
+    background-position:-15px -315px;
+}
+
+.x-tool-expand {
+    background-position:0 -330px;
+}
+
+.x-tool-expand-over {
+    background-position:-15px -330px;
+}
+
+.x-tool-collapse {
+    background-position:0 -345px;
+}
+
+.x-tool-collapse-over {
+    background-position:-15px -345px;
+}
+
+.x-tool-resize {
+    background-position:0 -360px;
+}
+
+.x-tool-resize-over {
+    background-position:-15px -360px;
+}
+
+.x-tool-move {
+    background-position:0 -375px;
+}
+
+.x-tool-move-over {
+    background-position:-15px -375px;
+}
+
+/* Ghosting */
+.x-panel-ghost {
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    opacity:.65;
+    -moz-opacity:.65;
+    filter:alpha(opacity=65);
+}
+
+.x-panel-ghost ul {
+    margin:0;
+    padding:0;
+    overflow:hidden;
+    font-size:0;
+    line-height:0;
+    border:1px solid;
+    border-top:0 none;
+    display:block;
+}
+
+.x-panel-ghost * {
+    cursor:move !important;
+}
+
+.x-panel-dd-spacer {
+    border:2px dashed;
+}
+
+/* Buttons */
+.x-panel-btns {
+    padding:5px;
+    overflow:hidden;
+}
+
+.x-panel-btns td.x-toolbar-cell{
+	padding:3px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-left{
+	background-position:0 -147px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-right{
+	background-position:0 -168px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-center{
+	background-position:0 -189px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-center{
+	background-position:0 -105px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-center{
+	background-position:0 -126px;
+}
+
+.x-panel-btns .x-btn-click  .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+	white-space: nowrap;
+}
+/**
+ * W3C Suggested Default style sheet for HTML 4
+ * http://www.w3.org/TR/CSS21/sample.html
+ *
+ * Resets for Ext.Panel @cfg normal: true
+ */
+.x-panel-reset .x-panel-body html,
+.x-panel-reset .x-panel-body address,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body body,
+.x-panel-reset .x-panel-body dd,
+.x-panel-reset .x-panel-body div,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dt,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body frame, frameset,
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body noframes,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body center,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body hr,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body pre 			  { display: block }
+.x-panel-reset .x-panel-body li              { display: list-item }
+.x-panel-reset .x-panel-body head            { display: none }
+.x-panel-reset .x-panel-body table           { display: table }
+.x-panel-reset .x-panel-body tr              { display: table-row }
+.x-panel-reset .x-panel-body thead           { display: table-header-group }
+.x-panel-reset .x-panel-body tbody           { display: table-row-group }
+.x-panel-reset .x-panel-body tfoot           { display: table-footer-group }
+.x-panel-reset .x-panel-body col             { display: table-column }
+.x-panel-reset .x-panel-body colgroup        { display: table-column-group }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th 	          { display: table-cell }
+.x-panel-reset .x-panel-body caption         { display: table-caption }
+.x-panel-reset .x-panel-body th              { font-weight: bolder; text-align: center }
+.x-panel-reset .x-panel-body caption         { text-align: center }
+.x-panel-reset .x-panel-body body            { margin: 8px }
+.x-panel-reset .x-panel-body h1              { font-size: 2em; margin: .67em 0 }
+.x-panel-reset .x-panel-body h2              { font-size: 1.5em; margin: .75em 0 }
+.x-panel-reset .x-panel-body h3              { font-size: 1.17em; margin: .83em 0 }
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu            { margin: 1.12em 0 }
+.x-panel-reset .x-panel-body h5              { font-size: .83em; margin: 1.5em 0 }
+.x-panel-reset .x-panel-body h6              { font-size: .75em; margin: 1.67em 0 }
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body b,
+.x-panel-reset .x-panel-body strong          { font-weight: bolder }
+.x-panel-reset .x-panel-body blockquote      { margin-left: 40px; margin-right: 40px }
+.x-panel-reset .x-panel-body i,
+.x-panel-reset .x-panel-body cite,
+.x-panel-reset .x-panel-body em,
+.x-panel-reset .x-panel-body var,
+.x-panel-reset .x-panel-body address    	  { font-style: italic }
+.x-panel-reset .x-panel-body pre,
+.x-panel-reset .x-panel-body tt,
+.x-panel-reset .x-panel-body code,
+.x-panel-reset .x-panel-body kbd,
+.x-panel-reset .x-panel-body samp       	  { font-family: monospace }
+.x-panel-reset .x-panel-body pre             { white-space: pre }
+.x-panel-reset .x-panel-body button,
+.x-panel-reset .x-panel-body textarea,
+.x-panel-reset .x-panel-body input,
+.x-panel-reset .x-panel-body select   		  { display: inline-block }
+.x-panel-reset .x-panel-body big             { font-size: 1.17em }
+.x-panel-reset .x-panel-body small,
+.x-panel-reset .x-panel-body sub,
+.x-panel-reset .x-panel-body sup 			  { font-size: .83em }
+.x-panel-reset .x-panel-body sub             { vertical-align: sub }
+.x-panel-reset .x-panel-body sup             { vertical-align: super }
+.x-panel-reset .x-panel-body table           { border-spacing: 2px; }
+.x-panel-reset .x-panel-body thead,
+.x-panel-reset .x-panel-body tbody,
+.x-panel-reset .x-panel-body tfoot           { vertical-align: middle }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th          	  { vertical-align: inherit }
+.x-panel-reset .x-panel-body s,
+.x-panel-reset .x-panel-body strike,
+.x-panel-reset .x-panel-body del  			  { text-decoration: line-through }
+.x-panel-reset .x-panel-body hr              { border: 1px inset }
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body dd        	  { margin-left: 40px }
+.x-panel-reset .x-panel-body ul, .x-panel-reset .x-panel-body menu, .x-panel-reset .x-panel-body dir { list-style-type: disc;}
+.x-panel-reset .x-panel-body ol              { list-style-type: decimal }
+.x-panel-reset .x-panel-body ol ul,
+.x-panel-reset .x-panel-body ul ol,
+.x-panel-reset .x-panel-body ul ul,
+.x-panel-reset .x-panel-body ol ol    		  { margin-top: 0; margin-bottom: 0 }
+.x-panel-reset .x-panel-body u,
+.x-panel-reset .x-panel-body ins          	  { text-decoration: underline }
+.x-panel-reset .x-panel-body br:before       { content: "\A" }
+.x-panel-reset .x-panel-body :before, .x-panel-reset .x-panel-body :after { white-space: pre-line }
+.x-panel-reset .x-panel-body center          { text-align: center }
+.x-panel-reset .x-panel-body :link, .x-panel-reset .x-panel-body :visited { text-decoration: underline }
+.x-panel-reset .x-panel-body :focus          { outline: invert dotted thin }
+
+/* Begin bidirectionality settings (do not change) */
+.x-panel-reset .x-panel-body BDO[DIR="ltr"]  { direction: ltr; unicode-bidi: bidi-override }
+.x-panel-reset .x-panel-body BDO[DIR="rtl"]  { direction: rtl; unicode-bidi: bidi-override }
+.x-window {
+    zoom:1;
+}
+
+.x-window .x-window-handle {
+    opacity:0;
+    -moz-opacity:0;
+    filter:alpha(opacity=0);
+}
+
+.x-window-proxy {
+    border:1px solid;
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    display:none;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-window-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-window-bwrap {
+    z-index:1;
+    position:relative;
+    zoom:1;
+    left:0;top:0;
+}
+
+.x-window-tl .x-window-header {
+    padding:5px 0 4px 0;
+}
+
+.x-window-header-text {
+    cursor:pointer;
+}
+
+.x-window-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    zoom:1;
+}
+
+.x-window-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    z-index:1;
+    position:relative;
+}
+
+.x-window-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+}
+
+.x-window-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-window-bc .x-window-footer {
+    padding-bottom:6px;
+    zoom:1;
+    font-size:0;
+    line-height:0;
+}
+
+.x-window-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-mc {
+    border:1px solid;
+    padding:0;
+    margin:0;
+}
+
+.x-window-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-body {
+    overflow:hidden;
+}
+
+.x-window-bwrap {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-bl, .x-window-maximized .x-window-br,
+    .x-window-maximized .x-window-ml, .x-window-maximized .x-window-mr,
+    .x-window-maximized .x-window-tl, .x-window-maximized .x-window-tr {
+    padding:0;
+}
+
+.x-window-maximized .x-window-footer {
+    padding-bottom:0;
+}
+
+.x-window-maximized .x-window-tc {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-window-maximized .x-window-mc {
+    border-left:0 none;
+    border-right:0 none;
+}
+
+.x-window-tbar .x-toolbar, .x-window-bbar .x-toolbar {
+    border-left:0 none;
+    border-right: 0 none;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}
+
+.x-window-draggable, .x-window-draggable .x-window-header-text {
+    cursor:move;
+}
+
+.x-window-maximized .x-window-draggable, .x-window-maximized .x-window-draggable .x-window-header-text {
+    cursor:default;
+}
+
+.x-window-body {
+    background-color:transparent;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-window-maximized-ct {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-handle {
+    display:none;
+}
+
+.x-window-sizing-ghost ul {
+    border:0 none !important;
+}
+
+.x-dlg-focus{
+	-moz-outline:0 none;
+	outline:0 none;
+	width:0;
+	height:0;
+	overflow:hidden;
+	position:absolute;
+	top:0;
+	left:0;
+}
+
+.ext-webkit .x-dlg-focus{
+    width: 1px;
+    height: 1px;
+}
+
+.x-dlg-mask{
+    z-index:10000;
+    display:none;
+    position:absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity:.50;
+    filter: alpha(opacity=50);
+}
+
+body.ext-ie6.x-body-masked select {
+	visibility:hidden;
+}
+
+body.ext-ie6.x-body-masked .x-window select {
+	visibility:visible;
+}
+
+.x-window-plain .x-window-mc {
+    border: 1px solid;
+}
+
+.x-window-plain .x-window-body {
+    border: 1px solid;
+    background:transparent !important;
+}.x-html-editor-wrap {
+    border:1px solid;
+}
+
+.x-html-editor-tb .x-btn-text {
+    background:transparent no-repeat;
+}
+
+.x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {
+    background-position:0 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);    
+}
+
+.x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {
+    background-position:-16px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {
+    background-position:-32px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {
+    background-position:-160px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-backcolor, .x-menu-item img.x-edit-backcolor {
+    background-position:-176px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyleft, .x-menu-item img.x-edit-justifyleft {
+    background-position:-112px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifycenter, .x-menu-item img.x-edit-justifycenter {
+    background-position:-128px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyright, .x-menu-item img.x-edit-justifyright {
+    background-position:-144px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertorderedlist, .x-menu-item img.x-edit-insertorderedlist {
+    background-position:-80px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertunorderedlist, .x-menu-item img.x-edit-insertunorderedlist {
+    background-position:-96px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-increasefontsize, .x-menu-item img.x-edit-increasefontsize {
+    background-position:-48px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-decreasefontsize, .x-menu-item img.x-edit-decreasefontsize {
+    background-position:-64px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-sourceedit, .x-menu-item img.x-edit-sourceedit {
+    background-position:-192px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-createlink, .x-menu-item img.x-edit-createlink {
+    background-position:-208px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {
+    padding:5px;
+    padding-bottom:1px;
+}
+
+.x-html-editor-tb .x-toolbar {
+    position:static !important;
+}.x-panel-noborder .x-panel-body-noborder {
+    border-width:0;
+}
+
+.x-panel-noborder .x-panel-header-noborder {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-width:1px 0 0 0;
+    border-style:solid;
+}
+
+.x-window-noborder .x-window-mc {
+    border-width:0;
+}
+
+.x-window-plain .x-window-body-noborder {
+    border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-body-noborder {
+	border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-header-noborder {
+    border-width: 0 0 1px 0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-footer-noborder {
+    border-width: 1px 0 0 0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-width: 1px 0 0 0;
+    border-style:solid;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}.x-border-layout-ct {
+    position: relative;
+}
+
+.x-border-panel {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-tool-collapse-south {
+    background-position:0 -195px;
+}
+
+.x-tool-collapse-south-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-collapse-north {
+    background-position:0 -210px;
+}
+
+.x-tool-collapse-north-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-collapse-west {
+    background-position:0 -180px;
+}
+
+.x-tool-collapse-west-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-collapse-east {
+    background-position:0 -165px;
+}
+
+.x-tool-collapse-east-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-south {
+    background-position:0 -210px;
+}
+
+.x-tool-expand-south-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-expand-north {
+    background-position:0 -195px;
+}
+.x-tool-expand-north-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-expand-west {
+    background-position:0 -165px;
+}
+
+.x-tool-expand-west-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-east {
+    background-position:0 -180px;
+}
+
+.x-tool-expand-east-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-expand-north, .x-tool-expand-south {
+    float:right;
+    margin:3px;
+}
+
+.x-tool-expand-east, .x-tool-expand-west {
+    float:none;
+    margin:3px 2px;
+}
+
+.x-accordion-hd .x-tool-toggle {
+    background-position:0 -255px;
+}
+
+.x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -255px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle {
+    background-position:0 -240px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -240px;
+}
+
+.x-accordion-hd {
+	padding-top:4px;
+	padding-bottom:3px;
+	border-top:0 none;
+    background: transparent repeat-x 0 -9px;
+}
+
+.x-layout-collapsed{
+    position:absolute;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+    width:20px;
+    height:20px;
+    overflow:hidden;
+	border:1px solid;
+	z-index:20;
+}
+
+.ext-border-box .x-layout-collapsed{
+    width:22px;
+    height:22px;
+}
+
+.x-layout-collapsed-over{
+    cursor:pointer;
+}
+
+.x-layout-collapsed-west .x-layout-collapsed-tools, .x-layout-collapsed-east .x-layout-collapsed-tools{
+	position:absolute;
+    top:0;
+    left:0;
+    width:20px;
+    height:20px;
+}
+
+
+.x-layout-split{
+    position:absolute;
+    height:5px;
+    width:5px;
+    line-height:1px;
+    font-size:1px;
+    z-index:3;
+    background-color:transparent;
+}
+
+/* IE6 strict won't drag w/out a color */
+.ext-strict .ext-ie6 .x-layout-split{
+    background-color: #fff !important;
+    filter: alpha(opacity=1);
+}
+
+.x-layout-split-h{
+    background-image:url(../images/default/s.gif);
+    background-position: left;
+}
+
+.x-layout-split-v{
+    background-image:url(../images/default/s.gif);
+    background-position: top;
+}
+
+.x-column-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column {
+    float:left;
+    padding:0;
+    margin:0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column-inner {
+    overflow:hidden;
+    zoom:1;
+}
+
+/* mini mode */
+.x-layout-mini {
+    position:absolute;
+    top:0;
+    left:0;
+    display:block;
+    width:5px;
+    height:35px;
+    cursor:pointer;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-layout-mini-over, .x-layout-collapsed-over .x-layout-mini{
+    opacity:1;
+    -moz-opacity:1;
+    filter:none;
+}
+
+.x-layout-split-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-split-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west, .x-layout-cmini-east {
+    border:0 none;
+    width:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-layout-cmini-north, .x-layout-cmini-south {
+    border:0 none;
+    height:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-viewport, .x-viewport body {
+    margin: 0;
+    padding: 0;
+    border: 0 none;
+    overflow: hidden;
+    height: 100%;
+}
+
+.x-abs-layout-item {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.ext-ie input.x-abs-layout-item, .ext-ie textarea.x-abs-layout-item {
+    margin:0;
+}
+
+.x-box-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-box-inner {
+    overflow:hidden;
+    zoom:1;
+    position:relative;
+    left:0;
+    top:0;
+}
+
+.x-box-item {
+    position:absolute;
+    left:0;
+    top:0;
+}.x-progress-wrap {
+    border:1px solid;
+    overflow:hidden;
+}
+
+.x-progress-inner {
+    height:18px;
+    background:repeat-x;
+    position:relative;
+}
+
+.x-progress-bar {
+    height:18px;
+    float:left;
+    width:0;
+    background: repeat-x left center;
+    border-top:1px solid;
+    border-bottom:1px solid;
+    border-right:1px solid;
+}
+
+.x-progress-text {
+    padding:1px 5px;
+    overflow:hidden;
+    position:absolute;
+    left:0;
+    text-align:center;
+}
+
+.x-progress-text-back {
+    line-height:16px;
+}
+
+.ext-ie .x-progress-text-back {
+    line-height:15px;
+}
+
+.ext-strict .ext-ie7 .x-progress-text-back{
+    width: 100%;
+}
+.x-list-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    height:22px;
+}
+
+.x-list-header-inner div {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.x-list-header-inner div em {
+    display:block;
+    border-left:1px solid;
+    padding:4px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    line-height:14px;
+}
+
+.x-list-body {
+    overflow:auto;
+    overflow-x:hidden;
+    overflow-y:auto;
+    zoom:1;
+    float: left;
+    width: 100%;
+}
+
+.x-list-body dl {
+    zoom:1;
+}
+
+.x-list-body dt {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor:pointer;
+    zoom:1;
+}
+
+.x-list-body dt em {
+    display:block;
+    padding:3px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+}
+
+.x-list-resizer {
+    border-left:1px solid;
+    border-right:1px solid;
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-list-header-inner em.sort-asc {
+    background: transparent no-repeat center 0;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+.x-list-header-inner em.sort-desc {
+    background: transparent no-repeat center -23px;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+/* Shared styles */
+.x-slider {
+    zoom:1;
+}
+
+.x-slider-inner {
+    position:relative;
+    left:0;
+    top:0;
+    overflow:visible;
+    zoom:1;
+}
+
+.x-slider-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+	display:block;
+	overflow:hidden;  
+}
+
+/* Horizontal styles */
+.x-slider-horz {
+    padding-left:7px;
+    background:transparent no-repeat 0 -22px;
+}
+
+.x-slider-horz .x-slider-end {
+    padding-right:7px;
+    zoom:1;
+    background:transparent no-repeat right -44px;
+}
+
+.x-slider-horz .x-slider-inner {
+    background:transparent repeat-x 0 0;
+    height:22px;
+}
+
+.x-slider-horz .x-slider-thumb {
+    width:14px;
+    height:15px;
+    position:absolute;
+    left:0;
+    top:3px;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-horz .x-slider-thumb-over {
+    background-position: -14px -15px;
+}
+
+.x-slider-horz .x-slider-thumb-drag {
+    background-position: -28px -30px;
+}
+
+/* Vertical styles */
+.x-slider-vert {
+    padding-top:7px;
+    background:transparent no-repeat -44px 0;
+    width:22px;
+}
+
+.x-slider-vert .x-slider-end {
+    padding-bottom:7px;
+    zoom:1;
+    background:transparent no-repeat -22px bottom;
+}
+
+.x-slider-vert .x-slider-inner {
+    background:transparent repeat-y 0 0;
+}
+
+.x-slider-vert .x-slider-thumb {
+    width:15px;
+    height:14px;
+    position:absolute;
+    left:3px;
+    bottom:0;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-vert .x-slider-thumb-over {
+    background-position: -15px -14px;
+}
+
+.x-slider-vert .x-slider-thumb-drag {
+    background-position: -30px -28px;
+}.x-window-dlg .x-window-body {
+    border:0 none !important;
+    padding:5px 10px;
+    overflow:hidden !important;
+}
+
+.x-window-dlg .x-window-mc {
+    border:0 none !important;
+}
+
+.x-window-dlg .ext-mb-input {
+    margin-top:4px;
+    width:95%;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    margin-top:4px;
+}
+
+.x-window-dlg .x-progress-wrap {
+    margin-top:4px;
+}
+
+.ext-ie .x-window-dlg .x-progress-wrap {
+    margin-top:6px;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background:transparent no-repeat left;
+    display:block;
+    width:300px;
+    padding-left:18px;
+    line-height:18px;
+}
+
+.x-window-dlg .ext-mb-icon {
+    float:left;
+    width:47px;
+    height:32px;
+}
+
+.x-window-dlg .x-dlg-icon .ext-mb-content{
+    zoom: 1; 
+    margin-left: 47px;
+}
+
+.x-window-dlg .ext-mb-info, .x-window-dlg .ext-mb-warning, .x-window-dlg .ext-mb-question, .x-window-dlg .ext-mb-error {
+    background:transparent no-repeat top left;
+}
+
+.ext-gecko2 .ext-mb-fix-cursor {
+    overflow:auto;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/ext-all.css b/src/main/webapp/lib/ext-3.4.0/css/ext-all.css
new file mode 100644
index 0000000000000000000000000000000000000000..38dff3e08e6918140e1a58d3423ea2f9c59d953a
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/ext-all.css
@@ -0,0 +1,6993 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
+
+.ext-forced-border-box, .ext-forced-border-box * {
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+}
+.ext-el-mask {
+    z-index: 100;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width: 100%;
+    height: 100%;
+    zoom: 1;
+}
+
+.ext-el-mask-msg {
+    z-index: 20001;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border:1px solid;
+    background:repeat-x 0 -16px;
+    padding:2px;
+}
+
+.ext-el-mask-msg div {
+    padding:5px 10px 5px 10px;
+    border:1px solid;
+    cursor:wait;
+}
+
+.ext-shim {
+    position:absolute;
+    visibility:hidden;
+    left:0;
+    top:0;
+    overflow:hidden;
+}
+
+.ext-ie .ext-shim {
+    filter: alpha(opacity=0);
+}
+
+.ext-ie6 .ext-shim {
+    margin-left: 5px;
+    margin-top: 3px;
+}
+
+.x-mask-loading div {
+    padding:5px 10px 5px 25px;
+    background:no-repeat 5px 5px;
+    line-height:16px;
+}
+
+/* class for hiding elements without using display:none */
+.x-hidden, .x-hide-offsets {
+    position:absolute !important;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+}
+
+.x-hide-display {
+    display:none !important;
+}
+
+.x-hide-nosize,
+.x-hide-nosize *    /* Emulate display:none for children */
+ {
+   height:0px!important;
+   width:0px!important;
+   visibility:hidden!important;
+   border:none!important;
+   zoom:1;
+}
+
+.x-hide-visibility {
+    visibility:hidden !important;
+}
+
+.x-masked {
+    overflow: hidden !important;
+}
+.x-masked-relative {
+    position: relative !important;
+}
+
+.x-masked select, .x-masked object, .x-masked embed {
+    visibility: hidden;
+}
+
+.x-layer {
+    visibility: hidden;
+}
+
+.x-unselectable, .x-unselectable * {
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-repaint {
+    zoom: 1;
+    background-color: transparent;
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-item-disabled {
+    cursor: default;
+    opacity: .6;
+    -moz-opacity: .6;
+    filter: alpha(opacity=60);
+}
+
+.x-item-disabled * {
+    cursor: default !important;
+}
+
+.x-form-radio-group .x-item-disabled {
+    filter: none;
+}
+
+.x-splitbar-proxy {
+    position: absolute;
+    visibility: hidden;
+    z-index: 20001;
+    zoom: 1;
+    line-height: 1px;
+    font-size: 1px;
+    overflow: hidden;
+}
+
+.x-splitbar-h, .x-splitbar-proxy-h {
+    cursor: e-resize;
+    cursor: col-resize;
+}
+
+.x-splitbar-v, .x-splitbar-proxy-v {
+    cursor: s-resize;
+    cursor: row-resize;
+}
+
+.x-color-palette {
+    width: 150px;
+    height: 92px;
+    cursor: pointer;
+}
+
+.x-color-palette a {
+    border: 1px solid;
+    float: left;
+    padding: 2px;
+    text-decoration: none;
+    -moz-outline: 0 none;
+    outline: 0 none;
+    cursor: pointer;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border: 1px solid;
+}
+
+.x-color-palette em {
+    display: block;
+    border: 1px solid;
+}
+
+.x-color-palette em span {
+    cursor: pointer;
+    display: block;
+    height: 10px;
+    line-height: 10px;
+    width: 10px;
+}
+
+.x-ie-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+    zoom:1;
+}
+
+.x-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+}
+
+.x-shadow * {
+    overflow: hidden;
+}
+
+.x-shadow * {
+    padding: 0;
+    border: 0;
+    margin: 0;
+    clear: none;
+    zoom: 1;
+}
+
+/* top  bottom */
+.x-shadow .xstc, .x-shadow .xsbc {
+    height: 6px;
+    float: left;
+}
+
+/* corners */
+.x-shadow .xstl, .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbr {
+    width: 6px;
+    height: 6px;
+    float: left;
+}
+
+/* sides */
+.x-shadow .xsc {
+    width: 100%;
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    width: 6px;
+    float: left;
+    height: 100%;
+}
+
+.x-shadow .xsmc {
+    float: left;
+    height: 100%;
+    background-color: transparent;
+}
+
+.x-shadow .xst, .x-shadow .xsb {
+    height: 6px;
+    overflow: hidden;
+    width: 100%;
+}
+
+.x-shadow .xsml {
+    background: transparent repeat-y 0 0;
+}
+
+.x-shadow .xsmr {
+    background: transparent repeat-y -6px 0;
+}
+
+.x-shadow .xstl {
+    background: transparent no-repeat 0 0;
+}
+
+.x-shadow .xstc {
+    background: transparent repeat-x 0 -30px;
+}
+
+.x-shadow .xstr {
+    background: transparent repeat-x 0 -18px;
+}
+
+.x-shadow .xsbl {
+    background: transparent no-repeat 0 -12px;
+}
+
+.x-shadow .xsbc {
+    background: transparent repeat-x 0 -36px;
+}
+
+.x-shadow .xsbr {
+    background: transparent repeat-x 0 -6px;
+}
+
+.loading-indicator {
+    background: no-repeat left;
+    padding-left: 20px;
+    line-height: 16px;
+    margin: 3px;
+}
+
+.x-text-resize {
+    position: absolute;
+    left: -1000px;
+    top: -1000px;
+    visibility: hidden;
+    zoom: 1;
+}
+
+.x-drag-overlay {
+    width: 100%;
+    height: 100%;
+    display: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    background-image:url(../images/default/s.gif);
+    z-index: 20000;
+}
+
+.x-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.x-spotlight {
+    z-index: 8999;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width:0;
+    height:0;
+    zoom: 1;
+}
+
+#x-history-frame {
+    position:absolute;
+    top:-1px;
+    left:0;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+
+#x-history-field {
+    position:absolute;
+    top:0;
+    left:-1px;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+.x-resizable-handle {
+    position:absolute;
+    z-index:100;
+    /* ie needs these */
+    font-size:1px;
+    line-height:6px;
+    overflow:hidden;
+	filter:alpha(opacity=0);
+	opacity:0;
+	zoom:1;
+}
+
+.x-resizable-handle-east{
+    width:6px;
+    cursor:e-resize;
+    right:0;
+    top:0;
+    height:100%;
+}
+
+.ext-ie .x-resizable-handle-east {
+    margin-right:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-south{
+    width:100%;
+    cursor:s-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+}
+
+.ext-ie .x-resizable-handle-south {
+    margin-bottom:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-west{
+    width:6px;
+    cursor:w-resize;
+    left:0;
+    top:0;
+    height:100%;
+}
+
+.x-resizable-handle-north{
+    width:100%;
+    cursor:n-resize;
+    left:0;
+    top:0;
+    height:6px;
+}
+
+.x-resizable-handle-southeast{
+    width:6px;
+    cursor:se-resize;
+    right:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northwest{
+    width:6px;
+    cursor:nw-resize;
+    left:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northeast{
+    width:6px;
+    cursor:ne-resize;
+    right:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-southwest{
+    width:6px;
+    cursor:sw-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle{
+    filter:alpha(opacity=100);
+	opacity:1;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+	background-position: left;
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-position: top;
+}
+
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-position: top left;
+}
+
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-position:bottom right;
+}
+
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-position: bottom left;
+}
+
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-position: top right;
+}
+
+.x-resizable-proxy{
+    border: 1px dashed;
+    position:absolute;
+    overflow:hidden;
+    display:none;
+	left:0;
+    top:0;
+    z-index:50000;
+}
+
+.x-resizable-overlay{
+    width:100%;
+	height:100%;
+	display:none;
+	position:absolute;
+	left:0;
+	top:0;
+	z-index:200000;
+	-moz-opacity: 0;
+    opacity:0;
+    filter: alpha(opacity=0);
+}
+.x-tab-panel {
+    overflow:hidden;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border: 1px solid;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header {
+	border: 1px solid;
+	padding-bottom: 2px;
+}
+
+.x-tab-panel-footer {
+	border: 1px solid;
+	padding-top: 2px;
+}
+
+.x-tab-strip-wrap {
+	width:100%;
+    overflow:hidden;
+    position:relative;
+    zoom:1;
+}
+
+ul.x-tab-strip {
+	display:block;
+    width:5000px;
+    zoom:1;
+}
+
+ul.x-tab-strip-top{
+	padding-top: 1px;
+	background: repeat-x bottom;
+	border-bottom: 1px solid;
+}
+
+ul.x-tab-strip-bottom{
+	padding-bottom: 1px;
+	background: repeat-x top;
+	border-top: 1px solid;
+	border-bottom: 0 none;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-top {
+    background:transparent !important;
+    padding-top:0 !important;
+}
+
+.x-tab-panel-header-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border:1px solid;
+    height:2px;
+    font-size:1px;
+    line-height:1px;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer {
+    border-top: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-bottom: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-bottom {
+    background:transparent !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-footer-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-top:0 !important;
+}
+
+.ext-border-box .x-tab-panel-header-plain .x-tab-strip-spacer,
+.ext-border-box .x-tab-panel-footer-plain .x-tab-strip-spacer {
+    height:3px;
+}
+
+ul.x-tab-strip li {
+    float:left;
+    margin-left:2px;
+}
+
+ul.x-tab-strip li.x-tab-edge {
+    float:left;
+    margin:0 !important;
+    padding:0 !important;
+    border:0 none !important;
+    font-size:1px !important;
+    line-height:1px !important;
+    overflow:hidden;
+    zoom:1;
+    background:transparent !important;
+    width:1px;
+}
+
+.x-tab-strip a, .x-tab-strip span, .x-tab-strip em {
+	display:block;
+}
+
+.x-tab-strip a {
+	text-decoration:none !important;
+	-moz-outline: none;
+	outline: none;
+	cursor:pointer;
+}
+
+.x-tab-strip-inner {
+    overflow:hidden;
+	text-overflow: ellipsis;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	white-space: nowrap;
+	cursor:pointer;
+    padding:4px 0;
+}
+
+.x-tab-strip-top .x-tab-with-icon .x-tab-right {
+    padding-left:6px;
+}
+
+.x-tab-strip .x-tab-with-icon span.x-tab-strip-text {
+	padding-left:20px;
+    background-position: 0 3px;
+    background-repeat: no-repeat;
+}
+
+.x-tab-strip-active, .x-tab-strip-active a.x-tab-right {
+    cursor:default;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	cursor:default;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	cursor:default;
+}
+
+.x-tab-panel-body {
+    overflow:hidden;
+}
+
+.x-tab-panel-bwrap {
+    overflow:hidden;
+}
+
+.ext-ie .x-tab-strip .x-tab-right {
+    position:relative;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+    margin-bottom:-1px;
+}
+
+/*
+ * Horrible hack for IE8 in quirks mode
+ */
+.ext-ie8 .x-tab-strip li {
+    position: relative;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top .x-tab-right {
+    top: 1px;
+}
+.ext-ie8 .x-tab-strip-top {
+    padding-top: 1;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top {
+    padding-top: 0;
+}
+.ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:3px;
+}
+.ext-border-box .ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:4px;
+}
+.ext-ie8 .x-tab-strip-bottom .x-tab-right{
+    top:0;
+}
+
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-bottom:5px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+    margin-top:-1px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-top:5px;
+}
+
+.x-tab-strip-top .x-tab-right {
+	background: transparent no-repeat 0 -51px;
+    padding-left:10px;
+}
+
+.x-tab-strip-top .x-tab-left {
+	background: transparent no-repeat right -351px;
+    padding-right:10px;
+}
+
+.x-tab-strip-top .x-tab-strip-inner {
+	background: transparent repeat-x 0 -201px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-right {
+	 background-position:0 -101px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-left {
+	 background-position:right -401px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-strip-inner {
+	 background-position:0 -251px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+	background-position: 0 0;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-left {
+	background-position: right -301px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-strip-inner {
+	background-position: 0 -151px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+    margin-right: 3px;
+    padding:0 10px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+    padding:0;
+}
+
+.x-tab-strip .x-tab-strip-close {
+    display:none;
+}
+
+.x-tab-strip-closable {
+    position:relative;
+}
+
+.x-tab-strip-closable .x-tab-left {
+    padding-right:19px;
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    opacity:.6;
+    -moz-opacity:.6;
+    background-repeat:no-repeat;
+    display:block;
+	width:11px;
+    height:11px;
+    position:absolute;
+    top:3px;
+    right:3px;
+    cursor:pointer;
+    z-index:2;
+}
+
+.x-tab-strip .x-tab-strip-active a.x-tab-strip-close {
+    opacity:.8;
+    -moz-opacity:.8;
+}
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+    opacity:1;
+    -moz-opacity:1;
+}
+
+.x-tab-panel-body {
+    border: 1px solid;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background: transparent no-repeat -18px 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    left:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background: transparent no-repeat 0 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    right:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+
+.x-tab-scroller-right-over {
+    background-position: -18px 0;
+}
+
+.x-tab-scroller-right-disabled {
+    background-position: 0 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scrolling-bottom .x-tab-scroller-left, .x-tab-scrolling-bottom .x-tab-scroller-right{
+    margin-top: 1px;
+}
+
+.x-tab-scrolling .x-tab-strip-wrap {
+    margin-left:18px;
+    margin-right:18px;
+}
+
+.x-tab-scrolling {
+    position:relative;    
+}
+
+.x-tab-panel-bbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-tab-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}/* all fields */
+.x-form-field{
+    margin: 0 0 0 0;
+}
+
+.ext-webkit *:focus{
+    outline: none !important;
+}
+
+/* ---- text fields ---- */
+.x-form-text, textarea.x-form-field{
+    padding:1px 3px;
+    background:repeat-x 0 0;
+    border:1px solid;
+}
+
+textarea.x-form-field {
+    padding:2px 3px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:22px;
+    line-height:18px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-form-text, .ext-ie7 .x-form-text {
+    margin:-1px 0; /* ie bogus margin bug */
+    height:22px; /* ie quirks */
+    line-height:18px;
+}
+
+.x-quirks .ext-ie9 .x-form-text {
+    height: 22px;
+    padding-top: 3px;
+    padding-bottom: 0px;
+}
+
+/* Ugly hacks for the bogus 1px margin bug in IE9 quirks */
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-text,
+.x-quirks .ext-ie9 .x-form-field-trigger-wrap .x-form-text {
+    margin-top: -1px;
+    margin-bottom: -1px;
+}
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-element {
+    margin-bottom: -1px;
+}
+
+.ext-ie6 .x-form-field-wrap .x-form-file-btn, .ext-ie7 .x-form-field-wrap .x-form-file-btn {
+    top: -1px; /* because of all these margin hacks, these buttons are off by one pixel in IE6,7 */
+}
+
+.ext-ie6 textarea.x-form-field, .ext-ie7 textarea.x-form-field {
+    margin:-1px 0; /* ie bogus margin bug */
+}
+
+.ext-strict .x-form-text {
+    height:18px;
+}
+
+.ext-safari.ext-mac textarea.x-form-field {
+    margin-bottom:-2px; /* another bogus margin bug, safari/mac only */
+}
+
+/*
+.ext-strict .ext-ie8 .x-form-text, .ext-strict .ext-ie8 textarea.x-form-field {
+    margin-bottom: 1px;
+}
+*/
+
+.ext-gecko .x-form-text , .ext-ie8 .x-form-text {
+    padding-top:2px; /* FF won't center the text vertically */
+    padding-bottom:0;
+}
+
+.ext-ie6 .x-form-composite .x-form-text.x-box-item, .ext-ie7 .x-form-composite .x-form-text.x-box-item {
+    margin: 0 !important; /* clear ie bogus margin bug fix */
+}
+
+textarea {
+    resize: none;  /* Disable browser resizable textarea */
+}
+
+/* select boxes */
+.x-form-select-one {
+    height:20px;
+    line-height:18px;
+    vertical-align:middle;
+    border: 1px solid;
+}
+
+/* multi select boxes */
+
+/* --- TODO --- */
+
+/* 2.0.2 style */
+.x-form-check-wrap {
+    line-height:18px;
+    height: auto;
+}
+
+.ext-ie .x-form-check-wrap input {
+    width:15px;
+    height:15px;
+}
+
+.x-form-check-wrap input{
+    vertical-align: bottom;
+}
+
+.x-editor .x-form-check-wrap {
+    padding:3px;
+}
+
+.x-editor .x-form-checkbox {
+    height:13px;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid;
+    margin-bottom: 5px;
+    padding-left: 3px !important;
+    float: none !important;
+}
+
+/* wrapped fields and triggers */
+.x-form-field-wrap .x-form-trigger{
+    width:17px;
+    height:21px;
+    border:0;
+    background:transparent no-repeat 0 0;
+    cursor:pointer;
+    border-bottom: 1px solid;
+    position:absolute;
+    top:0;
+}
+
+.x-form-field-wrap .x-form-date-trigger, .x-form-field-wrap .x-form-clear-trigger, .x-form-field-wrap .x-form-search-trigger{
+    cursor:pointer;
+}
+
+.x-form-field-wrap .x-form-twin-triggers .x-form-trigger{
+    position:static;
+    top:auto;
+    vertical-align:top;
+}
+
+.x-form-field-wrap {
+    position:relative;
+    left:0;top:0;
+    text-align: left;
+    zoom:1;
+    white-space: nowrap;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {
+    right: 0; /* IE8 Strict mode trigger bug */
+}
+
+.x-form-field-wrap .x-form-trigger-over{
+    background-position:-17px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click{
+    background-position:-34px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    background-position:-51px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over{
+    background-position:-68px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click{
+    background-position:-85px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-trigger-noedit{
+    cursor:pointer;
+}
+
+/* field focus style */
+.x-form-focus, textarea.x-form-focus{
+    border: 1px solid;
+}
+
+/* invalid fields */
+.x-form-invalid, textarea.x-form-invalid{
+    background:repeat-x bottom;
+    border: 1px solid;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background:repeat-x bottom;
+}
+
+/* editors */
+.x-editor {
+    visibility:hidden;
+    padding:0;
+    margin:0;
+}
+
+.x-form-grow-sizer {
+    left: -10000px;
+    padding: 8px 3px;
+    position: absolute;
+    visibility:hidden;
+    top: -10000px;
+    white-space: pre-wrap;
+    white-space: -moz-pre-wrap;
+    white-space: -pre-wrap;
+    white-space: -o-pre-wrap;
+    word-wrap: break-word;
+    zoom:1;
+}
+
+.x-form-grow-sizer p {
+    margin:0 !important;
+    border:0 none !important;
+    padding:0 !important;
+}
+
+/* Form Items CSS */
+
+.x-form-item {
+    display:block;
+    margin-bottom:4px;
+    zoom:1;
+}
+
+.x-form-item label.x-form-item-label {
+    display:block;
+    float:left;
+    width:100px;
+    padding:3px;
+    padding-left:0;
+    clear:left;
+    z-index:2;
+    position:relative;
+}
+
+.x-form-element {
+    padding-left:105px;
+    position:relative;
+}
+
+.x-form-invalid-msg {
+    padding:2px;
+    padding-left:18px;
+    background: transparent no-repeat 0 2px;
+    line-height:16px;
+    width:200px;
+}
+
+.x-form-label-left label.x-form-item-label {
+   text-align:left;
+}
+
+.x-form-label-right label.x-form-item-label {
+   text-align:right;
+}
+
+.x-form-label-top .x-form-item label.x-form-item-label {
+    width:auto;
+    float:none;
+    clear:none;
+    display:inline;
+    margin-bottom:4px;
+    position:static;
+}
+
+.x-form-label-top .x-form-element {
+    padding-left:0;
+    padding-top:4px;
+}
+
+.x-form-label-top .x-form-item {
+    padding-bottom:4px;
+}
+
+/* Editor small font for grid, toolbar and tree */
+.x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    margin-top:-1px !important; /* ie bogus margin bug */
+    margin-bottom:-1px !important;
+    height:20px !important; /* ie quirks */
+    line-height:16px !important;
+}
+
+.ext-strict .x-small-editor .x-form-text {
+    height:16px !important;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+}
+
+.ext-border-box .x-small-editor .x-form-text {
+    height:20px;
+}
+
+.x-small-editor .x-form-select-one {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.x-small-editor .x-form-num-field {
+    text-align:right;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger{
+    height:19px;
+}
+
+.ext-webkit .x-small-editor .x-form-text{padding-top:3px;font-size:100%;}
+
+.ext-strict .ext-webkit .x-small-editor .x-form-text{
+    height:14px !important;
+}
+
+.x-form-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+.x-form-clear-left {
+    clear:left;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.ext-ie6 .x-form-check-wrap input, .ext-border-box .x-form-check-wrap input{
+   margin-top: 3px;
+}
+
+.x-form-cb-label {
+    position: relative;
+    margin-left:4px;
+    top: 2px;
+}
+
+.ext-ie .x-form-cb-label{
+    top: 1px;
+}
+
+.ext-ie6 .x-form-cb-label, .ext-border-box .x-form-cb-label{
+    top: 3px;
+}
+
+.x-form-display-field{
+    padding-top: 2px;
+}
+
+.ext-gecko .x-form-display-field, .ext-strict .ext-ie7 .x-form-display-field{
+    padding-top: 1px;
+}
+
+.ext-ie .x-form-display-field{
+    padding-top: 3px;
+}
+
+.ext-strict .ext-ie8 .x-form-display-field{
+    padding-top: 0;
+}
+
+.x-form-column {
+    float:left;
+    padding:0;
+    margin:0;
+    width:48%;
+    overflow:hidden;
+    zoom:1;
+}
+
+/* buttons */
+.x-form .x-form-btns-ct .x-btn{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns td {
+    border:0;
+    padding:0;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-right table{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-left table{
+    float:left;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center{
+    text-align:center; /*ie*/
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center table{
+    margin:0 auto; /*everyone else*/
+}
+
+.x-form .x-form-btns-ct table td.x-form-btn-td{
+    padding:3px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-left{
+    background-position:0 -147px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-right{
+    background-position:0 -168px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-center{
+    background-position:0 -189px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-center{
+    background-position:0 -126px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click  .x-btn-right{
+    background-position:0 -84px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-left{
+    background-position:0 -63px;
+}
+
+.x-form-invalid-icon {
+    width:16px;
+    height:18px;
+    visibility:hidden;
+    position:absolute;
+    left:0;
+    top:0;
+    display:block;
+    background:transparent no-repeat 0 2px;
+}
+
+/* fieldsets */
+.x-fieldset {
+    border:1px solid;
+    padding:10px;
+    margin-bottom:10px;
+    display:block; /* preserve margins in IE */
+}
+
+/* make top of checkbox/tools visible in webkit */
+.ext-webkit .x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset legend {
+    margin-bottom:10px;
+}
+
+.ext-strict .ext-ie9 .x-fieldset legend.x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset {
+    padding-top: 0;
+    padding-bottom:10px;
+}
+
+.x-fieldset legend .x-tool-toggle {
+    margin-right:3px;
+    margin-left:0;
+    float:left !important;
+}
+
+.x-fieldset legend input {
+    margin-right:3px;
+    float:left !important;
+    height:13px;
+    width:13px;
+}
+
+fieldset.x-panel-collapsed {
+    padding-bottom:0 !important;
+    border-width: 1px 1px 0 1px !important;
+    border-left-color: transparent;
+    border-right-color: transparent;
+}
+
+.ext-ie6 fieldset.x-panel-collapsed{
+    padding-bottom:0 !important;
+    border-width: 1px 0 0 0 !important;
+    margin-left: 1px;
+    margin-right: 1px;
+}
+
+fieldset.x-panel-collapsed .x-fieldset-bwrap {
+    visibility:hidden;
+    position:absolute;
+    left:-1000px;
+    top:-1000px;
+}
+
+.ext-ie .x-fieldset-bwrap {
+    zoom:1;
+}
+
+.x-fieldset-noborder {
+    border:0px none transparent;
+}
+
+.x-fieldset-noborder legend {
+    margin-left:-3px;
+}
+
+/* IE legend positioning bug */
+.ext-ie .x-fieldset-noborder legend {
+    position: relative;
+    margin-bottom:23px;
+}
+.ext-ie .x-fieldset-noborder legend span {
+    position: absolute;
+    left:16px;
+}
+
+.ext-gecko .x-window-body .x-form-item {
+    -moz-outline: none;
+    outline: none;
+    overflow: auto;
+}
+
+.ext-mac.ext-gecko .x-window-body .x-form-item {
+    overflow:hidden;
+}
+
+.ext-gecko .x-form-item {
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-hide-label label.x-form-item-label {
+     display:none;
+}
+
+.x-hide-label .x-form-element {
+     padding-left: 0 !important;
+}
+
+.x-form-label-top .x-hide-label label.x-form-item-label{
+    display: none;
+}
+
+.x-fieldset {
+    overflow:hidden;
+}
+
+.x-fieldset-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-fieldset-body {
+    overflow:hidden;
+}
+.x-btn{
+	cursor:pointer;
+	white-space: nowrap;
+}
+
+.x-btn button{
+    border:0 none;
+    background-color:transparent;
+    padding-left:3px;
+    padding-right:3px;
+    cursor:pointer;
+    margin:0;
+    overflow:visible;
+    width:auto;
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+* html .ext-ie .x-btn button {
+    width:1px;
+}
+
+.ext-gecko .x-btn button, .ext-webkit .x-btn button {
+    padding-left:0;
+    padding-right:0;
+}
+
+.ext-gecko .x-btn button::-moz-focus-inner {
+    padding:0;
+}
+
+.ext-ie .x-btn button {
+    padding-top:2px;
+}
+
+.x-btn td {
+    padding:0 !important;
+}
+
+.x-btn-text {
+    cursor:pointer;
+	white-space: nowrap;
+    padding:0;
+}
+
+/* icon placement and sizing styles */
+
+/* Only text */
+.x-btn-noicon .x-btn-small .x-btn-text{
+	height: 16px;
+}
+
+.x-btn-noicon .x-btn-medium .x-btn-text{
+    height: 24px;
+}
+
+.x-btn-noicon .x-btn-large .x-btn-text{
+    height: 32px;
+}
+
+/* Only icons */
+.x-btn-icon .x-btn-text{
+    background-position: center;
+	background-repeat: no-repeat;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 16px;
+}
+
+.x-btn-icon .x-btn-medium .x-btn-text{
+    height: 24px;
+	width: 24px;
+}
+
+.x-btn-icon .x-btn-large .x-btn-text{
+    height: 32px;
+	width: 32px;
+}
+
+/* Icons and text */
+/* left */
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:34px;
+    height:32px;
+}
+
+/* top */
+.x-btn-text-icon .x-btn-icon-small-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:34px;
+}
+
+/* right */
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:34px;
+    height:32px;
+}
+
+/* bottom */
+.x-btn-text-icon .x-btn-icon-small-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:34px;
+}
+
+/* background positioning */
+.x-btn-tr i, .x-btn-tl i, .x-btn-mr i, .x-btn-ml i, .x-btn-br i, .x-btn-bl i{
+	font-size:1px;
+    line-height:1px;
+    width:3px;
+    display:block;
+    overflow:hidden;
+}
+
+.x-btn-tr i, .x-btn-tl i, .x-btn-br i, .x-btn-bl i{
+	height:3px;
+}
+
+.x-btn-tl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 0;
+}
+.x-btn-tr{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px 0;
+}
+.x-btn-tc{
+	height:3px;
+	background:repeat-x 0 -6px;
+}
+
+.x-btn-ml{
+	width:3px;
+	background:no-repeat 0 -24px;
+}
+.x-btn-mr{
+	width:3px;
+	background:no-repeat -3px -24px;
+}
+
+.x-btn-mc{
+	background:repeat-x 0 -1096px;
+    vertical-align: middle;
+	text-align:center;
+	padding:0 5px;
+	cursor:pointer;
+	white-space:nowrap;
+}
+
+/* Fixes an issue with the button height */
+.ext-strict .ext-ie6 .x-btn-mc, .ext-strict .ext-ie7 .x-btn-mc {
+    height: 100%;
+}
+
+.x-btn-bl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 -3px;
+}
+
+.x-btn-br{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px -3px;
+}
+
+.x-btn-bc{
+	height:3px;
+	background:repeat-x 0 -15px;
+}
+
+.x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-btn-click .x-btn-tl, .x-btn-menu-active .x-btn-tl, .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-btn-click .x-btn-tr, .x-btn-menu-active .x-btn-tr, .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-btn-click .x-btn-tc, .x-btn-menu-active .x-btn-tc, .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-btn-click .x-btn-ml, .x-btn-menu-active .x-btn-ml, .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-btn-click .x-btn-mr, .x-btn-menu-active .x-btn-mr, .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-btn-click .x-btn-mc, .x-btn-menu-active .x-btn-mc, .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-btn-click .x-btn-bl, .x-btn-menu-active .x-btn-bl, .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-btn-click .x-btn-br, .x-btn-menu-active .x-btn-br, .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-btn-click .x-btn-bc, .x-btn-menu-active .x-btn-bc, .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-btn-disabled *{
+	cursor:default !important;
+}
+
+
+/* With a menu arrow */
+/* right */
+.x-btn-mc em.x-btn-arrow {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:10px;
+}
+
+.x-btn-mc em.x-btn-split {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:14px;
+}
+
+/* bottom */
+.x-btn-mc em.x-btn-arrow-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+/* height adjustment class */
+.x-btn-as-arrow .x-btn-mc em {
+    display:block;
+    background-color:transparent;
+	padding-bottom:14px;
+}
+
+/* groups */
+.x-btn-group {
+    padding:1px;
+}
+
+.x-btn-group-header {
+    padding:2px;
+    text-align:center;
+}
+
+.x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+.x-btn-group-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:3px;
+}
+
+.x-btn-group-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-btn-group-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-br {
+	background: transparent no-repeat right bottom;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-mc {
+    border:0 none;
+    padding:1px 0 0 0;
+    margin:0;
+}
+
+.x-btn-group-mc .x-btn-group-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-btn-group-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-mr {
+	background: transparent repeat-y right 0;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-btn-group-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-btn-group-bc {
+	height:3px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-btn-group-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    height:2px;
+}.x-toolbar{
+    border-style:solid;
+    border-width:0 0 1px 0;
+    display: block;
+	padding:2px;
+    background:repeat-x top left;
+    position:relative;
+    left:0;
+    top:0;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-toolbar-left {
+    width: 100%;
+}
+
+.x-toolbar .x-item-disabled .x-btn-icon {
+    opacity: .35;
+    -moz-opacity: .35;
+    filter: alpha(opacity=35);
+}
+
+.x-toolbar td {
+	vertical-align:middle;
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+	white-space: nowrap;
+}
+
+.x-toolbar .x-item-disabled {
+	cursor:default;
+	opacity:.6;
+	-moz-opacity:.6;
+	filter:alpha(opacity=60);
+}
+
+.x-toolbar .x-item-disabled * {
+	cursor:default;
+}
+
+.x-toolbar .x-toolbar-cell {
+    vertical-align:middle;
+}
+
+.x-toolbar .x-btn-tl, .x-toolbar .x-btn-tr, .x-toolbar .x-btn-tc, .x-toolbar .x-btn-ml, .x-toolbar .x-btn-mr,
+.x-toolbar .x-btn-mc, .x-toolbar .x-btn-bl, .x-toolbar .x-btn-br, .x-toolbar .x-btn-bc
+{
+	background-position: 500px 500px;
+}
+
+/* These rules are duplicated from button.css to give priority of x-toolbar rules above */
+.x-toolbar .x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-toolbar .x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-toolbar .x-btn-click .x-btn-tl, .x-toolbar .x-btn-menu-active .x-btn-tl, .x-toolbar .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tr, .x-toolbar .x-btn-menu-active .x-btn-tr, .x-toolbar .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tc, .x-toolbar .x-btn-menu-active .x-btn-tc, .x-toolbar .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-menu-active .x-btn-ml, .x-toolbar .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mr, .x-toolbar .x-btn-menu-active .x-btn-mr, .x-toolbar .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mc, .x-toolbar .x-btn-menu-active .x-btn-mc, .x-toolbar .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bl, .x-toolbar .x-btn-menu-active .x-btn-bl, .x-toolbar .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-br, .x-toolbar .x-btn-menu-active .x-btn-br, .x-toolbar .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-toolbar div.xtb-text{
+    padding:2px 2px 0;
+    line-height:16px;
+    display:block;
+}
+
+.x-toolbar .xtb-sep {
+	background-position: center;
+	background-repeat: no-repeat;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	width:4px;
+	overflow: hidden;
+	cursor:default;
+	margin: 0 2px 0;
+	border:0;
+}
+
+.x-toolbar .xtb-spacer {
+    width:2px;
+}
+
+/* Paging Toolbar */
+.x-tbar-page-number{
+	width:30px;
+	height:14px;
+}
+
+.ext-ie .x-tbar-page-number{
+    margin-top: 2px;
+}
+
+.x-paging-info {
+    position:absolute;
+    top:5px;
+    right: 8px;
+}
+
+/* floating */
+.x-toolbar-ct {
+    width:100%;
+}
+
+.x-toolbar-right td {
+    text-align: center;
+}
+
+.x-panel-tbar, .x-panel-bbar, .x-window-tbar, .x-window-bbar, .x-tab-panel-tbar, .x-tab-panel-bbar, .x-plain-tbar, .x-plain-bbar {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-toolbar-more .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 12px;
+}
+
+.x-toolbar-more em.x-btn-arrow {
+    display:inline;
+    background-color:transparent;
+	padding-right:0;
+}
+
+.x-toolbar-more .x-btn-mc em.x-btn-arrow {
+    background-image: none;
+}
+
+div.x-toolbar-no-items {
+    color:gray !important;
+    padding:5px 10px !important;
+}
+
+/* fix ie toolbar form items */
+.ext-border-box .x-toolbar-cell .x-form-text {
+    margin-bottom:-1px !important;
+}
+
+.ext-border-box .x-toolbar-cell .x-form-field-wrap .x-form-text {
+    margin:0 !important;
+}
+
+.ext-ie .x-toolbar-cell .x-form-field-wrap {
+    height:21px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-text, .ext-strict .ext-ie .x-toolbar-cell .x-form-text {
+    top: 0px;
+}
+
+.x-toolbar-right td .x-form-field-trigger-wrap{
+    text-align: left;
+}
+
+.x-toolbar-cell .x-form-checkbox, .x-toolbar-cell .x-form-radio{
+    margin-top: 5px;
+}
+
+.x-toolbar-cell .x-form-cb-label{
+    vertical-align: bottom;
+    top: 1px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-checkbox, .ext-ie .x-toolbar-cell .x-form-radio{
+    margin-top: 4px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-cb-label{
+    top: 0;
+}
+/* Grid3 styles */
+.x-grid3 {
+	position:relative;
+	overflow:hidden;
+}
+
+.x-grid-panel .x-panel-body {
+    overflow:hidden !important;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border:1px solid;
+}
+
+.x-grid3 table {
+    table-layout:fixed;
+}
+
+.x-grid3-viewport{
+	overflow:hidden;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+    -moz-outline: none;
+    outline: none;
+	-moz-user-focus: normal;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td {
+    line-height:13px;
+    vertical-align: top;
+	padding-left:1px;
+    padding-right:1px;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-cell{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-row td {
+    line-height:15px;
+    vertical-align:middle;
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+.x-grid3-hd-row .x-grid3-marker-hd {
+    padding:3px;
+}
+
+.x-grid3-row .x-grid3-marker {
+    padding:3px;
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner{
+	overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    padding:3px 3px 3px 5px;
+    white-space: nowrap;
+}
+
+/* ActionColumn, reduce padding to accommodate 16x16 icons in normal row height */
+.x-action-col-cell .x-grid3-cell-inner {
+    padding-top: 1px;
+    padding-bottom: 1px;
+}
+
+.x-action-col-icon {
+    cursor: pointer;
+}
+
+.x-grid3-hd-inner {
+    position:relative;
+	cursor:inherit;
+	padding:4px 3px 4px 5px;
+}
+
+.x-grid3-row-body {
+    white-space:normal;
+}
+
+.x-grid3-body-cell {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+/* IE Quirks to clip */
+.ext-ie .x-grid3-cell-inner, .ext-ie .x-grid3-hd-inner{
+	width:100%;
+}
+
+/* reverse above in strict mode */
+.ext-strict .x-grid3-cell-inner, .ext-strict .x-grid3-hd-inner{
+	width:auto;
+}
+
+.x-grid-row-loading {
+    background: no-repeat center center;
+}
+
+.x-grid-page {
+    overflow:hidden;
+}
+
+.x-grid3-row {
+	cursor: default;
+    border: 1px solid;
+    width:100%;
+}
+
+.x-grid3-row-over {
+	border:1px solid;
+    background: repeat-x left top;
+}
+
+.x-grid3-resize-proxy {
+	width:1px;
+    left:0;
+	cursor: e-resize;
+	cursor: col-resize;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-resize-marker {
+	width:1px;
+	left:0;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: text;
+    -khtml-user-select: text;
+    -webkit-user-select:ignore;
+}
+
+/* header styles */
+.x-grid3-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    padding:1px 0 0 0;
+}
+
+.x-grid3-header-pop {
+    border-left:1px solid;
+    float:right;
+    clear:none;
+}
+
+.x-grid3-header-pop-inner {
+    border-left:1px solid;
+    width:14px;
+    height:19px;
+    background: transparent no-repeat center center;
+}
+
+.ext-ie .x-grid3-header-pop-inner {
+    width:15px;
+}
+
+.ext-strict .x-grid3-header-pop-inner {
+    width:14px; 
+}
+
+.x-grid3-header-inner {
+    overflow:hidden;
+    zoom:1;
+    float:left;
+}
+
+.x-grid3-header-offset {
+    padding-left:1px;
+    text-align: left;
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background: repeat-x left bottom;
+
+}
+
+.x-grid3-sort-icon{
+	background-repeat: no-repeat;
+	display: none;
+	height: 4px;
+	width: 13px;
+	margin-left:3px;
+	vertical-align: middle;
+}
+
+.sort-asc .x-grid3-sort-icon, .sort-desc .x-grid3-sort-icon {
+	display: inline;
+}
+
+/* Header position fixes for IE strict mode */
+.ext-strict .ext-ie .x-grid3-header-inner, .ext-strict .ext-ie6 .x-grid3-hd {
+    position:relative;
+}
+
+.ext-strict .ext-ie6 .x-grid3-hd-inner{
+    position:static;
+}
+
+/* Body Styles */
+.x-grid3-body {
+	zoom:1;
+}
+
+.x-grid3-scroller {
+	overflow:auto;
+    zoom:1;
+    position:relative;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	display: block;
+	padding: 3px 5px 3px 5px;
+	-moz-user-select: none;
+	-khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-split {
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor: e-resize;
+	cursor: col-resize;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	overflow: hidden;
+	position: absolute;
+	top: 2px;
+	width: 6px;
+	z-index: 3;
+}
+
+/* Column Reorder DD */
+.x-dd-drag-proxy .x-grid3-hd-inner{
+	background: repeat-x left bottom;
+	width:120px;
+	padding:3px;
+	border:1px solid;
+	overflow:hidden;
+}
+
+.col-move-top, .col-move-bottom{
+	width:9px;
+	height:9px;
+	position:absolute;
+	top:0;
+	line-height:1px;
+	font-size:1px;
+	overflow:hidden;
+	visibility:hidden;
+	z-index:20000;
+    background:transparent no-repeat left top;
+}
+
+/* Selection Styles */
+.x-grid3-row-selected {
+	border:1px dotted;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background: repeat-x 0 bottom !important;
+    vertical-align:middle !important;
+    padding:0;
+    border-top:1px solid;
+    border-bottom:none !important;
+    border-right:1px solid !important;
+    text-align:center;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    padding:0 4px;
+    text-align:center;
+}
+
+/* dirty cells */
+.x-grid3-dirty-cell {
+    background: transparent no-repeat 0 0;
+}
+
+/* Grid Toolbars */
+.x-grid3-topbar, .x-grid3-bottombar{
+    overflow:hidden;
+	display:none;
+	zoom:1;
+    position:relative;
+}
+
+.x-grid3-topbar .x-toolbar{
+	border-right:0 none;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-right:0 none;
+	border-bottom:0 none;
+	border-top:1px solid;
+}
+
+/* Props Grid Styles */
+.x-props-grid .x-grid3-cell{
+	padding:1px;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background:transparent repeat-y -16px !important;
+    padding-left:12px;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    padding:1px;
+    padding-right:0;
+    border:0 none;
+    border-right:1px solid;
+}
+
+/* dd */
+.x-grid3-col-dd {
+    border:0 none;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-dd-drag-ghost .x-grid3-dd-wrap {
+    padding:1px 3px 3px 1px;
+}
+
+.x-grid3-hd {
+    -moz-user-select:none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-btn {
+    display:none;
+    position:absolute;
+    width:14px;
+    background:no-repeat left center;
+    right:0;
+    top:0;
+    z-index:2;
+	cursor:pointer;
+}
+
+.x-grid3-hd-over .x-grid3-hd-btn, .x-grid3-hd-menu-open .x-grid3-hd-btn {
+    display:block;
+}
+
+a.x-grid3-hd-btn:hover {
+    background-position:-14px center;
+}
+
+/* Expanders */
+.x-grid3-body .x-grid3-td-expander {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-expander .x-grid3-cell-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-expander {
+    width:100%;
+    height:18px;
+    background-position:4px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-expander {
+    background-position:4px 2px;
+}
+
+.x-grid3-row-expanded .x-grid3-row-expander {
+    background-position:-21px 2px;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-body {
+    display:none !important;
+}
+
+.x-grid3-row-expanded .x-grid3-row-body {
+    display:block !important;
+}
+
+/* Checkers */
+.x-grid3-body .x-grid3-td-checker {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-checker .x-grid3-cell-inner, .x-grid3-header .x-grid3-td-checker .x-grid3-hd-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    width:100%;
+    height:18px;
+    background-position:2px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row .x-grid3-row-checker {
+    background-position:2px 2px;
+}
+
+.x-grid3-row-selected .x-grid3-row-checker, .x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker {
+    background-position:-23px 2px;
+}
+
+.x-grid3-hd-checker {
+    background-position:2px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker {
+    background-position:2px 3px;
+}
+
+.x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 3px;
+}
+
+/* Numberer */
+.x-grid3-body .x-grid3-td-numberer {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+    padding:3px 5px 0 0 !important;
+    text-align:right;
+}
+
+/* Row Icon */
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background:transparent repeat-y right;
+    vertical-align:top;
+    text-align:center;
+}
+
+.x-grid3-body .x-grid3-td-row-icon .x-grid3-cell-inner {
+    padding:0 !important;
+    background-position:center center;
+    background-repeat:no-repeat;
+    width:16px;
+    height:16px;
+    margin-left:2px;
+    margin-top:3px;
+}
+
+/* All specials */
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-check-col-td .x-grid3-cell-inner {
+    padding: 1px 0 0 0 !important;
+}
+
+.x-grid3-check-col {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-check-col-on {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+/* Grouping classes */
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom: 2px solid;
+    cursor:pointer;
+    padding-top:6px;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background:transparent no-repeat 3px 3px;
+    padding:4px 4px 4px 17px;
+}
+
+.x-grid-group-collapsed .x-grid-group-body {
+    display:none;
+}
+
+.ext-ie6 .x-grid3 .x-editor .x-form-text, .ext-ie7 .x-grid3 .x-editor .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-ie .x-props-grid .x-editor .x-form-text {
+    position:static;
+    top:0;
+}
+
+.x-grid-empty {
+    padding:10px;
+}
+
+/* fix floating toolbar issue */
+.ext-ie7 .x-grid-panel .x-panel-bbar {
+    position:relative;
+}
+
+
+/* Reset position to static when Grid Panel has been framed */
+/* to resolve 'snapping' from top to bottom behavior. */
+/* @forumThread 86656 */
+.ext-ie7 .x-grid-panel .x-panel-mc .x-panel-bbar {
+    position: static;
+}
+
+.ext-ie6 .x-grid3-header {
+    position: relative;
+}
+
+/* Fix WebKit bug in Grids */
+.ext-webkit .x-grid-panel .x-panel-bwrap{
+    -webkit-user-select:none;
+}
+.ext-webkit .x-tbar-page-number{
+    -webkit-user-select:ignore;
+}
+/* end*/
+
+/* column lines */
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    padding-right:0;
+    border-right:1px solid;
+}
+.x-pivotgrid .x-grid3-header-offset table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-header-offset table td {
+    padding: 4px 3px 4px 5px;
+    text-align: center;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    line-height: 13px;
+    font-family: tahoma;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    display: block;
+    float: left;
+}
+
+.x-pivotgrid .x-grid3-row-headers table {
+    height: 100%;
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    height: 18px;
+    padding: 2px 7px 0 0;
+    text-align: right;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    font-family: tahoma;
+}
+
+.ext-gecko .x-pivotgrid .x-grid3-row-headers table td {
+    height: 21px;
+}
+
+.x-grid3-header-title {
+    top: 0%;
+    left: 0%;
+    position: absolute;
+    text-align: center;
+    vertical-align: middle;
+    font-family: tahoma;
+    font-size: 11px;
+    padding: auto 1px;
+    display: table-cell;
+}
+
+.x-grid3-header-title span {
+    position: absolute;
+    top: 50%;
+    left: 0%;
+    width: 100%;
+    margin-top: -6px;
+}.x-dd-drag-proxy{
+	position:absolute;
+	left:0;
+    top:0;
+	visibility:hidden;
+	z-index:15000;
+}
+
+.x-dd-drag-ghost{
+	-moz-opacity: 0.85;
+    opacity:.85;
+    filter: alpha(opacity=85);
+    border: 1px solid;
+	padding:3px;
+	padding-left:20px;
+	white-space:nowrap;
+}
+
+.x-dd-drag-repair .x-dd-drag-ghost{
+	-moz-opacity: 0.4;
+    opacity:.4;
+    filter: alpha(opacity=40);
+	border:0 none;
+	padding:0;
+	background-color:transparent;
+}
+
+.x-dd-drag-repair .x-dd-drop-icon{
+	visibility:hidden;
+}
+
+.x-dd-drop-icon{
+    position:absolute;
+	top:3px;
+	left:3px;
+	display:block;
+	width:16px;
+	height:16px;
+	background-color:transparent;
+	background-position: center;
+	background-repeat: no-repeat;
+	z-index:1;
+}
+
+.x-view-selector {
+    position:absolute;
+    left:0;
+    top:0;
+    width:0;
+    border:1px dotted;
+	opacity: .5;
+    -moz-opacity: .5;
+    filter:alpha(opacity=50);
+    zoom:1;
+}.ext-strict .ext-ie .x-tree .x-panel-bwrap{
+    position:relative;
+    overflow:hidden;
+}
+
+.x-tree-icon, .x-tree-ec-icon, .x-tree-elbow-line, .x-tree-elbow, .x-tree-elbow-end, .x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+    background-repeat: no-repeat;
+}
+
+.x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .x-tree-node-icon{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	background-position:center;
+    background-repeat: no-repeat;
+}
+
+.ext-ie .x-tree-node-indent img, .ext-ie .x-tree-node-icon, .ext-ie .x-tree-ec-icon {
+    vertical-align: middle !important;
+}
+
+.ext-strict .ext-ie8 .x-tree-node-indent img, .ext-strict .ext-ie8 .x-tree-node-icon, .ext-strict .ext-ie8 .x-tree-ec-icon {
+    vertical-align: top !important;
+}
+
+/* checkboxes */
+
+input.x-tree-node-cb {
+    margin-left:1px;
+    height: 19px;
+	vertical-align: bottom;
+}
+
+.ext-ie input.x-tree-node-cb {
+    margin-left:0;
+    margin-top: 1px;
+    width: 16px;
+    height: 16px;
+    vertical-align: middle;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb{
+    margin: 1px 1px;
+    height: 14px;
+    vertical-align: bottom;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb + a{
+    vertical-align: bottom;
+}
+
+.ext-opera input.x-tree-node-cb {
+    height: 14px;
+    vertical-align: middle;
+}
+
+.x-tree-noicon .x-tree-node-icon{
+	width:0; height:0;
+}
+
+/* No line styles */
+.x-tree-no-lines .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+/* Arrows */
+.x-tree-arrows .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	cursor:pointer;
+}
+
+.ext-ie ul.x-tree-node-ct{
+    font-size:0;
+    line-height:0;
+    zoom:1;
+}
+
+.x-tree-node{
+	white-space: nowrap;
+}
+
+.x-tree-node-el {
+    line-height:18px;
+    cursor:pointer;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	text-decoration:none;
+	-khtml-user-select:none;
+	-moz-user-select:none;
+    -webkit-user-select:ignore;
+    -kthml-user-focus:normal;
+    -moz-user-focus:normal;
+    -moz-outline: 0 none;
+    outline:0 none;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	text-decoration:none;
+	padding:1px 3px 1px 2px;
+}
+
+.x-tree-node .x-tree-node-disabled .x-tree-node-icon{
+	-moz-opacity: 0.5;
+   opacity:.5;
+   filter: alpha(opacity=50);
+}
+
+.x-tree-node .x-tree-node-inline-icon{
+	background-color:transparent;
+}
+
+.x-tree-node a:hover, .x-dd-drag-ghost a:hover{
+	text-decoration:none;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:1px dotted;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top:1px dotted;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above{
+	 border-top:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom:2px solid;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top:2px solid;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 border:1px dotted;
+}
+
+.x-dd-drag-ghost .x-tree-node-indent, .x-dd-drag-ghost .x-tree-ec-icon{
+	display:none !important;
+}
+
+/* Fix for ie rootVisible:false issue */
+.x-tree-root-ct {
+    zoom:1;
+}
+.x-date-picker {
+    border: 1px solid;
+    border-top:0 none;
+	position:relative;
+}
+
+.x-date-picker a {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+.x-date-inner, .x-date-inner td, .x-date-inner th{
+    border-collapse:separate;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background: repeat-x 0 -83px;
+	overflow:hidden;
+}
+
+.x-date-middle .x-btn-tc,.x-date-middle .x-btn-tl,.x-date-middle .x-btn-tr,
+.x-date-middle .x-btn-mc,.x-date-middle .x-btn-ml,.x-date-middle .x-btn-mr,
+.x-date-middle .x-btn-bc,.x-date-middle .x-btn-bl,.x-date-middle .x-btn-br{
+	background:transparent !important;
+    vertical-align:middle;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background:transparent no-repeat right 0;
+}
+
+.x-date-right, .x-date-left {
+    width:18px;
+}
+
+.x-date-right{
+    text-align:right;
+}
+
+.x-date-middle {
+    padding-top:2px;
+    padding-bottom:2px;
+    width:130px; /* FF3 */
+}
+
+.x-date-right a, .x-date-left a{
+    display:block;
+    width:16px;
+	height:16px;
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor:pointer;
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a:hover, .x-date-left a:hover{
+    -moz-opacity: 1;
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+
+.x-item-disabled .x-date-right a:hover, .x-item-disabled .x-date-left a:hover{
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a {
+    margin-right:2px;
+    text-decoration:none !important;
+}
+
+.x-date-left a{
+    margin-left:2px;
+    text-decoration:none !important;
+}
+
+table.x-date-inner {
+    width: 100%;
+    table-layout:fixed;
+}
+
+.ext-webkit table.x-date-inner{
+    /* Fix for webkit browsers */
+    width: 175px;
+}
+
+
+.x-date-inner th {
+    width:25px;
+}
+
+.x-date-inner th {
+    background: repeat-x left top;
+    text-align:right !important;
+	border-bottom: 1px solid;
+	cursor:default;
+    padding:0;
+    border-collapse:separate;
+}
+
+.x-date-inner th span {
+    display:block;
+    padding:2px;
+    padding-right:7px;
+}
+
+.x-date-inner td {
+    border: 1px solid;
+	text-align:right;
+    padding:0;
+}
+
+.x-date-inner a {
+    padding:2px 5px;
+    display:block;
+	text-decoration:none;
+    text-align:right;
+    zoom:1;
+}
+
+.x-date-inner .x-date-active{
+	cursor:pointer;
+	color:black;
+}
+
+.x-date-inner .x-date-selected a{
+	background: repeat-x left top;
+	border:1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-today a{
+	border: 1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+    text-decoration:none !important;
+}
+
+.x-date-bottom {
+    padding:4px;
+    border-top: 1px solid;
+    background: repeat-x left top;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    text-decoration:none !important;
+}
+
+.x-item-disabled .x-date-inner a:hover{
+    background: none;
+}
+
+.x-date-inner .x-date-disabled a {
+	cursor:default;
+}
+
+.x-date-menu .x-menu-item {
+	padding:1px 24px 1px 4px;
+	white-space: nowrap;
+}
+
+.x-date-menu .x-menu-item .x-menu-item-icon {
+    width:10px;
+    height:10px;
+    margin-right:5px;
+    background-position:center -4px !important;
+}
+
+.x-date-mp {
+	position:absolute;
+	left:0;
+	top:0;
+	display:none;
+}
+
+.x-date-mp td {
+    padding:2px;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+td.x-date-mp-month,td.x-date-mp-year,td.x-date-mp-ybtn {
+    border: 0 none;
+	text-align:center;
+	vertical-align: middle;
+	width:25%;
+}
+
+.x-date-mp-ok {
+	margin-right:3px;
+}
+
+.x-date-mp-btns button {
+	text-decoration:none;
+	text-align:center;
+	text-decoration:none !important;
+	border:1px solid;
+	padding:1px 3px 1px;
+	cursor:pointer;
+}
+
+.x-date-mp-btns {
+	background: repeat-x left top;
+}
+
+.x-date-mp-btns td {
+	border-top: 1px solid;
+    text-align:center;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	display:block;
+	padding:2px 4px;
+	text-decoration:none;
+	text-align:center;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	text-decoration:none;
+	cursor:pointer;
+}
+
+td.x-date-mp-sel a {
+	padding:1px 3px;
+	background: repeat-x left top;
+	border:1px solid;
+}
+
+.x-date-mp-ybtn a {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    cursor:pointer;
+    background:transparent no-repeat;
+    display:block;
+    margin:0 auto;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next {
+    background-position:0 -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next:hover {
+    background-position:-15px -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev {
+    background-position:0 -105px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev:hover {
+    background-position:-15px -105px;
+}
+
+.x-date-mp-ybtn {
+   text-align:center;
+}
+
+td.x-date-mp-sep {
+   border-right:1px solid;
+}.x-tip{
+	position: absolute;
+	top: 0;
+    left:0;
+    visibility: hidden;
+	z-index: 20002;
+    border:0 none;
+}
+
+.x-tip .x-tip-close{
+	height: 15px;
+	float:right;
+	width: 15px;
+    margin:0 0 2px 2px;
+    cursor:pointer;
+    display:none;
+}
+
+.x-tip .x-tip-tc {
+	background: transparent no-repeat 0 -62px;
+	padding-top:3px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-bc {
+	background: transparent no-repeat 0 -121px;
+	height:3px;
+    overflow:hidden;
+}
+
+.x-tip .x-tip-bl {
+	background: transparent no-repeat 0 -59px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-br {
+	background: transparent no-repeat right -59px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mc {
+    border:0 none;
+}
+
+.x-tip .x-tip-ml {
+	background: no-repeat 0 -124px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mr {
+	background: transparent no-repeat right -124px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.ext-ie .x-tip .x-tip-header,.ext-ie .x-tip .x-tip-tc {
+    font-size:0;
+    line-height:0;
+}
+
+.ext-border-box .x-tip .x-tip-header, .ext-border-box .x-tip .x-tip-tc{
+    line-height: 1px;
+}
+
+.x-tip .x-tip-header-text {
+    padding:0;
+    margin:0 0 2px 0;
+}
+
+.x-tip .x-tip-body {
+    margin:0 !important;
+    line-height:14px;
+    padding:0;
+}
+
+.x-tip .x-tip-body .loading-indicator {
+    margin:0;
+}
+
+.x-tip-draggable .x-tip-header,.x-tip-draggable .x-tip-header-text {
+    cursor:move;
+}
+
+.x-form-invalid-tip .x-tip-tc {
+	background: repeat-x 0 -12px;
+    padding-top:6px;
+}
+
+.x-form-invalid-tip .x-tip-bc {
+	background: repeat-x 0 -18px;
+    height:6px;
+}
+
+.x-form-invalid-tip .x-tip-bl {
+	background: no-repeat 0 -6px;
+}
+
+.x-form-invalid-tip .x-tip-br {
+	background: no-repeat right -6px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding:2px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding-left:24px;
+    background:transparent no-repeat 2px 2px;
+}
+
+.x-tip-anchor {
+    position: absolute;
+    width: 9px;
+    height: 10px;
+    overflow:hidden;
+    background: transparent no-repeat 0 0;
+    zoom:1;
+}
+.x-tip-anchor-bottom {
+    background-position: -9px 0;
+}
+.x-tip-anchor-right {
+    background-position: -18px 0;
+    width: 10px;
+}
+.x-tip-anchor-left {
+    background-position: -28px 0;
+    width: 10px;
+}.x-menu {
+	z-index: 15000;
+	zoom: 1;
+	background: repeat-y;
+}
+
+.x-menu-floating{
+    border: 1px solid;
+}
+
+.x-menu a {
+    text-decoration: none !important;
+}
+
+.ext-ie .x-menu {
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-menu-list{
+    padding: 2px;
+	background-color:transparent;
+	border:0 none;
+    overflow:hidden;
+    overflow-y: hidden;
+}
+
+.ext-strict .ext-ie .x-menu-list{
+    position: relative;
+}
+
+.x-menu li{
+	line-height:100%;
+}
+
+.x-menu li.x-menu-sep-li{
+	font-size:1px;
+	line-height:1px;
+}
+
+.x-menu-list-item{
+    white-space: nowrap;
+	display:block;
+	padding:1px;
+}
+
+.x-menu-item{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-menu-item-arrow{
+	background:transparent no-repeat right;
+}
+
+.x-menu-sep {
+	display:block;
+	font-size:1px;
+	line-height:1px;
+	margin: 2px 3px;
+	border-bottom:1px solid;
+    overflow:hidden;
+}
+
+.x-menu-focus {
+	position:absolute;
+	left:-1px;
+	top:-1px;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+    overflow:hidden;
+    display:block;
+}
+
+a.x-menu-item {
+    cursor: pointer;
+    display: block;
+    line-height: 16px;
+    outline-color: -moz-use-text-color;
+    outline-style: none;
+    outline-width: 0;
+    padding: 3px 21px 3px 27px;
+    position: relative;
+    text-decoration: none;
+    white-space: nowrap;
+}
+
+.x-menu-item-active {
+    background-repeat: repeat-x;
+    background-position: left bottom;
+    border-style:solid;
+    border-width: 1px 0;
+    margin:0 1px;
+	padding: 0;
+}
+
+.x-menu-item-active a.x-menu-item {
+    border-style:solid;
+    border-width:0 1px;
+    margin:0 -1px;
+}
+
+.x-menu-item-icon {
+	border: 0 none;
+	height: 16px;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	position: absolute;
+    left: 3px;
+    top: 3px;
+    margin: 0;
+    background-position:center;
+}
+
+.ext-ie .x-menu-item-icon {
+    left: -24px;
+}
+.ext-strict .x-menu-item-icon {
+    left: 3px;
+}
+
+.ext-ie6 .x-menu-item-icon {
+    left: -24px;
+}
+
+.ext-ie .x-menu-item-icon {
+    vertical-align: middle;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background: transparent no-repeat center;
+}
+
+.x-menu-group-item .x-menu-item-icon{
+	background-color: transparent;
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background: transparent no-repeat center;
+}
+
+.x-date-menu .x-menu-list{
+    padding: 0;
+}
+
+.x-menu-date-item{
+	padding:0;
+}
+
+.x-menu .x-color-palette, .x-menu .x-date-picker{
+    margin-left: 26px;
+	margin-right:4px;
+}
+
+.x-menu .x-date-picker{
+    border:1px solid;
+    margin-top:2px;
+    margin-bottom:2px;
+}
+
+.x-menu-plain .x-color-palette, .x-menu-plain .x-date-picker{
+	 margin: 0;
+	 border: 0 none;
+}
+
+.x-date-menu {
+   padding:0 !important;
+}
+
+/*
+ * fixes separator visibility problem in IE 6
+ */
+.ext-strict .ext-ie6 .x-menu-sep-li {
+    padding: 3px 4px;
+}
+.ext-strict .ext-ie6 .x-menu-sep {
+    margin: 0;
+    height: 1px;
+}
+
+/*
+ * Fixes an issue with "fat" separators in webkit
+ */
+.ext-webkit .x-menu-sep{
+    height: 1px;
+}
+
+/*
+ * Ugly mess to remove the white border under the picker
+ */
+.ext-ie .x-date-menu{
+    height: 199px;
+}
+
+.ext-strict .ext-ie .x-date-menu, .ext-border-box .ext-ie8 .x-date-menu{
+    height: 197px;
+}
+
+.ext-strict .ext-ie7 .x-date-menu{
+    height: 195px;
+}
+
+.ext-strict .ext-ie8 .x-date-menu{
+    height: auto;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border:1px dotted !important;
+	padding:0;
+}
+
+.x-menu .x-menu-scroller {
+    width: 100%;
+	background-repeat:no-repeat;
+	background-position:center;
+	height:8px;
+    line-height: 8px;
+	cursor:pointer;
+    margin: 0;
+    padding: 0;
+}
+
+.x-menu .x-menu-scroller-active{
+    height: 6px;
+    line-height: 6px;
+}
+
+.x-menu-list-item-indent{
+    padding-left: 27px;
+}/*
+ Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:
+  <div class="x-box-blue">
+        <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>
+        <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">
+            <h3>YOUR TITLE HERE (optional)</h3>
+            <div>YOUR CONTENT HERE</div>
+        </div></div></div>
+        <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
+    </div>
+ */
+
+.x-box-tl {
+	background: transparent no-repeat 0 0;
+    zoom:1;
+}
+
+.x-box-tc {
+	height: 8px;
+	background: transparent repeat-x 0 0;
+	overflow: hidden;
+}
+
+.x-box-tr {
+	background: transparent no-repeat right -8px;
+}
+
+.x-box-ml {
+	background: transparent repeat-y 0;
+	padding-left: 4px;
+	overflow: hidden;
+    zoom:1;
+}
+
+.x-box-mc {
+	background: repeat-x 0 -16px;
+	padding: 4px 10px;
+}
+
+.x-box-mc h3 {
+	margin: 0 0 4px 0;
+    zoom:1;
+}
+
+.x-box-mr {
+	background: transparent repeat-y right;
+	padding-right: 4px;
+	overflow: hidden;
+}
+
+.x-box-bl {
+	background: transparent no-repeat 0 -16px;
+    zoom:1;
+}
+
+.x-box-bc {
+	background: transparent repeat-x 0 -8px;
+	height: 8px;
+	overflow: hidden;
+}
+
+.x-box-br {
+	background: transparent no-repeat right -24px;
+}
+
+.x-box-tl, .x-box-bl {
+	padding-left: 8px;
+	overflow: hidden;
+}
+
+.x-box-tr, .x-box-br {
+	padding-right: 8px;
+	overflow: hidden;
+}.x-combo-list {
+    border:1px solid;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-combo-list-inner {
+    overflow:auto;
+    position:relative; /* for calculating scroll offsets */
+    zoom:1;
+    overflow-x:hidden;
+}
+
+.x-combo-list-hd {
+    border-bottom:1px solid;
+    padding:3px;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom:1px solid;
+}
+
+.x-combo-list-item {
+    padding:2px;
+    border:1px solid;
+    white-space: nowrap;
+    overflow:hidden;
+    text-overflow: ellipsis;
+}
+
+.x-combo-list .x-combo-selected{
+	border:1px dotted !important;
+    cursor:pointer;
+}
+
+.x-combo-list .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}.x-panel {
+    border-style: solid;
+    border-width:0;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+    padding:5px 3px 4px 5px;
+    border:1px solid;
+    line-height: 15px;
+    background: transparent repeat-x 0 -1px;
+}
+
+.x-panel-body {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    position: relative; /* added for item scroll positioning */
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom: 0 none;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top:1px solid;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-tl .x-panel-header {
+    padding:5px 0 4px 0;
+    border:0 none;
+    background:transparent no-repeat;
+}
+
+.x-panel-tl .x-panel-icon, .x-window-tl .x-panel-icon {
+    padding-left:20px !important;
+    background-repeat:no-repeat;
+    background-position:0 4px;
+    zoom:1;
+}
+
+.x-panel-inline-icon {
+    width:16px;
+	height:16px;
+    background-repeat:no-repeat;
+    background-position:0 0;
+	vertical-align:middle;
+	margin-right:4px;
+	margin-top:-1px;
+	margin-bottom:-1px;
+}
+
+.x-panel-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+/* fix ie7 strict mode bug */
+.ext-strict .ext-ie7 .x-panel-tc {
+    overflow: visible;
+}
+
+.x-panel-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    border-bottom:1px solid;
+}
+
+.x-panel-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:6px;
+}
+
+.x-panel-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-panel-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-mc {
+    border:0 none;
+    padding:0;
+    margin:0;
+    padding-top:6px;
+}
+
+.x-panel-mc .x-panel-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-panel-ml {
+	background: repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-panel-bc, .x-panel-nofooter .x-window-bc {
+	height:6px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-panel-bwrap {
+    overflow:hidden;
+    zoom:1;
+    left:0;
+    top:0;
+}
+.x-panel-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-collapsed .x-resizable-handle{
+    display:none;
+}
+
+.ext-gecko .x-panel-animated div {
+    overflow:hidden !important;
+}
+
+/* Plain */
+.x-plain-body {
+    overflow:hidden;
+}
+
+.x-plain-bbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-tbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-plain {
+    overflow:hidden;
+}
+
+/* Tools */
+.x-tool {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    float:right;
+    cursor:pointer;
+    background:transparent no-repeat;
+    margin-left:2px;
+}
+
+/* expand / collapse tools */
+.x-tool-toggle {
+    background-position:0 -60px;
+}
+
+.x-tool-toggle-over {
+    background-position:-15px -60px;
+}
+
+.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+
+.x-tool-close {
+    background-position:0 -0;
+}
+
+.x-tool-close-over {
+    background-position:-15px 0;
+}
+
+.x-tool-minimize {
+    background-position:0 -15px;
+}
+
+.x-tool-minimize-over {
+    background-position:-15px -15px;
+}
+
+.x-tool-maximize {
+    background-position:0 -30px;
+}
+
+.x-tool-maximize-over {
+    background-position:-15px -30px;
+}
+
+.x-tool-restore {
+    background-position:0 -45px;
+}
+
+.x-tool-restore-over {
+    background-position:-15px -45px;
+}
+
+.x-tool-gear {
+    background-position:0 -90px;
+}
+
+.x-tool-gear-over {
+    background-position:-15px -90px;
+}
+
+.x-tool-prev {
+    background-position:0 -105px;
+}
+
+.x-tool-prev-over {
+    background-position:-15px -105px;
+}
+
+.x-tool-next {
+    background-position:0 -120px;
+}
+
+.x-tool-next-over {
+    background-position:-15px -120px;
+}
+
+.x-tool-pin {
+    background-position:0 -135px;
+}
+
+.x-tool-pin-over {
+    background-position:-15px -135px;
+}
+
+.x-tool-unpin {
+    background-position:0 -150px;
+}
+
+.x-tool-unpin-over {
+    background-position:-15px -150px;
+}
+
+.x-tool-right {
+    background-position:0 -165px;
+}
+
+.x-tool-right-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-left {
+    background-position:0 -180px;
+}
+
+.x-tool-left-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-down {
+    background-position:0 -195px;
+}
+
+.x-tool-down-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-up {
+    background-position:0 -210px;
+}
+
+.x-tool-up-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-refresh {
+    background-position:0 -225px;
+}
+
+.x-tool-refresh-over {
+    background-position:-15px -225px;
+}
+
+.x-tool-plus {
+    background-position:0 -240px;
+}
+
+.x-tool-plus-over {
+    background-position:-15px -240px;
+}
+
+.x-tool-minus {
+    background-position:0 -255px;
+}
+
+.x-tool-minus-over {
+    background-position:-15px -255px;
+}
+
+.x-tool-search {
+    background-position:0 -270px;
+}
+
+.x-tool-search-over {
+    background-position:-15px -270px;
+}
+
+.x-tool-save {
+    background-position:0 -285px;
+}
+
+.x-tool-save-over {
+    background-position:-15px -285px;
+}
+
+.x-tool-help {
+    background-position:0 -300px;
+}
+
+.x-tool-help-over {
+    background-position:-15px -300px;
+}
+
+.x-tool-print {
+    background-position:0 -315px;
+}
+
+.x-tool-print-over {
+    background-position:-15px -315px;
+}
+
+.x-tool-expand {
+    background-position:0 -330px;
+}
+
+.x-tool-expand-over {
+    background-position:-15px -330px;
+}
+
+.x-tool-collapse {
+    background-position:0 -345px;
+}
+
+.x-tool-collapse-over {
+    background-position:-15px -345px;
+}
+
+.x-tool-resize {
+    background-position:0 -360px;
+}
+
+.x-tool-resize-over {
+    background-position:-15px -360px;
+}
+
+.x-tool-move {
+    background-position:0 -375px;
+}
+
+.x-tool-move-over {
+    background-position:-15px -375px;
+}
+
+/* Ghosting */
+.x-panel-ghost {
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    opacity:.65;
+    -moz-opacity:.65;
+    filter:alpha(opacity=65);
+}
+
+.x-panel-ghost ul {
+    margin:0;
+    padding:0;
+    overflow:hidden;
+    font-size:0;
+    line-height:0;
+    border:1px solid;
+    border-top:0 none;
+    display:block;
+}
+
+.x-panel-ghost * {
+    cursor:move !important;
+}
+
+.x-panel-dd-spacer {
+    border:2px dashed;
+}
+
+/* Buttons */
+.x-panel-btns {
+    padding:5px;
+    overflow:hidden;
+}
+
+.x-panel-btns td.x-toolbar-cell{
+	padding:3px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-left{
+	background-position:0 -147px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-right{
+	background-position:0 -168px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-center{
+	background-position:0 -189px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-center{
+	background-position:0 -105px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-center{
+	background-position:0 -126px;
+}
+
+.x-panel-btns .x-btn-click  .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+	white-space: nowrap;
+}
+/**
+ * W3C Suggested Default style sheet for HTML 4
+ * http://www.w3.org/TR/CSS21/sample.html
+ *
+ * Resets for Ext.Panel @cfg normal: true
+ */
+.x-panel-reset .x-panel-body html,
+.x-panel-reset .x-panel-body address,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body body,
+.x-panel-reset .x-panel-body dd,
+.x-panel-reset .x-panel-body div,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dt,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body frame, frameset,
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body noframes,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body center,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body hr,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body pre 			  { display: block }
+.x-panel-reset .x-panel-body li              { display: list-item }
+.x-panel-reset .x-panel-body head            { display: none }
+.x-panel-reset .x-panel-body table           { display: table }
+.x-panel-reset .x-panel-body tr              { display: table-row }
+.x-panel-reset .x-panel-body thead           { display: table-header-group }
+.x-panel-reset .x-panel-body tbody           { display: table-row-group }
+.x-panel-reset .x-panel-body tfoot           { display: table-footer-group }
+.x-panel-reset .x-panel-body col             { display: table-column }
+.x-panel-reset .x-panel-body colgroup        { display: table-column-group }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th 	          { display: table-cell }
+.x-panel-reset .x-panel-body caption         { display: table-caption }
+.x-panel-reset .x-panel-body th              { font-weight: bolder; text-align: center }
+.x-panel-reset .x-panel-body caption         { text-align: center }
+.x-panel-reset .x-panel-body body            { margin: 8px }
+.x-panel-reset .x-panel-body h1              { font-size: 2em; margin: .67em 0 }
+.x-panel-reset .x-panel-body h2              { font-size: 1.5em; margin: .75em 0 }
+.x-panel-reset .x-panel-body h3              { font-size: 1.17em; margin: .83em 0 }
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu            { margin: 1.12em 0 }
+.x-panel-reset .x-panel-body h5              { font-size: .83em; margin: 1.5em 0 }
+.x-panel-reset .x-panel-body h6              { font-size: .75em; margin: 1.67em 0 }
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body b,
+.x-panel-reset .x-panel-body strong          { font-weight: bolder }
+.x-panel-reset .x-panel-body blockquote      { margin-left: 40px; margin-right: 40px }
+.x-panel-reset .x-panel-body i,
+.x-panel-reset .x-panel-body cite,
+.x-panel-reset .x-panel-body em,
+.x-panel-reset .x-panel-body var,
+.x-panel-reset .x-panel-body address    	  { font-style: italic }
+.x-panel-reset .x-panel-body pre,
+.x-panel-reset .x-panel-body tt,
+.x-panel-reset .x-panel-body code,
+.x-panel-reset .x-panel-body kbd,
+.x-panel-reset .x-panel-body samp       	  { font-family: monospace }
+.x-panel-reset .x-panel-body pre             { white-space: pre }
+.x-panel-reset .x-panel-body button,
+.x-panel-reset .x-panel-body textarea,
+.x-panel-reset .x-panel-body input,
+.x-panel-reset .x-panel-body select   		  { display: inline-block }
+.x-panel-reset .x-panel-body big             { font-size: 1.17em }
+.x-panel-reset .x-panel-body small,
+.x-panel-reset .x-panel-body sub,
+.x-panel-reset .x-panel-body sup 			  { font-size: .83em }
+.x-panel-reset .x-panel-body sub             { vertical-align: sub }
+.x-panel-reset .x-panel-body sup             { vertical-align: super }
+.x-panel-reset .x-panel-body table           { border-spacing: 2px; }
+.x-panel-reset .x-panel-body thead,
+.x-panel-reset .x-panel-body tbody,
+.x-panel-reset .x-panel-body tfoot           { vertical-align: middle }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th          	  { vertical-align: inherit }
+.x-panel-reset .x-panel-body s,
+.x-panel-reset .x-panel-body strike,
+.x-panel-reset .x-panel-body del  			  { text-decoration: line-through }
+.x-panel-reset .x-panel-body hr              { border: 1px inset }
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body dd        	  { margin-left: 40px }
+.x-panel-reset .x-panel-body ul, .x-panel-reset .x-panel-body menu, .x-panel-reset .x-panel-body dir { list-style-type: disc;}
+.x-panel-reset .x-panel-body ol              { list-style-type: decimal }
+.x-panel-reset .x-panel-body ol ul,
+.x-panel-reset .x-panel-body ul ol,
+.x-panel-reset .x-panel-body ul ul,
+.x-panel-reset .x-panel-body ol ol    		  { margin-top: 0; margin-bottom: 0 }
+.x-panel-reset .x-panel-body u,
+.x-panel-reset .x-panel-body ins          	  { text-decoration: underline }
+.x-panel-reset .x-panel-body br:before       { content: "\A" }
+.x-panel-reset .x-panel-body :before, .x-panel-reset .x-panel-body :after { white-space: pre-line }
+.x-panel-reset .x-panel-body center          { text-align: center }
+.x-panel-reset .x-panel-body :link, .x-panel-reset .x-panel-body :visited { text-decoration: underline }
+.x-panel-reset .x-panel-body :focus          { outline: invert dotted thin }
+
+/* Begin bidirectionality settings (do not change) */
+.x-panel-reset .x-panel-body BDO[DIR="ltr"]  { direction: ltr; unicode-bidi: bidi-override }
+.x-panel-reset .x-panel-body BDO[DIR="rtl"]  { direction: rtl; unicode-bidi: bidi-override }
+.x-window {
+    zoom:1;
+}
+
+.x-window .x-window-handle {
+    opacity:0;
+    -moz-opacity:0;
+    filter:alpha(opacity=0);
+}
+
+.x-window-proxy {
+    border:1px solid;
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    display:none;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-window-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-window-bwrap {
+    z-index:1;
+    position:relative;
+    zoom:1;
+    left:0;top:0;
+}
+
+.x-window-tl .x-window-header {
+    padding:5px 0 4px 0;
+}
+
+.x-window-header-text {
+    cursor:pointer;
+}
+
+.x-window-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    zoom:1;
+}
+
+.x-window-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    z-index:1;
+    position:relative;
+}
+
+.x-window-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+}
+
+.x-window-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-window-bc .x-window-footer {
+    padding-bottom:6px;
+    zoom:1;
+    font-size:0;
+    line-height:0;
+}
+
+.x-window-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-mc {
+    border:1px solid;
+    padding:0;
+    margin:0;
+}
+
+.x-window-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-body {
+    overflow:hidden;
+}
+
+.x-window-bwrap {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-bl, .x-window-maximized .x-window-br,
+    .x-window-maximized .x-window-ml, .x-window-maximized .x-window-mr,
+    .x-window-maximized .x-window-tl, .x-window-maximized .x-window-tr {
+    padding:0;
+}
+
+.x-window-maximized .x-window-footer {
+    padding-bottom:0;
+}
+
+.x-window-maximized .x-window-tc {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-window-maximized .x-window-mc {
+    border-left:0 none;
+    border-right:0 none;
+}
+
+.x-window-tbar .x-toolbar, .x-window-bbar .x-toolbar {
+    border-left:0 none;
+    border-right: 0 none;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}
+
+.x-window-draggable, .x-window-draggable .x-window-header-text {
+    cursor:move;
+}
+
+.x-window-maximized .x-window-draggable, .x-window-maximized .x-window-draggable .x-window-header-text {
+    cursor:default;
+}
+
+.x-window-body {
+    background-color:transparent;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-window-maximized-ct {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-handle {
+    display:none;
+}
+
+.x-window-sizing-ghost ul {
+    border:0 none !important;
+}
+
+.x-dlg-focus{
+	-moz-outline:0 none;
+	outline:0 none;
+	width:0;
+	height:0;
+	overflow:hidden;
+	position:absolute;
+	top:0;
+	left:0;
+}
+
+.ext-webkit .x-dlg-focus{
+    width: 1px;
+    height: 1px;
+}
+
+.x-dlg-mask{
+    z-index:10000;
+    display:none;
+    position:absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity:.50;
+    filter: alpha(opacity=50);
+}
+
+body.ext-ie6.x-body-masked select {
+	visibility:hidden;
+}
+
+body.ext-ie6.x-body-masked .x-window select {
+	visibility:visible;
+}
+
+.x-window-plain .x-window-mc {
+    border: 1px solid;
+}
+
+.x-window-plain .x-window-body {
+    border: 1px solid;
+    background:transparent !important;
+}.x-html-editor-wrap {
+    border:1px solid;
+}
+
+.x-html-editor-tb .x-btn-text {
+    background:transparent no-repeat;
+}
+
+.x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {
+    background-position:0 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);    
+}
+
+.x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {
+    background-position:-16px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {
+    background-position:-32px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {
+    background-position:-160px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-backcolor, .x-menu-item img.x-edit-backcolor {
+    background-position:-176px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyleft, .x-menu-item img.x-edit-justifyleft {
+    background-position:-112px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifycenter, .x-menu-item img.x-edit-justifycenter {
+    background-position:-128px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyright, .x-menu-item img.x-edit-justifyright {
+    background-position:-144px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertorderedlist, .x-menu-item img.x-edit-insertorderedlist {
+    background-position:-80px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertunorderedlist, .x-menu-item img.x-edit-insertunorderedlist {
+    background-position:-96px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-increasefontsize, .x-menu-item img.x-edit-increasefontsize {
+    background-position:-48px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-decreasefontsize, .x-menu-item img.x-edit-decreasefontsize {
+    background-position:-64px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-sourceedit, .x-menu-item img.x-edit-sourceedit {
+    background-position:-192px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-createlink, .x-menu-item img.x-edit-createlink {
+    background-position:-208px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {
+    padding:5px;
+    padding-bottom:1px;
+}
+
+.x-html-editor-tb .x-toolbar {
+    position:static !important;
+}.x-panel-noborder .x-panel-body-noborder {
+    border-width:0;
+}
+
+.x-panel-noborder .x-panel-header-noborder {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-width:1px 0 0 0;
+    border-style:solid;
+}
+
+.x-window-noborder .x-window-mc {
+    border-width:0;
+}
+
+.x-window-plain .x-window-body-noborder {
+    border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-body-noborder {
+	border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-header-noborder {
+    border-width: 0 0 1px 0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-footer-noborder {
+    border-width: 1px 0 0 0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-width: 1px 0 0 0;
+    border-style:solid;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}.x-border-layout-ct {
+    position: relative;
+}
+
+.x-border-panel {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-tool-collapse-south {
+    background-position:0 -195px;
+}
+
+.x-tool-collapse-south-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-collapse-north {
+    background-position:0 -210px;
+}
+
+.x-tool-collapse-north-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-collapse-west {
+    background-position:0 -180px;
+}
+
+.x-tool-collapse-west-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-collapse-east {
+    background-position:0 -165px;
+}
+
+.x-tool-collapse-east-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-south {
+    background-position:0 -210px;
+}
+
+.x-tool-expand-south-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-expand-north {
+    background-position:0 -195px;
+}
+.x-tool-expand-north-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-expand-west {
+    background-position:0 -165px;
+}
+
+.x-tool-expand-west-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-east {
+    background-position:0 -180px;
+}
+
+.x-tool-expand-east-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-expand-north, .x-tool-expand-south {
+    float:right;
+    margin:3px;
+}
+
+.x-tool-expand-east, .x-tool-expand-west {
+    float:none;
+    margin:3px 2px;
+}
+
+.x-accordion-hd .x-tool-toggle {
+    background-position:0 -255px;
+}
+
+.x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -255px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle {
+    background-position:0 -240px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -240px;
+}
+
+.x-accordion-hd {
+	padding-top:4px;
+	padding-bottom:3px;
+	border-top:0 none;
+    background: transparent repeat-x 0 -9px;
+}
+
+.x-layout-collapsed{
+    position:absolute;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+    width:20px;
+    height:20px;
+    overflow:hidden;
+	border:1px solid;
+	z-index:20;
+}
+
+.ext-border-box .x-layout-collapsed{
+    width:22px;
+    height:22px;
+}
+
+.x-layout-collapsed-over{
+    cursor:pointer;
+}
+
+.x-layout-collapsed-west .x-layout-collapsed-tools, .x-layout-collapsed-east .x-layout-collapsed-tools{
+	position:absolute;
+    top:0;
+    left:0;
+    width:20px;
+    height:20px;
+}
+
+
+.x-layout-split{
+    position:absolute;
+    height:5px;
+    width:5px;
+    line-height:1px;
+    font-size:1px;
+    z-index:3;
+    background-color:transparent;
+}
+
+/* IE6 strict won't drag w/out a color */
+.ext-strict .ext-ie6 .x-layout-split{
+    background-color: #fff !important;
+    filter: alpha(opacity=1);
+}
+
+.x-layout-split-h{
+    background-image:url(../images/default/s.gif);
+    background-position: left;
+}
+
+.x-layout-split-v{
+    background-image:url(../images/default/s.gif);
+    background-position: top;
+}
+
+.x-column-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column {
+    float:left;
+    padding:0;
+    margin:0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column-inner {
+    overflow:hidden;
+    zoom:1;
+}
+
+/* mini mode */
+.x-layout-mini {
+    position:absolute;
+    top:0;
+    left:0;
+    display:block;
+    width:5px;
+    height:35px;
+    cursor:pointer;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-layout-mini-over, .x-layout-collapsed-over .x-layout-mini{
+    opacity:1;
+    -moz-opacity:1;
+    filter:none;
+}
+
+.x-layout-split-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-split-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west, .x-layout-cmini-east {
+    border:0 none;
+    width:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-layout-cmini-north, .x-layout-cmini-south {
+    border:0 none;
+    height:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-viewport, .x-viewport body {
+    margin: 0;
+    padding: 0;
+    border: 0 none;
+    overflow: hidden;
+    height: 100%;
+}
+
+.x-abs-layout-item {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.ext-ie input.x-abs-layout-item, .ext-ie textarea.x-abs-layout-item {
+    margin:0;
+}
+
+.x-box-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-box-inner {
+    overflow:hidden;
+    zoom:1;
+    position:relative;
+    left:0;
+    top:0;
+}
+
+.x-box-item {
+    position:absolute;
+    left:0;
+    top:0;
+}.x-progress-wrap {
+    border:1px solid;
+    overflow:hidden;
+}
+
+.x-progress-inner {
+    height:18px;
+    background:repeat-x;
+    position:relative;
+}
+
+.x-progress-bar {
+    height:18px;
+    float:left;
+    width:0;
+    background: repeat-x left center;
+    border-top:1px solid;
+    border-bottom:1px solid;
+    border-right:1px solid;
+}
+
+.x-progress-text {
+    padding:1px 5px;
+    overflow:hidden;
+    position:absolute;
+    left:0;
+    text-align:center;
+}
+
+.x-progress-text-back {
+    line-height:16px;
+}
+
+.ext-ie .x-progress-text-back {
+    line-height:15px;
+}
+
+.ext-strict .ext-ie7 .x-progress-text-back{
+    width: 100%;
+}
+.x-list-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    height:22px;
+}
+
+.x-list-header-inner div {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.x-list-header-inner div em {
+    display:block;
+    border-left:1px solid;
+    padding:4px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    line-height:14px;
+}
+
+.x-list-body {
+    overflow:auto;
+    overflow-x:hidden;
+    overflow-y:auto;
+    zoom:1;
+    float: left;
+    width: 100%;
+}
+
+.x-list-body dl {
+    zoom:1;
+}
+
+.x-list-body dt {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor:pointer;
+    zoom:1;
+}
+
+.x-list-body dt em {
+    display:block;
+    padding:3px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+}
+
+.x-list-resizer {
+    border-left:1px solid;
+    border-right:1px solid;
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-list-header-inner em.sort-asc {
+    background: transparent no-repeat center 0;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+.x-list-header-inner em.sort-desc {
+    background: transparent no-repeat center -23px;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+/* Shared styles */
+.x-slider {
+    zoom:1;
+}
+
+.x-slider-inner {
+    position:relative;
+    left:0;
+    top:0;
+    overflow:visible;
+    zoom:1;
+}
+
+.x-slider-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+	display:block;
+	overflow:hidden;  
+}
+
+/* Horizontal styles */
+.x-slider-horz {
+    padding-left:7px;
+    background:transparent no-repeat 0 -22px;
+}
+
+.x-slider-horz .x-slider-end {
+    padding-right:7px;
+    zoom:1;
+    background:transparent no-repeat right -44px;
+}
+
+.x-slider-horz .x-slider-inner {
+    background:transparent repeat-x 0 0;
+    height:22px;
+}
+
+.x-slider-horz .x-slider-thumb {
+    width:14px;
+    height:15px;
+    position:absolute;
+    left:0;
+    top:3px;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-horz .x-slider-thumb-over {
+    background-position: -14px -15px;
+}
+
+.x-slider-horz .x-slider-thumb-drag {
+    background-position: -28px -30px;
+}
+
+/* Vertical styles */
+.x-slider-vert {
+    padding-top:7px;
+    background:transparent no-repeat -44px 0;
+    width:22px;
+}
+
+.x-slider-vert .x-slider-end {
+    padding-bottom:7px;
+    zoom:1;
+    background:transparent no-repeat -22px bottom;
+}
+
+.x-slider-vert .x-slider-inner {
+    background:transparent repeat-y 0 0;
+}
+
+.x-slider-vert .x-slider-thumb {
+    width:15px;
+    height:14px;
+    position:absolute;
+    left:3px;
+    bottom:0;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-vert .x-slider-thumb-over {
+    background-position: -15px -14px;
+}
+
+.x-slider-vert .x-slider-thumb-drag {
+    background-position: -30px -28px;
+}.x-window-dlg .x-window-body {
+    border:0 none !important;
+    padding:5px 10px;
+    overflow:hidden !important;
+}
+
+.x-window-dlg .x-window-mc {
+    border:0 none !important;
+}
+
+.x-window-dlg .ext-mb-input {
+    margin-top:4px;
+    width:95%;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    margin-top:4px;
+}
+
+.x-window-dlg .x-progress-wrap {
+    margin-top:4px;
+}
+
+.ext-ie .x-window-dlg .x-progress-wrap {
+    margin-top:6px;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background:transparent no-repeat left;
+    display:block;
+    width:300px;
+    padding-left:18px;
+    line-height:18px;
+}
+
+.x-window-dlg .ext-mb-icon {
+    float:left;
+    width:47px;
+    height:32px;
+}
+
+.x-window-dlg .x-dlg-icon .ext-mb-content{
+    zoom: 1; 
+    margin-left: 47px;
+}
+
+.x-window-dlg .ext-mb-info, .x-window-dlg .ext-mb-warning, .x-window-dlg .ext-mb-question, .x-window-dlg .ext-mb-error {
+    background:transparent no-repeat top left;
+}
+
+.ext-gecko2 .ext-mb-fix-cursor {
+    overflow:auto;
+}.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#6593cf;
+    background-color:#c3daf9;
+    background-image:url(../images/default/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#a3bad9;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #deecfd;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #deecfd;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#8db2e3;
+}
+
+ul.x-tab-strip-top{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-bg.gif);
+	border-bottom-color:#8db2e3;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#8db2e3;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#8db2e3;
+    background-color: #deecfd;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#416aa3;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#15428b;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#15428b;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/default/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#8db2e3;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/default/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/default/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}.x-form-field {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field {
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#b5b8c8;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #15428b;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger {
+    background-image:url(../images/default/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger {
+    background-image: url(../images/default/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger {
+    background-image: url(../images/default/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger {
+    background-image: url(../images/default/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    border-bottom-color:#7eadd9;
+}
+
+.x-item-disabled .x-form-trigger-over {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus {
+	border-color:#7eadd9;
+}
+
+.x-form-invalid, textarea.x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-invalid.x-form-composite {
+    border: none;
+    background-image: none;
+}
+
+.x-form-invalid.x-form-composite .x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#b5b8c8;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+}
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/default/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #3e6aaa;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}.x-toolbar{
+	border-color:#a9bfd3;
+    background-color:#d0def0;
+    background-image:url(../images/default/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
+{
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
+{
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-blue-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/default/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/refresh-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/default/toolbar/more.gif) !important;
+}.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/default/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/default/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/default/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/default/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/default/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#99bbe8;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+	font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#aaccf6;
+    border-right-color:#aaccf6;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#ebf3fd;
+    background-image:url(../images/default/grid/grid3-hrow-over.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#15428b;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/default/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+td.grid-hd-group-cell {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}
+
+.x-grid3-row-selected {
+	background-color: #dfe8f6 !important;
+	background-image: none;
+	border-color:#a3bae9;
+}
+
+.x-grid3-cell-selected{
+	background-color: #b8cfee !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#15428b !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c3daf9;
+    background-image:url(../images/default/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/default/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#99bbe8;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-collapse.gif);
+    color:#3764a0;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #d9e8fb;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}.x-date-picker {
+    border-color: #1b376c;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/default/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/default/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/default/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+	border-bottom-color:#a3bad9;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#233d6d;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#dfecfb;
+	background-image:url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#a3bad9;
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#ddecfe;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#15428b;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#15428b;
+	background-color: #ddecfe;
+}
+
+td.x-date-mp-sel a {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}.x-tip .x-tip-close{
+	background-image: url(../images/default/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/default/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);
+}.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#718bb7;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/default/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/default/menu/item-over.gif);
+	background-color: #dbecf4;
+    border-color:#aaccf6;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#aaccf6;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/default/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#f0f0f0 !important;
+    background-image: none;
+}
+
+.x-date-menu, .x-color-menu{
+    background-color: #fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}.x-combo-list {
+    border-color:#98c0f4;
+    background-color:#ddecfe;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#a3bae9 !important;
+    background-color:#dfe8f6;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}.x-panel {
+    border-color: #99bbe8;
+}
+
+.x-panel-header {
+    color:#15428b;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#99bbe8;
+    background-image: url(../images/default/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#99bbe8;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/default/panel/corners-sprite.gif);
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-bc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/default/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/default/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#cbddf3;
+}
+
+.x-panel-ghost ul {
+    border-color:#99bbe8;
+}
+
+.x-panel-dd-spacer {
+    border-color:#99bbe8;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#c7dffc;
+    border-color:#99bbe8;
+}
+
+.x-window-tl .x-window-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#99bbe8;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-window-ml {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#84a0c4;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+}.x-html-editor-wrap {
+    border-color:#a9bfd3;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}.x-border-layout-ct {
+    background-color:#dfe8f6;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/default/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#d2e0f2;
+	border-color:#98c0f4;
+}
+
+.x-layout-collapsed-over{
+    background-color:#d9e8fb;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}.x-progress-wrap {
+    border-color:#6593cf;
+}
+
+.x-progress-inner {
+    background-color:#e0e8f3;
+    background-image:url(../images/default/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#9cbfee;
+    background-image:url(../images/default/progress/progress-bg.gif);
+    border-top-color:#d1e4fd;
+    border-bottom-color:#7fa9e4;
+    border-right-color:#7fa9e4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#396095;
+}.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#dfe8f6;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/default/grid/sort-hd.gif);
+    border-color: #99bbe8;
+}.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-v-thumb.png);
+}.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/default/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/default/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/default/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/default/window/icon-error.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/layerlegend.css b/src/main/webapp/lib/ext-3.4.0/css/layerlegend.css
new file mode 100644
index 0000000000000000000000000000000000000000..b19c40f8ce05d6ad0168ebc86e0950425f22afd5
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/layerlegend.css
@@ -0,0 +1 @@
+.gx-ruledrag-insert-below{border-bottom:1px dotted;}.gx-ruledrag-insert-above{border-top:1px dotted;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/popup.css b/src/main/webapp/lib/ext-3.4.0/css/popup.css
new file mode 100644
index 0000000000000000000000000000000000000000..8d17a7b350b1b7c19e39188d02bd6a6c4fb1b5c1
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/popup.css
@@ -0,0 +1 @@
+.gx-popup-anc{background:transparent url(../images/default/anchor.png) no-repeat 0 0;position:absolute;left:5px;z-index:2;height:16px;width:31px;pointer-events:none;}.gx-popup-anc.top{background:transparent url(../images/default/anchor-top.png) no-repeat 0 0;top:-16px;}.gx-popup-anc.right{left:auto;right:5px;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/reset-min.css b/src/main/webapp/lib/ext-3.4.0/css/reset-min.css
new file mode 100644
index 0000000000000000000000000000000000000000..f503196be0dc6094287631e95755f5da6c36fbed
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/reset-min.css
@@ -0,0 +1,7 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/borders.css b/src/main/webapp/lib/ext-3.4.0/css/structure/borders.css
new file mode 100644
index 0000000000000000000000000000000000000000..61512a33d5b6912848fca96bad0a152bb4e1846d
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/borders.css
@@ -0,0 +1,54 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel-noborder .x-panel-body-noborder {
+    border-width:0;
+}
+
+.x-panel-noborder .x-panel-header-noborder {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-width:1px 0 0 0;
+    border-style:solid;
+}
+
+.x-window-noborder .x-window-mc {
+    border-width:0;
+}
+
+.x-window-plain .x-window-body-noborder {
+    border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-body-noborder {
+	border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-header-noborder {
+    border-width: 0 0 1px 0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-footer-noborder {
+    border-width: 1px 0 0 0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-width: 1px 0 0 0;
+    border-style:solid;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/box.css b/src/main/webapp/lib/ext-3.4.0/css/structure/box.css
new file mode 100644
index 0000000000000000000000000000000000000000..f65830428828dd8dc13093cbeead6f3e15b18747
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/box.css
@@ -0,0 +1,80 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/*
+ Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:
+  <div class="x-box-blue">
+        <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>
+        <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">
+            <h3>YOUR TITLE HERE (optional)</h3>
+            <div>YOUR CONTENT HERE</div>
+        </div></div></div>
+        <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
+    </div>
+ */
+
+.x-box-tl {
+	background: transparent no-repeat 0 0;
+    zoom:1;
+}
+
+.x-box-tc {
+	height: 8px;
+	background: transparent repeat-x 0 0;
+	overflow: hidden;
+}
+
+.x-box-tr {
+	background: transparent no-repeat right -8px;
+}
+
+.x-box-ml {
+	background: transparent repeat-y 0;
+	padding-left: 4px;
+	overflow: hidden;
+    zoom:1;
+}
+
+.x-box-mc {
+	background: repeat-x 0 -16px;
+	padding: 4px 10px;
+}
+
+.x-box-mc h3 {
+	margin: 0 0 4px 0;
+    zoom:1;
+}
+
+.x-box-mr {
+	background: transparent repeat-y right;
+	padding-right: 4px;
+	overflow: hidden;
+}
+
+.x-box-bl {
+	background: transparent no-repeat 0 -16px;
+    zoom:1;
+}
+
+.x-box-bc {
+	background: transparent repeat-x 0 -8px;
+	height: 8px;
+	overflow: hidden;
+}
+
+.x-box-br {
+	background: transparent no-repeat right -24px;
+}
+
+.x-box-tl, .x-box-bl {
+	padding-left: 8px;
+	overflow: hidden;
+}
+
+.x-box-tr, .x-box-br {
+	padding-right: 8px;
+	overflow: hidden;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/button.css b/src/main/webapp/lib/ext-3.4.0/css/structure/button.css
new file mode 100644
index 0000000000000000000000000000000000000000..fb8cdc289f0e9333347aa669c7485a03bc70e27c
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/button.css
@@ -0,0 +1,445 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-btn{
+	cursor:pointer;
+	white-space: nowrap;
+}
+
+.x-btn button{
+    border:0 none;
+    background-color:transparent;
+    padding-left:3px;
+    padding-right:3px;
+    cursor:pointer;
+    margin:0;
+    overflow:visible;
+    width:auto;
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+* html .ext-ie .x-btn button {
+    width:1px;
+}
+
+.ext-gecko .x-btn button, .ext-webkit .x-btn button {
+    padding-left:0;
+    padding-right:0;
+}
+
+.ext-gecko .x-btn button::-moz-focus-inner {
+    padding:0;
+}
+
+.ext-ie .x-btn button {
+    padding-top:2px;
+}
+
+.x-btn td {
+    padding:0 !important;
+}
+
+.x-btn-text {
+    cursor:pointer;
+	white-space: nowrap;
+    padding:0;
+}
+
+/* icon placement and sizing styles */
+
+/* Only text */
+.x-btn-noicon .x-btn-small .x-btn-text{
+	height: 16px;
+}
+
+.x-btn-noicon .x-btn-medium .x-btn-text{
+    height: 24px;
+}
+
+.x-btn-noicon .x-btn-large .x-btn-text{
+    height: 32px;
+}
+
+/* Only icons */
+.x-btn-icon .x-btn-text{
+    background-position: center;
+	background-repeat: no-repeat;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 16px;
+}
+
+.x-btn-icon .x-btn-medium .x-btn-text{
+    height: 24px;
+	width: 24px;
+}
+
+.x-btn-icon .x-btn-large .x-btn-text{
+    height: 32px;
+	width: 32px;
+}
+
+/* Icons and text */
+/* left */
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:34px;
+    height:32px;
+}
+
+/* top */
+.x-btn-text-icon .x-btn-icon-small-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:34px;
+}
+
+/* right */
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:34px;
+    height:32px;
+}
+
+/* bottom */
+.x-btn-text-icon .x-btn-icon-small-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:34px;
+}
+
+/* background positioning */
+.x-btn-tr i, .x-btn-tl i, .x-btn-mr i, .x-btn-ml i, .x-btn-br i, .x-btn-bl i{
+	font-size:1px;
+    line-height:1px;
+    width:3px;
+    display:block;
+    overflow:hidden;
+}
+
+.x-btn-tr i, .x-btn-tl i, .x-btn-br i, .x-btn-bl i{
+	height:3px;
+}
+
+.x-btn-tl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 0;
+}
+.x-btn-tr{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px 0;
+}
+.x-btn-tc{
+	height:3px;
+	background:repeat-x 0 -6px;
+}
+
+.x-btn-ml{
+	width:3px;
+	background:no-repeat 0 -24px;
+}
+.x-btn-mr{
+	width:3px;
+	background:no-repeat -3px -24px;
+}
+
+.x-btn-mc{
+	background:repeat-x 0 -1096px;
+    vertical-align: middle;
+	text-align:center;
+	padding:0 5px;
+	cursor:pointer;
+	white-space:nowrap;
+}
+
+/* Fixes an issue with the button height */
+.ext-strict .ext-ie6 .x-btn-mc, .ext-strict .ext-ie7 .x-btn-mc {
+    height: 100%;
+}
+
+.x-btn-bl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 -3px;
+}
+
+.x-btn-br{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px -3px;
+}
+
+.x-btn-bc{
+	height:3px;
+	background:repeat-x 0 -15px;
+}
+
+.x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-btn-click .x-btn-tl, .x-btn-menu-active .x-btn-tl, .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-btn-click .x-btn-tr, .x-btn-menu-active .x-btn-tr, .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-btn-click .x-btn-tc, .x-btn-menu-active .x-btn-tc, .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-btn-click .x-btn-ml, .x-btn-menu-active .x-btn-ml, .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-btn-click .x-btn-mr, .x-btn-menu-active .x-btn-mr, .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-btn-click .x-btn-mc, .x-btn-menu-active .x-btn-mc, .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-btn-click .x-btn-bl, .x-btn-menu-active .x-btn-bl, .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-btn-click .x-btn-br, .x-btn-menu-active .x-btn-br, .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-btn-click .x-btn-bc, .x-btn-menu-active .x-btn-bc, .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-btn-disabled *{
+	cursor:default !important;
+}
+
+
+/* With a menu arrow */
+/* right */
+.x-btn-mc em.x-btn-arrow {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:10px;
+}
+
+.x-btn-mc em.x-btn-split {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:14px;
+}
+
+/* bottom */
+.x-btn-mc em.x-btn-arrow-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+/* height adjustment class */
+.x-btn-as-arrow .x-btn-mc em {
+    display:block;
+    background-color:transparent;
+	padding-bottom:14px;
+}
+
+/* groups */
+.x-btn-group {
+    padding:1px;
+}
+
+.x-btn-group-header {
+    padding:2px;
+    text-align:center;
+}
+
+.x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+.x-btn-group-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:3px;
+}
+
+.x-btn-group-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-btn-group-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-br {
+	background: transparent no-repeat right bottom;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-mc {
+    border:0 none;
+    padding:1px 0 0 0;
+    margin:0;
+}
+
+.x-btn-group-mc .x-btn-group-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-btn-group-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-mr {
+	background: transparent repeat-y right 0;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-btn-group-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-btn-group-bc {
+	height:3px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-btn-group-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    height:2px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/combo.css b/src/main/webapp/lib/ext-3.4.0/css/structure/combo.css
new file mode 100644
index 0000000000000000000000000000000000000000..3edeea1b80d06de6fb2c89acf01c18e4a13cefc7
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/combo.css
@@ -0,0 +1,45 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-combo-list {
+    border:1px solid;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-combo-list-inner {
+    overflow:auto;
+    position:relative; /* for calculating scroll offsets */
+    zoom:1;
+    overflow-x:hidden;
+}
+
+.x-combo-list-hd {
+    border-bottom:1px solid;
+    padding:3px;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom:1px solid;
+}
+
+.x-combo-list-item {
+    padding:2px;
+    border:1px solid;
+    white-space: nowrap;
+    overflow:hidden;
+    text-overflow: ellipsis;
+}
+
+.x-combo-list .x-combo-selected{
+	border:1px dotted !important;
+    cursor:pointer;
+}
+
+.x-combo-list .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/core.css b/src/main/webapp/lib/ext-3.4.0/css/structure/core.css
new file mode 100644
index 0000000000000000000000000000000000000000..caf75a3b4bf941d8d1d8b7e4523858b22962ffdb
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/core.css
@@ -0,0 +1,341 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    z-index: 100;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width: 100%;
+    height: 100%;
+    zoom: 1;
+}
+
+.ext-el-mask-msg {
+    z-index: 20001;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border:1px solid;
+    background:repeat-x 0 -16px;
+    padding:2px;
+}
+
+.ext-el-mask-msg div {
+    padding:5px 10px 5px 10px;
+    border:1px solid;
+    cursor:wait;
+}
+
+.ext-shim {
+    position:absolute;
+    visibility:hidden;
+    left:0;
+    top:0;
+    overflow:hidden;
+}
+
+.ext-ie .ext-shim {
+    filter: alpha(opacity=0);
+}
+
+.ext-ie6 .ext-shim {
+    margin-left: 5px;
+    margin-top: 3px;
+}
+
+.x-mask-loading div {
+    padding:5px 10px 5px 25px;
+    background:no-repeat 5px 5px;
+    line-height:16px;
+}
+
+/* class for hiding elements without using display:none */
+.x-hidden, .x-hide-offsets {
+    position:absolute !important;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+}
+
+.x-hide-display {
+    display:none !important;
+}
+
+.x-hide-nosize,
+.x-hide-nosize *    /* Emulate display:none for children */
+ {
+   height:0px!important;
+   width:0px!important;
+   visibility:hidden!important;
+   border:none!important;
+   zoom:1;
+}
+
+.x-hide-visibility {
+    visibility:hidden !important;
+}
+
+.x-masked {
+    overflow: hidden !important;
+}
+.x-masked-relative {
+    position: relative !important;
+}
+
+.x-masked select, .x-masked object, .x-masked embed {
+    visibility: hidden;
+}
+
+.x-layer {
+    visibility: hidden;
+}
+
+.x-unselectable, .x-unselectable * {
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-repaint {
+    zoom: 1;
+    background-color: transparent;
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-item-disabled {
+    cursor: default;
+    opacity: .6;
+    -moz-opacity: .6;
+    filter: alpha(opacity=60);
+}
+
+.x-item-disabled * {
+    cursor: default !important;
+}
+
+.x-form-radio-group .x-item-disabled {
+    filter: none;
+}
+
+.x-splitbar-proxy {
+    position: absolute;
+    visibility: hidden;
+    z-index: 20001;
+    zoom: 1;
+    line-height: 1px;
+    font-size: 1px;
+    overflow: hidden;
+}
+
+.x-splitbar-h, .x-splitbar-proxy-h {
+    cursor: e-resize;
+    cursor: col-resize;
+}
+
+.x-splitbar-v, .x-splitbar-proxy-v {
+    cursor: s-resize;
+    cursor: row-resize;
+}
+
+.x-color-palette {
+    width: 150px;
+    height: 92px;
+    cursor: pointer;
+}
+
+.x-color-palette a {
+    border: 1px solid;
+    float: left;
+    padding: 2px;
+    text-decoration: none;
+    -moz-outline: 0 none;
+    outline: 0 none;
+    cursor: pointer;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border: 1px solid;
+}
+
+.x-color-palette em {
+    display: block;
+    border: 1px solid;
+}
+
+.x-color-palette em span {
+    cursor: pointer;
+    display: block;
+    height: 10px;
+    line-height: 10px;
+    width: 10px;
+}
+
+.x-ie-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+    zoom:1;
+}
+
+.x-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+}
+
+.x-shadow * {
+    overflow: hidden;
+}
+
+.x-shadow * {
+    padding: 0;
+    border: 0;
+    margin: 0;
+    clear: none;
+    zoom: 1;
+}
+
+/* top  bottom */
+.x-shadow .xstc, .x-shadow .xsbc {
+    height: 6px;
+    float: left;
+}
+
+/* corners */
+.x-shadow .xstl, .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbr {
+    width: 6px;
+    height: 6px;
+    float: left;
+}
+
+/* sides */
+.x-shadow .xsc {
+    width: 100%;
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    width: 6px;
+    float: left;
+    height: 100%;
+}
+
+.x-shadow .xsmc {
+    float: left;
+    height: 100%;
+    background-color: transparent;
+}
+
+.x-shadow .xst, .x-shadow .xsb {
+    height: 6px;
+    overflow: hidden;
+    width: 100%;
+}
+
+.x-shadow .xsml {
+    background: transparent repeat-y 0 0;
+}
+
+.x-shadow .xsmr {
+    background: transparent repeat-y -6px 0;
+}
+
+.x-shadow .xstl {
+    background: transparent no-repeat 0 0;
+}
+
+.x-shadow .xstc {
+    background: transparent repeat-x 0 -30px;
+}
+
+.x-shadow .xstr {
+    background: transparent repeat-x 0 -18px;
+}
+
+.x-shadow .xsbl {
+    background: transparent no-repeat 0 -12px;
+}
+
+.x-shadow .xsbc {
+    background: transparent repeat-x 0 -36px;
+}
+
+.x-shadow .xsbr {
+    background: transparent repeat-x 0 -6px;
+}
+
+.loading-indicator {
+    background: no-repeat left;
+    padding-left: 20px;
+    line-height: 16px;
+    margin: 3px;
+}
+
+.x-text-resize {
+    position: absolute;
+    left: -1000px;
+    top: -1000px;
+    visibility: hidden;
+    zoom: 1;
+}
+
+.x-drag-overlay {
+    width: 100%;
+    height: 100%;
+    display: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    background-image:url(../images/default/s.gif);
+    z-index: 20000;
+}
+
+.x-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.x-spotlight {
+    z-index: 8999;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width:0;
+    height:0;
+    zoom: 1;
+}
+
+#x-history-frame {
+    position:absolute;
+    top:-1px;
+    left:0;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+
+#x-history-field {
+    position:absolute;
+    top:0;
+    left:-1px;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/date-picker.css b/src/main/webapp/lib/ext-3.4.0/css/structure/date-picker.css
new file mode 100644
index 0000000000000000000000000000000000000000..8d5f409442154957470d4ba9aed8cba92f3eab21
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/date-picker.css
@@ -0,0 +1,271 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-date-picker {
+    border: 1px solid;
+    border-top:0 none;
+	position:relative;
+}
+
+.x-date-picker a {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+.x-date-inner, .x-date-inner td, .x-date-inner th{
+    border-collapse:separate;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background: repeat-x 0 -83px;
+	overflow:hidden;
+}
+
+.x-date-middle .x-btn-tc,.x-date-middle .x-btn-tl,.x-date-middle .x-btn-tr,
+.x-date-middle .x-btn-mc,.x-date-middle .x-btn-ml,.x-date-middle .x-btn-mr,
+.x-date-middle .x-btn-bc,.x-date-middle .x-btn-bl,.x-date-middle .x-btn-br{
+	background:transparent !important;
+    vertical-align:middle;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background:transparent no-repeat right 0;
+}
+
+.x-date-right, .x-date-left {
+    width:18px;
+}
+
+.x-date-right{
+    text-align:right;
+}
+
+.x-date-middle {
+    padding-top:2px;
+    padding-bottom:2px;
+    width:130px; /* FF3 */
+}
+
+.x-date-right a, .x-date-left a{
+    display:block;
+    width:16px;
+	height:16px;
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor:pointer;
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a:hover, .x-date-left a:hover{
+    -moz-opacity: 1;
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+
+.x-item-disabled .x-date-right a:hover, .x-item-disabled .x-date-left a:hover{
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a {
+    margin-right:2px;
+    text-decoration:none !important;
+}
+
+.x-date-left a{
+    margin-left:2px;
+    text-decoration:none !important;
+}
+
+table.x-date-inner {
+    width: 100%;
+    table-layout:fixed;
+}
+
+.ext-webkit table.x-date-inner{
+    /* Fix for webkit browsers */
+    width: 175px;
+}
+
+
+.x-date-inner th {
+    width:25px;
+}
+
+.x-date-inner th {
+    background: repeat-x left top;
+    text-align:right !important;
+	border-bottom: 1px solid;
+	cursor:default;
+    padding:0;
+    border-collapse:separate;
+}
+
+.x-date-inner th span {
+    display:block;
+    padding:2px;
+    padding-right:7px;
+}
+
+.x-date-inner td {
+    border: 1px solid;
+	text-align:right;
+    padding:0;
+}
+
+.x-date-inner a {
+    padding:2px 5px;
+    display:block;
+	text-decoration:none;
+    text-align:right;
+    zoom:1;
+}
+
+.x-date-inner .x-date-active{
+	cursor:pointer;
+	color:black;
+}
+
+.x-date-inner .x-date-selected a{
+	background: repeat-x left top;
+	border:1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-today a{
+	border: 1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+    text-decoration:none !important;
+}
+
+.x-date-bottom {
+    padding:4px;
+    border-top: 1px solid;
+    background: repeat-x left top;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    text-decoration:none !important;
+}
+
+.x-item-disabled .x-date-inner a:hover{
+    background: none;
+}
+
+.x-date-inner .x-date-disabled a {
+	cursor:default;
+}
+
+.x-date-menu .x-menu-item {
+	padding:1px 24px 1px 4px;
+	white-space: nowrap;
+}
+
+.x-date-menu .x-menu-item .x-menu-item-icon {
+    width:10px;
+    height:10px;
+    margin-right:5px;
+    background-position:center -4px !important;
+}
+
+.x-date-mp {
+	position:absolute;
+	left:0;
+	top:0;
+	display:none;
+}
+
+.x-date-mp td {
+    padding:2px;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+td.x-date-mp-month,td.x-date-mp-year,td.x-date-mp-ybtn {
+    border: 0 none;
+	text-align:center;
+	vertical-align: middle;
+	width:25%;
+}
+
+.x-date-mp-ok {
+	margin-right:3px;
+}
+
+.x-date-mp-btns button {
+	text-decoration:none;
+	text-align:center;
+	text-decoration:none !important;
+	border:1px solid;
+	padding:1px 3px 1px;
+	cursor:pointer;
+}
+
+.x-date-mp-btns {
+	background: repeat-x left top;
+}
+
+.x-date-mp-btns td {
+	border-top: 1px solid;
+    text-align:center;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	display:block;
+	padding:2px 4px;
+	text-decoration:none;
+	text-align:center;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	text-decoration:none;
+	cursor:pointer;
+}
+
+td.x-date-mp-sel a {
+	padding:1px 3px;
+	background: repeat-x left top;
+	border:1px solid;
+}
+
+.x-date-mp-ybtn a {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    cursor:pointer;
+    background:transparent no-repeat;
+    display:block;
+    margin:0 auto;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next {
+    background-position:0 -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next:hover {
+    background-position:-15px -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev {
+    background-position:0 -105px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev:hover {
+    background-position:-15px -105px;
+}
+
+.x-date-mp-ybtn {
+   text-align:center;
+}
+
+td.x-date-mp-sep {
+   border-right:1px solid;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/dd.css b/src/main/webapp/lib/ext-3.4.0/css/structure/dd.css
new file mode 100644
index 0000000000000000000000000000000000000000..6a5a6c34b26819d01099f672cee877da2745986f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/dd.css
@@ -0,0 +1,61 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-dd-drag-proxy{
+	position:absolute;
+	left:0;
+    top:0;
+	visibility:hidden;
+	z-index:15000;
+}
+
+.x-dd-drag-ghost{
+	-moz-opacity: 0.85;
+    opacity:.85;
+    filter: alpha(opacity=85);
+    border: 1px solid;
+	padding:3px;
+	padding-left:20px;
+	white-space:nowrap;
+}
+
+.x-dd-drag-repair .x-dd-drag-ghost{
+	-moz-opacity: 0.4;
+    opacity:.4;
+    filter: alpha(opacity=40);
+	border:0 none;
+	padding:0;
+	background-color:transparent;
+}
+
+.x-dd-drag-repair .x-dd-drop-icon{
+	visibility:hidden;
+}
+
+.x-dd-drop-icon{
+    position:absolute;
+	top:3px;
+	left:3px;
+	display:block;
+	width:16px;
+	height:16px;
+	background-color:transparent;
+	background-position: center;
+	background-repeat: no-repeat;
+	z-index:1;
+}
+
+.x-view-selector {
+    position:absolute;
+    left:0;
+    top:0;
+    width:0;
+    border:1px dotted;
+	opacity: .5;
+    -moz-opacity: .5;
+    filter:alpha(opacity=50);
+    zoom:1;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/debug.css b/src/main/webapp/lib/ext-3.4.0/css/structure/debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..9c18de97ed5b9ef4afbe6409c309cf250b1267e7
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/debug.css
@@ -0,0 +1,26 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+#x-debug-browser .x-tree .x-tree-node a span {
+    padding-top:2px;
+    line-height:18px;
+}
+
+#x-debug-browser  .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+#x-debug-browser  .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+#x-debug-browser.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -60px;
+}
+
+#x-debug-browser.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -60px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/dialog.css b/src/main/webapp/lib/ext-3.4.0/css/structure/dialog.css
new file mode 100644
index 0000000000000000000000000000000000000000..09092019d50e0f0432be566f7bd075571ebaadaf
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/dialog.css
@@ -0,0 +1,59 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-dlg .x-window-body {
+    border:0 none !important;
+    padding:5px 10px;
+    overflow:hidden !important;
+}
+
+.x-window-dlg .x-window-mc {
+    border:0 none !important;
+}
+
+.x-window-dlg .ext-mb-input {
+    margin-top:4px;
+    width:95%;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    margin-top:4px;
+}
+
+.x-window-dlg .x-progress-wrap {
+    margin-top:4px;
+}
+
+.ext-ie .x-window-dlg .x-progress-wrap {
+    margin-top:6px;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background:transparent no-repeat left;
+    display:block;
+    width:300px;
+    padding-left:18px;
+    line-height:18px;
+}
+
+.x-window-dlg .ext-mb-icon {
+    float:left;
+    width:47px;
+    height:32px;
+}
+
+.x-window-dlg .x-dlg-icon .ext-mb-content{
+    zoom: 1; 
+    margin-left: 47px;
+}
+
+.x-window-dlg .ext-mb-info, .x-window-dlg .ext-mb-warning, .x-window-dlg .ext-mb-question, .x-window-dlg .ext-mb-error {
+    background:transparent no-repeat top left;
+}
+
+.ext-gecko2 .ext-mb-fix-cursor {
+    overflow:auto;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/editor.css b/src/main/webapp/lib/ext-3.4.0/css/structure/editor.css
new file mode 100644
index 0000000000000000000000000000000000000000..dd5840a8b05a182902c43f1c198b185cf6fcc050
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/editor.css
@@ -0,0 +1,92 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-html-editor-wrap {
+    border:1px solid;
+}
+
+.x-html-editor-tb .x-btn-text {
+    background:transparent no-repeat;
+}
+
+.x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {
+    background-position:0 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);    
+}
+
+.x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {
+    background-position:-16px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {
+    background-position:-32px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {
+    background-position:-160px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-backcolor, .x-menu-item img.x-edit-backcolor {
+    background-position:-176px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyleft, .x-menu-item img.x-edit-justifyleft {
+    background-position:-112px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifycenter, .x-menu-item img.x-edit-justifycenter {
+    background-position:-128px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyright, .x-menu-item img.x-edit-justifyright {
+    background-position:-144px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertorderedlist, .x-menu-item img.x-edit-insertorderedlist {
+    background-position:-80px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertunorderedlist, .x-menu-item img.x-edit-insertunorderedlist {
+    background-position:-96px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-increasefontsize, .x-menu-item img.x-edit-increasefontsize {
+    background-position:-48px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-decreasefontsize, .x-menu-item img.x-edit-decreasefontsize {
+    background-position:-64px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-sourceedit, .x-menu-item img.x-edit-sourceedit {
+    background-position:-192px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-createlink, .x-menu-item img.x-edit-createlink {
+    background-position:-208px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {
+    padding:5px;
+    padding-bottom:1px;
+}
+
+.x-html-editor-tb .x-toolbar {
+    position:static !important;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/form.css b/src/main/webapp/lib/ext-3.4.0/css/structure/form.css
new file mode 100644
index 0000000000000000000000000000000000000000..9e7684bfd4f38e3713e7f8509c6de38bb090746c
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/form.css
@@ -0,0 +1,597 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/* all fields */
+.x-form-field{
+    margin: 0 0 0 0;
+}
+
+.ext-webkit *:focus{
+    outline: none !important;
+}
+
+/* ---- text fields ---- */
+.x-form-text, textarea.x-form-field{
+    padding:1px 3px;
+    background:repeat-x 0 0;
+    border:1px solid;
+}
+
+textarea.x-form-field {
+    padding:2px 3px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:22px;
+    line-height:18px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-form-text, .ext-ie7 .x-form-text {
+    margin:-1px 0; /* ie bogus margin bug */
+    height:22px; /* ie quirks */
+    line-height:18px;
+}
+
+.x-quirks .ext-ie9 .x-form-text {
+    height: 22px;
+    padding-top: 3px;
+    padding-bottom: 0px;
+}
+
+/* Ugly hacks for the bogus 1px margin bug in IE9 quirks */
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-text,
+.x-quirks .ext-ie9 .x-form-field-trigger-wrap .x-form-text {
+    margin-top: -1px;
+    margin-bottom: -1px;
+}
+.x-quirks .ext-ie9 .x-input-wrapper .x-form-element {
+    margin-bottom: -1px;
+}
+
+.ext-ie6 .x-form-field-wrap .x-form-file-btn, .ext-ie7 .x-form-field-wrap .x-form-file-btn {
+    top: -1px; /* because of all these margin hacks, these buttons are off by one pixel in IE6,7 */
+}
+
+.ext-ie6 textarea.x-form-field, .ext-ie7 textarea.x-form-field {
+    margin:-1px 0; /* ie bogus margin bug */
+}
+
+.ext-strict .x-form-text {
+    height:18px;
+}
+
+.ext-safari.ext-mac textarea.x-form-field {
+    margin-bottom:-2px; /* another bogus margin bug, safari/mac only */
+}
+
+/*
+.ext-strict .ext-ie8 .x-form-text, .ext-strict .ext-ie8 textarea.x-form-field {
+    margin-bottom: 1px;
+}
+*/
+
+.ext-gecko .x-form-text , .ext-ie8 .x-form-text {
+    padding-top:2px; /* FF won't center the text vertically */
+    padding-bottom:0;
+}
+
+.ext-ie6 .x-form-composite .x-form-text.x-box-item, .ext-ie7 .x-form-composite .x-form-text.x-box-item {
+    margin: 0 !important; /* clear ie bogus margin bug fix */
+}
+
+textarea {
+    resize: none;  /* Disable browser resizable textarea */
+}
+
+/* select boxes */
+.x-form-select-one {
+    height:20px;
+    line-height:18px;
+    vertical-align:middle;
+    border: 1px solid;
+}
+
+/* multi select boxes */
+
+/* --- TODO --- */
+
+/* 2.0.2 style */
+.x-form-check-wrap {
+    line-height:18px;
+    height: auto;
+}
+
+.ext-ie .x-form-check-wrap input {
+    width:15px;
+    height:15px;
+}
+
+.x-form-check-wrap input{
+    vertical-align: bottom;
+}
+
+.x-editor .x-form-check-wrap {
+    padding:3px;
+}
+
+.x-editor .x-form-checkbox {
+    height:13px;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid;
+    margin-bottom: 5px;
+    padding-left: 3px !important;
+    float: none !important;
+}
+
+/* wrapped fields and triggers */
+.x-form-field-wrap .x-form-trigger{
+    width:17px;
+    height:21px;
+    border:0;
+    background:transparent no-repeat 0 0;
+    cursor:pointer;
+    border-bottom: 1px solid;
+    position:absolute;
+    top:0;
+}
+
+.x-form-field-wrap .x-form-date-trigger, .x-form-field-wrap .x-form-clear-trigger, .x-form-field-wrap .x-form-search-trigger{
+    cursor:pointer;
+}
+
+.x-form-field-wrap .x-form-twin-triggers .x-form-trigger{
+    position:static;
+    top:auto;
+    vertical-align:top;
+}
+
+.x-form-field-wrap {
+    position:relative;
+    left:0;top:0;
+    text-align: left;
+    zoom:1;
+    white-space: nowrap;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {
+    right: 0; /* IE8 Strict mode trigger bug */
+}
+
+.x-form-field-wrap .x-form-trigger-over{
+    background-position:-17px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click{
+    background-position:-34px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    background-position:-51px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over{
+    background-position:-68px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click{
+    background-position:-85px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-trigger-noedit{
+    cursor:pointer;
+}
+
+/* field focus style */
+.x-form-focus, textarea.x-form-focus{
+    border: 1px solid;
+}
+
+/* invalid fields */
+.x-form-invalid, textarea.x-form-invalid{
+    background:repeat-x bottom;
+    border: 1px solid;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background:repeat-x bottom;
+}
+
+/* editors */
+.x-editor {
+    visibility:hidden;
+    padding:0;
+    margin:0;
+}
+
+.x-form-grow-sizer {
+    left: -10000px;
+    padding: 8px 3px;
+    position: absolute;
+    visibility:hidden;
+    top: -10000px;
+    white-space: pre-wrap;
+    white-space: -moz-pre-wrap;
+    white-space: -pre-wrap;
+    white-space: -o-pre-wrap;
+    word-wrap: break-word;
+    zoom:1;
+}
+
+.x-form-grow-sizer p {
+    margin:0 !important;
+    border:0 none !important;
+    padding:0 !important;
+}
+
+/* Form Items CSS */
+
+.x-form-item {
+    display:block;
+    margin-bottom:4px;
+    zoom:1;
+}
+
+.x-form-item label.x-form-item-label {
+    display:block;
+    float:left;
+    width:100px;
+    padding:3px;
+    padding-left:0;
+    clear:left;
+    z-index:2;
+    position:relative;
+}
+
+.x-form-element {
+    padding-left:105px;
+    position:relative;
+}
+
+.x-form-invalid-msg {
+    padding:2px;
+    padding-left:18px;
+    background: transparent no-repeat 0 2px;
+    line-height:16px;
+    width:200px;
+}
+
+.x-form-label-left label.x-form-item-label {
+   text-align:left;
+}
+
+.x-form-label-right label.x-form-item-label {
+   text-align:right;
+}
+
+.x-form-label-top .x-form-item label.x-form-item-label {
+    width:auto;
+    float:none;
+    clear:none;
+    display:inline;
+    margin-bottom:4px;
+    position:static;
+}
+
+.x-form-label-top .x-form-element {
+    padding-left:0;
+    padding-top:4px;
+}
+
+.x-form-label-top .x-form-item {
+    padding-bottom:4px;
+}
+
+/* Editor small font for grid, toolbar and tree */
+.x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    margin-top:-1px !important; /* ie bogus margin bug */
+    margin-bottom:-1px !important;
+    height:20px !important; /* ie quirks */
+    line-height:16px !important;
+}
+
+.ext-strict .x-small-editor .x-form-text {
+    height:16px !important;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+}
+
+.ext-border-box .x-small-editor .x-form-text {
+    height:20px;
+}
+
+.x-small-editor .x-form-select-one {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.x-small-editor .x-form-num-field {
+    text-align:right;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger{
+    height:19px;
+}
+
+.ext-webkit .x-small-editor .x-form-text{padding-top:3px;font-size:100%;}
+
+.ext-strict .ext-webkit .x-small-editor .x-form-text{
+    height:14px !important;
+}
+
+.x-form-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+.x-form-clear-left {
+    clear:left;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.ext-ie6 .x-form-check-wrap input, .ext-border-box .x-form-check-wrap input{
+   margin-top: 3px;
+}
+
+.x-form-cb-label {
+    position: relative;
+    margin-left:4px;
+    top: 2px;
+}
+
+.ext-ie .x-form-cb-label{
+    top: 1px;
+}
+
+.ext-ie6 .x-form-cb-label, .ext-border-box .x-form-cb-label{
+    top: 3px;
+}
+
+.x-form-display-field{
+    padding-top: 2px;
+}
+
+.ext-gecko .x-form-display-field, .ext-strict .ext-ie7 .x-form-display-field{
+    padding-top: 1px;
+}
+
+.ext-ie .x-form-display-field{
+    padding-top: 3px;
+}
+
+.ext-strict .ext-ie8 .x-form-display-field{
+    padding-top: 0;
+}
+
+.x-form-column {
+    float:left;
+    padding:0;
+    margin:0;
+    width:48%;
+    overflow:hidden;
+    zoom:1;
+}
+
+/* buttons */
+.x-form .x-form-btns-ct .x-btn{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns td {
+    border:0;
+    padding:0;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-right table{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-left table{
+    float:left;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center{
+    text-align:center; /*ie*/
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center table{
+    margin:0 auto; /*everyone else*/
+}
+
+.x-form .x-form-btns-ct table td.x-form-btn-td{
+    padding:3px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-left{
+    background-position:0 -147px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-right{
+    background-position:0 -168px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-center{
+    background-position:0 -189px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-center{
+    background-position:0 -126px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click  .x-btn-right{
+    background-position:0 -84px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-left{
+    background-position:0 -63px;
+}
+
+.x-form-invalid-icon {
+    width:16px;
+    height:18px;
+    visibility:hidden;
+    position:absolute;
+    left:0;
+    top:0;
+    display:block;
+    background:transparent no-repeat 0 2px;
+}
+
+/* fieldsets */
+.x-fieldset {
+    border:1px solid;
+    padding:10px;
+    margin-bottom:10px;
+    display:block; /* preserve margins in IE */
+}
+
+/* make top of checkbox/tools visible in webkit */
+.ext-webkit .x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset legend {
+    margin-bottom:10px;
+}
+
+.ext-strict .ext-ie9 .x-fieldset legend.x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset {
+    padding-top: 0;
+    padding-bottom:10px;
+}
+
+.x-fieldset legend .x-tool-toggle {
+    margin-right:3px;
+    margin-left:0;
+    float:left !important;
+}
+
+.x-fieldset legend input {
+    margin-right:3px;
+    float:left !important;
+    height:13px;
+    width:13px;
+}
+
+fieldset.x-panel-collapsed {
+    padding-bottom:0 !important;
+    border-width: 1px 1px 0 1px !important;
+    border-left-color: transparent;
+    border-right-color: transparent;
+}
+
+.ext-ie6 fieldset.x-panel-collapsed{
+    padding-bottom:0 !important;
+    border-width: 1px 0 0 0 !important;
+    margin-left: 1px;
+    margin-right: 1px;
+}
+
+fieldset.x-panel-collapsed .x-fieldset-bwrap {
+    visibility:hidden;
+    position:absolute;
+    left:-1000px;
+    top:-1000px;
+}
+
+.ext-ie .x-fieldset-bwrap {
+    zoom:1;
+}
+
+.x-fieldset-noborder {
+    border:0px none transparent;
+}
+
+.x-fieldset-noborder legend {
+    margin-left:-3px;
+}
+
+/* IE legend positioning bug */
+.ext-ie .x-fieldset-noborder legend {
+    position: relative;
+    margin-bottom:23px;
+}
+.ext-ie .x-fieldset-noborder legend span {
+    position: absolute;
+    left:16px;
+}
+
+.ext-gecko .x-window-body .x-form-item {
+    -moz-outline: none;
+    outline: none;
+    overflow: auto;
+}
+
+.ext-mac.ext-gecko .x-window-body .x-form-item {
+    overflow:hidden;
+}
+
+.ext-gecko .x-form-item {
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-hide-label label.x-form-item-label {
+     display:none;
+}
+
+.x-hide-label .x-form-element {
+     padding-left: 0 !important;
+}
+
+.x-form-label-top .x-hide-label label.x-form-item-label{
+    display: none;
+}
+
+.x-fieldset {
+    overflow:hidden;
+}
+
+.x-fieldset-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-fieldset-body {
+    overflow:hidden;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/grid.css b/src/main/webapp/lib/ext-3.4.0/css/structure/grid.css
new file mode 100644
index 0000000000000000000000000000000000000000..4a3401e63a2b7f22bddbd01fdc0b592581189a3e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/grid.css
@@ -0,0 +1,588 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/* Grid3 styles */
+.x-grid3 {
+	position:relative;
+	overflow:hidden;
+}
+
+.x-grid-panel .x-panel-body {
+    overflow:hidden !important;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border:1px solid;
+}
+
+.x-grid3 table {
+    table-layout:fixed;
+}
+
+.x-grid3-viewport{
+	overflow:hidden;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+    -moz-outline: none;
+    outline: none;
+	-moz-user-focus: normal;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td {
+    line-height:13px;
+    vertical-align: top;
+	padding-left:1px;
+    padding-right:1px;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-cell{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-row td {
+    line-height:15px;
+    vertical-align:middle;
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+.x-grid3-hd-row .x-grid3-marker-hd {
+    padding:3px;
+}
+
+.x-grid3-row .x-grid3-marker {
+    padding:3px;
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner{
+	overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    padding:3px 3px 3px 5px;
+    white-space: nowrap;
+}
+
+/* ActionColumn, reduce padding to accommodate 16x16 icons in normal row height */
+.x-action-col-cell .x-grid3-cell-inner {
+    padding-top: 1px;
+    padding-bottom: 1px;
+}
+
+.x-action-col-icon {
+    cursor: pointer;
+}
+
+.x-grid3-hd-inner {
+    position:relative;
+	cursor:inherit;
+	padding:4px 3px 4px 5px;
+}
+
+.x-grid3-row-body {
+    white-space:normal;
+}
+
+.x-grid3-body-cell {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+/* IE Quirks to clip */
+.ext-ie .x-grid3-cell-inner, .ext-ie .x-grid3-hd-inner{
+	width:100%;
+}
+
+/* reverse above in strict mode */
+.ext-strict .x-grid3-cell-inner, .ext-strict .x-grid3-hd-inner{
+	width:auto;
+}
+
+.x-grid-row-loading {
+    background: no-repeat center center;
+}
+
+.x-grid-page {
+    overflow:hidden;
+}
+
+.x-grid3-row {
+	cursor: default;
+    border: 1px solid;
+    width:100%;
+}
+
+.x-grid3-row-over {
+	border:1px solid;
+    background: repeat-x left top;
+}
+
+.x-grid3-resize-proxy {
+	width:1px;
+    left:0;
+	cursor: e-resize;
+	cursor: col-resize;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-resize-marker {
+	width:1px;
+	left:0;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: text;
+    -khtml-user-select: text;
+    -webkit-user-select:ignore;
+}
+
+/* header styles */
+.x-grid3-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    padding:1px 0 0 0;
+}
+
+.x-grid3-header-pop {
+    border-left:1px solid;
+    float:right;
+    clear:none;
+}
+
+.x-grid3-header-pop-inner {
+    border-left:1px solid;
+    width:14px;
+    height:19px;
+    background: transparent no-repeat center center;
+}
+
+.ext-ie .x-grid3-header-pop-inner {
+    width:15px;
+}
+
+.ext-strict .x-grid3-header-pop-inner {
+    width:14px; 
+}
+
+.x-grid3-header-inner {
+    overflow:hidden;
+    zoom:1;
+    float:left;
+}
+
+.x-grid3-header-offset {
+    padding-left:1px;
+    text-align: left;
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background: repeat-x left bottom;
+
+}
+
+.x-grid3-sort-icon{
+	background-repeat: no-repeat;
+	display: none;
+	height: 4px;
+	width: 13px;
+	margin-left:3px;
+	vertical-align: middle;
+}
+
+.sort-asc .x-grid3-sort-icon, .sort-desc .x-grid3-sort-icon {
+	display: inline;
+}
+
+/* Header position fixes for IE strict mode */
+.ext-strict .ext-ie .x-grid3-header-inner, .ext-strict .ext-ie6 .x-grid3-hd {
+    position:relative;
+}
+
+.ext-strict .ext-ie6 .x-grid3-hd-inner{
+    position:static;
+}
+
+/* Body Styles */
+.x-grid3-body {
+	zoom:1;
+}
+
+.x-grid3-scroller {
+	overflow:auto;
+    zoom:1;
+    position:relative;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	display: block;
+	padding: 3px 5px 3px 5px;
+	-moz-user-select: none;
+	-khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-split {
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor: e-resize;
+	cursor: col-resize;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	overflow: hidden;
+	position: absolute;
+	top: 2px;
+	width: 6px;
+	z-index: 3;
+}
+
+/* Column Reorder DD */
+.x-dd-drag-proxy .x-grid3-hd-inner{
+	background: repeat-x left bottom;
+	width:120px;
+	padding:3px;
+	border:1px solid;
+	overflow:hidden;
+}
+
+.col-move-top, .col-move-bottom{
+	width:9px;
+	height:9px;
+	position:absolute;
+	top:0;
+	line-height:1px;
+	font-size:1px;
+	overflow:hidden;
+	visibility:hidden;
+	z-index:20000;
+    background:transparent no-repeat left top;
+}
+
+/* Selection Styles */
+.x-grid3-row-selected {
+	border:1px dotted;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background: repeat-x 0 bottom !important;
+    vertical-align:middle !important;
+    padding:0;
+    border-top:1px solid;
+    border-bottom:none !important;
+    border-right:1px solid !important;
+    text-align:center;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    padding:0 4px;
+    text-align:center;
+}
+
+/* dirty cells */
+.x-grid3-dirty-cell {
+    background: transparent no-repeat 0 0;
+}
+
+/* Grid Toolbars */
+.x-grid3-topbar, .x-grid3-bottombar{
+    overflow:hidden;
+	display:none;
+	zoom:1;
+    position:relative;
+}
+
+.x-grid3-topbar .x-toolbar{
+	border-right:0 none;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-right:0 none;
+	border-bottom:0 none;
+	border-top:1px solid;
+}
+
+/* Props Grid Styles */
+.x-props-grid .x-grid3-cell{
+	padding:1px;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background:transparent repeat-y -16px !important;
+    padding-left:12px;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    padding:1px;
+    padding-right:0;
+    border:0 none;
+    border-right:1px solid;
+}
+
+/* dd */
+.x-grid3-col-dd {
+    border:0 none;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-dd-drag-ghost .x-grid3-dd-wrap {
+    padding:1px 3px 3px 1px;
+}
+
+.x-grid3-hd {
+    -moz-user-select:none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-btn {
+    display:none;
+    position:absolute;
+    width:14px;
+    background:no-repeat left center;
+    right:0;
+    top:0;
+    z-index:2;
+	cursor:pointer;
+}
+
+.x-grid3-hd-over .x-grid3-hd-btn, .x-grid3-hd-menu-open .x-grid3-hd-btn {
+    display:block;
+}
+
+a.x-grid3-hd-btn:hover {
+    background-position:-14px center;
+}
+
+/* Expanders */
+.x-grid3-body .x-grid3-td-expander {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-expander .x-grid3-cell-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-expander {
+    width:100%;
+    height:18px;
+    background-position:4px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-expander {
+    background-position:4px 2px;
+}
+
+.x-grid3-row-expanded .x-grid3-row-expander {
+    background-position:-21px 2px;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-body {
+    display:none !important;
+}
+
+.x-grid3-row-expanded .x-grid3-row-body {
+    display:block !important;
+}
+
+/* Checkers */
+.x-grid3-body .x-grid3-td-checker {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-checker .x-grid3-cell-inner, .x-grid3-header .x-grid3-td-checker .x-grid3-hd-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    width:100%;
+    height:18px;
+    background-position:2px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row .x-grid3-row-checker {
+    background-position:2px 2px;
+}
+
+.x-grid3-row-selected .x-grid3-row-checker, .x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker {
+    background-position:-23px 2px;
+}
+
+.x-grid3-hd-checker {
+    background-position:2px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker {
+    background-position:2px 3px;
+}
+
+.x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 3px;
+}
+
+/* Numberer */
+.x-grid3-body .x-grid3-td-numberer {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+    padding:3px 5px 0 0 !important;
+    text-align:right;
+}
+
+/* Row Icon */
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background:transparent repeat-y right;
+    vertical-align:top;
+    text-align:center;
+}
+
+.x-grid3-body .x-grid3-td-row-icon .x-grid3-cell-inner {
+    padding:0 !important;
+    background-position:center center;
+    background-repeat:no-repeat;
+    width:16px;
+    height:16px;
+    margin-left:2px;
+    margin-top:3px;
+}
+
+/* All specials */
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-check-col-td .x-grid3-cell-inner {
+    padding: 1px 0 0 0 !important;
+}
+
+.x-grid3-check-col {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-check-col-on {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+/* Grouping classes */
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom: 2px solid;
+    cursor:pointer;
+    padding-top:6px;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background:transparent no-repeat 3px 3px;
+    padding:4px 4px 4px 17px;
+}
+
+.x-grid-group-collapsed .x-grid-group-body {
+    display:none;
+}
+
+.ext-ie6 .x-grid3 .x-editor .x-form-text, .ext-ie7 .x-grid3 .x-editor .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-ie .x-props-grid .x-editor .x-form-text {
+    position:static;
+    top:0;
+}
+
+.x-grid-empty {
+    padding:10px;
+}
+
+/* fix floating toolbar issue */
+.ext-ie7 .x-grid-panel .x-panel-bbar {
+    position:relative;
+}
+
+
+/* Reset position to static when Grid Panel has been framed */
+/* to resolve 'snapping' from top to bottom behavior. */
+/* @forumThread 86656 */
+.ext-ie7 .x-grid-panel .x-panel-mc .x-panel-bbar {
+    position: static;
+}
+
+.ext-ie6 .x-grid3-header {
+    position: relative;
+}
+
+/* Fix WebKit bug in Grids */
+.ext-webkit .x-grid-panel .x-panel-bwrap{
+    -webkit-user-select:none;
+}
+.ext-webkit .x-tbar-page-number{
+    -webkit-user-select:ignore;
+}
+/* end*/
+
+/* column lines */
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    padding-right:0;
+    border-right:1px solid;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/layout.css b/src/main/webapp/lib/ext-3.4.0/css/structure/layout.css
new file mode 100644
index 0000000000000000000000000000000000000000..89c2601b615c1d3d3b879ecbf6e7a78ff8f12f15
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/layout.css
@@ -0,0 +1,296 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-border-layout-ct {
+    position: relative;
+}
+
+.x-border-panel {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-tool-collapse-south {
+    background-position:0 -195px;
+}
+
+.x-tool-collapse-south-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-collapse-north {
+    background-position:0 -210px;
+}
+
+.x-tool-collapse-north-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-collapse-west {
+    background-position:0 -180px;
+}
+
+.x-tool-collapse-west-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-collapse-east {
+    background-position:0 -165px;
+}
+
+.x-tool-collapse-east-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-south {
+    background-position:0 -210px;
+}
+
+.x-tool-expand-south-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-expand-north {
+    background-position:0 -195px;
+}
+.x-tool-expand-north-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-expand-west {
+    background-position:0 -165px;
+}
+
+.x-tool-expand-west-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-east {
+    background-position:0 -180px;
+}
+
+.x-tool-expand-east-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-expand-north, .x-tool-expand-south {
+    float:right;
+    margin:3px;
+}
+
+.x-tool-expand-east, .x-tool-expand-west {
+    float:none;
+    margin:3px 2px;
+}
+
+.x-accordion-hd .x-tool-toggle {
+    background-position:0 -255px;
+}
+
+.x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -255px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle {
+    background-position:0 -240px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -240px;
+}
+
+.x-accordion-hd {
+	padding-top:4px;
+	padding-bottom:3px;
+	border-top:0 none;
+    background: transparent repeat-x 0 -9px;
+}
+
+.x-layout-collapsed{
+    position:absolute;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+    width:20px;
+    height:20px;
+    overflow:hidden;
+	border:1px solid;
+	z-index:20;
+}
+
+.ext-border-box .x-layout-collapsed{
+    width:22px;
+    height:22px;
+}
+
+.x-layout-collapsed-over{
+    cursor:pointer;
+}
+
+.x-layout-collapsed-west .x-layout-collapsed-tools, .x-layout-collapsed-east .x-layout-collapsed-tools{
+	position:absolute;
+    top:0;
+    left:0;
+    width:20px;
+    height:20px;
+}
+
+
+.x-layout-split{
+    position:absolute;
+    height:5px;
+    width:5px;
+    line-height:1px;
+    font-size:1px;
+    z-index:3;
+    background-color:transparent;
+}
+
+/* IE6 strict won't drag w/out a color */
+.ext-strict .ext-ie6 .x-layout-split{
+    background-color: #fff !important;
+    filter: alpha(opacity=1);
+}
+
+.x-layout-split-h{
+    background-image:url(../images/default/s.gif);
+    background-position: left;
+}
+
+.x-layout-split-v{
+    background-image:url(../images/default/s.gif);
+    background-position: top;
+}
+
+.x-column-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column {
+    float:left;
+    padding:0;
+    margin:0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column-inner {
+    overflow:hidden;
+    zoom:1;
+}
+
+/* mini mode */
+.x-layout-mini {
+    position:absolute;
+    top:0;
+    left:0;
+    display:block;
+    width:5px;
+    height:35px;
+    cursor:pointer;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-layout-mini-over, .x-layout-collapsed-over .x-layout-mini{
+    opacity:1;
+    -moz-opacity:1;
+    filter:none;
+}
+
+.x-layout-split-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-split-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west, .x-layout-cmini-east {
+    border:0 none;
+    width:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-layout-cmini-north, .x-layout-cmini-south {
+    border:0 none;
+    height:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-viewport, .x-viewport body {
+    margin: 0;
+    padding: 0;
+    border: 0 none;
+    overflow: hidden;
+    height: 100%;
+}
+
+.x-abs-layout-item {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.ext-ie input.x-abs-layout-item, .ext-ie textarea.x-abs-layout-item {
+    margin:0;
+}
+
+.x-box-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-box-inner {
+    overflow:hidden;
+    zoom:1;
+    position:relative;
+    left:0;
+    top:0;
+}
+
+.x-box-item {
+    position:absolute;
+    left:0;
+    top:0;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/list-view.css b/src/main/webapp/lib/ext-3.4.0/css/structure/list-view.css
new file mode 100644
index 0000000000000000000000000000000000000000..1b166d59138a35764908c68a9673cb1f35fc8d7b
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/list-view.css
@@ -0,0 +1,86 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-list-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    height:22px;
+}
+
+.x-list-header-inner div {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.x-list-header-inner div em {
+    display:block;
+    border-left:1px solid;
+    padding:4px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    line-height:14px;
+}
+
+.x-list-body {
+    overflow:auto;
+    overflow-x:hidden;
+    overflow-y:auto;
+    zoom:1;
+    float: left;
+    width: 100%;
+}
+
+.x-list-body dl {
+    zoom:1;
+}
+
+.x-list-body dt {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor:pointer;
+    zoom:1;
+}
+
+.x-list-body dt em {
+    display:block;
+    padding:3px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+}
+
+.x-list-resizer {
+    border-left:1px solid;
+    border-right:1px solid;
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-list-header-inner em.sort-asc {
+    background: transparent no-repeat center 0;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+.x-list-header-inner em.sort-desc {
+    background: transparent no-repeat center -23px;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/menu.css b/src/main/webapp/lib/ext-3.4.0/css/structure/menu.css
new file mode 100644
index 0000000000000000000000000000000000000000..a9565b276051d15c0594311cbcef09c7a546076f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/menu.css
@@ -0,0 +1,245 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-menu {
+	z-index: 15000;
+	zoom: 1;
+	background: repeat-y;
+}
+
+.x-menu-floating{
+    border: 1px solid;
+}
+
+.x-menu a {
+    text-decoration: none !important;
+}
+
+.ext-ie .x-menu {
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-menu-list{
+    padding: 2px;
+	background-color:transparent;
+	border:0 none;
+    overflow:hidden;
+    overflow-y: hidden;
+}
+
+.ext-strict .ext-ie .x-menu-list{
+    position: relative;
+}
+
+.x-menu li{
+	line-height:100%;
+}
+
+.x-menu li.x-menu-sep-li{
+	font-size:1px;
+	line-height:1px;
+}
+
+.x-menu-list-item{
+    white-space: nowrap;
+	display:block;
+	padding:1px;
+}
+
+.x-menu-item{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-menu-item-arrow{
+	background:transparent no-repeat right;
+}
+
+.x-menu-sep {
+	display:block;
+	font-size:1px;
+	line-height:1px;
+	margin: 2px 3px;
+	border-bottom:1px solid;
+    overflow:hidden;
+}
+
+.x-menu-focus {
+	position:absolute;
+	left:-1px;
+	top:-1px;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+    overflow:hidden;
+    display:block;
+}
+
+a.x-menu-item {
+    cursor: pointer;
+    display: block;
+    line-height: 16px;
+    outline-color: -moz-use-text-color;
+    outline-style: none;
+    outline-width: 0;
+    padding: 3px 21px 3px 27px;
+    position: relative;
+    text-decoration: none;
+    white-space: nowrap;
+}
+
+.x-menu-item-active {
+    background-repeat: repeat-x;
+    background-position: left bottom;
+    border-style:solid;
+    border-width: 1px 0;
+    margin:0 1px;
+	padding: 0;
+}
+
+.x-menu-item-active a.x-menu-item {
+    border-style:solid;
+    border-width:0 1px;
+    margin:0 -1px;
+}
+
+.x-menu-item-icon {
+	border: 0 none;
+	height: 16px;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	position: absolute;
+    left: 3px;
+    top: 3px;
+    margin: 0;
+    background-position:center;
+}
+
+.ext-ie .x-menu-item-icon {
+    left: -24px;
+}
+.ext-strict .x-menu-item-icon {
+    left: 3px;
+}
+
+.ext-ie6 .x-menu-item-icon {
+    left: -24px;
+}
+
+.ext-ie .x-menu-item-icon {
+    vertical-align: middle;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background: transparent no-repeat center;
+}
+
+.x-menu-group-item .x-menu-item-icon{
+	background-color: transparent;
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background: transparent no-repeat center;
+}
+
+.x-date-menu .x-menu-list{
+    padding: 0;
+}
+
+.x-menu-date-item{
+	padding:0;
+}
+
+.x-menu .x-color-palette, .x-menu .x-date-picker{
+    margin-left: 26px;
+	margin-right:4px;
+}
+
+.x-menu .x-date-picker{
+    border:1px solid;
+    margin-top:2px;
+    margin-bottom:2px;
+}
+
+.x-menu-plain .x-color-palette, .x-menu-plain .x-date-picker{
+	 margin: 0;
+	 border: 0 none;
+}
+
+.x-date-menu {
+   padding:0 !important;
+}
+
+/*
+ * fixes separator visibility problem in IE 6
+ */
+.ext-strict .ext-ie6 .x-menu-sep-li {
+    padding: 3px 4px;
+}
+.ext-strict .ext-ie6 .x-menu-sep {
+    margin: 0;
+    height: 1px;
+}
+
+/*
+ * Fixes an issue with "fat" separators in webkit
+ */
+.ext-webkit .x-menu-sep{
+    height: 1px;
+}
+
+/*
+ * Ugly mess to remove the white border under the picker
+ */
+.ext-ie .x-date-menu{
+    height: 199px;
+}
+
+.ext-strict .ext-ie .x-date-menu, .ext-border-box .ext-ie8 .x-date-menu{
+    height: 197px;
+}
+
+.ext-strict .ext-ie7 .x-date-menu{
+    height: 195px;
+}
+
+.ext-strict .ext-ie8 .x-date-menu{
+    height: auto;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border:1px dotted !important;
+	padding:0;
+}
+
+.x-menu .x-menu-scroller {
+    width: 100%;
+	background-repeat:no-repeat;
+	background-position:center;
+	height:8px;
+    line-height: 8px;
+	cursor:pointer;
+    margin: 0;
+    padding: 0;
+}
+
+.x-menu .x-menu-scroller-active{
+    height: 6px;
+    line-height: 6px;
+}
+
+.x-menu-list-item-indent{
+    padding-left: 27px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/panel-reset.css b/src/main/webapp/lib/ext-3.4.0/css/structure/panel-reset.css
new file mode 100644
index 0000000000000000000000000000000000000000..42fe645827649b23ecc5bd7954e86b9199b4db4b
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/panel-reset.css
@@ -0,0 +1,130 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/**
+ * W3C Suggested Default style sheet for HTML 4
+ * http://www.w3.org/TR/CSS21/sample.html
+ *
+ * Resets for Ext.Panel @cfg normal: true
+ */
+.x-panel-reset .x-panel-body html,
+.x-panel-reset .x-panel-body address,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body body,
+.x-panel-reset .x-panel-body dd,
+.x-panel-reset .x-panel-body div,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dt,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body frame, frameset,
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body noframes,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body center,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body hr,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body pre 			  { display: block }
+.x-panel-reset .x-panel-body li              { display: list-item }
+.x-panel-reset .x-panel-body head            { display: none }
+.x-panel-reset .x-panel-body table           { display: table }
+.x-panel-reset .x-panel-body tr              { display: table-row }
+.x-panel-reset .x-panel-body thead           { display: table-header-group }
+.x-panel-reset .x-panel-body tbody           { display: table-row-group }
+.x-panel-reset .x-panel-body tfoot           { display: table-footer-group }
+.x-panel-reset .x-panel-body col             { display: table-column }
+.x-panel-reset .x-panel-body colgroup        { display: table-column-group }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th 	          { display: table-cell }
+.x-panel-reset .x-panel-body caption         { display: table-caption }
+.x-panel-reset .x-panel-body th              { font-weight: bolder; text-align: center }
+.x-panel-reset .x-panel-body caption         { text-align: center }
+.x-panel-reset .x-panel-body body            { margin: 8px }
+.x-panel-reset .x-panel-body h1              { font-size: 2em; margin: .67em 0 }
+.x-panel-reset .x-panel-body h2              { font-size: 1.5em; margin: .75em 0 }
+.x-panel-reset .x-panel-body h3              { font-size: 1.17em; margin: .83em 0 }
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu            { margin: 1.12em 0 }
+.x-panel-reset .x-panel-body h5              { font-size: .83em; margin: 1.5em 0 }
+.x-panel-reset .x-panel-body h6              { font-size: .75em; margin: 1.67em 0 }
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body b,
+.x-panel-reset .x-panel-body strong          { font-weight: bolder }
+.x-panel-reset .x-panel-body blockquote      { margin-left: 40px; margin-right: 40px }
+.x-panel-reset .x-panel-body i,
+.x-panel-reset .x-panel-body cite,
+.x-panel-reset .x-panel-body em,
+.x-panel-reset .x-panel-body var,
+.x-panel-reset .x-panel-body address    	  { font-style: italic }
+.x-panel-reset .x-panel-body pre,
+.x-panel-reset .x-panel-body tt,
+.x-panel-reset .x-panel-body code,
+.x-panel-reset .x-panel-body kbd,
+.x-panel-reset .x-panel-body samp       	  { font-family: monospace }
+.x-panel-reset .x-panel-body pre             { white-space: pre }
+.x-panel-reset .x-panel-body button,
+.x-panel-reset .x-panel-body textarea,
+.x-panel-reset .x-panel-body input,
+.x-panel-reset .x-panel-body select   		  { display: inline-block }
+.x-panel-reset .x-panel-body big             { font-size: 1.17em }
+.x-panel-reset .x-panel-body small,
+.x-panel-reset .x-panel-body sub,
+.x-panel-reset .x-panel-body sup 			  { font-size: .83em }
+.x-panel-reset .x-panel-body sub             { vertical-align: sub }
+.x-panel-reset .x-panel-body sup             { vertical-align: super }
+.x-panel-reset .x-panel-body table           { border-spacing: 2px; }
+.x-panel-reset .x-panel-body thead,
+.x-panel-reset .x-panel-body tbody,
+.x-panel-reset .x-panel-body tfoot           { vertical-align: middle }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th          	  { vertical-align: inherit }
+.x-panel-reset .x-panel-body s,
+.x-panel-reset .x-panel-body strike,
+.x-panel-reset .x-panel-body del  			  { text-decoration: line-through }
+.x-panel-reset .x-panel-body hr              { border: 1px inset }
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body dd        	  { margin-left: 40px }
+.x-panel-reset .x-panel-body ul, .x-panel-reset .x-panel-body menu, .x-panel-reset .x-panel-body dir { list-style-type: disc;}
+.x-panel-reset .x-panel-body ol              { list-style-type: decimal }
+.x-panel-reset .x-panel-body ol ul,
+.x-panel-reset .x-panel-body ul ol,
+.x-panel-reset .x-panel-body ul ul,
+.x-panel-reset .x-panel-body ol ol    		  { margin-top: 0; margin-bottom: 0 }
+.x-panel-reset .x-panel-body u,
+.x-panel-reset .x-panel-body ins          	  { text-decoration: underline }
+.x-panel-reset .x-panel-body br:before       { content: "\A" }
+.x-panel-reset .x-panel-body :before, .x-panel-reset .x-panel-body :after { white-space: pre-line }
+.x-panel-reset .x-panel-body center          { text-align: center }
+.x-panel-reset .x-panel-body :link, .x-panel-reset .x-panel-body :visited { text-decoration: underline }
+.x-panel-reset .x-panel-body :focus          { outline: invert dotted thin }
+
+/* Begin bidirectionality settings (do not change) */
+.x-panel-reset .x-panel-body BDO[DIR="ltr"]  { direction: ltr; unicode-bidi: bidi-override }
+.x-panel-reset .x-panel-body BDO[DIR="rtl"]  { direction: rtl; unicode-bidi: bidi-override }
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/panel.css b/src/main/webapp/lib/ext-3.4.0/css/structure/panel.css
new file mode 100644
index 0000000000000000000000000000000000000000..204b78777ea2668e9429771508ad1c883b67633e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/panel.css
@@ -0,0 +1,493 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel {
+    border-style: solid;
+    border-width:0;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+    padding:5px 3px 4px 5px;
+    border:1px solid;
+    line-height: 15px;
+    background: transparent repeat-x 0 -1px;
+}
+
+.x-panel-body {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    position: relative; /* added for item scroll positioning */
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom: 0 none;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top:1px solid;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-tl .x-panel-header {
+    padding:5px 0 4px 0;
+    border:0 none;
+    background:transparent no-repeat;
+}
+
+.x-panel-tl .x-panel-icon, .x-window-tl .x-panel-icon {
+    padding-left:20px !important;
+    background-repeat:no-repeat;
+    background-position:0 4px;
+    zoom:1;
+}
+
+.x-panel-inline-icon {
+    width:16px;
+	height:16px;
+    background-repeat:no-repeat;
+    background-position:0 0;
+	vertical-align:middle;
+	margin-right:4px;
+	margin-top:-1px;
+	margin-bottom:-1px;
+}
+
+.x-panel-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+/* fix ie7 strict mode bug */
+.ext-strict .ext-ie7 .x-panel-tc {
+    overflow: visible;
+}
+
+.x-panel-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    border-bottom:1px solid;
+}
+
+.x-panel-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:6px;
+}
+
+.x-panel-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-panel-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-mc {
+    border:0 none;
+    padding:0;
+    margin:0;
+    padding-top:6px;
+}
+
+.x-panel-mc .x-panel-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-panel-ml {
+	background: repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-panel-bc, .x-panel-nofooter .x-window-bc {
+	height:6px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-panel-bwrap {
+    overflow:hidden;
+    zoom:1;
+    left:0;
+    top:0;
+}
+.x-panel-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-collapsed .x-resizable-handle{
+    display:none;
+}
+
+.ext-gecko .x-panel-animated div {
+    overflow:hidden !important;
+}
+
+/* Plain */
+.x-plain-body {
+    overflow:hidden;
+}
+
+.x-plain-bbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-tbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-plain {
+    overflow:hidden;
+}
+
+/* Tools */
+.x-tool {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    float:right;
+    cursor:pointer;
+    background:transparent no-repeat;
+    margin-left:2px;
+}
+
+/* expand / collapse tools */
+.x-tool-toggle {
+    background-position:0 -60px;
+}
+
+.x-tool-toggle-over {
+    background-position:-15px -60px;
+}
+
+.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+
+.x-tool-close {
+    background-position:0 -0;
+}
+
+.x-tool-close-over {
+    background-position:-15px 0;
+}
+
+.x-tool-minimize {
+    background-position:0 -15px;
+}
+
+.x-tool-minimize-over {
+    background-position:-15px -15px;
+}
+
+.x-tool-maximize {
+    background-position:0 -30px;
+}
+
+.x-tool-maximize-over {
+    background-position:-15px -30px;
+}
+
+.x-tool-restore {
+    background-position:0 -45px;
+}
+
+.x-tool-restore-over {
+    background-position:-15px -45px;
+}
+
+.x-tool-gear {
+    background-position:0 -90px;
+}
+
+.x-tool-gear-over {
+    background-position:-15px -90px;
+}
+
+.x-tool-prev {
+    background-position:0 -105px;
+}
+
+.x-tool-prev-over {
+    background-position:-15px -105px;
+}
+
+.x-tool-next {
+    background-position:0 -120px;
+}
+
+.x-tool-next-over {
+    background-position:-15px -120px;
+}
+
+.x-tool-pin {
+    background-position:0 -135px;
+}
+
+.x-tool-pin-over {
+    background-position:-15px -135px;
+}
+
+.x-tool-unpin {
+    background-position:0 -150px;
+}
+
+.x-tool-unpin-over {
+    background-position:-15px -150px;
+}
+
+.x-tool-right {
+    background-position:0 -165px;
+}
+
+.x-tool-right-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-left {
+    background-position:0 -180px;
+}
+
+.x-tool-left-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-down {
+    background-position:0 -195px;
+}
+
+.x-tool-down-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-up {
+    background-position:0 -210px;
+}
+
+.x-tool-up-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-refresh {
+    background-position:0 -225px;
+}
+
+.x-tool-refresh-over {
+    background-position:-15px -225px;
+}
+
+.x-tool-plus {
+    background-position:0 -240px;
+}
+
+.x-tool-plus-over {
+    background-position:-15px -240px;
+}
+
+.x-tool-minus {
+    background-position:0 -255px;
+}
+
+.x-tool-minus-over {
+    background-position:-15px -255px;
+}
+
+.x-tool-search {
+    background-position:0 -270px;
+}
+
+.x-tool-search-over {
+    background-position:-15px -270px;
+}
+
+.x-tool-save {
+    background-position:0 -285px;
+}
+
+.x-tool-save-over {
+    background-position:-15px -285px;
+}
+
+.x-tool-help {
+    background-position:0 -300px;
+}
+
+.x-tool-help-over {
+    background-position:-15px -300px;
+}
+
+.x-tool-print {
+    background-position:0 -315px;
+}
+
+.x-tool-print-over {
+    background-position:-15px -315px;
+}
+
+.x-tool-expand {
+    background-position:0 -330px;
+}
+
+.x-tool-expand-over {
+    background-position:-15px -330px;
+}
+
+.x-tool-collapse {
+    background-position:0 -345px;
+}
+
+.x-tool-collapse-over {
+    background-position:-15px -345px;
+}
+
+.x-tool-resize {
+    background-position:0 -360px;
+}
+
+.x-tool-resize-over {
+    background-position:-15px -360px;
+}
+
+.x-tool-move {
+    background-position:0 -375px;
+}
+
+.x-tool-move-over {
+    background-position:-15px -375px;
+}
+
+/* Ghosting */
+.x-panel-ghost {
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    opacity:.65;
+    -moz-opacity:.65;
+    filter:alpha(opacity=65);
+}
+
+.x-panel-ghost ul {
+    margin:0;
+    padding:0;
+    overflow:hidden;
+    font-size:0;
+    line-height:0;
+    border:1px solid;
+    border-top:0 none;
+    display:block;
+}
+
+.x-panel-ghost * {
+    cursor:move !important;
+}
+
+.x-panel-dd-spacer {
+    border:2px dashed;
+}
+
+/* Buttons */
+.x-panel-btns {
+    padding:5px;
+    overflow:hidden;
+}
+
+.x-panel-btns td.x-toolbar-cell{
+	padding:3px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-left{
+	background-position:0 -147px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-right{
+	background-position:0 -168px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-center{
+	background-position:0 -189px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-center{
+	background-position:0 -105px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-center{
+	background-position:0 -126px;
+}
+
+.x-panel-btns .x-btn-click  .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+	white-space: nowrap;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/pivotgrid.css b/src/main/webapp/lib/ext-3.4.0/css/structure/pivotgrid.css
new file mode 100644
index 0000000000000000000000000000000000000000..d526d7205e215f3e12779512f40901214375e2a2
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/pivotgrid.css
@@ -0,0 +1,65 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-pivotgrid .x-grid3-header-offset table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-header-offset table td {
+    padding: 4px 3px 4px 5px;
+    text-align: center;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    line-height: 13px;
+    font-family: tahoma;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    display: block;
+    float: left;
+}
+
+.x-pivotgrid .x-grid3-row-headers table {
+    height: 100%;
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    height: 18px;
+    padding: 2px 7px 0 0;
+    text-align: right;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    font-family: tahoma;
+}
+
+.ext-gecko .x-pivotgrid .x-grid3-row-headers table td {
+    height: 21px;
+}
+
+.x-grid3-header-title {
+    top: 0%;
+    left: 0%;
+    position: absolute;
+    text-align: center;
+    vertical-align: middle;
+    font-family: tahoma;
+    font-size: 11px;
+    padding: auto 1px;
+    display: table-cell;
+}
+
+.x-grid3-header-title span {
+    position: absolute;
+    top: 50%;
+    left: 0%;
+    width: 100%;
+    margin-top: -6px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/progress.css b/src/main/webapp/lib/ext-3.4.0/css/structure/progress.css
new file mode 100644
index 0000000000000000000000000000000000000000..906ddfcd6ce0d9a183d5456532bf4e75a107aa25
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/progress.css
@@ -0,0 +1,46 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-progress-wrap {
+    border:1px solid;
+    overflow:hidden;
+}
+
+.x-progress-inner {
+    height:18px;
+    background:repeat-x;
+    position:relative;
+}
+
+.x-progress-bar {
+    height:18px;
+    float:left;
+    width:0;
+    background: repeat-x left center;
+    border-top:1px solid;
+    border-bottom:1px solid;
+    border-right:1px solid;
+}
+
+.x-progress-text {
+    padding:1px 5px;
+    overflow:hidden;
+    position:absolute;
+    left:0;
+    text-align:center;
+}
+
+.x-progress-text-back {
+    line-height:16px;
+}
+
+.ext-ie .x-progress-text-back {
+    line-height:15px;
+}
+
+.ext-strict .ext-ie7 .x-progress-text-back{
+    width: 100%;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/qtips.css b/src/main/webapp/lib/ext-3.4.0/css/structure/qtips.css
new file mode 100644
index 0000000000000000000000000000000000000000..bcc7d3bf0dea32c97da2bd0d9af5950e23d56841
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/qtips.css
@@ -0,0 +1,153 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tip{
+	position: absolute;
+	top: 0;
+    left:0;
+    visibility: hidden;
+	z-index: 20002;
+    border:0 none;
+}
+
+.x-tip .x-tip-close{
+	height: 15px;
+	float:right;
+	width: 15px;
+    margin:0 0 2px 2px;
+    cursor:pointer;
+    display:none;
+}
+
+.x-tip .x-tip-tc {
+	background: transparent no-repeat 0 -62px;
+	padding-top:3px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-bc {
+	background: transparent no-repeat 0 -121px;
+	height:3px;
+    overflow:hidden;
+}
+
+.x-tip .x-tip-bl {
+	background: transparent no-repeat 0 -59px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-br {
+	background: transparent no-repeat right -59px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mc {
+    border:0 none;
+}
+
+.x-tip .x-tip-ml {
+	background: no-repeat 0 -124px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mr {
+	background: transparent no-repeat right -124px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.ext-ie .x-tip .x-tip-header,.ext-ie .x-tip .x-tip-tc {
+    font-size:0;
+    line-height:0;
+}
+
+.ext-border-box .x-tip .x-tip-header, .ext-border-box .x-tip .x-tip-tc{
+    line-height: 1px;
+}
+
+.x-tip .x-tip-header-text {
+    padding:0;
+    margin:0 0 2px 0;
+}
+
+.x-tip .x-tip-body {
+    margin:0 !important;
+    line-height:14px;
+    padding:0;
+}
+
+.x-tip .x-tip-body .loading-indicator {
+    margin:0;
+}
+
+.x-tip-draggable .x-tip-header,.x-tip-draggable .x-tip-header-text {
+    cursor:move;
+}
+
+.x-form-invalid-tip .x-tip-tc {
+	background: repeat-x 0 -12px;
+    padding-top:6px;
+}
+
+.x-form-invalid-tip .x-tip-bc {
+	background: repeat-x 0 -18px;
+    height:6px;
+}
+
+.x-form-invalid-tip .x-tip-bl {
+	background: no-repeat 0 -6px;
+}
+
+.x-form-invalid-tip .x-tip-br {
+	background: no-repeat right -6px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding:2px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding-left:24px;
+    background:transparent no-repeat 2px 2px;
+}
+
+.x-tip-anchor {
+    position: absolute;
+    width: 9px;
+    height: 10px;
+    overflow:hidden;
+    background: transparent no-repeat 0 0;
+    zoom:1;
+}
+.x-tip-anchor-bottom {
+    background-position: -9px 0;
+}
+.x-tip-anchor-right {
+    background-position: -18px 0;
+    width: 10px;
+}
+.x-tip-anchor-left {
+    background-position: -28px 0;
+    width: 10px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/reset.css b/src/main/webapp/lib/ext-3.4.0/css/structure/reset.css
new file mode 100644
index 0000000000000000000000000000000000000000..763a46a35adec2ec388f0430f8de1b093ef629b4
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/reset.css
@@ -0,0 +1,13 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
+
+.ext-forced-border-box, .ext-forced-border-box * {
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/resizable.css b/src/main/webapp/lib/ext-3.4.0/css/structure/resizable.css
new file mode 100644
index 0000000000000000000000000000000000000000..ed3b5e5d5d5a8756b67f5653d5f885b7c790fe5e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/resizable.css
@@ -0,0 +1,149 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-resizable-handle {
+    position:absolute;
+    z-index:100;
+    /* ie needs these */
+    font-size:1px;
+    line-height:6px;
+    overflow:hidden;
+	filter:alpha(opacity=0);
+	opacity:0;
+	zoom:1;
+}
+
+.x-resizable-handle-east{
+    width:6px;
+    cursor:e-resize;
+    right:0;
+    top:0;
+    height:100%;
+}
+
+.ext-ie .x-resizable-handle-east {
+    margin-right:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-south{
+    width:100%;
+    cursor:s-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+}
+
+.ext-ie .x-resizable-handle-south {
+    margin-bottom:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-west{
+    width:6px;
+    cursor:w-resize;
+    left:0;
+    top:0;
+    height:100%;
+}
+
+.x-resizable-handle-north{
+    width:100%;
+    cursor:n-resize;
+    left:0;
+    top:0;
+    height:6px;
+}
+
+.x-resizable-handle-southeast{
+    width:6px;
+    cursor:se-resize;
+    right:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northwest{
+    width:6px;
+    cursor:nw-resize;
+    left:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northeast{
+    width:6px;
+    cursor:ne-resize;
+    right:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-southwest{
+    width:6px;
+    cursor:sw-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle{
+    filter:alpha(opacity=100);
+	opacity:1;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+	background-position: left;
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-position: top;
+}
+
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-position: top left;
+}
+
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-position:bottom right;
+}
+
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-position: bottom left;
+}
+
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-position: top right;
+}
+
+.x-resizable-proxy{
+    border: 1px dashed;
+    position:absolute;
+    overflow:hidden;
+    display:none;
+	left:0;
+    top:0;
+    z-index:50000;
+}
+
+.x-resizable-overlay{
+    width:100%;
+	height:100%;
+	display:none;
+	position:absolute;
+	left:0;
+	top:0;
+	z-index:200000;
+	-moz-opacity: 0;
+    opacity:0;
+    filter: alpha(opacity=0);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/slider.css b/src/main/webapp/lib/ext-3.4.0/css/structure/slider.css
new file mode 100644
index 0000000000000000000000000000000000000000..51538af44240a1071d1bf2c7611229fa663b9f1a
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/slider.css
@@ -0,0 +1,103 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/* Shared styles */
+.x-slider {
+    zoom:1;
+}
+
+.x-slider-inner {
+    position:relative;
+    left:0;
+    top:0;
+    overflow:visible;
+    zoom:1;
+}
+
+.x-slider-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+	display:block;
+	overflow:hidden;  
+}
+
+/* Horizontal styles */
+.x-slider-horz {
+    padding-left:7px;
+    background:transparent no-repeat 0 -22px;
+}
+
+.x-slider-horz .x-slider-end {
+    padding-right:7px;
+    zoom:1;
+    background:transparent no-repeat right -44px;
+}
+
+.x-slider-horz .x-slider-inner {
+    background:transparent repeat-x 0 0;
+    height:22px;
+}
+
+.x-slider-horz .x-slider-thumb {
+    width:14px;
+    height:15px;
+    position:absolute;
+    left:0;
+    top:3px;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-horz .x-slider-thumb-over {
+    background-position: -14px -15px;
+}
+
+.x-slider-horz .x-slider-thumb-drag {
+    background-position: -28px -30px;
+}
+
+/* Vertical styles */
+.x-slider-vert {
+    padding-top:7px;
+    background:transparent no-repeat -44px 0;
+    width:22px;
+}
+
+.x-slider-vert .x-slider-end {
+    padding-bottom:7px;
+    zoom:1;
+    background:transparent no-repeat -22px bottom;
+}
+
+.x-slider-vert .x-slider-inner {
+    background:transparent repeat-y 0 0;
+}
+
+.x-slider-vert .x-slider-thumb {
+    width:15px;
+    height:14px;
+    position:absolute;
+    left:3px;
+    bottom:0;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-vert .x-slider-thumb-over {
+    background-position: -15px -14px;
+}
+
+.x-slider-vert .x-slider-thumb-drag {
+    background-position: -30px -28px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/tabs.css b/src/main/webapp/lib/ext-3.4.0/css/structure/tabs.css
new file mode 100644
index 0000000000000000000000000000000000000000..e0f542c077c8e0501460b75643ac709632dd37c4
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/tabs.css
@@ -0,0 +1,392 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tab-panel {
+    overflow:hidden;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border: 1px solid;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header {
+	border: 1px solid;
+	padding-bottom: 2px;
+}
+
+.x-tab-panel-footer {
+	border: 1px solid;
+	padding-top: 2px;
+}
+
+.x-tab-strip-wrap {
+	width:100%;
+    overflow:hidden;
+    position:relative;
+    zoom:1;
+}
+
+ul.x-tab-strip {
+	display:block;
+    width:5000px;
+    zoom:1;
+}
+
+ul.x-tab-strip-top{
+	padding-top: 1px;
+	background: repeat-x bottom;
+	border-bottom: 1px solid;
+}
+
+ul.x-tab-strip-bottom{
+	padding-bottom: 1px;
+	background: repeat-x top;
+	border-top: 1px solid;
+	border-bottom: 0 none;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-top {
+    background:transparent !important;
+    padding-top:0 !important;
+}
+
+.x-tab-panel-header-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border:1px solid;
+    height:2px;
+    font-size:1px;
+    line-height:1px;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer {
+    border-top: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-bottom: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-bottom {
+    background:transparent !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-footer-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-top:0 !important;
+}
+
+.ext-border-box .x-tab-panel-header-plain .x-tab-strip-spacer,
+.ext-border-box .x-tab-panel-footer-plain .x-tab-strip-spacer {
+    height:3px;
+}
+
+ul.x-tab-strip li {
+    float:left;
+    margin-left:2px;
+}
+
+ul.x-tab-strip li.x-tab-edge {
+    float:left;
+    margin:0 !important;
+    padding:0 !important;
+    border:0 none !important;
+    font-size:1px !important;
+    line-height:1px !important;
+    overflow:hidden;
+    zoom:1;
+    background:transparent !important;
+    width:1px;
+}
+
+.x-tab-strip a, .x-tab-strip span, .x-tab-strip em {
+	display:block;
+}
+
+.x-tab-strip a {
+	text-decoration:none !important;
+	-moz-outline: none;
+	outline: none;
+	cursor:pointer;
+}
+
+.x-tab-strip-inner {
+    overflow:hidden;
+	text-overflow: ellipsis;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	white-space: nowrap;
+	cursor:pointer;
+    padding:4px 0;
+}
+
+.x-tab-strip-top .x-tab-with-icon .x-tab-right {
+    padding-left:6px;
+}
+
+.x-tab-strip .x-tab-with-icon span.x-tab-strip-text {
+	padding-left:20px;
+    background-position: 0 3px;
+    background-repeat: no-repeat;
+}
+
+.x-tab-strip-active, .x-tab-strip-active a.x-tab-right {
+    cursor:default;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	cursor:default;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	cursor:default;
+}
+
+.x-tab-panel-body {
+    overflow:hidden;
+}
+
+.x-tab-panel-bwrap {
+    overflow:hidden;
+}
+
+.ext-ie .x-tab-strip .x-tab-right {
+    position:relative;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+    margin-bottom:-1px;
+}
+
+/*
+ * Horrible hack for IE8 in quirks mode
+ */
+.ext-ie8 .x-tab-strip li {
+    position: relative;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top .x-tab-right {
+    top: 1px;
+}
+.ext-ie8 .x-tab-strip-top {
+    padding-top: 1;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top {
+    padding-top: 0;
+}
+.ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:3px;
+}
+.ext-border-box .ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:4px;
+}
+.ext-ie8 .x-tab-strip-bottom .x-tab-right{
+    top:0;
+}
+
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-bottom:5px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+    margin-top:-1px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-top:5px;
+}
+
+.x-tab-strip-top .x-tab-right {
+	background: transparent no-repeat 0 -51px;
+    padding-left:10px;
+}
+
+.x-tab-strip-top .x-tab-left {
+	background: transparent no-repeat right -351px;
+    padding-right:10px;
+}
+
+.x-tab-strip-top .x-tab-strip-inner {
+	background: transparent repeat-x 0 -201px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-right {
+	 background-position:0 -101px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-left {
+	 background-position:right -401px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-strip-inner {
+	 background-position:0 -251px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+	background-position: 0 0;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-left {
+	background-position: right -301px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-strip-inner {
+	background-position: 0 -151px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+    margin-right: 3px;
+    padding:0 10px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+    padding:0;
+}
+
+.x-tab-strip .x-tab-strip-close {
+    display:none;
+}
+
+.x-tab-strip-closable {
+    position:relative;
+}
+
+.x-tab-strip-closable .x-tab-left {
+    padding-right:19px;
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    opacity:.6;
+    -moz-opacity:.6;
+    background-repeat:no-repeat;
+    display:block;
+	width:11px;
+    height:11px;
+    position:absolute;
+    top:3px;
+    right:3px;
+    cursor:pointer;
+    z-index:2;
+}
+
+.x-tab-strip .x-tab-strip-active a.x-tab-strip-close {
+    opacity:.8;
+    -moz-opacity:.8;
+}
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+    opacity:1;
+    -moz-opacity:1;
+}
+
+.x-tab-panel-body {
+    border: 1px solid;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background: transparent no-repeat -18px 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    left:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background: transparent no-repeat 0 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    right:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+
+.x-tab-scroller-right-over {
+    background-position: -18px 0;
+}
+
+.x-tab-scroller-right-disabled {
+    background-position: 0 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scrolling-bottom .x-tab-scroller-left, .x-tab-scrolling-bottom .x-tab-scroller-right{
+    margin-top: 1px;
+}
+
+.x-tab-scrolling .x-tab-strip-wrap {
+    margin-left:18px;
+    margin-right:18px;
+}
+
+.x-tab-scrolling {
+    position:relative;    
+}
+
+.x-tab-panel-bbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-tab-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/toolbar.css b/src/main/webapp/lib/ext-3.4.0/css/structure/toolbar.css
new file mode 100644
index 0000000000000000000000000000000000000000..e2d962c2b6ac53ce2ccd831cc7110ae29c21e3af
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/toolbar.css
@@ -0,0 +1,246 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-toolbar{
+    border-style:solid;
+    border-width:0 0 1px 0;
+    display: block;
+	padding:2px;
+    background:repeat-x top left;
+    position:relative;
+    left:0;
+    top:0;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-toolbar-left {
+    width: 100%;
+}
+
+.x-toolbar .x-item-disabled .x-btn-icon {
+    opacity: .35;
+    -moz-opacity: .35;
+    filter: alpha(opacity=35);
+}
+
+.x-toolbar td {
+	vertical-align:middle;
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+	white-space: nowrap;
+}
+
+.x-toolbar .x-item-disabled {
+	cursor:default;
+	opacity:.6;
+	-moz-opacity:.6;
+	filter:alpha(opacity=60);
+}
+
+.x-toolbar .x-item-disabled * {
+	cursor:default;
+}
+
+.x-toolbar .x-toolbar-cell {
+    vertical-align:middle;
+}
+
+.x-toolbar .x-btn-tl, .x-toolbar .x-btn-tr, .x-toolbar .x-btn-tc, .x-toolbar .x-btn-ml, .x-toolbar .x-btn-mr,
+.x-toolbar .x-btn-mc, .x-toolbar .x-btn-bl, .x-toolbar .x-btn-br, .x-toolbar .x-btn-bc
+{
+	background-position: 500px 500px;
+}
+
+/* These rules are duplicated from button.css to give priority of x-toolbar rules above */
+.x-toolbar .x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-toolbar .x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-toolbar .x-btn-click .x-btn-tl, .x-toolbar .x-btn-menu-active .x-btn-tl, .x-toolbar .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tr, .x-toolbar .x-btn-menu-active .x-btn-tr, .x-toolbar .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tc, .x-toolbar .x-btn-menu-active .x-btn-tc, .x-toolbar .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-menu-active .x-btn-ml, .x-toolbar .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mr, .x-toolbar .x-btn-menu-active .x-btn-mr, .x-toolbar .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mc, .x-toolbar .x-btn-menu-active .x-btn-mc, .x-toolbar .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bl, .x-toolbar .x-btn-menu-active .x-btn-bl, .x-toolbar .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-br, .x-toolbar .x-btn-menu-active .x-btn-br, .x-toolbar .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-toolbar div.xtb-text{
+    padding:2px 2px 0;
+    line-height:16px;
+    display:block;
+}
+
+.x-toolbar .xtb-sep {
+	background-position: center;
+	background-repeat: no-repeat;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	width:4px;
+	overflow: hidden;
+	cursor:default;
+	margin: 0 2px 0;
+	border:0;
+}
+
+.x-toolbar .xtb-spacer {
+    width:2px;
+}
+
+/* Paging Toolbar */
+.x-tbar-page-number{
+	width:30px;
+	height:14px;
+}
+
+.ext-ie .x-tbar-page-number{
+    margin-top: 2px;
+}
+
+.x-paging-info {
+    position:absolute;
+    top:5px;
+    right: 8px;
+}
+
+/* floating */
+.x-toolbar-ct {
+    width:100%;
+}
+
+.x-toolbar-right td {
+    text-align: center;
+}
+
+.x-panel-tbar, .x-panel-bbar, .x-window-tbar, .x-window-bbar, .x-tab-panel-tbar, .x-tab-panel-bbar, .x-plain-tbar, .x-plain-bbar {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-toolbar-more .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 12px;
+}
+
+.x-toolbar-more em.x-btn-arrow {
+    display:inline;
+    background-color:transparent;
+	padding-right:0;
+}
+
+.x-toolbar-more .x-btn-mc em.x-btn-arrow {
+    background-image: none;
+}
+
+div.x-toolbar-no-items {
+    color:gray !important;
+    padding:5px 10px !important;
+}
+
+/* fix ie toolbar form items */
+.ext-border-box .x-toolbar-cell .x-form-text {
+    margin-bottom:-1px !important;
+}
+
+.ext-border-box .x-toolbar-cell .x-form-field-wrap .x-form-text {
+    margin:0 !important;
+}
+
+.ext-ie .x-toolbar-cell .x-form-field-wrap {
+    height:21px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-text, .ext-strict .ext-ie .x-toolbar-cell .x-form-text {
+    top: 0px;
+}
+
+.x-toolbar-right td .x-form-field-trigger-wrap{
+    text-align: left;
+}
+
+.x-toolbar-cell .x-form-checkbox, .x-toolbar-cell .x-form-radio{
+    margin-top: 5px;
+}
+
+.x-toolbar-cell .x-form-cb-label{
+    vertical-align: bottom;
+    top: 1px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-checkbox, .ext-ie .x-toolbar-cell .x-form-radio{
+    margin-top: 4px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-cb-label{
+    top: 0;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/tree.css b/src/main/webapp/lib/ext-3.4.0/css/structure/tree.css
new file mode 100644
index 0000000000000000000000000000000000000000..08d32b97d5359b59a918a8552fc6058878dab6bc
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/tree.css
@@ -0,0 +1,218 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-strict .ext-ie .x-tree .x-panel-bwrap{
+    position:relative;
+    overflow:hidden;
+}
+
+.x-tree-icon, .x-tree-ec-icon, .x-tree-elbow-line, .x-tree-elbow, .x-tree-elbow-end, .x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+    background-repeat: no-repeat;
+}
+
+.x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .x-tree-node-icon{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	background-position:center;
+    background-repeat: no-repeat;
+}
+
+.ext-ie .x-tree-node-indent img, .ext-ie .x-tree-node-icon, .ext-ie .x-tree-ec-icon {
+    vertical-align: middle !important;
+}
+
+.ext-strict .ext-ie8 .x-tree-node-indent img, .ext-strict .ext-ie8 .x-tree-node-icon, .ext-strict .ext-ie8 .x-tree-ec-icon {
+    vertical-align: top !important;
+}
+
+/* checkboxes */
+
+input.x-tree-node-cb {
+    margin-left:1px;
+    height: 19px;
+	vertical-align: bottom;
+}
+
+.ext-ie input.x-tree-node-cb {
+    margin-left:0;
+    margin-top: 1px;
+    width: 16px;
+    height: 16px;
+    vertical-align: middle;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb{
+    margin: 1px 1px;
+    height: 14px;
+    vertical-align: bottom;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb + a{
+    vertical-align: bottom;
+}
+
+.ext-opera input.x-tree-node-cb {
+    height: 14px;
+    vertical-align: middle;
+}
+
+.x-tree-noicon .x-tree-node-icon{
+	width:0; height:0;
+}
+
+/* No line styles */
+.x-tree-no-lines .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+/* Arrows */
+.x-tree-arrows .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	cursor:pointer;
+}
+
+.ext-ie ul.x-tree-node-ct{
+    font-size:0;
+    line-height:0;
+    zoom:1;
+}
+
+.x-tree-node{
+	white-space: nowrap;
+}
+
+.x-tree-node-el {
+    line-height:18px;
+    cursor:pointer;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	text-decoration:none;
+	-khtml-user-select:none;
+	-moz-user-select:none;
+    -webkit-user-select:ignore;
+    -kthml-user-focus:normal;
+    -moz-user-focus:normal;
+    -moz-outline: 0 none;
+    outline:0 none;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	text-decoration:none;
+	padding:1px 3px 1px 2px;
+}
+
+.x-tree-node .x-tree-node-disabled .x-tree-node-icon{
+	-moz-opacity: 0.5;
+   opacity:.5;
+   filter: alpha(opacity=50);
+}
+
+.x-tree-node .x-tree-node-inline-icon{
+	background-color:transparent;
+}
+
+.x-tree-node a:hover, .x-dd-drag-ghost a:hover{
+	text-decoration:none;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:1px dotted;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top:1px dotted;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above{
+	 border-top:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom:2px solid;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top:2px solid;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 border:1px dotted;
+}
+
+.x-dd-drag-ghost .x-tree-node-indent, .x-dd-drag-ghost .x-tree-ec-icon{
+	display:none !important;
+}
+
+/* Fix for ie rootVisible:false issue */
+.x-tree-root-ct {
+    zoom:1;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/structure/window.css b/src/main/webapp/lib/ext-3.4.0/css/structure/window.css
new file mode 100644
index 0000000000000000000000000000000000000000..3871e642c1ffc85f4c28f2fd60889e2782ca6ee0
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/structure/window.css
@@ -0,0 +1,222 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window {
+    zoom:1;
+}
+
+.x-window .x-window-handle {
+    opacity:0;
+    -moz-opacity:0;
+    filter:alpha(opacity=0);
+}
+
+.x-window-proxy {
+    border:1px solid;
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    display:none;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-window-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-window-bwrap {
+    z-index:1;
+    position:relative;
+    zoom:1;
+    left:0;top:0;
+}
+
+.x-window-tl .x-window-header {
+    padding:5px 0 4px 0;
+}
+
+.x-window-header-text {
+    cursor:pointer;
+}
+
+.x-window-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    zoom:1;
+}
+
+.x-window-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    z-index:1;
+    position:relative;
+}
+
+.x-window-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+}
+
+.x-window-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-window-bc .x-window-footer {
+    padding-bottom:6px;
+    zoom:1;
+    font-size:0;
+    line-height:0;
+}
+
+.x-window-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-mc {
+    border:1px solid;
+    padding:0;
+    margin:0;
+}
+
+.x-window-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-body {
+    overflow:hidden;
+}
+
+.x-window-bwrap {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-bl, .x-window-maximized .x-window-br,
+    .x-window-maximized .x-window-ml, .x-window-maximized .x-window-mr,
+    .x-window-maximized .x-window-tl, .x-window-maximized .x-window-tr {
+    padding:0;
+}
+
+.x-window-maximized .x-window-footer {
+    padding-bottom:0;
+}
+
+.x-window-maximized .x-window-tc {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-window-maximized .x-window-mc {
+    border-left:0 none;
+    border-right:0 none;
+}
+
+.x-window-tbar .x-toolbar, .x-window-bbar .x-toolbar {
+    border-left:0 none;
+    border-right: 0 none;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}
+
+.x-window-draggable, .x-window-draggable .x-window-header-text {
+    cursor:move;
+}
+
+.x-window-maximized .x-window-draggable, .x-window-maximized .x-window-draggable .x-window-header-text {
+    cursor:default;
+}
+
+.x-window-body {
+    background-color:transparent;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-window-maximized-ct {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-handle {
+    display:none;
+}
+
+.x-window-sizing-ghost ul {
+    border:0 none !important;
+}
+
+.x-dlg-focus{
+	-moz-outline:0 none;
+	outline:0 none;
+	width:0;
+	height:0;
+	overflow:hidden;
+	position:absolute;
+	top:0;
+	left:0;
+}
+
+.ext-webkit .x-dlg-focus{
+    width: 1px;
+    height: 1px;
+}
+
+.x-dlg-mask{
+    z-index:10000;
+    display:none;
+    position:absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity:.50;
+    filter: alpha(opacity=50);
+}
+
+body.ext-ie6.x-body-masked select {
+	visibility:hidden;
+}
+
+body.ext-ie6.x-body-masked .x-window select {
+	visibility:visible;
+}
+
+.x-window-plain .x-window-mc {
+    border: 1px solid;
+}
+
+.x-window-plain .x-window-body {
+    border: 1px solid;
+    background:transparent !important;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/symbolizercolumn.css b/src/main/webapp/lib/ext-3.4.0/css/symbolizercolumn.css
new file mode 100644
index 0000000000000000000000000000000000000000..b820b8aa1e426c0db3c7cd3f1c8559cec58368be
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/symbolizercolumn.css
@@ -0,0 +1 @@
+.gx-grid-symbolizercol div{padding:0;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/borders.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/borders.css
new file mode 100644
index 0000000000000000000000000000000000000000..01a4c1b007d650429f1e31b30048926d26c75059
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/borders.css
@@ -0,0 +1,25 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#343d4e;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#343d4e;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#343d4e;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#343d4e;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#343d4e;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/box.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/box.css
new file mode 100644
index 0000000000000000000000000000000000000000..9e4d28df0074dad5031e865ca10da3a988a02319
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/box.css
@@ -0,0 +1,74 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 15px;
+}
+
+.x-box-mc h3 {
+	font-size: 18px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/button.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/button.css
new file mode 100644
index 0000000000000000000000000000000000000000..be747381933d72a8cd3507c2a5a8e5b4bd2cf596
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/button.css
@@ -0,0 +1,136 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-btn {
+	font:normal 14px tahoma, verdana, helvetica;
+}
+
+.x-btn button {
+    font:normal 14px arial,tahoma,verdana,helvetica;
+    color:#fffffa;
+    padding-left:6px !important;
+    padding-right:6px !important;
+}
+
+.x-btn-over .x-btn button{
+    color:#fff;
+}
+
+.x-btn-noicon .x-btn-small .x-btn-text, .x-btn-text-icon .x-btn-icon-small-left .x-btn-text,
+.x-btn-icon .x-btn-small .x-btn-text, .x-btn-text-icon .x-btn-icon-small-right .x-btn-text {
+    height:18px;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text {
+    width:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text {
+    padding-left:21px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text {
+    padding-right:21px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text {
+    padding-left:29px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text {
+    padding-right:29px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text {
+    padding-left:37px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text {
+    padding-right:37px !important;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/access/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#fff;
+}
+
+.x-btn-disabled *{
+	color:#eee !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/access/button/arrow.gif);
+    padding-right:13px;
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow.gif);
+    padding-right:20px;
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/access/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #d2d2d2;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/access/button/group-lr.gif);
+}
+
+.x-btn-group-mr {
+	background-image: url(../images/access/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/combo.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/combo.css
new file mode 100644
index 0000000000000000000000000000000000000000..d619754b6d08b8d98655def3b4d0fbd5f417822e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/combo.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-combo-list {
+    border:2px solid #232732;
+    background-color:#555566;
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#414551;
+}
+
+.x-combo-list-hd {
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+    color:#fff;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#556;
+}
+
+.x-combo-list .x-combo-selected {
+	border-color:#e5872c !important;
+    background-color:#e5872c;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/core.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/core.css
new file mode 100644
index 0000000000000000000000000000000000000000..377192af3bffcfdbc130068264c7fcf35a61cdd8
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/core.css
@@ -0,0 +1,81 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+body {
+	background-color:#16181a;
+	color:#fcfcfc;
+}
+
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#223;
+    background-color:#3f4757;
+    background-image:url(../images/access/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #232d38;
+    border-color:#556;
+    color:#fff;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#232d38;
+    background-image:url(../images/access/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: #ddd;
+}
+
+.x-item-disabled * {
+    color: #ddd !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 14px;
+    background-image: url(../images/access/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/date-picker.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/date-picker.css
new file mode 100644
index 0000000000000000000000000000000000000000..1509a612d75f4df32da243bdc7196616bbad6295
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/date-picker.css
@@ -0,0 +1,145 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-date-picker {
+    border-color: #737b8c;
+    background-color:#21252e;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/access/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 14px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/access/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/access/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/access/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#363d4a;
+    background-image:url(../images/access/toolbar/bg.gif);
+	border-bottom-color:#535b5c;
+    font:normal 13px arial, helvetica,tahoma,sans-serif;
+	color:#fff;
+}
+
+.x-date-inner td {
+    border-color:#112;
+}
+
+.x-date-inner a {
+    font:normal 14px arial, helvetica,tahoma,sans-serif;
+    color:#fff;
+    padding:2px 7px 1px 3px; /* Structure to account for larger, bolder fonts in Access theme. */
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#e5872c;
+	background-image:none;
+	border-color:#864900;
+    padding:1px 6px 1px 2px; /* Structure to account for larger, bolder fonts in Access theme. */
+}
+
+.x-date-inner .x-date-today a{
+	border-color:#99a;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#737b8c;
+    background-color:#464d5a;
+    background-image:url(../images/access/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#fff;
+    background-color:#7e5530;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:13px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#21252e;
+}
+
+.x-date-mp td {
+	font:normal 14px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 14px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/access/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#fff;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#fff;
+	background-color: #7e5530;
+}
+
+td.x-date-mp-sel a {
+    background-color: #e5872c;
+	background-image: none;
+	border-color:#864900;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/access/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/dd.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/dd.css
new file mode 100644
index 0000000000000000000000000000000000000000..51c05e450330cd54d732f710f8f9b842a1d768de
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/dd.css
@@ -0,0 +1,29 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 14px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/debug.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..f23055d814ce9adf7351983a228b784066608989
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/debug.css
@@ -0,0 +1,24 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+#x-debug-browser .x-tree .x-tree-node a span {
+    color:#222297;
+    font-size:14px;
+    font-family:"monotype","courier new",sans-serif;
+}
+
+#x-debug-browser .x-tree a i {
+    color:#ff4545;
+    font-style:normal;
+}
+
+#x-debug-browser .x-tree a em {
+    color:#999;
+}
+
+#x-debug-browser .x-tree .x-tree-node .x-tree-selected a span{
+    background-color:#c3daf9;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/dialog.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/dialog.css
new file mode 100644
index 0000000000000000000000000000000000000000..fc95f911d4a4cff22e95829b55edc38e511f0d04
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/dialog.css
@@ -0,0 +1,34 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:15px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 15px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/access/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/access/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/access/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/access/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/access/window/icon-error.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/editor.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/editor.css
new file mode 100644
index 0000000000000000000000000000000000000000..b9c88fbf50665ca33fe4caa9ae6831687bd8a4b0
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/editor.css
@@ -0,0 +1,16 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-html-editor-wrap {
+    border-color:#737B8C;
+    background-color:#fff;
+}
+.x-html-editor-wrap iframe {
+    background-color: #fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/access/editor/tb-sprite.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/form.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/form.css
new file mode 100644
index 0000000000000000000000000000000000000000..2fa569f2349d5031fc5f211db8510fb9aac470db
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/form.css
@@ -0,0 +1,176 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-form-field {
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field{
+    color: #ffffff;
+    background-color:#33373d;
+    background-image:url(../images/access/form/text-bg.gif);
+    border-color:#737b8c;
+    border-width:2px;
+}
+
+.ext-webkit .x-form-text, .ext-webkit textarea.x-form-field{
+    border-width:2px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:26px;
+}
+
+.ext-strict .x-form-text {
+    height:20px;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #fff;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger{
+    background-image:url(../images/access/form/trigger.gif);
+    border-bottom-color:#737b8c;
+    border-bottom-width:2px;
+    height:24px;
+    width:20px;
+}
+
+.x-form-field-wrap .x-form-trigger.x-form-trigger-over{
+    border-bottom-color:#d97e27;
+}
+
+.x-form-field-wrap .x-form-trigger.x-form-trigger-click{
+    border-bottom-color:#c86e19;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger {
+    height:24px;
+}
+
+.x-form-field-wrap .x-form-trigger-over {
+    background-position:-20px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click {
+    background-position:-40px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    background-position:-60px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over {
+    background-position:-80px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click {
+    background-position:-100px 0;
+}
+
+.x-form-field-wrap .x-form-date-trigger{
+    background-image: url(../images/access/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger{
+    background-image: url(../images/access/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger{
+    background-image: url(../images/access/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom-color:#737b8c;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus{
+	border-color:#ff9c33;
+}
+
+.x-form-invalid, textarea.x-form-invalid,
+.ext-webkit .x-form-invalid, .ext-webkit textarea.x-form-invalid{
+    background-color:#15171a;
+	background-image:url(../images/access/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+/*
+.ext-safari .x-form-invalid{
+	background-color:#fee;
+	border-color:#ff7870;
+}
+*/
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background-color:#fff;
+	background-image:url(../images/access/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:#dadadd;
+}
+
+.x-small-editor .x-form-text {
+    height: 26px;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-safari .x-small-editor .x-form-field {
+    font:normal 15px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/access/form/exclamation.gif);
+    height:25px;
+    width:19px;
+    background-position:center right;
+}
+
+.x-fieldset {
+    border-color:#737B8C;
+}
+
+.x-fieldset legend {
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+    color:#fff;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/grid.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/grid.css
new file mode 100644
index 0000000000000000000000000000000000000000..5c13dc4ca8d6212117141009ad7faf9c6b067081
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/grid.css
@@ -0,0 +1,288 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-grid3 {
+    background-color:#1f2933;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#223;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    border-left-color:#556;
+    border-right-color:#223;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border:0 none;
+    border-bottom:1px solid #111;
+    border-right:1px solid #1a1a1c;
+}
+
+.x-grid3-row-alt{
+	background-color:#1b232b;
+}
+
+.x-grid3-row-over {
+    background-color:#7e5530;
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#3b3f50;
+	background-image:url(../images/access/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#889;
+    border-right-color:#445;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#4e628a;
+    background-image:url(../images/access/grid/grid3-hrow-over.gif);
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner {
+    color:#fff;
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/access/grid/sort_asc.gif);
+	width:15px;
+	height:9px;
+	margin-left:5px;
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/access/grid/sort_desc.gif);
+	width:15px;
+	height:9px;
+	margin-left:5px;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#fff;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#fff;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/access/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+.x-grid3-row-selected {
+	background-color: #e5872c !important;
+	background-image: none;
+	border-style: solid;
+}
+
+.x-grid3-row-selected .x-grid3-cell {
+    color: #fff;
+}
+
+.x-grid3-cell-selected {
+	background-color: #ffa340 !important;
+	color:#fff;
+}
+
+.x-grid3-cell-selected span{
+	color:#fff !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#fff;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#fff;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#fff !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/access/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/access/grid/grid3-special-col-bg.gif) !important;
+    color:#fff !important;
+}
+.x-props-grid .x-grid3-td-value {
+    color:#fff !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#263240 !important;
+    border-right-color:#223;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c2c9d0;
+    background-image:url(../images/access/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/access/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#fff;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/access/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#4e628a;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/access/grid/group-collapse.gif);
+    background-position:3px 6px;
+    color:#ffd;
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/access/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row{
+    border-top-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/layout.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/layout.css
new file mode 100644
index 0000000000000000000000000000000000000000..22e482ddfe101c34b80a6b938d0560051896dfab
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/layout.css
@@ -0,0 +1,56 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-border-layout-ct {
+    background-color:#3f4757;
+}
+
+.x-accordion-hd {
+	color:#fff;
+    font-weight:normal;
+    background-image: url(../images/access/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#323845;
+	border-color:#1a1a1c;
+}
+
+.x-layout-collapsed-over{
+    background-color:#2d3440;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/list-view.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/list-view.css
new file mode 100644
index 0000000000000000000000000000000000000000..a62ae7a9af5c2907c155b9d177769cc8e9ed4988
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/list-view.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-list-header{
+    background-color:#393d4e;
+	background-image:url(../images/access/toolbar/bg.gif);
+	background-position:0 top;
+}
+
+.x-list-header-inner div em {
+    border-left-color:#667;
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+    line-height: 14px;
+}
+
+.x-list-body-inner {
+    background-color:#1B232B;
+}
+
+.x-list-body dt em {
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#7E5530;
+}
+
+.x-list-selected {
+    background-color:#E5872C;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/access/grid/sort-hd.gif);
+    border-color: #3e4e6c;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/menu.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/menu.css
new file mode 100644
index 0000000000000000000000000000000000000000..bebe24f2ec18eb0171fb9754a63b00f775240916
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/menu.css
@@ -0,0 +1,79 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-menu {
+	border-color:#222;
+    background-color:#414551;
+	background-image:url(../images/access/menu/menu.gif);
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 14px tahoma,arial, sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/access/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#223;
+	border-bottom-color:#666;
+}
+
+a.x-menu-item {
+	color:#fffff6;
+}
+
+.x-menu-item-active {
+	background-color: #f09134;
+	background-image: none;
+    border-color:#b36427;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#b36427;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/access/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/panel.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/panel.css
new file mode 100644
index 0000000000000000000000000000000000000000..9c78ad6dd8e4f102cb4448ab196b275aa57312a0
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/panel.css
@@ -0,0 +1,94 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel {
+    border-color: #18181a;
+    font-size: 14px;
+}
+
+.x-panel-header {
+    color:#fff;
+    font-weight:bold; 
+    font-size: 14px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#18181a;
+    background-image: url(../images/access/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    color: #fffff6;
+    border-color:#18181a;
+    background-color:#232d38;
+}
+
+.x-tab-panel .x-panel-body {
+    color: #fffff6;
+    border-color:#18181a;
+    background-color:#1f2730;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#223;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#223;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#223;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#fff;
+    font:bold 14px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+    background-image: url(../images/access/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+    background-image: url(../images/access/panel/corners-sprite.gif);
+    border-bottom-color:#222224;
+}
+
+.x-panel-bc {
+	background-image: url(../images/access/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    background-color:#3f4757;
+}
+
+.x-panel-ml {
+    background-image:url(../images/access/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/access/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/access/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#3f4757;
+}
+
+.x-panel-ghost ul {
+    border-color:#18181a;
+}
+
+.x-panel-dd-spacer {
+    border-color:#18181a;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 14px arial,tahoma, helvetica, sans-serif;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/progress.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/progress.css
new file mode 100644
index 0000000000000000000000000000000000000000..f62cfaec664793cd36aae731e797483e4ce759da
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/progress.css
@@ -0,0 +1,35 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-progress-wrap {
+    border-color:#18181a;
+}
+
+.x-progress-inner {
+    background-color:#232d38;
+    background-image:none;
+}
+
+.x-progress-bar {
+    background-color:#f39a00;
+    background-image:url(../images/access/progress/progress-bg.gif);
+    border-top-color:#a66900;
+    border-bottom-color:#a66900;
+    border-right-color:#ffb941;
+    height: 20px !important; /* structural override for Accessibility Theme */
+}
+
+.x-progress-text {
+    font-size:14px;
+    font-weight:bold;
+    color:#fff;
+    padding: 0 5px !important; /* structural override for Accessibility Theme */
+}
+
+.x-progress-text-back {
+    color:#aaa;
+    line-height: 19px;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/qtips.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/qtips.css
new file mode 100644
index 0000000000000000000000000000000000000000..a72bc2cca538d6d5afb86037b2e51fb7e69d8f40
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/qtips.css
@@ -0,0 +1,44 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tip .x-tip-close{
+	background-image: url(../images/access/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/access/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 14px tahoma,arial,helvetica,sans-serif;
+    color:#ffd;
+}
+
+.x-tip .x-tip-body {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    color:#000;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/access/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/access/qtip/tip-anchor-sprite.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/resizable.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/resizable.css
new file mode 100644
index 0000000000000000000000000000000000000000..b77c01e17dd7281c04479cbc9eb1dc4c9426b70a
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/resizable.css
@@ -0,0 +1,44 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-resizable-handle {
+	background-color:#fff;
+	color: #000;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/access/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/access/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/access/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/access/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/access/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/access/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/access/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/slider.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/slider.css
new file mode 100644
index 0000000000000000000000000000000000000000..b3632384e5726814a3b9a994d7e6445f81d24d9b
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/slider.css
@@ -0,0 +1,21 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/access/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/access/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/access/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/access/slider/slider-v-thumb.png);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/tabs.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/tabs.css
new file mode 100644
index 0000000000000000000000000000000000000000..2c105a37903149c36068bc0f0d2ad5bf1b56c62d
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/tabs.css
@@ -0,0 +1,119 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color:#e18325;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#222;
+}
+
+ul.x-tab-strip-top{
+    background-color:#343843;
+	background-image: url(../images/access/tabs/tab-strip-bg.gif);
+	border-bottom-color:#343d4e;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#343843;
+	background-image: url(../images/access/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#343843;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#222;
+    background-color:#e18325;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 14px tahoma,arial,helvetica;
+	color:#fff;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#fff;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#fff;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/access/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/access/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/access/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/access/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/access/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/access/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/access/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#18181a;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/access/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/access/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/toolbar.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/toolbar.css
new file mode 100644
index 0000000000000000000000000000000000000000..ce24301ed32d12b392c1efbe7063bcc447a36618
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/toolbar.css
@@ -0,0 +1,120 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-toolbar{
+	border-color:#18181a;
+    background-color:#393d4e;
+    background-image:url(../images/access/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 14px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split 
+{
+    background-image:url(../images/access/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom 
+{
+    background-image:url(../images/access/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/access/grid/grid-blue-split.gif);
+}
+
+.x-toolbar .x-btn {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-arrow {
+    padding-right:10px;
+}
+
+.x-toolbar .x-btn-text-icon .x-btn-icon-small-left .x-btn-text {
+    padding-left:18px !important;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    padding-right:14px;
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/access/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/access/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/access/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/access/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/access/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/access/grid/loading.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/access/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/access/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/access/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/access/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/access/toolbar/more.gif) !important;
+}
+
+.x-statusbar .x-status-busy {
+    background-image: url(../images/access/grid/loading.gif);
+}
+
+.x-statusbar .x-status-text-panel {
+    border-color: #99bbe8 #fff #fff #99bbe8;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/tree.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/tree.css
new file mode 100644
index 0000000000000000000000000000000000000000..61fc2e0e3cb0290258e6c0c9a66a912f96749a84
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/tree.css
@@ -0,0 +1,165 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/access/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/access/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.ext-ie .x-tree-node-el input {
+    width:14px;
+    height:14px;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/access/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/access/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/access/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/access/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/access/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/access/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/access/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/access/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/access/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/access/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/access/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#fff;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-selected a, .x-dd-drag-ghost a{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-selected a span, .x-dd-drag-ghost a span{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #7e5530;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #e5872c;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-access/window.css b/src/main/webapp/lib/ext-3.4.0/css/theme-access/window.css
new file mode 100644
index 0000000000000000000000000000000000000000..066c6ac707aa0d10175f752e48cf4c1ea8f450c1
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-access/window.css
@@ -0,0 +1,87 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-proxy {
+    background-color:#1f2833;
+    border-color:#18181a;
+}
+
+.x-window-tl .x-window-header {
+    color:#fff;
+	font:bold 14px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/access/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/access/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/access/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/access/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/access/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/access/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#18181a;
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    background-color:#1f2833;
+}
+
+.x-window-ml {
+	background-image: url(../images/access/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/access/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#323945;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#323945;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#323945;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #464f61;
+    border-color: #636778;
+}
+
+.x-window-plain .x-window-body {
+    color: #fffff6;
+    border-color: #464F61;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #464f61;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/borders.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/borders.css
new file mode 100644
index 0000000000000000000000000000000000000000..8da99742ba35ce5c15b32f8a14a407799f326449
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/borders.css
@@ -0,0 +1,29 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-border-layout-ct {
+    background-color:#f0f0f0;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/box.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/box.css
new file mode 100644
index 0000000000000000000000000000000000000000..50794180edc8b5be28c1fc18901f5c146ba4d7c8
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/box.css
@@ -0,0 +1,74 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/button.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/button.css
new file mode 100644
index 0000000000000000000000000000000000000000..6cd0c84bdf63aaa565ac30dd8ff92c00c7ddd451
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/button.css
@@ -0,0 +1,94 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/gray/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/gray/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/gray/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #666;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/gray/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/gray/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/combo.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/combo.css
new file mode 100644
index 0000000000000000000000000000000000000000..48137847e680db818ad371df97c6957b787c437a
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/combo.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-combo-list {
+    border-color:#ccc;
+    background-color:#ddd;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#333;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#BCBCBC;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#BEBEBE;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#777 !important;
+    background-color:#f0f0f0;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#BCBCBC;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/core.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/core.css
new file mode 100644
index 0000000000000000000000000000000000000000..76cb5e103f29e19f9b3354063bae8293c967217c
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/core.css
@@ -0,0 +1,83 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#999;
+    background-color:#ddd;
+    background-image:url(../images/gray/panel/white-top-bottom.gif);
+    background-position: 0 -1px;
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#d0d0d0;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#CFCFCF;
+    background-color: #eaeaea;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #eaeaea;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/date-picker.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/date-picker.css
new file mode 100644
index 0000000000000000000000000000000000000000..a67d32b983f6ca76d145fbae589a40aa524e471e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/date-picker.css
@@ -0,0 +1,143 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-date-picker {
+    border-color:#585858;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/gray/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/gray/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/gray/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/gray/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#D8D8D8;
+    background-image: url(../images/gray/panel/white-top-bottom.gif);
+	border-bottom-color:#AFAFAF;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#595959;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-image: none;
+    background-color:#D8D8D8;
+	border-color:#DCDCDC;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#AFAFAF;
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#D8D8D8;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#4E565F;
+	color:#fff;
+	border-color:#C0C0C0 #434343 #434343 #C0C0C0;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+}
+
+.x-date-mp-btns td {
+	border-top-color:#AFAFAF;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color: #333;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#333;
+	background-color:#FDFDFD;
+}
+
+td.x-date-mp-sel a {
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+	border-color:#DCDCDC;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/gray/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#D7D7D7;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dd.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dd.css
new file mode 100644
index 0000000000000000000000000000000000000000..a84897f0c8e5fa1e8c02c42490e1c47b26cb8988
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dd.css
@@ -0,0 +1,29 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#D6D6D6;
+    border-color:#888888;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/debug.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..6b48bad99c1025935656cf9683614e85f65942af
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/debug.css
@@ -0,0 +1,24 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+#x-debug-browser .x-tree .x-tree-node a span {
+    color:#222297;
+    font-size:11px;
+    font-family:"monotype","courier new",sans-serif;
+}
+
+#x-debug-browser .x-tree a i {
+    color:#ff4545;
+    font-style:normal;
+}
+
+#x-debug-browser .x-tree a em {
+    color:#999;
+}
+
+#x-debug-browser .x-tree .x-tree-node .x-tree-selected a span{
+    background-color:#D5D5D5;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dialog.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dialog.css
new file mode 100644
index 0000000000000000000000000000000000000000..a9984d58bc84c4edd48ed676ffde9986d0df72c9
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/dialog.css
@@ -0,0 +1,34 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/gray/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/gray/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/gray/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/gray/window/icon-error.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/editor.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/editor.css
new file mode 100644
index 0000000000000000000000000000000000000000..fc9671067f209f8d9e9f099340e56aa3de755e39
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/editor.css
@@ -0,0 +1,13 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-html-editor-wrap {
+    border-color:#BCBCBC;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/form.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/form.css
new file mode 100644
index 0000000000000000000000000000000000000000..4b950e661e27487216edb9b820798d7f481adf43
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/form.css
@@ -0,0 +1,117 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-form-field{
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field{
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#C1C1C1;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#C1C1C1;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #d0d0d0;
+    color: #333;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger{
+    background-image:url(../images/gray/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger{
+    background-image: url(../images/gray/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger{
+    background-image: url(../images/gray/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger{
+    background-image: url(../images/gray/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom-color: #777777;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus{
+	border-color:#777777;
+}
+
+.x-form-invalid, textarea.x-form-invalid{
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.ext-webkit .x-form-invalid{
+	background-color:#fee;
+	border-color:#ff7870;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 12px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#CCCCCC;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#777777;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/grid.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/grid.css
new file mode 100644
index 0000000000000000000000000000000000000000..b003318215573d14d86103ba8f09e253c29a0ced
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/grid.css
@@ -0,0 +1,276 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#d0d0d0;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+    font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow2.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#ACACAC;
+    border-right-color:#ACACAC;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#f9f9f9;
+    background-image:url(../images/gray/grid/grid3-hrow-over2.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/gray/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/gray/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#333;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow-over2.gif);
+	border-color:#ACACAC;
+}
+
+.col-move-top{
+	background-image:url(../images/gray/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/gray/grid/col-move-bottom.gif);
+}
+
+.x-grid3-row-selected {
+	background-color:#CCCCCC !important;
+	background-image: none;
+	border-color:#ACACAC;
+}
+
+.x-grid3-cell-selected{
+	background-color: #CBCBCB !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#333 !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#f9f9f9;
+    background-image:url(../images/gray/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/gray/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/gray/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/gray/grid/group-collapse.gif);
+    color:#5F5F5F;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/gray/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row{
+    border-top-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#B9B9B9;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/layout.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/layout.css
new file mode 100644
index 0000000000000000000000000000000000000000..86a86f4a2e0afcb786e27ca6eda1a850bc0b1366
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/layout.css
@@ -0,0 +1,53 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-border-layout-ct {
+    background-color:#f0f0f0;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/gray/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#dfdfdf;
+	border-color:#d0d0d0;
+}
+
+.x-layout-collapsed-over{
+    background-color:#e7e7e7;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/list-view.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/list-view.css
new file mode 100644
index 0000000000000000000000000000000000000000..deb9afdcc409d29fee4c81e84c7521f7f784ac43
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/list-view.css
@@ -0,0 +1,37 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow2.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#f0f0f0;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/gray/grid/sort-hd.gif);
+    border-color: #d0d0d0;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/menu.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/menu.css
new file mode 100644
index 0000000000000000000000000000000000000000..cbd577331303c3691fd03d22b8d05a8f71357167
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/menu.css
@@ -0,0 +1,82 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#7D7D7D;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/gray/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/gray/menu/item-over.gif);
+	background-color: #f1f1f1;
+    border-color:#ACACAC;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#ACACAC;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/gray/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#AFAFAF;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#B9B9B9 !important;
+    background-color:#F1F1F1;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/panel.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/panel.css
new file mode 100644
index 0000000000000000000000000000000000000000..1ea6c3d2ebce9ad1582075d27424e3abcbbfba4e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/panel.css
@@ -0,0 +1,87 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel {
+    border-color: #d0d0d0;
+}
+
+.x-panel-header {
+    color:#333;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#d0d0d0;
+    background-image: url(../images/gray/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#d0d0d0;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#d0d0d0;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#333;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/gray/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/gray/panel/corners-sprite.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-bc {
+	background-image: url(../images/gray/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#f1f1f1;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/gray/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/gray/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/gray/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#f2f2f2;
+}
+
+.x-panel-ghost ul {
+    border-color:#d0d0d0;
+}
+
+.x-panel-dd-spacer {
+    border-color:#d0d0d0;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/pivotgrid.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/pivotgrid.css
new file mode 100644
index 0000000000000000000000000000000000000000..a30305adf0b9a24d249a987c676c6cf7817347cb
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/pivotgrid.css
@@ -0,0 +1,28 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/gray/grid/grid3-hrow2.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #D0D0D0;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/progress.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/progress.css
new file mode 100644
index 0000000000000000000000000000000000000000..168debb9f54ecba50aa815d6b5cc609949bd6fe7
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/progress.css
@@ -0,0 +1,32 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-progress-wrap {
+    border-color:#8E8E8E;
+}
+
+.x-progress-inner {
+    background-color:#E7E7E7;
+    background-image:url(../images/gray/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#BCBCBC;
+    background-image:url(../images/gray/progress/progress-bg.gif);
+    border-top-color:#E2E2E2;
+    border-bottom-color:#A4A4A4;
+    border-right-color:#A4A4A4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#5F5F5F;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/qtips.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/qtips.css
new file mode 100644
index 0000000000000000000000000000000000000000..fdd266d65330f9fafe1d972b06407e2fae385773
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/qtips.css
@@ -0,0 +1,44 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tip .x-tip-close{
+	background-image: url(../images/gray/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/gray/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/gray/qtip/tip-anchor-sprite.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/resizable.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/resizable.css
new file mode 100644
index 0000000000000000000000000000000000000000..8f0cbbc81c3d189dee929d7a1d00f3657198d9ea
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/resizable.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/gray/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/gray/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/gray/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/gray/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/gray/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/gray/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/gray/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#565656;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/slider.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/slider.css
new file mode 100644
index 0000000000000000000000000000000000000000..af069a0ac06b8f770665b92c10de5cb16884906f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/slider.css
@@ -0,0 +1,21 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/gray/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/gray/slider/slider-v-thumb.png);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tabs.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tabs.css
new file mode 100644
index 0000000000000000000000000000000000000000..e07d5077c7055f0cf076754465e11e891826f840
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tabs.css
@@ -0,0 +1,127 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #eaeaea;
+	border-color:#d0d0d0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#d0d0d0;
+}
+
+ul.x-tab-strip-top{
+    background-color:#dbdbdb;
+	background-image: url(../images/gray/tabs/tab-strip-bg.gif);
+	border-bottom-color:#d0d0d0;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#dbdbdb;
+	background-image: url(../images/gray/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#d0d0d0;
+    background-color: #eaeaea;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#333;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#111;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#333;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/gray/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/gray/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/gray/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#d0d0d0;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/gray/tabs/scroll-left.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/gray/tabs/scroll-right.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#d0d0d0;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/toolbar.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/toolbar.css
new file mode 100644
index 0000000000000000000000000000000000000000..453d7d674710f7c8a877f60f761aa4aef03c82e3
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/toolbar.css
@@ -0,0 +1,95 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-toolbar{
+	border-color:#d0d0d0;
+    background-color:#f0f0f0;
+    background-image:url(../images/gray/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split 
+{
+    background-image:url(../images/gray/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom 
+{
+    background-image:url(../images/gray/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/gray/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/gray/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/gray/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/gray/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/gray/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/loading.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/gray/toolbar/more.gif) !important;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tree.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tree.css
new file mode 100644
index 0000000000000000000000000000000000000000..62134df8f805b5256391b43c3b33f11e62311176
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/tree.css
@@ -0,0 +1,157 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.ext-ie .x-tree-node-el input {
+    width:15px;
+    height:15px;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/gray/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/gray/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/gray/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/gray/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #ddd;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/theme-gray/window.css b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/window.css
new file mode 100644
index 0000000000000000000000000000000000000000..4098cbe8cdd0c69622fb28fa637918199d236a46
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/theme-gray/window.css
@@ -0,0 +1,86 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-proxy {
+    background-color:#fcfcfc;
+    border-color:#d0d0d0;
+}
+
+.x-window-tl .x-window-header {
+    color:#555;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/gray/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/gray/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/gray/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/gray/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/gray/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/gray/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#d0d0d0;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#e8e8e8;
+}
+
+.x-window-ml {
+	background-image: url(../images/gray/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/gray/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #E8E8E8;
+    border-color: #D0D0D0 #EEEEEE #EEEEEE #D0D0D0;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #EEEEEE #D0D0D0 #D0D0D0 #EEEEEE;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #E4E4E4;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/borders.css b/src/main/webapp/lib/ext-3.4.0/css/visual/borders.css
new file mode 100644
index 0000000000000000000000000000000000000000..f42ca6ace86ca9b78ceb52b2933089ed6ed6e7ee
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/borders.css
@@ -0,0 +1,25 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/box.css b/src/main/webapp/lib/ext-3.4.0/css/visual/box.css
new file mode 100644
index 0000000000000000000000000000000000000000..01f6988925e74c6b2790a2108ff27c09034ac43c
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/box.css
@@ -0,0 +1,74 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/button.css b/src/main/webapp/lib/ext-3.4.0/css/visual/button.css
new file mode 100644
index 0000000000000000000000000000000000000000..39a93ee73ae20995ff19351a674c5fb6bfc7c921
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/button.css
@@ -0,0 +1,94 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/default/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #3e6aaa;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/combo.css b/src/main/webapp/lib/ext-3.4.0/css/visual/combo.css
new file mode 100644
index 0000000000000000000000000000000000000000..7672901a6e1bf47e87155f09873148f3d895a4de
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/combo.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-combo-list {
+    border-color:#98c0f4;
+    background-color:#ddecfe;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#a3bae9 !important;
+    background-color:#dfe8f6;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/core.css b/src/main/webapp/lib/ext-3.4.0/css/visual/core.css
new file mode 100644
index 0000000000000000000000000000000000000000..5c2aea52a4f9bff3f0b59f021896e9d125070b66
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/core.css
@@ -0,0 +1,82 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#6593cf;
+    background-color:#c3daf9;
+    background-image:url(../images/default/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#a3bad9;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #deecfd;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/date-picker.css b/src/main/webapp/lib/ext-3.4.0/css/visual/date-picker.css
new file mode 100644
index 0000000000000000000000000000000000000000..93b593a3e89c08efd9857f870bfa871a7a42e4bd
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/date-picker.css
@@ -0,0 +1,143 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-date-picker {
+    border-color: #1b376c;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/default/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/default/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/default/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+	border-bottom-color:#a3bad9;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#233d6d;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#dfecfb;
+	background-image:url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#a3bad9;
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#ddecfe;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#15428b;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#15428b;
+	background-color: #ddecfe;
+}
+
+td.x-date-mp-sel a {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/dd.css b/src/main/webapp/lib/ext-3.4.0/css/visual/dd.css
new file mode 100644
index 0000000000000000000000000000000000000000..3dca9de4356d77f1708a6a9da439d4633175d9a2
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/dd.css
@@ -0,0 +1,29 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/debug.css b/src/main/webapp/lib/ext-3.4.0/css/visual/debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..111dd001d710373d9f66502211301ebc98c6dc4e
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/debug.css
@@ -0,0 +1,24 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+#x-debug-browser .x-tree .x-tree-node a span {
+    color:#222297;
+    font-size:11px;
+    font-family:"monotype","courier new",sans-serif;
+}
+
+#x-debug-browser .x-tree a i {
+    color:#ff4545;
+    font-style:normal;
+}
+
+#x-debug-browser .x-tree a em {
+    color:#999;
+}
+
+#x-debug-browser .x-tree .x-tree-node .x-tree-selected a span{
+    background-color:#c3daf9;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/dialog.css b/src/main/webapp/lib/ext-3.4.0/css/visual/dialog.css
new file mode 100644
index 0000000000000000000000000000000000000000..0cb26f8b4bdfcad2e9f9cf3a90c2ba5e68b7efa1
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/dialog.css
@@ -0,0 +1,34 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/default/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/default/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/default/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/default/window/icon-error.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/editor.css b/src/main/webapp/lib/ext-3.4.0/css/visual/editor.css
new file mode 100644
index 0000000000000000000000000000000000000000..9cc571cdc4f1be05871637807c534aa7d8cb34b7
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/editor.css
@@ -0,0 +1,13 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-html-editor-wrap {
+    border-color:#a9bfd3;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/form.css b/src/main/webapp/lib/ext-3.4.0/css/visual/form.css
new file mode 100644
index 0000000000000000000000000000000000000000..df551889ca8e9c95e56110608fab66c0716338d5
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/form.css
@@ -0,0 +1,123 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-form-field {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field {
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#b5b8c8;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #15428b;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger {
+    background-image:url(../images/default/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger {
+    background-image: url(../images/default/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger {
+    background-image: url(../images/default/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger {
+    background-image: url(../images/default/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    border-bottom-color:#7eadd9;
+}
+
+.x-item-disabled .x-form-trigger-over {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus {
+	border-color:#7eadd9;
+}
+
+.x-form-invalid, textarea.x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-invalid.x-form-composite {
+    border: none;
+    background-image: none;
+}
+
+.x-form-invalid.x-form-composite .x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#b5b8c8;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/grid.css b/src/main/webapp/lib/ext-3.4.0/css/visual/grid.css
new file mode 100644
index 0000000000000000000000000000000000000000..871bcca856dce5df36e45c36851dbe755c741492
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/grid.css
@@ -0,0 +1,277 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#99bbe8;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+	font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#aaccf6;
+    border-right-color:#aaccf6;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#ebf3fd;
+    background-image:url(../images/default/grid/grid3-hrow-over.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#15428b;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/default/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+td.grid-hd-group-cell {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}
+
+.x-grid3-row-selected {
+	background-color: #dfe8f6 !important;
+	background-image: none;
+	border-color:#a3bae9;
+}
+
+.x-grid3-cell-selected{
+	background-color: #b8cfee !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#15428b !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c3daf9;
+    background-image:url(../images/default/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/default/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#99bbe8;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-collapse.gif);
+    color:#3764a0;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/layout.css b/src/main/webapp/lib/ext-3.4.0/css/visual/layout.css
new file mode 100644
index 0000000000000000000000000000000000000000..eaa983eab4e1ec6d5a89893b06717115e0dab2df
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/layout.css
@@ -0,0 +1,53 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-border-layout-ct {
+    background-color:#dfe8f6;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/default/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#d2e0f2;
+	border-color:#98c0f4;
+}
+
+.x-layout-collapsed-over{
+    background-color:#d9e8fb;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/list-view.css b/src/main/webapp/lib/ext-3.4.0/css/visual/list-view.css
new file mode 100644
index 0000000000000000000000000000000000000000..424650b256ae1505ad2a38f8ef4b0c17d1936fbf
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/list-view.css
@@ -0,0 +1,37 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#dfe8f6;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/default/grid/sort-hd.gif);
+    border-color: #99bbe8;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/menu.css b/src/main/webapp/lib/ext-3.4.0/css/visual/menu.css
new file mode 100644
index 0000000000000000000000000000000000000000..49a816ada43c7796e69251ac484965f13b4ddb5f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/menu.css
@@ -0,0 +1,87 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#718bb7;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/default/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/default/menu/item-over.gif);
+	background-color: #dbecf4;
+    border-color:#aaccf6;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#aaccf6;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/default/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#f0f0f0 !important;
+    background-image: none;
+}
+
+.x-date-menu, .x-color-menu{
+    background-color: #fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/panel.css b/src/main/webapp/lib/ext-3.4.0/css/visual/panel.css
new file mode 100644
index 0000000000000000000000000000000000000000..d72ba21d4430e62a41ac627cfd0e729cf0e4ffdb
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/panel.css
@@ -0,0 +1,87 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-panel {
+    border-color: #99bbe8;
+}
+
+.x-panel-header {
+    color:#15428b;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#99bbe8;
+    background-image: url(../images/default/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#99bbe8;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/default/panel/corners-sprite.gif);
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-bc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/default/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/default/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#cbddf3;
+}
+
+.x-panel-ghost ul {
+    border-color:#99bbe8;
+}
+
+.x-panel-dd-spacer {
+    border-color:#99bbe8;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/pivotgrid.css b/src/main/webapp/lib/ext-3.4.0/css/visual/pivotgrid.css
new file mode 100644
index 0000000000000000000000000000000000000000..fb158a7002dcaeca3a3cf1ed0913db6802f230e1
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/pivotgrid.css
@@ -0,0 +1,28 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/progress.css b/src/main/webapp/lib/ext-3.4.0/css/visual/progress.css
new file mode 100644
index 0000000000000000000000000000000000000000..7d90190c0dae6edf7dd4e3f78525ee8eb8ec9aa2
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/progress.css
@@ -0,0 +1,32 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-progress-wrap {
+    border-color:#6593cf;
+}
+
+.x-progress-inner {
+    background-color:#e0e8f3;
+    background-image:url(../images/default/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#9cbfee;
+    background-image:url(../images/default/progress/progress-bg.gif);
+    border-top-color:#d1e4fd;
+    border-bottom-color:#7fa9e4;
+    border-right-color:#7fa9e4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#396095;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/qtips.css b/src/main/webapp/lib/ext-3.4.0/css/visual/qtips.css
new file mode 100644
index 0000000000000000000000000000000000000000..8c9eda5f0a05586d5675bf7cfd47d018a9b4efc9
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/qtips.css
@@ -0,0 +1,44 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tip .x-tip-close{
+	background-image: url(../images/default/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/default/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/resizable.css b/src/main/webapp/lib/ext-3.4.0/css/visual/resizable.css
new file mode 100644
index 0000000000000000000000000000000000000000..2ee809119f74812216aebade427187b8fe552517
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/resizable.css
@@ -0,0 +1,43 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/default/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/default/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/default/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/default/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/default/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/slider.css b/src/main/webapp/lib/ext-3.4.0/css/visual/slider.css
new file mode 100644
index 0000000000000000000000000000000000000000..b82a4e078642ff87049c520e78b1e7637f431142
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/slider.css
@@ -0,0 +1,21 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-v-thumb.png);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/tabs.css b/src/main/webapp/lib/ext-3.4.0/css/visual/tabs.css
new file mode 100644
index 0000000000000000000000000000000000000000..c3615288fa24ab5ef310caf4f9de989b735df640
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/tabs.css
@@ -0,0 +1,127 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #deecfd;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#8db2e3;
+}
+
+ul.x-tab-strip-top{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-bg.gif);
+	border-bottom-color:#8db2e3;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#8db2e3;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#8db2e3;
+    background-color: #deecfd;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#416aa3;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#15428b;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#15428b;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/default/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#8db2e3;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/default/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/default/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/toolbar.css b/src/main/webapp/lib/ext-3.4.0/css/visual/toolbar.css
new file mode 100644
index 0000000000000000000000000000000000000000..bfd0e5fe6d1e8c1a35bc7a120117c02488b1f20d
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/toolbar.css
@@ -0,0 +1,95 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-toolbar{
+	border-color:#a9bfd3;
+    background-color:#d0def0;
+    background-image:url(../images/default/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
+{
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
+{
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-blue-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/default/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/refresh-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/default/toolbar/more.gif) !important;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/tree.css b/src/main/webapp/lib/ext-3.4.0/css/visual/tree.css
new file mode 100644
index 0000000000000000000000000000000000000000..062379359792425d6949e3df889ecc04e0cd8d2f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/tree.css
@@ -0,0 +1,152 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #d9e8fb;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/visual/window.css b/src/main/webapp/lib/ext-3.4.0/css/visual/window.css
new file mode 100644
index 0000000000000000000000000000000000000000..e556dcf81f0f191dfe51ca199ad6805a600267fa
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/visual/window.css
@@ -0,0 +1,86 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.x-window-proxy {
+    background-color:#c7dffc;
+    border-color:#99bbe8;
+}
+
+.x-window-tl .x-window-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#99bbe8;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-window-ml {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#84a0c4;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/xtheme-access.css b/src/main/webapp/lib/ext-3.4.0/css/xtheme-access.css
new file mode 100644
index 0000000000000000000000000000000000000000..44d0f95e5f56fa0a050aafc95f08e27d588a9ca5
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/xtheme-access.css
@@ -0,0 +1,1820 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+body {
+	background-color:#16181a;
+	color:#fcfcfc;
+}
+
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#223;
+    background-color:#3f4757;
+    background-image:url(../images/access/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #232d38;
+    border-color:#556;
+    color:#fff;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#232d38;
+    background-image:url(../images/access/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: #ddd;
+}
+
+.x-item-disabled * {
+    color: #ddd !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 14px;
+    background-image: url(../images/access/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}.x-tab-panel-header, .x-tab-panel-footer {
+	background-color:#e18325;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#222;
+}
+
+ul.x-tab-strip-top{
+    background-color:#343843;
+	background-image: url(../images/access/tabs/tab-strip-bg.gif);
+	border-bottom-color:#343d4e;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#343843;
+	background-image: url(../images/access/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#343843;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#222;
+    background-color:#e18325;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 14px tahoma,arial,helvetica;
+	color:#fff;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#fff;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#fff;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/access/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/access/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/access/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/access/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/access/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/access/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/access/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#18181a;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/access/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/access/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+.x-form-field {
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field{
+    color: #ffffff;
+    background-color:#33373d;
+    background-image:url(../images/access/form/text-bg.gif);
+    border-color:#737b8c;
+    border-width:2px;
+}
+
+.ext-webkit .x-form-text, .ext-webkit textarea.x-form-field{
+    border-width:2px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:26px;
+}
+
+.ext-strict .x-form-text {
+    height:20px;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #fff;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger{
+    background-image:url(../images/access/form/trigger.gif);
+    border-bottom-color:#737b8c;
+    border-bottom-width:2px;
+    height:24px;
+    width:20px;
+}
+
+.x-form-field-wrap .x-form-trigger.x-form-trigger-over{
+    border-bottom-color:#d97e27;
+}
+
+.x-form-field-wrap .x-form-trigger.x-form-trigger-click{
+    border-bottom-color:#c86e19;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger {
+    height:24px;
+}
+
+.x-form-field-wrap .x-form-trigger-over {
+    background-position:-20px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click {
+    background-position:-40px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    background-position:-60px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over {
+    background-position:-80px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click {
+    background-position:-100px 0;
+}
+
+.x-form-field-wrap .x-form-date-trigger{
+    background-image: url(../images/access/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger{
+    background-image: url(../images/access/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger{
+    background-image: url(../images/access/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom-color:#737b8c;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus{
+	border-color:#ff9c33;
+}
+
+.x-form-invalid, textarea.x-form-invalid,
+.ext-webkit .x-form-invalid, .ext-webkit textarea.x-form-invalid{
+    background-color:#15171a;
+	background-image:url(../images/access/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+/*
+.ext-safari .x-form-invalid{
+	background-color:#fee;
+	border-color:#ff7870;
+}
+*/
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background-color:#fff;
+	background-image:url(../images/access/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:#dadadd;
+}
+
+.x-small-editor .x-form-text {
+    height: 26px;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-safari .x-small-editor .x-form-field {
+    font:normal 15px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/access/form/exclamation.gif);
+    height:25px;
+    width:19px;
+    background-position:center right;
+}
+
+.x-fieldset {
+    border-color:#737B8C;
+}
+
+.x-fieldset legend {
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+    color:#fff;
+}
+.x-btn {
+	font:normal 14px tahoma, verdana, helvetica;
+}
+
+.x-btn button {
+    font:normal 14px arial,tahoma,verdana,helvetica;
+    color:#fffffa;
+    padding-left:6px !important;
+    padding-right:6px !important;
+}
+
+.x-btn-over .x-btn button{
+    color:#fff;
+}
+
+.x-btn-noicon .x-btn-small .x-btn-text, .x-btn-text-icon .x-btn-icon-small-left .x-btn-text,
+.x-btn-icon .x-btn-small .x-btn-text, .x-btn-text-icon .x-btn-icon-small-right .x-btn-text {
+    height:18px;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text {
+    width:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text {
+    padding-left:21px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text {
+    padding-right:21px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text {
+    padding-left:29px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text {
+    padding-right:29px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text {
+    padding-left:37px !important;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text {
+    padding-right:37px !important;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/access/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#fff;
+}
+
+.x-btn-disabled *{
+	color:#eee !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/access/button/arrow.gif);
+    padding-right:13px;
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow.gif);
+    padding-right:20px;
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/access/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #d2d2d2;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/access/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/access/button/group-lr.gif);
+}
+
+.x-btn-group-mr {
+	background-image: url(../images/access/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/access/button/group-tb.gif);
+}
+.x-toolbar{
+	border-color:#18181a;
+    background-color:#393d4e;
+    background-image:url(../images/access/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 14px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/access/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split 
+{
+    background-image:url(../images/access/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/access/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom 
+{
+    background-image:url(../images/access/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/access/grid/grid-blue-split.gif);
+}
+
+.x-toolbar .x-btn {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-arrow {
+    padding-right:10px;
+}
+
+.x-toolbar .x-btn-text-icon .x-btn-icon-small-left .x-btn-text {
+    padding-left:18px !important;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    padding-right:14px;
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/access/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/access/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/access/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/access/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/access/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/access/grid/loading.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/access/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/access/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/access/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/access/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/access/toolbar/more.gif) !important;
+}
+
+.x-statusbar .x-status-busy {
+    background-image: url(../images/access/grid/loading.gif);
+}
+
+.x-statusbar .x-status-text-panel {
+    border-color: #99bbe8 #fff #fff #99bbe8;
+}
+.x-resizable-handle {
+	background-color:#fff;
+	color: #000;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/access/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/access/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/access/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/access/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/access/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/access/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/access/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#1f2933;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#223;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    border-left-color:#556;
+    border-right-color:#223;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border:0 none;
+    border-bottom:1px solid #111;
+    border-right:1px solid #1a1a1c;
+}
+
+.x-grid3-row-alt{
+	background-color:#1b232b;
+}
+
+.x-grid3-row-over {
+    background-color:#7e5530;
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#3b3f50;
+	background-image:url(../images/access/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#889;
+    border-right-color:#445;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#4e628a;
+    background-image:url(../images/access/grid/grid3-hrow-over.gif);
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner {
+    color:#fff;
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/access/grid/sort_asc.gif);
+	width:15px;
+	height:9px;
+	margin-left:5px;
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/access/grid/sort_desc.gif);
+	width:15px;
+	height:9px;
+	margin-left:5px;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#fff;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#fff;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/access/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+.x-grid3-row-selected {
+	background-color: #e5872c !important;
+	background-image: none;
+	border-style: solid;
+}
+
+.x-grid3-row-selected .x-grid3-cell {
+    color: #fff;
+}
+
+.x-grid3-cell-selected {
+	background-color: #ffa340 !important;
+	color:#fff;
+}
+
+.x-grid3-cell-selected span{
+	color:#fff !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#fff;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#fff;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#fff !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/access/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/access/grid/grid3-special-col-bg.gif) !important;
+    color:#fff !important;
+}
+.x-props-grid .x-grid3-td-value {
+    color:#fff !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#263240 !important;
+    border-right-color:#223;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/access/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c2c9d0;
+    background-image:url(../images/access/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/access/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#fff;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/access/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/access/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#4e628a;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/access/grid/group-collapse.gif);
+    background-position:3px 6px;
+    color:#ffd;
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/access/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row{
+    border-top-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 14px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}
+.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/access/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/access/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.ext-ie .x-tree-node-el input {
+    width:14px;
+    height:14px;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/access/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/access/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/access/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/access/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/access/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/access/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/access/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/access/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/access/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/access/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/access/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/access/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#fff;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-selected a, .x-dd-drag-ghost a{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-selected a span, .x-dd-drag-ghost a span{
+	color:#fff;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #7e5530;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #e5872c;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}
+.x-date-picker {
+    border-color: #737b8c;
+    background-color:#21252e;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/access/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 14px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/access/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/access/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/access/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#363d4a;
+    background-image:url(../images/access/toolbar/bg.gif);
+	border-bottom-color:#535b5c;
+    font:normal 13px arial, helvetica,tahoma,sans-serif;
+	color:#fff;
+}
+
+.x-date-inner td {
+    border-color:#112;
+}
+
+.x-date-inner a {
+    font:normal 14px arial, helvetica,tahoma,sans-serif;
+    color:#fff;
+    padding:2px 7px 1px 3px; /* Structure to account for larger, bolder fonts in Access theme. */
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#e5872c;
+	background-image:none;
+	border-color:#864900;
+    padding:1px 6px 1px 2px; /* Structure to account for larger, bolder fonts in Access theme. */
+}
+
+.x-date-inner .x-date-today a{
+	border-color:#99a;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#737b8c;
+    background-color:#464d5a;
+    background-image:url(../images/access/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#fff;
+    background-color:#7e5530;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:13px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#21252e;
+}
+
+.x-date-mp td {
+	font:normal 14px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 14px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/access/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#fff;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#fff;
+	background-color: #7e5530;
+}
+
+td.x-date-mp-sel a {
+    background-color: #e5872c;
+	background-image: none;
+	border-color:#864900;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/access/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}
+.x-tip .x-tip-close{
+	background-image: url(../images/access/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/access/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 14px tahoma,arial,helvetica,sans-serif;
+    color:#ffd;
+}
+
+.x-tip .x-tip-body {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    color:#000;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/access/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/access/qtip/tip-anchor-sprite.gif);
+}
+.x-menu {
+	border-color:#222;
+    background-color:#414551;
+	background-image:url(../images/access/menu/menu.gif);
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 14px tahoma,arial, sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/access/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#223;
+	border-bottom-color:#666;
+}
+
+a.x-menu-item {
+	color:#fffff6;
+}
+
+.x-menu-item-active {
+	background-color: #f09134;
+	background-image: none;
+    border-color:#b36427;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#b36427;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/access/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 15px;
+}
+
+.x-box-mc h3 {
+	font-size: 18px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}
+.x-combo-list {
+    border:2px solid #232732;
+    background-color:#555566;
+    font:normal 15px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#414551;
+}
+
+.x-combo-list-hd {
+    font:bold 14px tahoma, arial, helvetica, sans-serif;
+    color:#fff;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#556;
+}
+
+.x-combo-list .x-combo-selected {
+	border-color:#e5872c !important;
+    background-color:#e5872c;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 14px tahoma, arial, helvetica, sans-serif;
+}
+.x-panel {
+    border-color: #18181a;
+    font-size: 14px;
+}
+
+.x-panel-header {
+    color:#fff;
+    font-weight:bold; 
+    font-size: 14px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#18181a;
+    background-image: url(../images/access/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    color: #fffff6;
+    border-color:#18181a;
+    background-color:#232d38;
+}
+
+.x-tab-panel .x-panel-body {
+    color: #fffff6;
+    border-color:#18181a;
+    background-color:#1f2730;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#223;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#223;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#223;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#fff;
+    font:bold 14px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+    background-image: url(../images/access/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+    background-image: url(../images/access/panel/corners-sprite.gif);
+    border-bottom-color:#222224;
+}
+
+.x-panel-bc {
+	background-image: url(../images/access/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    background-color:#3f4757;
+}
+
+.x-panel-ml {
+    background-image:url(../images/access/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/access/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/access/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#3f4757;
+}
+
+.x-panel-ghost ul {
+    border-color:#18181a;
+}
+
+.x-panel-dd-spacer {
+    border-color:#18181a;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 14px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#1f2833;
+    border-color:#18181a;
+}
+
+.x-window-tl .x-window-header {
+    color:#fff;
+	font:bold 14px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/access/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/access/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/access/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/access/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/access/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/access/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#18181a;
+    font: normal 14px tahoma,arial,helvetica,sans-serif;
+    background-color:#1f2833;
+}
+
+.x-window-ml {
+	background-image: url(../images/access/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/access/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#323945;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#323945;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#323945;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #464f61;
+    border-color: #636778;
+}
+
+.x-window-plain .x-window-body {
+    color: #fffff6;
+    border-color: #464F61;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #464f61;
+}
+.x-html-editor-wrap {
+    border-color:#737B8C;
+    background-color:#fff;
+}
+.x-html-editor-wrap iframe {
+    background-color: #fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/access/editor/tb-sprite.gif);
+}.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#343d4e;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#343d4e;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#343d4e;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#343d4e;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#343d4e;
+}
+.x-border-layout-ct {
+    background-color:#3f4757;
+}
+
+.x-accordion-hd {
+	color:#fff;
+    font-weight:normal;
+    background-image: url(../images/access/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#323845;
+	border-color:#1a1a1c;
+}
+
+.x-layout-collapsed-over{
+    background-color:#2d3440;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-progress-wrap {
+    border-color:#18181a;
+}
+
+.x-progress-inner {
+    background-color:#232d38;
+    background-image:none;
+}
+
+.x-progress-bar {
+    background-color:#f39a00;
+    background-image:url(../images/access/progress/progress-bg.gif);
+    border-top-color:#a66900;
+    border-bottom-color:#a66900;
+    border-right-color:#ffb941;
+    height: 20px !important; /* structural override for Accessibility Theme */
+}
+
+.x-progress-text {
+    font-size:14px;
+    font-weight:bold;
+    color:#fff;
+    padding: 0 5px !important; /* structural override for Accessibility Theme */
+}
+
+.x-progress-text-back {
+    color:#aaa;
+    line-height: 19px;
+}
+.x-list-header{
+    background-color:#393d4e;
+	background-image:url(../images/access/toolbar/bg.gif);
+	background-position:0 top;
+}
+
+.x-list-header-inner div em {
+    border-left-color:#667;
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+    line-height: 14px;
+}
+
+.x-list-body-inner {
+    background-color:#1B232B;
+}
+
+.x-list-body dt em {
+    font:normal 14px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#7E5530;
+}
+
+.x-list-selected {
+    background-color:#E5872C;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/access/grid/sort-hd.gif);
+    border-color: #3e4e6c;
+}
+.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/access/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/access/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/access/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/access/slider/slider-v-thumb.png);
+}
+.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:15px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 15px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/access/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/access/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/access/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/access/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/access/window/icon-error.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/xtheme-blue.css b/src/main/webapp/lib/ext-3.4.0/css/xtheme-blue.css
new file mode 100644
index 0000000000000000000000000000000000000000..a6d1502e1d4eda24c5cf6a29591ae8e3c115cefb
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/xtheme-blue.css
@@ -0,0 +1,1674 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#6593cf;
+    background-color:#c3daf9;
+    background-image:url(../images/default/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#a3bad9;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #deecfd;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #deecfd;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#8db2e3;
+}
+
+ul.x-tab-strip-top{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-bg.gif);
+	border-bottom-color:#8db2e3;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#8db2e3;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#8db2e3;
+    background-color: #deecfd;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#416aa3;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#15428b;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#15428b;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/default/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#8db2e3;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/default/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/default/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}.x-form-field {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field {
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#b5b8c8;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #15428b;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger {
+    background-image:url(../images/default/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger {
+    background-image: url(../images/default/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger {
+    background-image: url(../images/default/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger {
+    background-image: url(../images/default/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    border-bottom-color:#7eadd9;
+}
+
+.x-item-disabled .x-form-trigger-over {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus {
+	border-color:#7eadd9;
+}
+
+.x-form-invalid, textarea.x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-invalid.x-form-composite {
+    border: none;
+    background-image: none;
+}
+
+.x-form-invalid.x-form-composite .x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#b5b8c8;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+}
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/default/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #3e6aaa;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}.x-toolbar{
+	border-color:#a9bfd3;
+    background-color:#d0def0;
+    background-image:url(../images/default/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
+{
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
+{
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-blue-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/default/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/refresh-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/default/toolbar/more.gif) !important;
+}.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/default/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/default/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/default/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/default/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/default/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#99bbe8;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+	font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#aaccf6;
+    border-right-color:#aaccf6;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#ebf3fd;
+    background-image:url(../images/default/grid/grid3-hrow-over.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#15428b;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/default/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+td.grid-hd-group-cell {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}
+
+.x-grid3-row-selected {
+	background-color: #dfe8f6 !important;
+	background-image: none;
+	border-color:#a3bae9;
+}
+
+.x-grid3-cell-selected{
+	background-color: #b8cfee !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#15428b !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c3daf9;
+    background-image:url(../images/default/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/default/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#99bbe8;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-collapse.gif);
+    color:#3764a0;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #d9e8fb;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}.x-date-picker {
+    border-color: #1b376c;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/default/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/default/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/default/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+	border-bottom-color:#a3bad9;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#233d6d;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#dfecfb;
+	background-image:url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#a3bad9;
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#ddecfe;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#15428b;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#15428b;
+	background-color: #ddecfe;
+}
+
+td.x-date-mp-sel a {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}.x-tip .x-tip-close{
+	background-image: url(../images/default/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/default/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);
+}.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#718bb7;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/default/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/default/menu/item-over.gif);
+	background-color: #dbecf4;
+    border-color:#aaccf6;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#aaccf6;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/default/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#f0f0f0 !important;
+    background-image: none;
+}
+
+.x-date-menu, .x-color-menu{
+    background-color: #fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}.x-combo-list {
+    border-color:#98c0f4;
+    background-color:#ddecfe;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#a3bae9 !important;
+    background-color:#dfe8f6;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}.x-panel {
+    border-color: #99bbe8;
+}
+
+.x-panel-header {
+    color:#15428b;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#99bbe8;
+    background-image: url(../images/default/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#99bbe8;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/default/panel/corners-sprite.gif);
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-bc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/default/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/default/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#cbddf3;
+}
+
+.x-panel-ghost ul {
+    border-color:#99bbe8;
+}
+
+.x-panel-dd-spacer {
+    border-color:#99bbe8;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#c7dffc;
+    border-color:#99bbe8;
+}
+
+.x-window-tl .x-window-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#99bbe8;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-window-ml {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#84a0c4;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+}.x-html-editor-wrap {
+    border-color:#a9bfd3;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}.x-border-layout-ct {
+    background-color:#dfe8f6;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/default/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#d2e0f2;
+	border-color:#98c0f4;
+}
+
+.x-layout-collapsed-over{
+    background-color:#d9e8fb;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}.x-progress-wrap {
+    border-color:#6593cf;
+}
+
+.x-progress-inner {
+    background-color:#e0e8f3;
+    background-image:url(../images/default/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#9cbfee;
+    background-image:url(../images/default/progress/progress-bg.gif);
+    border-top-color:#d1e4fd;
+    border-bottom-color:#7fa9e4;
+    border-right-color:#7fa9e4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#396095;
+}.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#dfe8f6;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/default/grid/sort-hd.gif);
+    border-color: #99bbe8;
+}.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-v-thumb.png);
+}.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/default/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/default/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/default/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/default/window/icon-error.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/css/xtheme-gray.css b/src/main/webapp/lib/ext-3.4.0/css/xtheme-gray.css
new file mode 100644
index 0000000000000000000000000000000000000000..8dc9c2a5ff3c97e19765a9a2dae570d3b065c5f0
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/xtheme-gray.css
@@ -0,0 +1,1682 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#999;
+    background-color:#ddd;
+    background-image:url(../images/gray/panel/white-top-bottom.gif);
+    background-position: 0 -1px;
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#d0d0d0;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#CFCFCF;
+    background-color: #eaeaea;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #eaeaea;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #eaeaea;
+	border-color:#d0d0d0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#d0d0d0;
+}
+
+ul.x-tab-strip-top{
+    background-color:#dbdbdb;
+	background-image: url(../images/gray/tabs/tab-strip-bg.gif);
+	border-bottom-color:#d0d0d0;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#dbdbdb;
+	background-image: url(../images/gray/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#d0d0d0;
+    background-color: #eaeaea;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#333;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#111;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#333;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/gray/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/gray/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/gray/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/gray/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/gray/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#d0d0d0;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/gray/tabs/scroll-left.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/gray/tabs/scroll-right.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#d0d0d0;
+}
+.x-form-field{
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field{
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#C1C1C1;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#C1C1C1;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #d0d0d0;
+    color: #333;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger{
+    background-image:url(../images/gray/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger{
+    background-image: url(../images/gray/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger{
+    background-image: url(../images/gray/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger{
+    background-image: url(../images/gray/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom-color: #777777;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus{
+	border-color:#777777;
+}
+
+.x-form-invalid, textarea.x-form-invalid{
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.ext-webkit .x-form-invalid{
+	background-color:#fee;
+	border-color:#ff7870;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 12px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#CCCCCC;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#777777;
+}.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/gray/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/gray/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/gray/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #666;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/gray/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/gray/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/gray/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/gray/button/group-tb.gif);
+}
+.x-toolbar{
+	border-color:#d0d0d0;
+    background-color:#f0f0f0;
+    background-image:url(../images/gray/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split 
+{
+    background-image:url(../images/gray/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, 
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom 
+{
+    background-image:url(../images/gray/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/gray/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/gray/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/gray/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/gray/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/gray/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/loading.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/gray/toolbar/more.gif) !important;
+}
+.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/gray/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/gray/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/gray/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/gray/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/gray/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/gray/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/gray/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#565656;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#d0d0d0;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+    font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow2.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#ACACAC;
+    border-right-color:#ACACAC;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#f9f9f9;
+    background-image:url(../images/gray/grid/grid3-hrow-over2.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/gray/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/gray/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#333;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow-over2.gif);
+	border-color:#ACACAC;
+}
+
+.col-move-top{
+	background-image:url(../images/gray/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/gray/grid/col-move-bottom.gif);
+}
+
+.x-grid3-row-selected {
+	background-color:#CCCCCC !important;
+	background-image: none;
+	border-color:#ACACAC;
+}
+
+.x-grid3-cell-selected{
+	background-color: #CBCBCB !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#333 !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#f9f9f9;
+    background-image:url(../images/gray/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/gray/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/gray/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/gray/grid/group-collapse.gif);
+    color:#5F5F5F;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/gray/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row{
+    border-top-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#B9B9B9;
+}
+.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/gray/grid/grid3-hrow2.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #D0D0D0;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#D6D6D6;
+    border-color:#888888;
+}.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.ext-ie .x-tree-node-el input {
+    width:15px;
+    height:15px;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/gray/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/gray/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/gray/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/gray/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/gray/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #ddd;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}
+.x-date-picker {
+    border-color:#585858;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/gray/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/gray/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/gray/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/gray/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#D8D8D8;
+    background-image: url(../images/gray/panel/white-top-bottom.gif);
+	border-bottom-color:#AFAFAF;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#595959;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-image: none;
+    background-color:#D8D8D8;
+	border-color:#DCDCDC;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#AFAFAF;
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#D8D8D8;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#4E565F;
+	color:#fff;
+	border-color:#C0C0C0 #434343 #434343 #C0C0C0;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+}
+
+.x-date-mp-btns td {
+	border-top-color:#AFAFAF;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color: #333;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#333;
+	background-color:#FDFDFD;
+}
+
+td.x-date-mp-sel a {
+    background-color:#D8D8D8;
+    background:#D8D8D8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px;
+	border-color:#DCDCDC;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/gray/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#D7D7D7;
+}.x-tip .x-tip-close{
+	background-image: url(../images/gray/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/gray/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/gray/qtip/tip-anchor-sprite.gif);
+}.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#7D7D7D;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/gray/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/gray/menu/item-over.gif);
+	background-color: #f1f1f1;
+    border-color:#ACACAC;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#ACACAC;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/gray/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#AFAFAF;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#B9B9B9 !important;
+    background-color:#F1F1F1;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}
+.x-combo-list {
+    border-color:#ccc;
+    background-color:#ddd;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#333;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#BCBCBC;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#BEBEBE;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#777 !important;
+    background-color:#f0f0f0;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#BCBCBC;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}.x-panel {
+    border-color: #d0d0d0;
+}
+
+.x-panel-header {
+    color:#333;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#d0d0d0;
+    background-image: url(../images/gray/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#d0d0d0;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#d0d0d0;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#333;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/gray/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/gray/panel/corners-sprite.gif);
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-bc {
+	background-image: url(../images/gray/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#f1f1f1;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/gray/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/gray/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/gray/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#f2f2f2;
+}
+
+.x-panel-ghost ul {
+    border-color:#d0d0d0;
+}
+
+.x-panel-dd-spacer {
+    border-color:#d0d0d0;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#fcfcfc;
+    border-color:#d0d0d0;
+}
+
+.x-window-tl .x-window-header {
+    color:#555;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/gray/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/gray/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/gray/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/gray/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/gray/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/gray/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#d0d0d0;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#e8e8e8;
+}
+
+.x-window-ml {
+	background-image: url(../images/gray/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/gray/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #E8E8E8;
+    border-color: #D0D0D0 #EEEEEE #EEEEEE #D0D0D0;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #EEEEEE #D0D0D0 #D0D0D0 #EEEEEE;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #E4E4E4;
+}
+.x-html-editor-wrap {
+    border-color:#BCBCBC;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#d0d0d0;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#d0d0d0;
+}
+
+.x-border-layout-ct {
+    background-color:#f0f0f0;
+}
+.x-border-layout-ct {
+    background-color:#f0f0f0;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/gray/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#dfdfdf;
+	border-color:#d0d0d0;
+}
+
+.x-layout-collapsed-over{
+    background-color:#e7e7e7;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-progress-wrap {
+    border-color:#8E8E8E;
+}
+
+.x-progress-inner {
+    background-color:#E7E7E7;
+    background-image:url(../images/gray/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#BCBCBC;
+    background-image:url(../images/gray/progress/progress-bg.gif);
+    border-top-color:#E2E2E2;
+    border-bottom-color:#A4A4A4;
+    border-right-color:#A4A4A4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#5F5F5F;
+}
+.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/gray/grid/grid3-hrow2.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#f0f0f0;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/gray/grid/sort-hd.gif);
+    border-color: #d0d0d0;
+}
+.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/gray/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/gray/slider/slider-v-thumb.png);
+}
+.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/gray/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/gray/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/gray/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/gray/window/icon-error.gif);
+}
diff --git a/src/main/webapp/lib/ext-3.4.0/css/yourtheme.css b/src/main/webapp/lib/ext-3.4.0/css/yourtheme.css
new file mode 100644
index 0000000000000000000000000000000000000000..ae791943aeae21dc202839698d11b73c51c2ef7c
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/css/yourtheme.css
@@ -0,0 +1,1652 @@
+/*!
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#6593cf;
+    background-color:#c3daf9;
+    background-image:url(../images/default/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#a3bad9;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #deecfd;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #deecfd;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#8db2e3;
+}
+
+ul.x-tab-strip-top{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-bg.gif);
+	border-bottom-color:#8db2e3;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#8db2e3;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#8db2e3;
+    background-color: #deecfd;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#416aa3;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#15428b;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#15428b;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/default/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#8db2e3;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/default/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/default/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}.x-form-field {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field {
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#b5b8c8;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #15428b;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger {
+    background-image:url(../images/default/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger {
+    background-image: url(../images/default/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger {
+    background-image: url(../images/default/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger {
+    background-image: url(../images/default/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    border-bottom-color:#7eadd9;
+}
+
+.x-item-disabled .x-form-trigger-over {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus {
+	border-color:#7eadd9;
+}
+
+.x-form-invalid, textarea.x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-invalid.x-form-composite {
+    border: none;
+    background-image: none;
+}
+
+.x-form-invalid.x-form-composite .x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#b5b8c8;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+}
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/default/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #3e6aaa;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}.x-toolbar{
+	border-color:#a9bfd3;
+    background-color:#d0def0;
+    background-image:url(../images/default/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
+{
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
+{
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-blue-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/default/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/refresh-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/default/toolbar/more.gif) !important;
+}.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/default/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/default/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/default/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/default/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/default/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#99bbe8;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+	font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#aaccf6;
+    border-right-color:#aaccf6;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#ebf3fd;
+    background-image:url(../images/default/grid/grid3-hrow-over.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#15428b;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/default/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+td.grid-hd-group-cell {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}
+
+.x-grid3-row-selected {
+	background-color: #dfe8f6 !important;
+	background-image: none;
+	border-color:#a3bae9;
+}
+
+.x-grid3-cell-selected{
+	background-color: #b8cfee !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#15428b !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c3daf9;
+    background-image:url(../images/default/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/default/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#99bbe8;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-collapse.gif);
+    color:#3764a0;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #d9e8fb;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}.x-date-picker {
+    border-color: #1b376c;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/default/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/default/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/default/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+	border-bottom-color:#a3bad9;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#233d6d;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#dfecfb;
+	background-image:url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#a3bad9;
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#ddecfe;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#15428b;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#15428b;
+	background-color: #ddecfe;
+}
+
+td.x-date-mp-sel a {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}.x-tip .x-tip-close{
+	background-image: url(../images/default/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/default/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);
+}.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#718bb7;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/default/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/default/menu/item-over.gif);
+	background-color: #dbecf4;
+    border-color:#aaccf6;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#aaccf6;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/default/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#f0f0f0 !important;
+    background-image: none;
+}
+
+.x-date-menu, .x-color-menu{
+    background-color: #fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}.x-combo-list {
+    border-color:#98c0f4;
+    background-color:#ddecfe;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#a3bae9 !important;
+    background-color:#dfe8f6;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}.x-panel {
+    border-color: #99bbe8;
+}
+
+.x-panel-header {
+    color:#15428b;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#99bbe8;
+    background-image: url(../images/default/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#99bbe8;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/default/panel/corners-sprite.gif);
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-bc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/default/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/default/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#cbddf3;
+}
+
+.x-panel-ghost ul {
+    border-color:#99bbe8;
+}
+
+.x-panel-dd-spacer {
+    border-color:#99bbe8;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#c7dffc;
+    border-color:#99bbe8;
+}
+
+.x-window-tl .x-window-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#99bbe8;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-window-ml {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#84a0c4;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+}.x-html-editor-wrap {
+    border-color:#a9bfd3;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}.x-border-layout-ct {
+    background-color:#dfe8f6;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/default/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#d2e0f2;
+	border-color:#98c0f4;
+}
+
+.x-layout-collapsed-over{
+    background-color:#d9e8fb;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}.x-progress-wrap {
+    border-color:#6593cf;
+}
+
+.x-progress-inner {
+    background-color:#e0e8f3;
+    background-image:url(../images/default/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#9cbfee;
+    background-image:url(../images/default/progress/progress-bg.gif);
+    border-top-color:#d1e4fd;
+    border-bottom-color:#7fa9e4;
+    border-right-color:#7fa9e4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#396095;
+}.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#dfe8f6;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/default/grid/sort-hd.gif);
+    border-color: #99bbe8;
+}.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-v-thumb.png);
+}.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/default/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/default/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/default/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/default/window/icon-error.gif);
+}
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/ext-all-debug.js b/src/main/webapp/lib/ext-3.4.0/ext-all-debug.js
new file mode 100644
index 0000000000000000000000000000000000000000..f878a114181aeb08a604384fca39c77fad18126b
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/ext-all-debug.js
@@ -0,0 +1,52079 @@
+
+(function(){
+
+var EXTUTIL = Ext.util,
+    EACH = Ext.each,
+    TRUE = true,
+    FALSE = false;
+
+EXTUTIL.Observable = function(){
+    
+    var me = this, e = me.events;
+    if(me.listeners){
+        me.on(me.listeners);
+        delete me.listeners;
+    }
+    me.events = e || {};
+};
+
+EXTUTIL.Observable.prototype = {
+    
+    filterOptRe : /^(?:scope|delay|buffer|single)$/,
+
+    
+    fireEvent : function(){
+        var a = Array.prototype.slice.call(arguments, 0),
+            ename = a[0].toLowerCase(),
+            me = this,
+            ret = TRUE,
+            ce = me.events[ename],
+            cc,
+            q,
+            c;
+        if (me.eventsSuspended === TRUE) {
+            if (q = me.eventQueue) {
+                q.push(a);
+            }
+        }
+        else if(typeof ce == 'object') {
+            if (ce.bubble){
+                if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
+                    return FALSE;
+                }
+                c = me.getBubbleTarget && me.getBubbleTarget();
+                if(c && c.enableBubble) {
+                    cc = c.events[ename];
+                    if(!cc || typeof cc != 'object' || !cc.bubble) {
+                        c.enableBubble(ename);
+                    }
+                    return c.fireEvent.apply(c, a);
+                }
+            }
+            else {
+                a.shift();
+                ret = ce.fire.apply(ce, a);
+            }
+        }
+        return ret;
+    },
+
+    
+    addListener : function(eventName, fn, scope, o){
+        var me = this,
+            e,
+            oe,
+            ce;
+            
+        if (typeof eventName == 'object') {
+            o = eventName;
+            for (e in o) {
+                oe = o[e];
+                if (!me.filterOptRe.test(e)) {
+                    me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
+                }
+            }
+        } else {
+            eventName = eventName.toLowerCase();
+            ce = me.events[eventName] || TRUE;
+            if (typeof ce == 'boolean') {
+                me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
+            }
+            ce.addListener(fn, scope, typeof o == 'object' ? o : {});
+        }
+    },
+
+    
+    removeListener : function(eventName, fn, scope){
+        var ce = this.events[eventName.toLowerCase()];
+        if (typeof ce == 'object') {
+            ce.removeListener(fn, scope);
+        }
+    },
+
+    
+    purgeListeners : function(){
+        var events = this.events,
+            evt,
+            key;
+        for(key in events){
+            evt = events[key];
+            if(typeof evt == 'object'){
+                evt.clearListeners();
+            }
+        }
+    },
+
+    
+    addEvents : function(o){
+        var me = this;
+        me.events = me.events || {};
+        if (typeof o == 'string') {
+            var a = arguments,
+                i = a.length;
+            while(i--) {
+                me.events[a[i]] = me.events[a[i]] || TRUE;
+            }
+        } else {
+            Ext.applyIf(me.events, o);
+        }
+    },
+
+    
+    hasListener : function(eventName){
+        var e = this.events[eventName.toLowerCase()];
+        return typeof e == 'object' && e.listeners.length > 0;
+    },
+
+    
+    suspendEvents : function(queueSuspended){
+        this.eventsSuspended = TRUE;
+        if(queueSuspended && !this.eventQueue){
+            this.eventQueue = [];
+        }
+    },
+
+    
+    resumeEvents : function(){
+        var me = this,
+            queued = me.eventQueue || [];
+        me.eventsSuspended = FALSE;
+        delete me.eventQueue;
+        EACH(queued, function(e) {
+            me.fireEvent.apply(me, e);
+        });
+    }
+};
+
+var OBSERVABLE = EXTUTIL.Observable.prototype;
+
+OBSERVABLE.on = OBSERVABLE.addListener;
+
+OBSERVABLE.un = OBSERVABLE.removeListener;
+
+
+EXTUTIL.Observable.releaseCapture = function(o){
+    o.fireEvent = OBSERVABLE.fireEvent;
+};
+
+function createTargeted(h, o, scope){
+    return function(){
+        if(o.target == arguments[0]){
+            h.apply(scope, Array.prototype.slice.call(arguments, 0));
+        }
+    };
+};
+
+function createBuffered(h, o, l, scope){
+    l.task = new EXTUTIL.DelayedTask();
+    return function(){
+        l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
+    };
+};
+
+function createSingle(h, e, fn, scope){
+    return function(){
+        e.removeListener(fn, scope);
+        return h.apply(scope, arguments);
+    };
+};
+
+function createDelayed(h, o, l, scope){
+    return function(){
+        var task = new EXTUTIL.DelayedTask(),
+            args = Array.prototype.slice.call(arguments, 0);
+        if(!l.tasks) {
+            l.tasks = [];
+        }
+        l.tasks.push(task);
+        task.delay(o.delay || 10, function(){
+            l.tasks.remove(task);
+            h.apply(scope, args);
+        }, scope);
+    };
+};
+
+EXTUTIL.Event = function(obj, name){
+    this.name = name;
+    this.obj = obj;
+    this.listeners = [];
+};
+
+EXTUTIL.Event.prototype = {
+    addListener : function(fn, scope, options){
+        var me = this,
+            l;
+        scope = scope || me.obj;
+        if(!me.isListening(fn, scope)){
+            l = me.createListener(fn, scope, options);
+            if(me.firing){ 
+                me.listeners = me.listeners.slice(0);
+            }
+            me.listeners.push(l);
+        }
+    },
+
+    createListener: function(fn, scope, o){
+        o = o || {};
+        scope = scope || this.obj;
+        var l = {
+            fn: fn,
+            scope: scope,
+            options: o
+        }, h = fn;
+        if(o.target){
+            h = createTargeted(h, o, scope);
+        }
+        if(o.delay){
+            h = createDelayed(h, o, l, scope);
+        }
+        if(o.single){
+            h = createSingle(h, this, fn, scope);
+        }
+        if(o.buffer){
+            h = createBuffered(h, o, l, scope);
+        }
+        l.fireFn = h;
+        return l;
+    },
+
+    findListener : function(fn, scope){
+        var list = this.listeners,
+            i = list.length,
+            l;
+
+        scope = scope || this.obj;
+        while(i--){
+            l = list[i];
+            if(l){
+                if(l.fn == fn && l.scope == scope){
+                    return i;
+                }
+            }
+        }
+        return -1;
+    },
+
+    isListening : function(fn, scope){
+        return this.findListener(fn, scope) != -1;
+    },
+
+    removeListener : function(fn, scope){
+        var index,
+            l,
+            k,
+            me = this,
+            ret = FALSE;
+        if((index = me.findListener(fn, scope)) != -1){
+            if (me.firing) {
+                me.listeners = me.listeners.slice(0);
+            }
+            l = me.listeners[index];
+            if(l.task) {
+                l.task.cancel();
+                delete l.task;
+            }
+            k = l.tasks && l.tasks.length;
+            if(k) {
+                while(k--) {
+                    l.tasks[k].cancel();
+                }
+                delete l.tasks;
+            }
+            me.listeners.splice(index, 1);
+            ret = TRUE;
+        }
+        return ret;
+    },
+
+    
+    clearListeners : function(){
+        var me = this,
+            l = me.listeners,
+            i = l.length;
+        while(i--) {
+            me.removeListener(l[i].fn, l[i].scope);
+        }
+    },
+
+    fire : function(){
+        var me = this,
+            listeners = me.listeners,
+            len = listeners.length,
+            i = 0,
+            l;
+
+        if(len > 0){
+            me.firing = TRUE;
+            var args = Array.prototype.slice.call(arguments, 0);
+            for (; i < len; i++) {
+                l = listeners[i];
+                if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
+                    return (me.firing = FALSE);
+                }
+            }
+        }
+        me.firing = FALSE;
+        return TRUE;
+    }
+
+};
+})();
+
+Ext.DomHelper = function(){
+    var tempTableEl = null,
+        emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
+        tableRe = /^table|tbody|tr|td$/i,
+        confRe = /tag|children|cn|html$/i,
+        tableElRe = /td|tr|tbody/i,
+        cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
+        endRe = /end/i,
+        pub,
+        
+        afterbegin = 'afterbegin',
+        afterend = 'afterend',
+        beforebegin = 'beforebegin',
+        beforeend = 'beforeend',
+        ts = '<table>',
+        te = '</table>',
+        tbs = ts+'<tbody>',
+        tbe = '</tbody>'+te,
+        trs = tbs + '<tr>',
+        tre = '</tr>'+tbe;
+
+    
+    function doInsert(el, o, returnElement, pos, sibling, append){
+        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
+        return returnElement ? Ext.get(newNode, true) : newNode;
+    }
+
+    
+    function createHtml(o){
+        var b = '',
+            attr,
+            val,
+            key,
+            cn;
+
+        if(typeof o == "string"){
+            b = o;
+        } else if (Ext.isArray(o)) {
+            for (var i=0; i < o.length; i++) {
+                if(o[i]) {
+                    b += createHtml(o[i]);
+                }
+            };
+        } else {
+            b += '<' + (o.tag = o.tag || 'div');
+            for (attr in o) {
+                val = o[attr];
+                if(!confRe.test(attr)){
+                    if (typeof val == "object") {
+                        b += ' ' + attr + '="';
+                        for (key in val) {
+                            b += key + ':' + val[key] + ';';
+                        };
+                        b += '"';
+                    }else{
+                        b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
+                    }
+                }
+            };
+            
+            if (emptyTags.test(o.tag)) {
+                b += '/>';
+            } else {
+                b += '>';
+                if ((cn = o.children || o.cn)) {
+                    b += createHtml(cn);
+                } else if(o.html){
+                    b += o.html;
+                }
+                b += '</' + o.tag + '>';
+            }
+        }
+        return b;
+    }
+
+    function ieTable(depth, s, h, e){
+        tempTableEl.innerHTML = [s, h, e].join('');
+        var i = -1,
+            el = tempTableEl,
+            ns;
+        while(++i < depth){
+            el = el.firstChild;
+        }
+
+        if(ns = el.nextSibling){
+            var df = document.createDocumentFragment();
+            while(el){
+                ns = el.nextSibling;
+                df.appendChild(el);
+                el = ns;
+            }
+            el = df;
+        }
+        return el;
+    }
+
+    
+    function insertIntoTable(tag, where, el, html) {
+        var node,
+            before;
+
+        tempTableEl = tempTableEl || document.createElement('div');
+
+        if(tag == 'td' && (where == afterbegin || where == beforeend) ||
+           !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
+            return;
+        }
+        before = where == beforebegin ? el :
+                 where == afterend ? el.nextSibling :
+                 where == afterbegin ? el.firstChild : null;
+
+        if (where == beforebegin || where == afterend) {
+            el = el.parentNode;
+        }
+
+        if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
+            node = ieTable(4, trs, html, tre);
+        } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
+                   (tag == 'tr' && (where == beforebegin || where == afterend))) {
+            node = ieTable(3, tbs, html, tbe);
+        } else {
+            node = ieTable(2, ts, html, te);
+        }
+        el.insertBefore(node, before);
+        return node;
+    }
+
+       
+    function createContextualFragment(html){
+        var div = document.createElement("div"),
+            fragment = document.createDocumentFragment(),
+            i = 0,
+            length, childNodes;
+        
+        div.innerHTML = html;
+        childNodes = div.childNodes;
+        length = childNodes.length;
+        
+        for (; i < length; i++) {
+            fragment.appendChild(childNodes[i].cloneNode(true));
+        }
+        
+        return fragment;
+    }
+    
+    pub = {
+        
+        markup : function(o){
+            return createHtml(o);
+        },
+
+        
+        applyStyles : function(el, styles){
+            if (styles) {
+                var matches;
+
+                el = Ext.fly(el);
+                if (typeof styles == "function") {
+                    styles = styles.call();
+                }
+                if (typeof styles == "string") {
+                    
+                    cssRe.lastIndex = 0;
+                    while ((matches = cssRe.exec(styles))) {
+                        el.setStyle(matches[1], matches[2]);
+                    }
+                } else if (typeof styles == "object") {
+                    el.setStyle(styles);
+                }
+            }
+        },
+        
+        insertHtml : function(where, el, html){
+            var hash = {},
+                hashVal,
+                range,
+                rangeEl,
+                setStart,
+                frag,
+                rs;
+
+            where = where.toLowerCase();
+            
+            hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
+            hash[afterend] = ['AfterEnd', 'nextSibling'];
+
+            if (el.insertAdjacentHTML) {
+                if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
+                    return rs;
+                }
+                
+                hash[afterbegin] = ['AfterBegin', 'firstChild'];
+                hash[beforeend] = ['BeforeEnd', 'lastChild'];
+                if ((hashVal = hash[where])) {
+                    el.insertAdjacentHTML(hashVal[0], html);
+                    return el[hashVal[1]];
+                }
+            } else {
+                range = el.ownerDocument.createRange();
+                setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
+                if (hash[where]) {
+                    range[setStart](el);
+                    if (!range.createContextualFragment) {
+                        frag = createContextualFragment(html);
+                    }
+                    else {
+                        frag = range.createContextualFragment(html);
+                    }
+                    el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
+                    return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
+                } else {
+                    rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
+                    if (el.firstChild) {
+                        range[setStart](el[rangeEl]);
+                        if (!range.createContextualFragment) {
+                            frag = createContextualFragment(html);
+                        }
+                        else {
+                            frag = range.createContextualFragment(html);
+                        }
+                        if(where == afterbegin){
+                            el.insertBefore(frag, el.firstChild);
+                        }else{
+                            el.appendChild(frag);
+                        }
+                    } else {
+                        el.innerHTML = html;
+                    }
+                    return el[rangeEl];
+                }
+            }
+            throw 'Illegal insertion point -> "' + where + '"';
+        },
+
+        
+        insertBefore : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforebegin);
+        },
+
+        
+        insertAfter : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterend, 'nextSibling');
+        },
+
+        
+        insertFirst : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
+        },
+
+        
+        append : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforeend, '', true);
+        },
+
+        
+        overwrite : function(el, o, returnElement){
+            el = Ext.getDom(el);
+            el.innerHTML = createHtml(o);
+            return returnElement ? Ext.get(el.firstChild) : el.firstChild;
+        },
+
+        createHtml : createHtml
+    };
+    return pub;
+}();
+
+Ext.Template = function(html){
+    var me = this,
+        a = arguments,
+        buf = [],
+        v;
+
+    if (Ext.isArray(html)) {
+        html = html.join("");
+    } else if (a.length > 1) {
+        for(var i = 0, len = a.length; i < len; i++){
+            v = a[i];
+            if(typeof v == 'object'){
+                Ext.apply(me, v);
+            } else {
+                buf.push(v);
+            }
+        };
+        html = buf.join('');
+    }
+
+    
+    me.html = html;
+    
+    if (me.compiled) {
+        me.compile();
+    }
+};
+Ext.Template.prototype = {
+    
+    re : /\{([\w\-]+)\}/g,
+    
+
+    
+    applyTemplate : function(values){
+        var me = this;
+
+        return me.compiled ?
+                me.compiled(values) :
+                me.html.replace(me.re, function(m, name){
+                    return values[name] !== undefined ? values[name] : "";
+                });
+    },
+
+    
+    set : function(html, compile){
+        var me = this;
+        me.html = html;
+        me.compiled = null;
+        return compile ? me.compile() : me;
+    },
+
+    
+    compile : function(){
+        var me = this,
+            sep = Ext.isGecko ? "+" : ",";
+
+        function fn(m, name){
+            name = "values['" + name + "']";
+            return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
+        }
+
+        eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
+             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
+             (Ext.isGecko ?  "';};" : "'].join('');};"));
+        return me;
+    },
+
+    
+    insertFirst: function(el, values, returnElement){
+        return this.doInsert('afterBegin', el, values, returnElement);
+    },
+
+    
+    insertBefore: function(el, values, returnElement){
+        return this.doInsert('beforeBegin', el, values, returnElement);
+    },
+
+    
+    insertAfter : function(el, values, returnElement){
+        return this.doInsert('afterEnd', el, values, returnElement);
+    },
+
+    
+    append : function(el, values, returnElement){
+        return this.doInsert('beforeEnd', el, values, returnElement);
+    },
+
+    doInsert : function(where, el, values, returnEl){
+        el = Ext.getDom(el);
+        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
+        return returnEl ? Ext.get(newNode, true) : newNode;
+    },
+
+    
+    overwrite : function(el, values, returnElement){
+        el = Ext.getDom(el);
+        el.innerHTML = this.applyTemplate(values);
+        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
+    }
+};
+
+Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
+
+
+Ext.Template.from = function(el, config){
+    el = Ext.getDom(el);
+    return new Ext.Template(el.value || el.innerHTML, config || '');
+};
+
+
+Ext.DomQuery = function(){
+    var cache = {}, 
+    	simpleCache = {}, 
+    	valueCache = {},
+    	nonSpace = /\S/,
+    	trimRe = /^\s+|\s+$/g,
+    	tplRe = /\{(\d+)\}/g,
+    	modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
+    	tagTokenRe = /^(#)?([\w\-\*]+)/,
+    	nthRe = /(\d*)n\+?(\d*)/, 
+    	nthRe2 = /\D/,
+    	
+	
+	
+	isIE = window.ActiveXObject ? true : false,
+	key = 30803;
+    
+    
+    
+    eval("var batch = 30803;");    	
+
+    
+    
+    function child(parent, index){
+        var i = 0,
+            n = parent.firstChild;
+        while(n){
+            if(n.nodeType == 1){
+               if(++i == index){
+                   return n;
+               }
+            }
+            n = n.nextSibling;
+        }
+        return null;
+    }
+
+    
+    function next(n){	
+        while((n = n.nextSibling) && n.nodeType != 1);
+        return n;
+    }
+
+    
+    function prev(n){
+        while((n = n.previousSibling) && n.nodeType != 1);
+        return n;
+    }
+
+    
+    
+    function children(parent){
+        var n = parent.firstChild,
+	    nodeIndex = -1,
+	    nextNode;
+	while(n){
+	    nextNode = n.nextSibling;
+	    
+	    if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
+		parent.removeChild(n);
+	    }else{
+		
+		n.nodeIndex = ++nodeIndex;
+	    }
+	    n = nextNode;
+	}
+	return this;
+    }
+
+
+    
+    
+    function byClassName(nodeSet, cls){
+        if(!cls){
+            return nodeSet;
+        }
+        var result = [], ri = -1;
+        for(var i = 0, ci; ci = nodeSet[i]; i++){
+            if((' '+ci.className+' ').indexOf(cls) != -1){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    };
+
+    function attrValue(n, attr){
+	
+        if(!n.tagName && typeof n.length != "undefined"){
+            n = n[0];
+        }
+        if(!n){
+            return null;
+        }
+
+        if(attr == "for"){
+            return n.htmlFor;
+        }
+        if(attr == "class" || attr == "className"){
+            return n.className;
+        }
+        return n.getAttribute(attr) || n[attr];
+
+    };
+
+
+    
+    
+    
+    function getNodes(ns, mode, tagName){
+        var result = [], ri = -1, cs;
+        if(!ns){
+            return result;
+        }
+        tagName = tagName || "*";
+	
+        if(typeof ns.getElementsByTagName != "undefined"){
+            ns = [ns];
+        }
+	
+	
+	
+        if(!mode){
+            for(var i = 0, ni; ni = ns[i]; i++){
+                cs = ni.getElementsByTagName(tagName);
+                for(var j = 0, ci; ci = cs[j]; j++){
+                    result[++ri] = ci;
+                }
+            }
+	
+	
+        } else if(mode == "/" || mode == ">"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, ni, cn; ni = ns[i]; i++){
+                cn = ni.childNodes;
+                for(var j = 0, cj; cj = cn[j]; j++){
+                    if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
+                        result[++ri] = cj;
+                    }
+                }
+            }
+	
+	
+        }else if(mode == "+"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, n; n = ns[i]; i++){
+                while((n = n.nextSibling) && n.nodeType != 1);
+                if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
+                    result[++ri] = n;
+                }
+            }
+	
+	
+        }else if(mode == "~"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, n; n = ns[i]; i++){
+                while((n = n.nextSibling)){
+                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
+                        result[++ri] = n;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    function concat(a, b){
+        if(b.slice){
+            return a.concat(b);
+        }
+        for(var i = 0, l = b.length; i < l; i++){
+            a[a.length] = b[i];
+        }
+        return a;
+    }
+
+    function byTag(cs, tagName){
+        if(cs.tagName || cs == document){
+            cs = [cs];
+        }
+        if(!tagName){
+            return cs;
+        }
+        var result = [], ri = -1;
+        tagName = tagName.toLowerCase();
+        for(var i = 0, ci; ci = cs[i]; i++){
+            if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    }
+
+    function byId(cs, id){
+        if(cs.tagName || cs == document){
+            cs = [cs];
+        }
+        if(!id){
+            return cs;
+        }
+        var result = [], ri = -1;
+        for(var i = 0, ci; ci = cs[i]; i++){
+            if(ci && ci.id == id){
+                result[++ri] = ci;
+                return result;
+            }
+        }
+        return result;
+    }
+
+    
+    
+    function byAttribute(cs, attr, value, op, custom){
+        var result = [], 
+            ri = -1, 
+            useGetStyle = custom == "{",	    
+            fn = Ext.DomQuery.operators[op],	    
+            a,
+            xml,
+            hasXml;
+            
+        for(var i = 0, ci; ci = cs[i]; i++){
+	    
+            if(ci.nodeType != 1){
+                continue;
+            }
+            
+            if(!hasXml){
+                xml = Ext.DomQuery.isXml(ci);
+                hasXml = true;
+            }
+	    
+            
+            if(!xml){
+                if(useGetStyle){
+                    a = Ext.DomQuery.getStyle(ci, attr);
+                } else if (attr == "class" || attr == "className"){
+                    a = ci.className;
+                } else if (attr == "for"){
+                    a = ci.htmlFor;
+                } else if (attr == "href"){
+		    
+		    
+                    a = ci.getAttribute("href", 2);
+                } else{
+                    a = ci.getAttribute(attr);
+                }
+            }else{
+                a = ci.getAttribute(attr);
+            }
+            if((fn && fn(a, value)) || (!fn && a)){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    }
+
+    function byPseudo(cs, name, value){
+        return Ext.DomQuery.pseudos[name](cs, value);
+    }
+
+    function nodupIEXml(cs){
+        var d = ++key, 
+            r;
+        cs[0].setAttribute("_nodup", d);
+        r = [cs[0]];
+        for(var i = 1, len = cs.length; i < len; i++){
+            var c = cs[i];
+            if(!c.getAttribute("_nodup") != d){
+                c.setAttribute("_nodup", d);
+                r[r.length] = c;
+            }
+        }
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i].removeAttribute("_nodup");
+        }
+        return r;
+    }
+
+    function nodup(cs){
+        if(!cs){
+            return [];
+        }
+        var len = cs.length, c, i, r = cs, cj, ri = -1;
+        if(!len || typeof cs.nodeType != "undefined" || len == 1){
+            return cs;
+        }
+        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
+            return nodupIEXml(cs);
+        }
+        var d = ++key;
+        cs[0]._nodup = d;
+        for(i = 1; c = cs[i]; i++){
+            if(c._nodup != d){
+                c._nodup = d;
+            }else{
+                r = [];
+                for(var j = 0; j < i; j++){
+                    r[++ri] = cs[j];
+                }
+                for(j = i+1; cj = cs[j]; j++){
+                    if(cj._nodup != d){
+                        cj._nodup = d;
+                        r[++ri] = cj;
+                    }
+                }
+                return r;
+            }
+        }
+        return r;
+    }
+
+    function quickDiffIEXml(c1, c2){
+        var d = ++key,
+            r = [];
+        for(var i = 0, len = c1.length; i < len; i++){
+            c1[i].setAttribute("_qdiff", d);
+        }        
+        for(var i = 0, len = c2.length; i < len; i++){
+            if(c2[i].getAttribute("_qdiff") != d){
+                r[r.length] = c2[i];
+            }
+        }
+        for(var i = 0, len = c1.length; i < len; i++){
+           c1[i].removeAttribute("_qdiff");
+        }
+        return r;
+    }
+
+    function quickDiff(c1, c2){
+        var len1 = c1.length,
+        	d = ++key,
+        	r = [];
+        if(!len1){
+            return c2;
+        }
+        if(isIE && typeof c1[0].selectSingleNode != "undefined"){
+            return quickDiffIEXml(c1, c2);
+        }        
+        for(var i = 0; i < len1; i++){
+            c1[i]._qdiff = d;
+        }        
+        for(var i = 0, len = c2.length; i < len; i++){
+            if(c2[i]._qdiff != d){
+                r[r.length] = c2[i];
+            }
+        }
+        return r;
+    }
+
+    function quickId(ns, mode, root, id){
+        if(ns == root){
+           var d = root.ownerDocument || root;
+           return d.getElementById(id);
+        }
+        ns = getNodes(ns, mode, "*");
+        return byId(ns, id);
+    }
+
+    return {
+        getStyle : function(el, name){
+            return Ext.fly(el).getStyle(name);
+        },
+        
+        compile : function(path, type){
+            type = type || "select";
+
+    	    
+            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
+        		mode,		
+        		lastPath,
+            	matchers = Ext.DomQuery.matchers,
+            	matchersLn = matchers.length,
+            	modeMatch,
+            	
+            	lmode = path.match(modeRe);
+            
+            if(lmode && lmode[1]){
+                fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
+                path = path.replace(lmode[1], "");
+            }
+	    
+            
+            while(path.substr(0, 1)=="/"){
+                path = path.substr(1);
+            }
+
+            while(path && lastPath != path){
+                lastPath = path;
+                var tokenMatch = path.match(tagTokenRe);
+                if(type == "select"){
+                    if(tokenMatch){
+			
+                        if(tokenMatch[1] == "#"){
+                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';			
+                        }else{
+                            fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
+                        }
+                        path = path.replace(tokenMatch[0], "");
+                    }else if(path.substr(0, 1) != '@'){
+                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
+                    }
+		
+                }else{
+                    if(tokenMatch){
+                        if(tokenMatch[1] == "#"){
+                            fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
+                        }else{
+                            fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
+                        }
+                        path = path.replace(tokenMatch[0], "");
+                    }
+                }
+                while(!(modeMatch = path.match(modeRe))){
+                    var matched = false;
+                    for(var j = 0; j < matchersLn; j++){
+                        var t = matchers[j];
+                        var m = path.match(t.re);
+                        if(m){
+                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
+				return m[i];
+			    });
+                            path = path.replace(m[0], "");
+                            matched = true;
+                            break;
+                        }
+                    }
+                    
+                    if(!matched){
+                        throw 'Error parsing selector, parsing failed at "' + path + '"';
+                    }
+                }
+                if(modeMatch[1]){
+                    fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
+                    path = path.replace(modeMatch[1], "");
+                }
+            }
+	    
+            fn[fn.length] = "return nodup(n);\n}";
+	    
+	    
+            eval(fn.join(""));
+            return f;
+        },
+
+        
+	jsSelect: function(path, root, type){
+	    
+	    root = root || document;
+	    
+            if(typeof root == "string"){
+                root = document.getElementById(root);
+            }
+            var paths = path.split(","),
+            	results = [];
+		
+	    
+            for(var i = 0, len = paths.length; i < len; i++){		
+                var subPath = paths[i].replace(trimRe, "");
+		
+                if(!cache[subPath]){
+                    cache[subPath] = Ext.DomQuery.compile(subPath);
+                    if(!cache[subPath]){
+                        throw subPath + " is not a valid selector";
+                    }
+                }
+                var result = cache[subPath](root);
+                if(result && result != document){
+                    results = results.concat(result);
+                }
+            }
+	    
+	    
+	    
+            if(paths.length > 1){
+                return nodup(results);
+            }
+            return results;
+        },
+	isXml: function(el) {
+	    var docEl = (el ? el.ownerDocument || el : 0).documentElement;
+	    return docEl ? docEl.nodeName !== "HTML" : false;
+	},
+        select : document.querySelectorAll ? function(path, root, type) {
+	    root = root || document;
+	    if (!Ext.DomQuery.isXml(root)) {
+		try {
+		    var cs = root.querySelectorAll(path);
+		    return Ext.toArray(cs);
+		}
+		catch (ex) {}		
+	    }	    
+	    return Ext.DomQuery.jsSelect.call(this, path, root, type);
+	} : function(path, root, type) {
+	    return Ext.DomQuery.jsSelect.call(this, path, root, type);
+	},
+
+        
+        selectNode : function(path, root){
+            return Ext.DomQuery.select(path, root)[0];
+        },
+
+        
+        selectValue : function(path, root, defaultValue){
+            path = path.replace(trimRe, "");
+            if(!valueCache[path]){
+                valueCache[path] = Ext.DomQuery.compile(path, "select");
+            }
+            var n = valueCache[path](root), v;
+            n = n[0] ? n[0] : n;
+            	    
+	    
+	    
+	    
+	    
+            if (typeof n.normalize == 'function') n.normalize();
+            
+            v = (n && n.firstChild ? n.firstChild.nodeValue : null);
+            return ((v === null||v === undefined||v==='') ? defaultValue : v);
+        },
+
+        
+        selectNumber : function(path, root, defaultValue){
+            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
+            return parseFloat(v);
+        },
+
+        
+        is : function(el, ss){
+            if(typeof el == "string"){
+                el = document.getElementById(el);
+            }
+            var isArray = Ext.isArray(el),
+            	result = Ext.DomQuery.filter(isArray ? el : [el], ss);
+            return isArray ? (result.length == el.length) : (result.length > 0);
+        },
+
+        
+        filter : function(els, ss, nonMatches){
+            ss = ss.replace(trimRe, "");
+            if(!simpleCache[ss]){
+                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
+            }
+            var result = simpleCache[ss](els);
+            return nonMatches ? quickDiff(result, els) : result;
+        },
+
+        
+        matchers : [{
+                re: /^\.([\w\-]+)/,
+                select: 'n = byClassName(n, " {1} ");'
+            }, {
+                re: /^\:([\w\-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
+                select: 'n = byPseudo(n, "{1}", "{2}");'
+            },{
+                re: /^(?:([\[\{])(?:@)?([\w\-]+)\s?(?:(=|.=)\s?(["']?)(.*?)\4)?[\]\}])/,
+                select: 'n = byAttribute(n, "{2}", "{5}", "{3}", "{1}");'
+            }, {
+                re: /^#([\w\-]+)/,
+                select: 'n = byId(n, "{1}");'
+            },{
+                re: /^@([\w\-]+)/,
+                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
+            }
+        ],
+
+        /**
+         * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
+         * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, &gt; &lt;.
+         */
+        operators : {
+            "=" : function(a, v){
+                return a == v;
+            },
+            "!=" : function(a, v){
+                return a != v;
+            },
+            "^=" : function(a, v){
+                return a && a.substr(0, v.length) == v;
+            },
+            "$=" : function(a, v){
+                return a && a.substr(a.length-v.length) == v;
+            },
+            "*=" : function(a, v){
+                return a && a.indexOf(v) !== -1;
+            },
+            "%=" : function(a, v){
+                return (a % v) == 0;
+            },
+            "|=" : function(a, v){
+                return a && (a == v || a.substr(0, v.length+1) == v+'-');
+            },
+            "~=" : function(a, v){
+                return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
+            }
+        },
+
+        /**
+         * <p>Object hash of "pseudo class" filter functions which are used when filtering selections. Each function is passed
+         * two parameters:</p><div class="mdetail-params"><ul>
+         * <li><b>c</b> : Array<div class="sub-desc">An Array of DOM elements to filter.</div></li>
+         * <li><b>v</b> : String<div class="sub-desc">The argument (if any) supplied in the selector.</div></li>
+         * </ul></div>
+         * <p>A filter function returns an Array of DOM elements which conform to the pseudo class.</p>
+         * <p>In addition to the provided pseudo classes listed above such as <code>first-child</code> and <code>nth-child</code>,
+         * developers may add additional, custom psuedo class filters to select elements according to application-specific requirements.</p>
+         * <p>For example, to filter <code>&lt;a></code> elements to only return links to <i>external</i> resources:</p>
+         * <code><pre>
+Ext.DomQuery.pseudos.external = function(c, v){
+    var r = [], ri = -1;
+    for(var i = 0, ci; ci = c[i]; i++){
+//      Include in result set only if it's a link to an external resource
+        if(ci.hostname != location.hostname){
+            r[++ri] = ci;
+        }
+    }
+    return r;
+};</pre></code>
+         * Then external links could be gathered with the following statement:<code><pre>
+var externalLinks = Ext.select("a:external");
+</code></pre>
+         */
+        pseudos : {
+            "first-child" : function(c){
+                var r = [], ri = -1, n;
+                for(var i = 0, ci; ci = n = c[i]; i++){
+                    while((n = n.previousSibling) && n.nodeType != 1);
+                    if(!n){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "last-child" : function(c){
+                var r = [], ri = -1, n;
+                for(var i = 0, ci; ci = n = c[i]; i++){
+                    while((n = n.nextSibling) && n.nodeType != 1);
+                    if(!n){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "nth-child" : function(c, a) {
+                var r = [], ri = -1,
+                	m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
+                	f = (m[1] || 1) - 0, l = m[2] - 0;
+                for(var i = 0, n; n = c[i]; i++){
+                    var pn = n.parentNode;
+                    if (batch != pn._batch) {
+                        var j = 0;
+                        for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
+                            if(cn.nodeType == 1){
+                               cn.nodeIndex = ++j;
+                            }
+                        }
+                        pn._batch = batch;
+                    }
+                    if (f == 1) {
+                        if (l == 0 || n.nodeIndex == l){
+                            r[++ri] = n;
+                        }
+                    } else if ((n.nodeIndex + l) % f == 0){
+                        r[++ri] = n;
+                    }
+                }
+
+                return r;
+            },
+
+            "only-child" : function(c){
+                var r = [], ri = -1;;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(!prev(ci) && !next(ci)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "empty" : function(c){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var cns = ci.childNodes, j = 0, cn, empty = true;
+                    while(cn = cns[j]){
+                        ++j;
+                        if(cn.nodeType == 1 || cn.nodeType == 3){
+                            empty = false;
+                            break;
+                        }
+                    }
+                    if(empty){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "contains" : function(c, v){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "nodeValue" : function(c, v){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(ci.firstChild && ci.firstChild.nodeValue == v){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "checked" : function(c){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(ci.checked == true){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "not" : function(c, ss){
+                return Ext.DomQuery.filter(c, ss, true);
+            },
+
+            "any" : function(c, selectors){
+                var ss = selectors.split('|'),
+                	r = [], ri = -1, s;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    for(var j = 0; s = ss[j]; j++){
+                        if(Ext.DomQuery.is(ci, s)){
+                            r[++ri] = ci;
+                            break;
+                        }
+                    }
+                }
+                return r;
+            },
+
+            "odd" : function(c){
+                return this["nth-child"](c, "odd");
+            },
+
+            "even" : function(c){
+                return this["nth-child"](c, "even");
+            },
+
+            "nth" : function(c, a){
+                return c[a-1] || [];
+            },
+
+            "first" : function(c){
+                return c[0] || [];
+            },
+
+            "last" : function(c){
+                return c[c.length-1] || [];
+            },
+
+            "has" : function(c, ss){
+                var s = Ext.DomQuery.select,
+                	r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(s(ss, ci).length > 0){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "next" : function(c, ss){
+                var is = Ext.DomQuery.is,
+                	r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var n = next(ci);
+                    if(n && is(n, ss)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "prev" : function(c, ss){
+                var is = Ext.DomQuery.is,
+                	r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var n = prev(ci);
+                    if(n && is(n, ss)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            }
+        }
+    };
+}();
+
+/**
+ * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Ext.DomQuery#select}
+ * @param {String} path The selector/xpath query
+ * @param {Node} root (optional) The start of the query (defaults to document).
+ * @return {Array}
+ * @member Ext
+ * @method query
+ */
+Ext.query = Ext.DomQuery.select;
+/**
+ * @class Ext.util.DelayedTask
+ * <p> The DelayedTask class provides a convenient way to "buffer" the execution of a method,
+ * performing setTimeout where a new timeout cancels the old timeout. When called, the
+ * task will wait the specified time period before executing. If durng that time period,
+ * the task is called again, the original call will be cancelled. This continues so that
+ * the function is only called a single time for each iteration.</p>
+ * <p>This method is especially useful for things like detecting whether a user has finished
+ * typing in a text field. An example would be performing validation on a keypress. You can
+ * use this class to buffer the keypress events for a certain number of milliseconds, and
+ * perform only if they stop for that amount of time.  Usage:</p><pre><code>
+var task = new Ext.util.DelayedTask(function(){
+    alert(Ext.getDom('myInputField').value.length);
+});
+// Wait 500ms before calling our function. If the user presses another key 
+// during that 500ms, it will be cancelled and we'll wait another 500ms.
+Ext.get('myInputField').on('keypress', function(){
+    task.{@link #delay}(500); 
+});
+ * </code></pre> 
+ * <p>Note that we are using a DelayedTask here to illustrate a point. The configuration
+ * option <tt>buffer</tt> for {@link Ext.util.Observable#addListener addListener/on} will
+ * also setup a delayed task for you to buffer events.</p> 
+ * @constructor The parameters to this constructor serve as defaults and are not required.
+ * @param {Function} fn (optional) The default function to call.
+ * @param {Object} scope The default scope (The <code><b>this</b></code> reference) in which the
+ * function is called. If not specified, <code>this</code> will refer to the browser window.
+ * @param {Array} args (optional) The default Array of arguments.
+ */
+Ext.util.DelayedTask = function(fn, scope, args){
+    var me = this,
+    	id,    	
+    	call = function(){
+    		clearInterval(id);
+	        id = null;
+	        fn.apply(scope, args || []);
+	    };
+	    
+    /**
+     * Cancels any pending timeout and queues a new one
+     * @param {Number} delay The milliseconds to delay
+     * @param {Function} newFn (optional) Overrides function passed to constructor
+     * @param {Object} newScope (optional) Overrides scope passed to constructor. Remember that if no scope
+     * is specified, <code>this</code> will refer to the browser window.
+     * @param {Array} newArgs (optional) Overrides args passed to constructor
+     */
+    me.delay = function(delay, newFn, newScope, newArgs){
+        me.cancel();
+        fn = newFn || fn;
+        scope = newScope || scope;
+        args = newArgs || args;
+        id = setInterval(call, delay);
+    };
+
+    /**
+     * Cancel the last queued timeout
+     */
+    me.cancel = function(){
+        if(id){
+            clearInterval(id);
+            id = null;
+        }
+    };
+};/**
+ * @class Ext.Element
+ * <p>Encapsulates a DOM element, adding simple DOM manipulation facilities, normalizing for browser differences.</p>
+ * <p>All instances of this class inherit the methods of {@link Ext.Fx} making visual effects easily available to all DOM elements.</p>
+ * <p>Note that the events documented in this class are not Ext events, they encapsulate browser events. To
+ * access the underlying browser event, see {@link Ext.EventObject#browserEvent}. Some older
+ * browsers may not support the full range of events. Which events are supported is beyond the control of ExtJs.</p>
+ * Usage:<br>
+<pre><code>
+// by id
+var el = Ext.get("my-div");
+
+// by DOM element reference
+var el = Ext.get(myDivElement);
+</code></pre>
+ * <b>Animations</b><br />
+ * <p>When an element is manipulated, by default there is no animation.</p>
+ * <pre><code>
+var el = Ext.get("my-div");
+
+// no animation
+el.setWidth(100);
+ * </code></pre>
+ * <p>Many of the functions for manipulating an element have an optional "animate" parameter.  This
+ * parameter can be specified as boolean (<tt>true</tt>) for default animation effects.</p>
+ * <pre><code>
+// default animation
+el.setWidth(100, true);
+ * </code></pre>
+ *
+ * <p>To configure the effects, an object literal with animation options to use as the Element animation
+ * configuration object can also be specified. Note that the supported Element animation configuration
+ * options are a subset of the {@link Ext.Fx} animation options specific to Fx effects.  The supported
+ * Element animation configuration options are:</p>
+<pre>
+Option    Default   Description
+--------- --------  ---------------------------------------------
+{@link Ext.Fx#duration duration}  .35       The duration of the animation in seconds
+{@link Ext.Fx#easing easing}    easeOut   The easing method
+{@link Ext.Fx#callback callback}  none      A function to execute when the anim completes
+{@link Ext.Fx#scope scope}     this      The scope (this) of the callback function
+</pre>
+ *
+ * <pre><code>
+// Element animation options object
+var opt = {
+    {@link Ext.Fx#duration duration}: 1,
+    {@link Ext.Fx#easing easing}: 'elasticIn',
+    {@link Ext.Fx#callback callback}: this.foo,
+    {@link Ext.Fx#scope scope}: this
+};
+// animation with some options set
+el.setWidth(100, opt);
+ * </code></pre>
+ * <p>The Element animation object being used for the animation will be set on the options
+ * object as "anim", which allows you to stop or manipulate the animation. Here is an example:</p>
+ * <pre><code>
+// using the "anim" property to get the Anim object
+if(opt.anim.isAnimated()){
+    opt.anim.stop();
+}
+ * </code></pre>
+ * <p>Also see the <tt>{@link #animate}</tt> method for another animation technique.</p>
+ * <p><b> Composite (Collections of) Elements</b></p>
+ * <p>For working with collections of Elements, see {@link Ext.CompositeElement}</p>
+ * @constructor Create a new Element directly.
+ * @param {String/HTMLElement} element
+ * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
+ */
+(function(){
+var DOC = document;
+
+Ext.Element = function(element, forceNew){
+    var dom = typeof element == "string" ?
+              DOC.getElementById(element) : element,
+        id;
+
+    if(!dom) return null;
+
+    id = dom.id;
+
+    if(!forceNew && id && Ext.elCache[id]){ // element object already exists
+        return Ext.elCache[id].el;
+    }
+
+    /**
+     * The DOM element
+     * @type HTMLElement
+     */
+    this.dom = dom;
+
+    /**
+     * The DOM element ID
+     * @type String
+     */
+    this.id = id || Ext.id(dom);
+};
+
+var DH = Ext.DomHelper,
+    El = Ext.Element,
+    EC = Ext.elCache;
+
+El.prototype = {
+    /**
+     * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
+     * @param {Object} o The object with the attributes
+     * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
+     * @return {Ext.Element} this
+     */
+    set : function(o, useSet){
+        var el = this.dom,
+            attr,
+            val,
+            useSet = (useSet !== false) && !!el.setAttribute;
+
+        for (attr in o) {
+            if (o.hasOwnProperty(attr)) {
+                val = o[attr];
+                if (attr == 'style') {
+                    DH.applyStyles(el, val);
+                } else if (attr == 'cls') {
+                    el.className = val;
+                } else if (useSet) {
+                    el.setAttribute(attr, val);
+                } else {
+                    el[attr] = val;
+                }
+            }
+        }
+        return this;
+    },
+
+//  Mouse events
+    /**
+     * @event click
+     * Fires when a mouse click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event contextmenu
+     * Fires when a right click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event dblclick
+     * Fires when a mouse double click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mousedown
+     * Fires when a mousedown is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseup
+     * Fires when a mouseup is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseover
+     * Fires when a mouseover is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mousemove
+     * Fires when a mousemove is detected with the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseout
+     * Fires when a mouseout is detected with the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseenter
+     * Fires when the mouse enters the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseleave
+     * Fires when the mouse leaves the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  Keyboard events
+    /**
+     * @event keypress
+     * Fires when a keypress is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event keydown
+     * Fires when a keydown is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event keyup
+     * Fires when a keyup is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+
+//  HTML frame/object events
+    /**
+     * @event load
+     * Fires when the user agent finishes loading all content within the element. Only supported by window, frames, objects and images.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event unload
+     * Fires when the user agent removes all content from a window or frame. For elements, it fires when the target element or any of its content has been removed.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event abort
+     * Fires when an object/image is stopped from loading before completely loaded.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event error
+     * Fires when an object/image/frame cannot be loaded properly.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event resize
+     * Fires when a document view is resized.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event scroll
+     * Fires when a document view is scrolled.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  Form events
+    /**
+     * @event select
+     * Fires when a user selects some text in a text field, including input and textarea.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event change
+     * Fires when a control loses the input focus and its value has been modified since gaining focus.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event submit
+     * Fires when a form is submitted.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event reset
+     * Fires when a form is reset.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event focus
+     * Fires when an element receives focus either via the pointing device or by tab navigation.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event blur
+     * Fires when an element loses focus either via the pointing device or by tabbing navigation.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  User Interface events
+    /**
+     * @event DOMFocusIn
+     * Where supported. Similar to HTML focus event, but can be applied to any focusable element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMFocusOut
+     * Where supported. Similar to HTML blur event, but can be applied to any focusable element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMActivate
+     * Where supported. Fires when an element is activated, for instance, through a mouse click or a keypress.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  DOM Mutation events
+    /**
+     * @event DOMSubtreeModified
+     * Where supported. Fires when the subtree is modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeInserted
+     * Where supported. Fires when a node has been added as a child of another node.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeRemoved
+     * Where supported. Fires when a descendant node of the element is removed.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeRemovedFromDocument
+     * Where supported. Fires when a node is being removed from a document.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeInsertedIntoDocument
+     * Where supported. Fires when a node is being inserted into a document.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMAttrModified
+     * Where supported. Fires when an attribute has been modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMCharacterDataModified
+     * Where supported. Fires when the character data has been modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+    /**
+     * The default unit to append to CSS values where a unit isn't provided (defaults to px).
+     * @type String
+     */
+    defaultUnit : "px",
+
+    /**
+     * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
+     * @param {String} selector The simple selector to test
+     * @return {Boolean} True if this element matches the selector, else false
+     */
+    is : function(simpleSelector){
+        return Ext.DomQuery.is(this.dom, simpleSelector);
+    },
+
+    /**
+     * Tries to focus the element. Any exceptions are caught and ignored.
+     * @param {Number} defer (optional) Milliseconds to defer the focus
+     * @return {Ext.Element} this
+     */
+    focus : function(defer, /* private */ dom) {
+        var me = this,
+            dom = dom || me.dom;
+        try{
+            if(Number(defer)){
+                me.focus.defer(defer, null, [null, dom]);
+            }else{
+                dom.focus();
+            }
+        }catch(e){}
+        return me;
+    },
+
+    /**
+     * Tries to blur the element. Any exceptions are caught and ignored.
+     * @return {Ext.Element} this
+     */
+    blur : function() {
+        try{
+            this.dom.blur();
+        }catch(e){}
+        return this;
+    },
+
+    /**
+     * Returns the value of the "value" attribute
+     * @param {Boolean} asNumber true to parse the value as a number
+     * @return {String/Number}
+     */
+    getValue : function(asNumber){
+        var val = this.dom.value;
+        return asNumber ? parseInt(val, 10) : val;
+    },
+
+    /**
+     * Appends an event handler to this element.  The shorthand version {@link #on} is equivalent.
+     * @param {String} eventName The name of event to handle.
+     * @param {Function} fn The handler function the event invokes. This function is passed
+     * the following parameters:<ul>
+     * <li><b>evt</b> : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
+     * <li><b>el</b> : HtmlElement<div class="sub-desc">The DOM element which was the target of the event.
+     * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
+     * <li><b>o</b> : Object<div class="sub-desc">The options object from the addListener call.</div></li>
+     * </ul>
+     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+     * <b>If omitted, defaults to this Element.</b>.
+     * @param {Object} options (optional) An object containing handler configuration properties.
+     * This may contain any of the following properties:<ul>
+     * <li><b>scope</b> Object : <div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+     * <b>If omitted, defaults to this Element.</b></div></li>
+     * <li><b>delegate</b> String: <div class="sub-desc">A simple selector to filter the target or look for a descendant of the target. See below for additional details.</div></li>
+     * <li><b>stopEvent</b> Boolean: <div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
+     * <li><b>preventDefault</b> Boolean: <div class="sub-desc">True to prevent the default action</div></li>
+     * <li><b>stopPropagation</b> Boolean: <div class="sub-desc">True to prevent event propagation</div></li>
+     * <li><b>normalized</b> Boolean: <div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
+     * <li><b>target</b> Ext.Element: <div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
+     * <li><b>delay</b> Number: <div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
+     * <li><b>single</b> Boolean: <div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
+     * <li><b>buffer</b> Number: <div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
+     * by the specified number of milliseconds. If the event fires again within that time, the original
+     * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
+     * </ul><br>
+     * <p>
+     * <b>Combining Options</b><br>
+     * In the following examples, the shorthand form {@link #on} is used rather than the more verbose
+     * addListener.  The two are equivalent.  Using the options argument, it is possible to combine different
+     * types of listeners:<br>
+     * <br>
+     * A delayed, one-time listener that auto stops the event and adds a custom argument (forumId) to the
+     * options object. The options object is available as the third parameter in the handler function.<div style="margin: 5px 20px 20px;">
+     * Code:<pre><code>
+el.on('click', this.onClick, this, {
+    single: true,
+    delay: 100,
+    stopEvent : true,
+    forumId: 4
+});</code></pre></p>
+     * <p>
+     * <b>Attaching multiple handlers in 1 call</b><br>
+     * The method also allows for a single argument to be passed which is a config object containing properties
+     * which specify multiple handlers.</p>
+     * <p>
+     * Code:<pre><code>
+el.on({
+    'click' : {
+        fn: this.onClick,
+        scope: this,
+        delay: 100
+    },
+    'mouseover' : {
+        fn: this.onMouseOver,
+        scope: this
+    },
+    'mouseout' : {
+        fn: this.onMouseOut,
+        scope: this
+    }
+});</code></pre>
+     * <p>
+     * Or a shorthand syntax:<br>
+     * Code:<pre><code></p>
+el.on({
+    'click' : this.onClick,
+    'mouseover' : this.onMouseOver,
+    'mouseout' : this.onMouseOut,
+    scope: this
+});
+     * </code></pre></p>
+     * <p><b>delegate</b></p>
+     * <p>This is a configuration option that you can pass along when registering a handler for
+     * an event to assist with event delegation. Event delegation is a technique that is used to
+     * reduce memory consumption and prevent exposure to memory-leaks. By registering an event
+     * for a container element as opposed to each element within a container. By setting this
+     * configuration option to a simple selector, the target element will be filtered to look for
+     * a descendant of the target.
+     * For example:<pre><code>
+// using this markup:
+&lt;div id='elId'>
+    &lt;p id='p1'>paragraph one&lt;/p>
+    &lt;p id='p2' class='clickable'>paragraph two&lt;/p>
+    &lt;p id='p3'>paragraph three&lt;/p>
+&lt;/div>
+// utilize event delegation to registering just one handler on the container element:
+el = Ext.get('elId');
+el.on(
+    'click',
+    function(e,t) {
+        // handle click
+        console.info(t.id); // 'p2'
+    },
+    this,
+    {
+        // filter the target element to be a descendant with the class 'clickable'
+        delegate: '.clickable'
+    }
+);
+     * </code></pre></p>
+     * @return {Ext.Element} this
+     */
+    addListener : function(eventName, fn, scope, options){
+        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+        return this;
+    },
+
+    /**
+     * Removes an event handler from this element.  The shorthand version {@link #un} is equivalent.
+     * <b>Note</b>: if a <i>scope</i> was explicitly specified when {@link #addListener adding} the
+     * listener, the same scope must be specified here.
+     * Example:
+     * <pre><code>
+el.removeListener('click', this.handlerFn);
+// or
+el.un('click', this.handlerFn);
+</code></pre>
+     * @param {String} eventName The name of the event from which to remove the handler.
+     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
+     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
+     * then this must refer to the same object.
+     * @return {Ext.Element} this
+     */
+    removeListener : function(eventName, fn, scope){
+        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
+        return this;
+    },
+
+    /**
+     * Removes all previous added listeners from this element
+     * @return {Ext.Element} this
+     */
+    removeAllListeners : function(){
+        Ext.EventManager.removeAll(this.dom);
+        return this;
+    },
+
+    /**
+     * Recursively removes all previous added listeners from this element and its children
+     * @return {Ext.Element} this
+     */
+    purgeAllListeners : function() {
+        Ext.EventManager.purgeElement(this, true);
+        return this;
+    },
+    /**
+     * @private Test if size has a unit, otherwise appends the default
+     */
+    addUnits : function(size){
+        if(size === "" || size == "auto" || size === undefined){
+            size = size || '';
+        } else if(!isNaN(size) || !unitPattern.test(size)){
+            size = size + (this.defaultUnit || 'px');
+        }
+        return size;
+    },
+
+    /**
+     * <p>Updates the <a href="http:
+     * from a specified URL. Note that this is subject to the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">Same Origin Policy</a></p>
+     * <p>Updating innerHTML of an element will <b>not</b> execute embedded <tt>&lt;script></tt> elements. This is a browser restriction.</p>
+     * @param {Mixed} options. Either a sring containing the URL from which to load the HTML, or an {@link Ext.Ajax#request} options object specifying
+     * exactly how to request the HTML.
+     * @return {Ext.Element} this
+     */
+    load : function(url, params, cb){
+        Ext.Ajax.request(Ext.apply({
+            params: params,
+            url: url.url || url,
+            callback: cb,
+            el: this.dom,
+            indicatorText: url.indicatorText || ''
+        }, Ext.isObject(url) ? url : {}));
+        return this;
+    },
+
+    
+    isBorderBox : function(){
+        return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
+    },
+
+    
+    remove : function(){
+        var me = this,
+            dom = me.dom;
+
+        if (dom) {
+            delete me.dom;
+            Ext.removeNode(dom);
+        }
+    },
+
+    
+    hover : function(overFn, outFn, scope, options){
+        var me = this;
+        me.on('mouseenter', overFn, scope || me.dom, options);
+        me.on('mouseleave', outFn, scope || me.dom, options);
+        return me;
+    },
+
+    
+    contains : function(el){
+        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
+    },
+
+    
+    getAttributeNS : function(ns, name){
+        return this.getAttribute(name, ns);
+    },
+
+    
+    getAttribute: (function(){
+        var test = document.createElement('table'),
+            isBrokenOnTable = false,
+            hasGetAttribute = 'getAttribute' in test,
+            unknownRe = /undefined|unknown/;
+            
+        if (hasGetAttribute) {
+            
+            try {
+                test.getAttribute('ext:qtip');
+            } catch (e) {
+                isBrokenOnTable = true;
+            }
+            
+            return function(name, ns) {
+                var el = this.dom,
+                    value;
+                
+                if (el.getAttributeNS) {
+                    value  = el.getAttributeNS(ns, name) || null;
+                }
+            
+                if (value == null) {
+                    if (ns) {
+                        if (isBrokenOnTable && el.tagName.toUpperCase() == 'TABLE') {
+                            try {
+                                value = el.getAttribute(ns + ':' + name);
+                            } catch (e) {
+                                value = '';
+                            }
+                        } else {
+                            value = el.getAttribute(ns + ':' + name);
+                        }
+                    } else {
+                        value = el.getAttribute(name) || el[name];
+                    }
+                }
+                return value || '';
+            };
+        } else {
+            return function(name, ns) {
+                var el = this.om,
+                    value,
+                    attribute;
+                
+                if (ns) {
+                    attribute = el[ns + ':' + name];
+                    value = unknownRe.test(typeof attribute) ? undefined : attribute;
+                } else {
+                    value = el[name];
+                }
+                return value || '';
+            };
+        }
+        test = null;
+    })(),
+        
+    
+    update : function(html) {
+        if (this.dom) {
+            this.dom.innerHTML = html;
+        }
+        return this;
+    }
+};
+
+var ep = El.prototype;
+
+El.addMethods = function(o){
+   Ext.apply(ep, o);
+};
+
+
+ep.on = ep.addListener;
+
+
+ep.un = ep.removeListener;
+
+
+ep.autoBoxAdjust = true;
+
+
+var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
+    docEl;
+
+
+
+
+El.get = function(el){
+    var ex,
+        elm,
+        id;
+    if(!el){ return null; }
+    if (typeof el == "string") { 
+        if (!(elm = DOC.getElementById(el))) {
+            return null;
+        }
+        if (EC[el] && EC[el].el) {
+            ex = EC[el].el;
+            ex.dom = elm;
+        } else {
+            ex = El.addToCache(new El(elm));
+        }
+        return ex;
+    } else if (el.tagName) { 
+        if(!(id = el.id)){
+            id = Ext.id(el);
+        }
+        if (EC[id] && EC[id].el) {
+            ex = EC[id].el;
+            ex.dom = el;
+        } else {
+            ex = El.addToCache(new El(el));
+        }
+        return ex;
+    } else if (el instanceof El) {
+        if(el != docEl){
+            
+            
+
+            
+            if (Ext.isIE && (el.id == undefined || el.id == '')) {
+                el.dom = el.dom;
+            } else {
+                el.dom = DOC.getElementById(el.id) || el.dom;
+            }
+        }
+        return el;
+    } else if(el.isComposite) {
+        return el;
+    } else if(Ext.isArray(el)) {
+        return El.select(el);
+    } else if(el == DOC) {
+        
+        if(!docEl){
+            var f = function(){};
+            f.prototype = El.prototype;
+            docEl = new f();
+            docEl.dom = DOC;
+        }
+        return docEl;
+    }
+    return null;
+};
+
+El.addToCache = function(el, id){
+    id = id || el.id;
+    EC[id] = {
+        el:  el,
+        data: {},
+        events: {}
+    };
+    return el;
+};
+
+
+El.data = function(el, key, value){
+    el = El.get(el);
+    if (!el) {
+        return null;
+    }
+    var c = EC[el.id].data;
+    if(arguments.length == 2){
+        return c[key];
+    }else{
+        return (c[key] = value);
+    }
+};
+
+
+
+
+function garbageCollect(){
+    if(!Ext.enableGarbageCollector){
+        clearInterval(El.collectorThreadId);
+    } else {
+        var eid,
+            el,
+            d,
+            o;
+
+        for(eid in EC){
+            o = EC[eid];
+            if(o.skipGC){
+                continue;
+            }
+            el = o.el;
+            d = el.dom;
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
+                if(Ext.enableListenerCollection){
+                    Ext.EventManager.removeAll(d);
+                }
+                delete EC[eid];
+            }
+        }
+        
+        if (Ext.isIE) {
+            var t = {};
+            for (eid in EC) {
+                t[eid] = EC[eid];
+            }
+            EC = Ext.elCache = t;
+        }
+    }
+}
+El.collectorThreadId = setInterval(garbageCollect, 30000);
+
+var flyFn = function(){};
+flyFn.prototype = El.prototype;
+
+
+El.Flyweight = function(dom){
+    this.dom = dom;
+};
+
+El.Flyweight.prototype = new flyFn();
+El.Flyweight.prototype.isFlyweight = true;
+El._flyweights = {};
+
+
+El.fly = function(el, named){
+    var ret = null;
+    named = named || '_global';
+
+    if (el = Ext.getDom(el)) {
+        (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
+        ret = El._flyweights[named];
+    }
+    return ret;
+};
+
+
+Ext.get = El.get;
+
+
+Ext.fly = El.fly;
+
+
+var noBoxAdjust = Ext.isStrict ? {
+    select:1
+} : {
+    input:1, select:1, textarea:1
+};
+if(Ext.isIE || Ext.isGecko){
+    noBoxAdjust['button'] = 1;
+}
+
+})();
+
+Ext.Element.addMethods(function(){
+	var PARENTNODE = 'parentNode',
+		NEXTSIBLING = 'nextSibling',
+		PREVIOUSSIBLING = 'previousSibling',
+		DQ = Ext.DomQuery,
+		GET = Ext.get;
+	
+	return {
+		
+	    findParent : function(simpleSelector, maxDepth, returnEl){
+	        var p = this.dom,
+	        	b = document.body, 
+	        	depth = 0, 	        	
+	        	stopEl;	        
+            if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
+                return null;
+            }
+	        maxDepth = maxDepth || 50;
+	        if (isNaN(maxDepth)) {
+	            stopEl = Ext.getDom(maxDepth);
+	            maxDepth = Number.MAX_VALUE;
+	        }
+	        while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
+	            if(DQ.is(p, simpleSelector)){
+	                return returnEl ? GET(p) : p;
+	            }
+	            depth++;
+	            p = p.parentNode;
+	        }
+	        return null;
+	    },
+	
+	    
+	    findParentNode : function(simpleSelector, maxDepth, returnEl){
+	        var p = Ext.fly(this.dom.parentNode, '_internal');
+	        return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
+	    },
+	
+	    
+	    up : function(simpleSelector, maxDepth){
+	        return this.findParentNode(simpleSelector, maxDepth, true);
+	    },
+	
+	    
+	    select : function(selector){
+	        return Ext.Element.select(selector, this.dom);
+	    },
+	
+	    
+	    query : function(selector){
+	        return DQ.select(selector, this.dom);
+	    },
+	
+	    
+	    child : function(selector, returnDom){
+	        var n = DQ.selectNode(selector, this.dom);
+	        return returnDom ? n : GET(n);
+	    },
+	
+	    
+	    down : function(selector, returnDom){
+	        var n = DQ.selectNode(" > " + selector, this.dom);
+	        return returnDom ? n : GET(n);
+	    },
+	
+		 
+	    parent : function(selector, returnDom){
+	        return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
+	    },
+	
+	     
+	    next : function(selector, returnDom){
+	        return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
+	    },
+	
+	    
+	    prev : function(selector, returnDom){
+	        return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
+	    },
+	
+	
+	    
+	    first : function(selector, returnDom){
+	        return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
+	    },
+	
+	    
+	    last : function(selector, returnDom){
+	        return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
+	    },
+	    
+	    matchNode : function(dir, start, selector, returnDom){
+	        var n = this.dom[start];
+	        while(n){
+	            if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
+	                return !returnDom ? GET(n) : n;
+	            }
+	            n = n[dir];
+	        }
+	        return null;
+	    }	
+    };
+}());
+Ext.Element.addMethods(
+function() {
+	var GETDOM = Ext.getDom,
+		GET = Ext.get,
+		DH = Ext.DomHelper;
+	
+	return {
+	    
+	    appendChild: function(el){        
+	        return GET(el).appendTo(this);        
+	    },
+	
+	    
+	    appendTo: function(el){        
+	        GETDOM(el).appendChild(this.dom);        
+	        return this;
+	    },
+	
+	    
+	    insertBefore: function(el){  	          
+	        (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
+	        return this;
+	    },
+	
+	    
+	    insertAfter: function(el){
+	        (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
+	        return this;
+	    },
+	
+	    
+	    insertFirst: function(el, returnDom){
+            el = el || {};
+            if(el.nodeType || el.dom || typeof el == 'string'){ 
+                el = GETDOM(el);
+                this.dom.insertBefore(el, this.dom.firstChild);
+                return !returnDom ? GET(el) : el;
+            }else{ 
+                return this.createChild(el, this.dom.firstChild, returnDom);
+            }
+        },
+	
+	    
+	    replace: function(el){
+	        el = GET(el);
+	        this.insertBefore(el);
+	        el.remove();
+	        return this;
+	    },
+	
+	    
+	    replaceWith: function(el){
+		    var me = this;
+                
+            if(el.nodeType || el.dom || typeof el == 'string'){
+                el = GETDOM(el);
+                me.dom.parentNode.insertBefore(el, me.dom);
+            }else{
+                el = DH.insertBefore(me.dom, el);
+            }
+	        
+	        delete Ext.elCache[me.id];
+	        Ext.removeNode(me.dom);      
+	        me.id = Ext.id(me.dom = el);
+	        Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
+            return me;
+	    },
+	    
+		
+		createChild: function(config, insertBefore, returnDom){
+		    config = config || {tag:'div'};
+		    return insertBefore ? 
+		    	   DH.insertBefore(insertBefore, config, returnDom !== true) :	
+		    	   DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
+		},
+		
+		
+		wrap: function(config, returnDom){        
+		    var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
+		    newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
+		    return newEl;
+		},
+		
+		
+		insertHtml : function(where, html, returnEl){
+		    var el = DH.insertHtml(where, this.dom, html);
+		    return returnEl ? Ext.get(el) : el;
+		}
+	};
+}());
+Ext.Element.addMethods(function(){
+    
+    var supports = Ext.supports,
+        propCache = {},
+        camelRe = /(-[a-z])/gi,
+        view = document.defaultView,
+        opacityRe = /alpha\(opacity=(.*)\)/i,
+        trimRe = /^\s+|\s+$/g,
+        EL = Ext.Element,
+        spacesRe = /\s+/,
+        wordsRe = /\w/g,
+        PADDING = "padding",
+        MARGIN = "margin",
+        BORDER = "border",
+        LEFT = "-left",
+        RIGHT = "-right",
+        TOP = "-top",
+        BOTTOM = "-bottom",
+        WIDTH = "-width",
+        MATH = Math,
+        HIDDEN = 'hidden',
+        ISCLIPPED = 'isClipped',
+        OVERFLOW = 'overflow',
+        OVERFLOWX = 'overflow-x',
+        OVERFLOWY = 'overflow-y',
+        ORIGINALCLIP = 'originalClip',
+        
+        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
+        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
+        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
+        data = Ext.Element.data;
+
+
+    
+    function camelFn(m, a) {
+        return a.charAt(1).toUpperCase();
+    }
+
+    function chkCache(prop) {
+        return propCache[prop] || (propCache[prop] = prop == 'float' ? (supports.cssFloat ? 'cssFloat' : 'styleFloat') : prop.replace(camelRe, camelFn));
+    }
+
+    return {
+        
+        adjustWidth : function(width) {
+            var me = this;
+            var isNum = (typeof width == "number");
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+            }
+            return (isNum && width < 0) ? 0 : width;
+        },
+
+        
+        adjustHeight : function(height) {
+            var me = this;
+            var isNum = (typeof height == "number");
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+            }
+            return (isNum && height < 0) ? 0 : height;
+        },
+
+
+        
+        addClass : function(className){
+            var me = this,
+                i,
+                len,
+                v,
+                cls = [];
+            
+            if (!Ext.isArray(className)) {
+                if (typeof className == 'string' && !this.hasClass(className)) {
+                    me.dom.className += " " + className;
+                }
+            }
+            else {
+                for (i = 0, len = className.length; i < len; i++) {
+                    v = className[i];
+                    if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
+                        cls.push(v);
+                    }
+                }
+                if (cls.length) {
+                    me.dom.className += " " + cls.join(" ");
+                }
+            }
+            return me;
+        },
+
+        
+        removeClass : function(className){
+            var me = this,
+                i,
+                idx,
+                len,
+                cls,
+                elClasses;
+            if (!Ext.isArray(className)){
+                className = [className];
+            }
+            if (me.dom && me.dom.className) {
+                elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
+                for (i = 0, len = className.length; i < len; i++) {
+                    cls = className[i];
+                    if (typeof cls == 'string') {
+                        cls = cls.replace(trimRe, '');
+                        idx = elClasses.indexOf(cls);
+                        if (idx != -1) {
+                            elClasses.splice(idx, 1);
+                        }
+                    }
+                }
+                me.dom.className = elClasses.join(" ");
+            }
+            return me;
+        },
+
+        
+        radioClass : function(className){
+            var cn = this.dom.parentNode.childNodes,
+                v,
+                i,
+                len;
+            className = Ext.isArray(className) ? className : [className];
+            for (i = 0, len = cn.length; i < len; i++) {
+                v = cn[i];
+                if (v && v.nodeType == 1) {
+                    Ext.fly(v, '_internal').removeClass(className);
+                }
+            };
+            return this.addClass(className);
+        },
+
+        
+        toggleClass : function(className){
+            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+        },
+
+        
+        hasClass : function(className){
+            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
+        },
+
+        
+        replaceClass : function(oldClassName, newClassName){
+            return this.removeClass(oldClassName).addClass(newClassName);
+        },
+
+        isStyle : function(style, val) {
+            return this.getStyle(style) == val;
+        },
+
+        
+        getStyle : function(){
+            return view && view.getComputedStyle ?
+                function(prop){
+                    var el = this.dom,
+                        v,
+                        cs,
+                        out,
+                        display;
+
+                    if(el == document){
+                        return null;
+                    }
+                    prop = chkCache(prop);
+                    out = (v = el.style[prop]) ? v :
+                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
+                           
+                    
+                    
+                    if(prop == 'marginRight' && out != '0px' && !supports.correctRightMargin){
+                        display = el.style.display;
+                        el.style.display = 'inline-block';
+                        out = view.getComputedStyle(el, '').marginRight;
+                        el.style.display = display;
+                    }
+                    
+                    if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.correctTransparentColor){
+                        out = 'transparent';
+                    }
+                    return out;
+                } :
+                function(prop){
+                    var el = this.dom,
+                        m,
+                        cs;
+
+                    if(el == document) return null;
+                    if (prop == 'opacity') {
+                        if (el.style.filter.match) {
+                            if(m = el.style.filter.match(opacityRe)){
+                                var fv = parseFloat(m[1]);
+                                if(!isNaN(fv)){
+                                    return fv ? fv / 100 : 0;
+                                }
+                            }
+                        }
+                        return 1;
+                    }
+                    prop = chkCache(prop);
+                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
+                };
+        }(),
+
+        
+        getColor : function(attr, defaultValue, prefix){
+            var v = this.getStyle(attr),
+                color = (typeof prefix != 'undefined') ? prefix : '#',
+                h;
+
+            if(!v || (/transparent|inherit/.test(v))) {
+                return defaultValue;
+            }
+            if(/^r/.test(v)){
+                Ext.each(v.slice(4, v.length -1).split(','), function(s){
+                    h = parseInt(s, 10);
+                    color += (h < 16 ? '0' : '') + h.toString(16);
+                });
+            }else{
+                v = v.replace('#', '');
+                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
+            }
+            return(color.length > 5 ? color.toLowerCase() : defaultValue);
+        },
+
+        
+        setStyle : function(prop, value){
+            var tmp, style;
+            
+            if (typeof prop != 'object') {
+                tmp = {};
+                tmp[prop] = value;
+                prop = tmp;
+            }
+            for (style in prop) {
+                value = prop[style];
+                style == 'opacity' ?
+                    this.setOpacity(value) :
+                    this.dom.style[chkCache(style)] = value;
+            }
+            return this;
+        },
+
+        
+         setOpacity : function(opacity, animate){
+            var me = this,
+                s = me.dom.style;
+
+            if(!animate || !me.anim){
+                if(Ext.isIE){
+                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
+                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');
+
+                    s.zoom = 1;
+                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
+                }else{
+                    s.opacity = opacity;
+                }
+            }else{
+                me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
+            }
+            return me;
+        },
+
+        
+        clearOpacity : function(){
+            var style = this.dom.style;
+            if(Ext.isIE){
+                if(!Ext.isEmpty(style.filter)){
+                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
+                }
+            }else{
+                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
+            }
+            return this;
+        },
+
+        
+        getHeight : function(contentHeight){
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
+
+            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
+            return h < 0 ? 0 : h;
+        },
+
+        
+        getWidth : function(contentWidth){
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
+            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
+            return w < 0 ? 0 : w;
+        },
+
+        
+        setWidth : function(width, animate){
+            var me = this;
+            width = me.adjustWidth(width);
+            !animate || !me.anim ?
+                me.dom.style.width = me.addUnits(width) :
+                me.anim({width : {to : width}}, me.preanim(arguments, 1));
+            return me;
+        },
+
+        
+         setHeight : function(height, animate){
+            var me = this;
+            height = me.adjustHeight(height);
+            !animate || !me.anim ?
+                me.dom.style.height = me.addUnits(height) :
+                me.anim({height : {to : height}}, me.preanim(arguments, 1));
+            return me;
+        },
+
+        
+        getBorderWidth : function(side){
+            return this.addStyles(side, borders);
+        },
+
+        
+        getPadding : function(side){
+            return this.addStyles(side, paddings);
+        },
+
+        
+        clip : function(){
+            var me = this,
+                dom = me.dom;
+
+            if(!data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, true);
+                data(dom, ORIGINALCLIP, {
+                    o: me.getStyle(OVERFLOW),
+                    x: me.getStyle(OVERFLOWX),
+                    y: me.getStyle(OVERFLOWY)
+                });
+                me.setStyle(OVERFLOW, HIDDEN);
+                me.setStyle(OVERFLOWX, HIDDEN);
+                me.setStyle(OVERFLOWY, HIDDEN);
+            }
+            return me;
+        },
+
+        
+        unclip : function(){
+            var me = this,
+                dom = me.dom;
+
+            if(data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, false);
+                var o = data(dom, ORIGINALCLIP);
+                if(o.o){
+                    me.setStyle(OVERFLOW, o.o);
+                }
+                if(o.x){
+                    me.setStyle(OVERFLOWX, o.x);
+                }
+                if(o.y){
+                    me.setStyle(OVERFLOWY, o.y);
+                }
+            }
+            return me;
+        },
+
+        
+        addStyles : function(sides, styles){
+            var ttlSize = 0,
+                sidesArr = sides.match(wordsRe),
+                side,
+                size,
+                i,
+                len = sidesArr.length;
+            for (i = 0; i < len; i++) {
+                side = sidesArr[i];
+                size = side && parseInt(this.getStyle(styles[side]), 10);
+                if (size) {
+                    ttlSize += MATH.abs(size);
+                }
+            }
+            return ttlSize;
+        },
+
+        margins : margins
+    };
+}()
+);
+
+(function(){
+var D = Ext.lib.Dom,
+        LEFT = "left",
+        RIGHT = "right",
+        TOP = "top",
+        BOTTOM = "bottom",
+        POSITION = "position",
+        STATIC = "static",
+        RELATIVE = "relative",
+        AUTO = "auto",
+        ZINDEX = "z-index";
+
+Ext.Element.addMethods({
+	
+    getX : function(){
+        return D.getX(this.dom);
+    },
+
+    
+    getY : function(){
+        return D.getY(this.dom);
+    },
+
+    
+    getXY : function(){
+        return D.getXY(this.dom);
+    },
+
+    
+    getOffsetsTo : function(el){
+        var o = this.getXY(),
+        	e = Ext.fly(el, '_internal').getXY();
+        return [o[0]-e[0],o[1]-e[1]];
+    },
+
+    
+    setX : function(x, animate){	    
+	    return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
+    },
+
+    
+    setY : function(y, animate){	    
+	    return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
+    },
+
+    
+    setLeft : function(left){
+        this.setStyle(LEFT, this.addUnits(left));
+        return this;
+    },
+
+    
+    setTop : function(top){
+        this.setStyle(TOP, this.addUnits(top));
+        return this;
+    },
+
+    
+    setRight : function(right){
+        this.setStyle(RIGHT, this.addUnits(right));
+        return this;
+    },
+
+    
+    setBottom : function(bottom){
+        this.setStyle(BOTTOM, this.addUnits(bottom));
+        return this;
+    },
+
+    
+    setXY : function(pos, animate){
+	    var me = this;
+        if(!animate || !me.anim){
+            D.setXY(me.dom, pos);
+        }else{
+            me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
+        }
+        return me;
+    },
+
+    
+    setLocation : function(x, y, animate){
+        return this.setXY([x, y], this.animTest(arguments, animate, 2));
+    },
+
+    
+    moveTo : function(x, y, animate){
+        return this.setXY([x, y], this.animTest(arguments, animate, 2));        
+    },    
+    
+    
+    getLeft : function(local){
+	    return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
+    },
+
+    
+    getRight : function(local){
+	    var me = this;
+	    return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
+    },
+
+    
+    getTop : function(local) {
+	    return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
+    },
+
+    
+    getBottom : function(local){
+	    var me = this;
+	    return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
+    },
+
+    
+    position : function(pos, zIndex, x, y){
+	    var me = this;
+	    
+        if(!pos && me.isStyle(POSITION, STATIC)){           
+            me.setStyle(POSITION, RELATIVE);           
+        } else if(pos) {
+            me.setStyle(POSITION, pos);
+        }
+        if(zIndex){
+            me.setStyle(ZINDEX, zIndex);
+        }
+        if(x || y) me.setXY([x || false, y || false]);
+    },
+
+    
+    clearPositioning : function(value){
+        value = value || '';
+        this.setStyle({
+            left : value,
+            right : value,
+            top : value,
+            bottom : value,
+            "z-index" : "",
+            position : STATIC
+        });
+        return this;
+    },
+
+    
+    getPositioning : function(){
+        var l = this.getStyle(LEFT);
+        var t = this.getStyle(TOP);
+        return {
+            "position" : this.getStyle(POSITION),
+            "left" : l,
+            "right" : l ? "" : this.getStyle(RIGHT),
+            "top" : t,
+            "bottom" : t ? "" : this.getStyle(BOTTOM),
+            "z-index" : this.getStyle(ZINDEX)
+        };
+    },
+    
+    
+    setPositioning : function(pc){
+	    var me = this,
+	    	style = me.dom.style;
+	    	
+        me.setStyle(pc);
+        
+        if(pc.right == AUTO){
+            style.right = "";
+        }
+        if(pc.bottom == AUTO){
+            style.bottom = "";
+        }
+        
+        return me;
+    },    
+	
+    
+    translatePoints : function(x, y){        	     
+	    y = isNaN(x[1]) ? y : x[1];
+        x = isNaN(x[0]) ? x : x[0];
+        var me = this,
+        	relative = me.isStyle(POSITION, RELATIVE),
+        	o = me.getXY(),
+        	l = parseInt(me.getStyle(LEFT), 10),
+        	t = parseInt(me.getStyle(TOP), 10);
+        
+        l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
+        t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
+
+        return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
+    },
+    
+    animTest : function(args, animate, i) {
+        return !!animate && this.preanim ? this.preanim(args, i) : false;
+    }
+});
+})();
+Ext.Element.addMethods({
+    
+    isScrollable : function(){
+        var dom = this.dom;
+        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
+    },
+
+    
+    scrollTo : function(side, value){
+        this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
+        return this;
+    },
+
+    
+    getScroll : function(){
+        var d = this.dom, 
+            doc = document,
+            body = doc.body,
+            docElement = doc.documentElement,
+            l,
+            t,
+            ret;
+
+        if(d == doc || d == body){
+            if(Ext.isIE && Ext.isStrict){
+                l = docElement.scrollLeft; 
+                t = docElement.scrollTop;
+            }else{
+                l = window.pageXOffset;
+                t = window.pageYOffset;
+            }
+            ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
+        }else{
+            ret = {left: d.scrollLeft, top: d.scrollTop};
+        }
+        return ret;
+    }
+});
+
+Ext.Element.VISIBILITY = 1;
+
+Ext.Element.DISPLAY = 2;
+
+
+Ext.Element.OFFSETS = 3;
+
+
+Ext.Element.ASCLASS = 4;
+
+
+Ext.Element.visibilityCls = 'x-hide-nosize';
+
+Ext.Element.addMethods(function(){
+    var El = Ext.Element,
+        OPACITY = "opacity",
+        VISIBILITY = "visibility",
+        DISPLAY = "display",
+        HIDDEN = "hidden",
+        OFFSETS = "offsets",
+        ASCLASS = "asclass",
+        NONE = "none",
+        NOSIZE = 'nosize',
+        ORIGINALDISPLAY = 'originalDisplay',
+        VISMODE = 'visibilityMode',
+        ISVISIBLE = 'isVisible',
+        data = El.data,
+        getDisplay = function(dom){
+            var d = data(dom, ORIGINALDISPLAY);
+            if(d === undefined){
+                data(dom, ORIGINALDISPLAY, d = '');
+            }
+            return d;
+        },
+        getVisMode = function(dom){
+            var m = data(dom, VISMODE);
+            if(m === undefined){
+                data(dom, VISMODE, m = 1);
+            }
+            return m;
+        };
+
+    return {
+        
+        originalDisplay : "",
+        visibilityMode : 1,
+
+        
+        setVisibilityMode : function(visMode){
+            data(this.dom, VISMODE, visMode);
+            return this;
+        },
+
+        
+        animate : function(args, duration, onComplete, easing, animType){
+            this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
+            return this;
+        },
+
+        
+        anim : function(args, opt, animType, defaultDur, defaultEase, cb){
+            animType = animType || 'run';
+            opt = opt || {};
+            var me = this,
+                anim = Ext.lib.Anim[animType](
+                    me.dom,
+                    args,
+                    (opt.duration || defaultDur) || .35,
+                    (opt.easing || defaultEase) || 'easeOut',
+                    function(){
+                        if(cb) cb.call(me);
+                        if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
+                    },
+                    me
+                );
+            opt.anim = anim;
+            return anim;
+        },
+
+        
+        preanim : function(a, i){
+            return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
+        },
+
+        
+        isVisible : function() {
+            var me = this,
+                dom = me.dom,
+                visible = data(dom, ISVISIBLE);
+
+            if(typeof visible == 'boolean'){ 
+                return visible;
+            }
+            
+            visible = !me.isStyle(VISIBILITY, HIDDEN) &&
+                      !me.isStyle(DISPLAY, NONE) &&
+                      !((getVisMode(dom) == El.ASCLASS) && me.hasClass(me.visibilityCls || El.visibilityCls));
+
+            data(dom, ISVISIBLE, visible);
+            return visible;
+        },
+
+        
+        setVisible : function(visible, animate){
+            var me = this, isDisplay, isVisibility, isOffsets, isNosize,
+                dom = me.dom,
+                visMode = getVisMode(dom);
+
+
+            
+            if (typeof animate == 'string'){
+                switch (animate) {
+                    case DISPLAY:
+                        visMode = El.DISPLAY;
+                        break;
+                    case VISIBILITY:
+                        visMode = El.VISIBILITY;
+                        break;
+                    case OFFSETS:
+                        visMode = El.OFFSETS;
+                        break;
+                    case NOSIZE:
+                    case ASCLASS:
+                        visMode = El.ASCLASS;
+                        break;
+                }
+                me.setVisibilityMode(visMode);
+                animate = false;
+            }
+
+            if (!animate || !me.anim) {
+                if(visMode == El.ASCLASS ){
+
+                    me[visible?'removeClass':'addClass'](me.visibilityCls || El.visibilityCls);
+
+                } else if (visMode == El.DISPLAY){
+
+                    return me.setDisplayed(visible);
+
+                } else if (visMode == El.OFFSETS){
+
+                    if (!visible){
+                        me.hideModeStyles = {
+                            position: me.getStyle('position'),
+                            top: me.getStyle('top'),
+                            left: me.getStyle('left')
+                        };
+                        me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
+                    } else {
+                        me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
+                        delete me.hideModeStyles;
+                    }
+
+                }else{
+                    me.fixDisplay();
+                    dom.style.visibility = visible ? "visible" : HIDDEN;
+                }
+            }else{
+                
+                if(visible){
+                    me.setOpacity(.01);
+                    me.setVisible(true);
+                }
+                me.anim({opacity: { to: (visible?1:0) }},
+                        me.preanim(arguments, 1),
+                        null,
+                        .35,
+                        'easeIn',
+                        function(){
+                            visible || me.setVisible(false).setOpacity(1);
+                        });
+            }
+            data(dom, ISVISIBLE, visible);  
+            return me;
+        },
+
+
+        
+        hasMetrics  : function(){
+            var dom = this.dom;
+            return this.isVisible() || (getVisMode(dom) == El.VISIBILITY);
+        },
+
+        
+        toggle : function(animate){
+            var me = this;
+            me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
+            return me;
+        },
+
+        
+        setDisplayed : function(value) {
+            if(typeof value == "boolean"){
+               value = value ? getDisplay(this.dom) : NONE;
+            }
+            this.setStyle(DISPLAY, value);
+            return this;
+        },
+
+        
+        fixDisplay : function(){
+            var me = this;
+            if(me.isStyle(DISPLAY, NONE)){
+                me.setStyle(VISIBILITY, HIDDEN);
+                me.setStyle(DISPLAY, getDisplay(this.dom)); 
+                if(me.isStyle(DISPLAY, NONE)){ 
+                    me.setStyle(DISPLAY, "block");
+                }
+            }
+        },
+
+        
+        hide : function(animate){
+            
+            if (typeof animate == 'string'){
+                this.setVisible(false, animate);
+                return this;
+            }
+            this.setVisible(false, this.preanim(arguments, 0));
+            return this;
+        },
+
+        
+        show : function(animate){
+            
+            if (typeof animate == 'string'){
+                this.setVisible(true, animate);
+                return this;
+            }
+            this.setVisible(true, this.preanim(arguments, 0));
+            return this;
+        }
+    };
+}());(function(){
+    
+    var NULL = null,
+        UNDEFINED = undefined,
+        TRUE = true,
+        FALSE = false,
+        SETX = "setX",
+        SETY = "setY",
+        SETXY = "setXY",
+        LEFT = "left",
+        BOTTOM = "bottom",
+        TOP = "top",
+        RIGHT = "right",
+        HEIGHT = "height",
+        WIDTH = "width",
+        POINTS = "points",
+        HIDDEN = "hidden",
+        ABSOLUTE = "absolute",
+        VISIBLE = "visible",
+        MOTION = "motion",
+        POSITION = "position",
+        EASEOUT = "easeOut",
+        
+        flyEl = new Ext.Element.Flyweight(),
+        queues = {},
+        getObject = function(o){
+            return o || {};
+        },
+        fly = function(dom){
+            flyEl.dom = dom;
+            flyEl.id = Ext.id(dom);
+            return flyEl;
+        },
+        
+        getQueue = function(id){
+            if(!queues[id]){
+                queues[id] = [];
+            }
+            return queues[id];
+        },
+        setQueue = function(id, value){
+            queues[id] = value;
+        };
+        
+
+Ext.enableFx = TRUE;
+
+
+Ext.Fx = {
+    
+    
+    
+    switchStatements : function(key, fn, argHash){
+        return fn.apply(this, argHash[key]);
+    },
+    
+    
+    slideIn : function(anchor, o){ 
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            st = dom.style,
+            xy,
+            r,
+            b,              
+            wrap,               
+            after,
+            st,
+            args, 
+            pt,
+            bw,
+            bh;
+            
+        anchor = anchor || "t";
+
+        me.queueFx(o, function(){            
+            xy = fly(dom).getXY();
+            
+            fly(dom).fixDisplay();            
+            
+            
+            r = fly(dom).getFxRestore();      
+            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
+            b.right = b.x + b.width;
+            b.bottom = b.y + b.height;
+            
+            
+            fly(dom).setWidth(b.width).setHeight(b.height);            
+            
+            
+            wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
+            
+            st.visibility = VISIBLE;
+            st.position = ABSOLUTE;
+            
+            
+            function after(){
+                 fly(dom).fxUnwrap(wrap, r.pos, o);
+                 st.width = r.width;
+                 st.height = r.height;
+                 fly(dom).afterFx(o);
+            }
+            
+            
+            pt = {to: [b.x, b.y]}; 
+            bw = {to: b.width};
+            bh = {to: b.height};
+                
+            function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
+                var ret = {};
+                fly(wrap).setWidth(ww).setHeight(wh);
+                if(fly(wrap)[sXY]){
+                    fly(wrap)[sXY](sXYval);                  
+                }
+                style[s1] = style[s2] = "0";                    
+                if(w){
+                    ret.width = w;
+                }
+                if(h){
+                    ret.height = h;
+                }
+                if(p){
+                    ret.points = p;
+                }
+                return ret;
+            };
+
+            args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
+                    t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
+                    l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
+                    r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
+                    b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
+                    tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
+                    bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
+                    br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
+                    tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
+                });
+            
+            st.visibility = VISIBLE;
+            fly(wrap).show();
+
+            arguments.callee.anim = fly(wrap).fxanim(args,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, 
+                after);
+        });
+        return me;
+    },
+    
+    
+    slideOut : function(anchor, o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            st = dom.style,
+            xy = me.getXY(),
+            wrap,
+            r,
+            b,
+            a,
+            zero = {to: 0}; 
+                    
+        anchor = anchor || "t";
+
+        me.queueFx(o, function(){
+            
+            
+            r = fly(dom).getFxRestore(); 
+            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
+            b.right = b.x + b.width;
+            b.bottom = b.y + b.height;
+                
+            
+            fly(dom).setWidth(b.width).setHeight(b.height);
+
+            
+            wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
+                
+            st.visibility = VISIBLE;
+            st.position = ABSOLUTE;
+            fly(wrap).setWidth(b.width).setHeight(b.height);            
+
+            function after(){
+                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
+                fly(dom).fxUnwrap(wrap, r.pos, o);
+                st.width = r.width;
+                st.height = r.height;
+                fly(dom).afterFx(o);
+            }            
+            
+            function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
+                var ret = {};
+                
+                style[s1] = style[s2] = "0";
+                ret[p1] = v1;               
+                if(p2){
+                    ret[p2] = v2;               
+                }
+                if(p3){
+                    ret[p3] = v3;
+                }
+                
+                return ret;
+            };
+            
+            a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
+                t  : [st, LEFT, BOTTOM, HEIGHT, zero],
+                l  : [st, RIGHT, TOP, WIDTH, zero],
+                r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
+                b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
+                tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
+                bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
+                br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
+                tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
+            });
+            
+            arguments.callee.anim = fly(wrap).fxanim(a,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, 
+                after);
+        });
+        return me;
+    },
+
+    
+    puff : function(o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            st = dom.style,
+            width,
+            height,
+            r;
+
+        me.queueFx(o, function(){
+            width = fly(dom).getWidth();
+            height = fly(dom).getHeight();
+            fly(dom).clearOpacity();
+            fly(dom).show();
+
+            
+            r = fly(dom).getFxRestore();                   
+            
+            function after(){
+                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
+                fly(dom).clearOpacity();  
+                fly(dom).setPositioning(r.pos);
+                st.width = r.width;
+                st.height = r.height;
+                st.fontSize = '';
+                fly(dom).afterFx(o);
+            }   
+
+            arguments.callee.anim = fly(dom).fxanim({
+                    width : {to : fly(dom).adjustWidth(width * 2)},
+                    height : {to : fly(dom).adjustHeight(height * 2)},
+                    points : {by : [-width * .5, -height * .5]},
+                    opacity : {to : 0},
+                    fontSize: {to : 200, unit: "%"}
+                },
+                o,
+                MOTION,
+                .5,
+                EASEOUT,
+                 after);
+        });
+        return me;
+    },
+
+    
+    switchOff : function(o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            st = dom.style,
+            r;
+
+        me.queueFx(o, function(){
+            fly(dom).clearOpacity();
+            fly(dom).clip();
+
+            
+            r = fly(dom).getFxRestore();
+                
+            function after(){
+                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
+                fly(dom).clearOpacity();
+                fly(dom).setPositioning(r.pos);
+                st.width = r.width;
+                st.height = r.height;   
+                fly(dom).afterFx(o);
+            };
+
+            fly(dom).fxanim({opacity : {to : 0.3}}, 
+                NULL, 
+                NULL, 
+                .1, 
+                NULL, 
+                function(){                                 
+                    fly(dom).clearOpacity();
+                        (function(){                            
+                            fly(dom).fxanim({
+                                height : {to : 1},
+                                points : {by : [0, fly(dom).getHeight() * .5]}
+                            }, 
+                            o, 
+                            MOTION, 
+                            0.3, 
+                            'easeIn', 
+                            after);
+                        }).defer(100);
+                });
+        });
+        return me;
+    },
+
+     
+    highlight : function(color, o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            attr = o.attr || "backgroundColor",
+            a = {},
+            restore;
+
+        me.queueFx(o, function(){
+            fly(dom).clearOpacity();
+            fly(dom).show();
+
+            function after(){
+                dom.style[attr] = restore;
+                fly(dom).afterFx(o);
+            }            
+            restore = dom.style[attr];
+            a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
+            arguments.callee.anim = fly(dom).fxanim(a,
+                o,
+                'color',
+                1,
+                'easeIn', 
+                after);
+        });
+        return me;
+    },
+
+   
+    frame : function(color, count, o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            proxy,
+            active;
+
+        me.queueFx(o, function(){
+            color = color || '#C3DAF9';
+            if(color.length == 6){
+                color = '#' + color;
+            }            
+            count = count || 1;
+            fly(dom).show();
+
+            var xy = fly(dom).getXY(),
+                b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
+                queue = function(){
+                    proxy = fly(document.body || document.documentElement).createChild({
+                        style:{
+                            position : ABSOLUTE,
+                            'z-index': 35000, 
+                            border : '0px solid ' + color
+                        }
+                    });
+                    return proxy.queueFx({}, animFn);
+                };
+            
+            
+            arguments.callee.anim = {
+                isAnimated: true,
+                stop: function() {
+                    count = 0;
+                    proxy.stopFx();
+                }
+            };
+            
+            function animFn(){
+                var scale = Ext.isBorderBox ? 2 : 1;
+                active = proxy.anim({
+                    top : {from : b.y, to : b.y - 20},
+                    left : {from : b.x, to : b.x - 20},
+                    borderWidth : {from : 0, to : 10},
+                    opacity : {from : 1, to : 0},
+                    height : {from : b.height, to : b.height + 20 * scale},
+                    width : {from : b.width, to : b.width + 20 * scale}
+                },{
+                    duration: o.duration || 1,
+                    callback: function() {
+                        proxy.remove();
+                        --count > 0 ? queue() : fly(dom).afterFx(o);
+                    }
+                });
+                arguments.callee.anim = {
+                    isAnimated: true,
+                    stop: function(){
+                        active.stop();
+                    }
+                };
+            };
+            queue();
+        });
+        return me;
+    },
+
+   
+    pause : function(seconds){        
+        var dom = this.dom,
+            t;
+
+        this.queueFx({}, function(){
+            t = setTimeout(function(){
+                fly(dom).afterFx({});
+            }, seconds * 1000);
+            arguments.callee.anim = {
+                isAnimated: true,
+                stop: function(){
+                    clearTimeout(t);
+                    fly(dom).afterFx({});
+                }
+            };
+        });
+        return this;
+    },
+
+   
+    fadeIn : function(o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            to = o.endOpacity || 1;
+        
+        me.queueFx(o, function(){
+            fly(dom).setOpacity(0);
+            fly(dom).fixDisplay();
+            dom.style.visibility = VISIBLE;
+            arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
+                o, NULL, .5, EASEOUT, function(){
+                if(to == 1){
+                    fly(dom).clearOpacity();
+                }
+                fly(dom).afterFx(o);
+            });
+        });
+        return me;
+    },
+
+   
+    fadeOut : function(o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            style = dom.style,
+            to = o.endOpacity || 0;         
+        
+        me.queueFx(o, function(){  
+            arguments.callee.anim = fly(dom).fxanim({ 
+                opacity : {to : to}},
+                o, 
+                NULL, 
+                .5, 
+                EASEOUT, 
+                function(){
+                    if(to == 0){
+                        Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
+                            style.display = "none" :
+                            style.visibility = HIDDEN;
+                            
+                        fly(dom).clearOpacity();
+                    }
+                    fly(dom).afterFx(o);
+            });
+        });
+        return me;
+    },
+
+   
+    scale : function(w, h, o){
+        this.shift(Ext.apply({}, o, {
+            width: w,
+            height: h
+        }));
+        return this;
+    },
+
+   
+    shift : function(o){
+        o = getObject(o);
+        var dom = this.dom,
+            a = {};
+                
+        this.queueFx(o, function(){
+            for (var prop in o) {
+                if (o[prop] != UNDEFINED) {                                                 
+                    a[prop] = {to : o[prop]};                   
+                }
+            } 
+            
+            a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
+            a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
+            
+            if (a.x || a.y || a.xy) {
+                a.points = a.xy || 
+                           {to : [ a.x ? a.x.to : fly(dom).getX(),
+                                   a.y ? a.y.to : fly(dom).getY()]};                  
+            }
+
+            arguments.callee.anim = fly(dom).fxanim(a,
+                o, 
+                MOTION, 
+                .35, 
+                EASEOUT, 
+                function(){
+                    fly(dom).afterFx(o);
+                });
+        });
+        return this;
+    },
+
+    
+    ghost : function(anchor, o){
+        o = getObject(o);
+        var me = this,
+            dom = me.dom,
+            st = dom.style,
+            a = {opacity: {to: 0}, points: {}},
+            pt = a.points,
+            r,
+            w,
+            h;
+            
+        anchor = anchor || "b";
+
+        me.queueFx(o, function(){
+            
+            r = fly(dom).getFxRestore();
+            w = fly(dom).getWidth();
+            h = fly(dom).getHeight();
+            
+            function after(){
+                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
+                fly(dom).clearOpacity();
+                fly(dom).setPositioning(r.pos);
+                st.width = r.width;
+                st.height = r.height;
+                fly(dom).afterFx(o);
+            }
+                
+            pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
+               t  : [0, -h],
+               l  : [-w, 0],
+               r  : [w, 0],
+               b  : [0, h],
+               tl : [-w, -h],
+               bl : [-w, h],
+               br : [w, h],
+               tr : [w, -h] 
+            });
+                
+            arguments.callee.anim = fly(dom).fxanim(a,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, after);
+        });
+        return me;
+    },
+
+    
+    syncFx : function(){
+        var me = this;
+        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
+            block : FALSE,
+            concurrent : TRUE,
+            stopFx : FALSE
+        });
+        return me;
+    },
+
+    
+    sequenceFx : function(){
+        var me = this;
+        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
+            block : FALSE,
+            concurrent : FALSE,
+            stopFx : FALSE
+        });
+        return me;
+    },
+
+    
+    nextFx : function(){        
+        var ef = getQueue(this.dom.id)[0];
+        if(ef){
+            ef.call(this);
+        }
+    },
+
+    
+    hasActiveFx : function(){
+        return getQueue(this.dom.id)[0];
+    },
+
+    
+    stopFx : function(finish){
+        var me = this,
+            id = me.dom.id;
+        if(me.hasActiveFx()){
+            var cur = getQueue(id)[0];
+            if(cur && cur.anim){
+                if(cur.anim.isAnimated){
+                    setQueue(id, [cur]); 
+                    cur.anim.stop(finish !== undefined ? finish : TRUE);
+                }else{
+                    setQueue(id, []);
+                }
+            }
+        }
+        return me;
+    },
+
+    
+    beforeFx : function(o){
+        if(this.hasActiveFx() && !o.concurrent){
+           if(o.stopFx){
+               this.stopFx();
+               return TRUE;
+           }
+           return FALSE;
+        }
+        return TRUE;
+    },
+
+    
+    hasFxBlock : function(){
+        var q = getQueue(this.dom.id);
+        return q && q[0] && q[0].block;
+    },
+
+    
+    queueFx : function(o, fn){
+        var me = fly(this.dom);
+        if(!me.hasFxBlock()){
+            Ext.applyIf(o, me.fxDefaults);
+            if(!o.concurrent){
+                var run = me.beforeFx(o);
+                fn.block = o.block;
+                getQueue(me.dom.id).push(fn);
+                if(run){
+                    me.nextFx();
+                }
+            }else{
+                fn.call(me);
+            }
+        }
+        return me;
+    },
+
+    
+    fxWrap : function(pos, o, vis){ 
+        var dom = this.dom,
+            wrap,
+            wrapXY;
+        if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
+            if(o.fixPosition){
+                wrapXY = fly(dom).getXY();
+            }
+            var div = document.createElement("div");
+            div.style.visibility = vis;
+            wrap = dom.parentNode.insertBefore(div, dom);
+            fly(wrap).setPositioning(pos);
+            if(fly(wrap).isStyle(POSITION, "static")){
+                fly(wrap).position("relative");
+            }
+            fly(dom).clearPositioning('auto');
+            fly(wrap).clip();
+            wrap.appendChild(dom);
+            if(wrapXY){
+                fly(wrap).setXY(wrapXY);
+            }
+        }
+        return wrap;
+    },
+
+    
+    fxUnwrap : function(wrap, pos, o){      
+        var dom = this.dom;
+        fly(dom).clearPositioning();
+        fly(dom).setPositioning(pos);
+        if(!o.wrap){
+            var pn = fly(wrap).dom.parentNode;
+            pn.insertBefore(dom, wrap); 
+            fly(wrap).remove();
+        }
+    },
+
+    
+    getFxRestore : function(){
+        var st = this.dom.style;
+        return {pos: this.getPositioning(), width: st.width, height : st.height};
+    },
+
+    
+    afterFx : function(o){
+        var dom = this.dom,
+            id = dom.id;
+        if(o.afterStyle){
+            fly(dom).setStyle(o.afterStyle);            
+        }
+        if(o.afterCls){
+            fly(dom).addClass(o.afterCls);
+        }
+        if(o.remove == TRUE){
+            fly(dom).remove();
+        }
+        if(o.callback){
+            o.callback.call(o.scope, fly(dom));
+        }
+        if(!o.concurrent){
+            getQueue(id).shift();
+            fly(dom).nextFx();
+        }
+    },
+
+    
+    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
+        animType = animType || 'run';
+        opt = opt || {};
+        var anim = Ext.lib.Anim[animType](
+                this.dom, 
+                args,
+                (opt.duration || defaultDur) || .35,
+                (opt.easing || defaultEase) || EASEOUT,
+                cb,            
+                this
+            );
+        opt.anim = anim;
+        return anim;
+    }
+};
+
+
+Ext.Fx.resize = Ext.Fx.scale;
+
+
+
+Ext.Element.addMethods(Ext.Fx);
+})();
+
+Ext.CompositeElementLite = function(els, root){
+    
+    this.elements = [];
+    this.add(els, root);
+    this.el = new Ext.Element.Flyweight();
+};
+
+Ext.CompositeElementLite.prototype = {
+    isComposite: true,
+
+    
+    getElement : function(el){
+        
+        var e = this.el;
+        e.dom = el;
+        e.id = el.id;
+        return e;
+    },
+
+    
+    transformElement : function(el){
+        return Ext.getDom(el);
+    },
+
+    
+    getCount : function(){
+        return this.elements.length;
+    },
+    
+    add : function(els, root){
+        var me = this,
+            elements = me.elements;
+        if(!els){
+            return this;
+        }
+        if(typeof els == "string"){
+            els = Ext.Element.selectorFunction(els, root);
+        }else if(els.isComposite){
+            els = els.elements;
+        }else if(!Ext.isIterable(els)){
+            els = [els];
+        }
+
+        for(var i = 0, len = els.length; i < len; ++i){
+            elements.push(me.transformElement(els[i]));
+        }
+        return me;
+    },
+
+    invoke : function(fn, args){
+        var me = this,
+            els = me.elements,
+            len = els.length,
+            e,
+            i;
+
+        for(i = 0; i < len; i++) {
+            e = els[i];
+            if(e){
+                Ext.Element.prototype[fn].apply(me.getElement(e), args);
+            }
+        }
+        return me;
+    },
+    
+    item : function(index){
+        var me = this,
+            el = me.elements[index],
+            out = null;
+
+        if(el){
+            out = me.getElement(el);
+        }
+        return out;
+    },
+
+    
+    addListener : function(eventName, handler, scope, opt){
+        var els = this.elements,
+            len = els.length,
+            i, e;
+
+        for(i = 0; i<len; i++) {
+            e = els[i];
+            if(e) {
+                Ext.EventManager.on(e, eventName, handler, scope || e, opt);
+            }
+        }
+        return this;
+    },
+    
+    each : function(fn, scope){
+        var me = this,
+            els = me.elements,
+            len = els.length,
+            i, e;
+
+        for(i = 0; i<len; i++) {
+            e = els[i];
+            if(e){
+                e = this.getElement(e);
+                if(fn.call(scope || e, e, me, i) === false){
+                    break;
+                }
+            }
+        }
+        return me;
+    },
+
+    
+    fill : function(els){
+        var me = this;
+        me.elements = [];
+        me.add(els);
+        return me;
+    },
+
+    
+    filter : function(selector){
+        var els = [],
+            me = this,
+            fn = Ext.isFunction(selector) ? selector
+                : function(el){
+                    return el.is(selector);
+                };
+
+        me.each(function(el, self, i) {
+            if (fn(el, i) !== false) {
+                els[els.length] = me.transformElement(el);
+            }
+        });
+        
+        me.elements = els;
+        return me;
+    },
+
+    
+    indexOf : function(el){
+        return this.elements.indexOf(this.transformElement(el));
+    },
+
+    
+    replaceElement : function(el, replacement, domReplace){
+        var index = !isNaN(el) ? el : this.indexOf(el),
+            d;
+        if(index > -1){
+            replacement = Ext.getDom(replacement);
+            if(domReplace){
+                d = this.elements[index];
+                d.parentNode.insertBefore(replacement, d);
+                Ext.removeNode(d);
+            }
+            this.elements.splice(index, 1, replacement);
+        }
+        return this;
+    },
+
+    
+    clear : function(){
+        this.elements = [];
+    }
+};
+
+Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
+
+
+Ext.CompositeElementLite.importElementMethods = function() {
+    var fnName,
+        ElProto = Ext.Element.prototype,
+        CelProto = Ext.CompositeElementLite.prototype;
+
+    for (fnName in ElProto) {
+        if (typeof ElProto[fnName] == 'function'){
+            (function(fnName) {
+                CelProto[fnName] = CelProto[fnName] || function() {
+                    return this.invoke(fnName, arguments);
+                };
+            }).call(CelProto, fnName);
+
+        }
+    }
+};
+
+Ext.CompositeElementLite.importElementMethods();
+
+if(Ext.DomQuery){
+    Ext.Element.selectorFunction = Ext.DomQuery.select;
+}
+
+
+Ext.Element.select = function(selector, root){
+    var els;
+    if(typeof selector == "string"){
+        els = Ext.Element.selectorFunction(selector, root);
+    }else if(selector.length !== undefined){
+        els = selector;
+    }else{
+        throw "Invalid selector";
+    }
+    return new Ext.CompositeElementLite(els);
+};
+
+Ext.select = Ext.Element.select;
+(function(){
+    var BEFOREREQUEST = "beforerequest",
+        REQUESTCOMPLETE = "requestcomplete",
+        REQUESTEXCEPTION = "requestexception",
+        UNDEFINED = undefined,
+        LOAD = 'load',
+        POST = 'POST',
+        GET = 'GET',
+        WINDOW = window;
+
+    
+    Ext.data.Connection = function(config){
+        Ext.apply(this, config);
+        this.addEvents(
+            
+            BEFOREREQUEST,
+            
+            REQUESTCOMPLETE,
+            
+            REQUESTEXCEPTION
+        );
+        Ext.data.Connection.superclass.constructor.call(this);
+    };
+
+    Ext.extend(Ext.data.Connection, Ext.util.Observable, {
+        
+        
+        
+        
+        
+        timeout : 30000,
+        
+        autoAbort:false,
+
+        
+        disableCaching: true,
+
+        
+        disableCachingParam: '_dc',
+
+        
+        request : function(o){
+            var me = this;
+            if(me.fireEvent(BEFOREREQUEST, me, o)){
+                if (o.el) {
+                    if(!Ext.isEmpty(o.indicatorText)){
+                        me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
+                    }
+                    if(me.indicatorText) {
+                        Ext.getDom(o.el).innerHTML = me.indicatorText;
+                    }
+                    o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
+                        Ext.getDom(o.el).innerHTML = response.responseText;
+                    });
+                }
+
+                var p = o.params,
+                    url = o.url || me.url,
+                    method,
+                    cb = {success: me.handleResponse,
+                          failure: me.handleFailure,
+                          scope: me,
+                          argument: {options: o},
+                          timeout : Ext.num(o.timeout, me.timeout)
+                    },
+                    form,
+                    serForm;
+
+
+                if (Ext.isFunction(p)) {
+                    p = p.call(o.scope||WINDOW, o);
+                }
+
+                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
+
+                if (Ext.isFunction(url)) {
+                    url = url.call(o.scope || WINDOW, o);
+                }
+
+                if((form = Ext.getDom(o.form))){
+                    url = url || form.action;
+                     if(o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
+                         return me.doFormUpload.call(me, o, p, url);
+                     }
+                    serForm = Ext.lib.Ajax.serializeForm(form);
+                    p = p ? (p + '&' + serForm) : serForm;
+                }
+
+                method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
+
+                if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
+                    var dcp = o.disableCachingParam || me.disableCachingParam;
+                    url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
+                }
+
+                o.headers = Ext.applyIf(o.headers || {}, me.defaultHeaders || {});
+
+                if(o.autoAbort === true || me.autoAbort) {
+                    me.abort();
+                }
+
+                if((method == GET || o.xmlData || o.jsonData) && p){
+                    url = Ext.urlAppend(url, p);
+                    p = '';
+                }
+                return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
+            }else{
+                return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
+            }
+        },
+
+        
+        isLoading : function(transId){
+            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
+        },
+
+        
+        abort : function(transId){
+            if(transId || this.isLoading()){
+                Ext.lib.Ajax.abort(transId || this.transId);
+            }
+        },
+
+        
+        handleResponse : function(response){
+            this.transId = false;
+            var options = response.argument.options;
+            response.argument = options ? options.argument : null;
+            this.fireEvent(REQUESTCOMPLETE, this, response, options);
+            if(options.success){
+                options.success.call(options.scope, response, options);
+            }
+            if(options.callback){
+                options.callback.call(options.scope, options, true, response);
+            }
+        },
+
+        
+        handleFailure : function(response, e){
+            this.transId = false;
+            var options = response.argument.options;
+            response.argument = options ? options.argument : null;
+            this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
+            if(options.failure){
+                options.failure.call(options.scope, response, options);
+            }
+            if(options.callback){
+                options.callback.call(options.scope, options, false, response);
+            }
+        },
+
+        
+        doFormUpload : function(o, ps, url){
+            var id = Ext.id(),
+                doc = document,
+                frame = doc.createElement('iframe'),
+                form = Ext.getDom(o.form),
+                hiddens = [],
+                hd,
+                encoding = 'multipart/form-data',
+                buf = {
+                    target: form.target,
+                    method: form.method,
+                    encoding: form.encoding,
+                    enctype: form.enctype,
+                    action: form.action
+                };
+
+            
+            Ext.fly(frame).set({
+                id: id,
+                name: id,
+                cls: 'x-hidden',
+                src: Ext.SSL_SECURE_URL
+            }); 
+
+            doc.body.appendChild(frame);
+
+            
+            if(Ext.isIE){
+               document.frames[id].name = id;
+            }
+
+
+            Ext.fly(form).set({
+                target: id,
+                method: POST,
+                enctype: encoding,
+                encoding: encoding,
+                action: url || buf.action
+            });
+
+            
+            Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
+                hd = doc.createElement('input');
+                Ext.fly(hd).set({
+                    type: 'hidden',
+                    value: v,
+                    name: k
+                });
+                form.appendChild(hd);
+                hiddens.push(hd);
+            });
+
+            function cb(){
+                var me = this,
+                    
+                    r = {responseText : '',
+                         responseXML : null,
+                         argument : o.argument},
+                    doc,
+                    firstChild;
+
+                try{
+                    doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
+                    if(doc){
+                        if(doc.body){
+                            if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
+                                r.responseText = firstChild.value;
+                            }else{
+                                r.responseText = doc.body.innerHTML;
+                            }
+                        }
+                        
+                        r.responseXML = doc.XMLDocument || doc;
+                    }
+                }
+                catch(e) {}
+
+                Ext.EventManager.removeListener(frame, LOAD, cb, me);
+
+                me.fireEvent(REQUESTCOMPLETE, me, r, o);
+
+                function runCallback(fn, scope, args){
+                    if(Ext.isFunction(fn)){
+                        fn.apply(scope, args);
+                    }
+                }
+
+                runCallback(o.success, o.scope, [r, o]);
+                runCallback(o.callback, o.scope, [o, true, r]);
+
+                if(!me.debugUploads){
+                    setTimeout(function(){Ext.removeNode(frame);}, 100);
+                }
+            }
+
+            Ext.EventManager.on(frame, LOAD, cb, this);
+            form.submit();
+
+            Ext.fly(form).set(buf);
+            Ext.each(hiddens, function(h) {
+                Ext.removeNode(h);
+            });
+        }
+    });
+})();
+
+
+Ext.Ajax = new Ext.data.Connection({
+    
+    
+    
+    
+    
+    
+
+    
+
+    
+    
+    
+    
+    
+    
+
+    
+    autoAbort : false,
+
+    
+    serializeForm : function(form){
+        return Ext.lib.Ajax.serializeForm(form);
+    }
+});
+
+Ext.util.JSON = new (function(){
+    var useHasOwn = !!{}.hasOwnProperty,
+        isNative = function() {
+            var useNative = null;
+
+            return function() {
+                if (useNative === null) {
+                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
+                }
+        
+                return useNative;
+            };
+        }(),
+        pad = function(n) {
+            return n < 10 ? "0" + n : n;
+        },
+        doDecode = function(json){
+            return json ? eval("(" + json + ")") : "";    
+        },
+        doEncode = function(o){
+            if(!Ext.isDefined(o) || o === null){
+                return "null";
+            }else if(Ext.isArray(o)){
+                return encodeArray(o);
+            }else if(Ext.isDate(o)){
+                return Ext.util.JSON.encodeDate(o);
+            }else if(Ext.isString(o)){
+                return encodeString(o);
+            }else if(typeof o == "number"){
+                
+                return isFinite(o) ? String(o) : "null";
+            }else if(Ext.isBoolean(o)){
+                return String(o);
+            }else {
+                var a = ["{"], b, i, v;
+                for (i in o) {
+                    
+                    if(!o.getElementsByTagName){
+                        if(!useHasOwn || o.hasOwnProperty(i)) {
+                            v = o[i];
+                            switch (typeof v) {
+                            case "undefined":
+                            case "function":
+                            case "unknown":
+                                break;
+                            default:
+                                if(b){
+                                    a.push(',');
+                                }
+                                a.push(doEncode(i), ":",
+                                        v === null ? "null" : doEncode(v));
+                                b = true;
+                            }
+                        }
+                    }
+                }
+                a.push("}");
+                return a.join("");
+            }    
+        },
+        m = {
+            "\b": '\\b',
+            "\t": '\\t',
+            "\n": '\\n',
+            "\f": '\\f',
+            "\r": '\\r',
+            '"' : '\\"',
+            "\\": '\\\\'
+        },
+        encodeString = function(s){
+            if (/["\\\x00-\x1f]/.test(s)) {
+                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                    var c = m[b];
+                    if(c){
+                        return c;
+                    }
+                    c = b.charCodeAt();
+                    return "\\u00" +
+                        Math.floor(c / 16).toString(16) +
+                        (c % 16).toString(16);
+                }) + '"';
+            }
+            return '"' + s + '"';
+        },
+        encodeArray = function(o){
+            var a = ["["], b, i, l = o.length, v;
+                for (i = 0; i < l; i += 1) {
+                    v = o[i];
+                    switch (typeof v) {
+                        case "undefined":
+                        case "function":
+                        case "unknown":
+                            break;
+                        default:
+                            if (b) {
+                                a.push(',');
+                            }
+                            a.push(v === null ? "null" : Ext.util.JSON.encode(v));
+                            b = true;
+                    }
+                }
+                a.push("]");
+                return a.join("");
+        };
+
+    
+    this.encodeDate = function(o){
+        return '"' + o.getFullYear() + "-" +
+                pad(o.getMonth() + 1) + "-" +
+                pad(o.getDate()) + "T" +
+                pad(o.getHours()) + ":" +
+                pad(o.getMinutes()) + ":" +
+                pad(o.getSeconds()) + '"';
+    };
+
+    
+    this.encode = function() {
+        var ec;
+        return function(o) {
+            if (!ec) {
+                
+                ec = isNative() ? JSON.stringify : doEncode;
+            }
+            return ec(o);
+        };
+    }();
+
+
+    
+    this.decode = function() {
+        var dc;
+        return function(json) {
+            if (!dc) {
+                
+                dc = isNative() ? JSON.parse : doDecode;
+            }
+            return dc(json);
+        };
+    }();
+
+})();
+
+Ext.encode = Ext.util.JSON.encode;
+
+Ext.decode = Ext.util.JSON.decode;
+
+Ext.EventManager = function(){
+    var docReadyEvent,
+        docReadyProcId,
+        docReadyState = false,
+        DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
+        E = Ext.lib.Event,
+        D = Ext.lib.Dom,
+        DOC = document,
+        WINDOW = window,
+        DOMCONTENTLOADED = "DOMContentLoaded",
+        COMPLETE = 'complete',
+        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
+        
+        specialElCache = [];
+
+     function getId(el){
+        var id = false,
+            i = 0,
+            len = specialElCache.length,
+            skip = false,
+            o;
+            
+        if (el) {
+            if (el.getElementById || el.navigator) {
+                
+                for(; i < len; ++i){
+                    o = specialElCache[i];
+                    if(o.el === el){
+                        id = o.id;
+                        break;
+                    }
+                }
+                if(!id){
+                    
+                    id = Ext.id(el);
+                    specialElCache.push({
+                        id: id,
+                        el: el
+                    });
+                    skip = true;
+                }
+            }else{
+                id = Ext.id(el);
+            }
+            if(!Ext.elCache[id]){
+                Ext.Element.addToCache(new Ext.Element(el), id);
+                if(skip){
+                    Ext.elCache[id].skipGC = true;
+                }
+            }
+        }
+        return id;
+     }
+
+    
+    function addListener(el, ename, fn, task, wrap, scope){
+        el = Ext.getDom(el);
+        var id = getId(el),
+            es = Ext.elCache[id].events,
+            wfn;
+
+        wfn = E.on(el, ename, wrap);
+        es[ename] = es[ename] || [];
+
+        
+        es[ename].push([fn, wrap, scope, wfn, task]);
+
+        
+        
+
+        
+        if(el.addEventListener && ename == "mousewheel"){
+            var args = ["DOMMouseScroll", wrap, false];
+            el.addEventListener.apply(el, args);
+            Ext.EventManager.addListener(WINDOW, 'unload', function(){
+                el.removeEventListener.apply(el, args);
+            });
+        }
+
+        
+        if(el == DOC && ename == "mousedown"){
+            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
+        }
+    }
+
+    function doScrollChk(){
+        
+        if(window != top){
+            return false;
+        }
+
+        try{
+            DOC.documentElement.doScroll('left');
+        }catch(e){
+             return false;
+        }
+
+        fireDocReady();
+        return true;
+    }
+    
+    function checkReadyState(e){
+
+        if(Ext.isIE && doScrollChk()){
+            return true;
+        }
+        if(DOC.readyState == COMPLETE){
+            fireDocReady();
+            return true;
+        }
+        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
+        return false;
+    }
+
+    var styles;
+    function checkStyleSheets(e){
+        styles || (styles = Ext.query('style, link[rel=stylesheet]'));
+        if(styles.length == DOC.styleSheets.length){
+            fireDocReady();
+            return true;
+        }
+        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
+        return false;
+    }
+
+    function OperaDOMContentLoaded(e){
+        DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
+        checkStyleSheets();
+    }
+
+    function fireDocReady(e){
+        if(!docReadyState){
+            docReadyState = true; 
+
+            if(docReadyProcId){
+                clearTimeout(docReadyProcId);
+            }
+            if(DETECT_NATIVE) {
+                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
+            }
+            if(Ext.isIE && checkReadyState.bindIE){  
+                DOC.detachEvent('onreadystatechange', checkReadyState);
+            }
+            E.un(WINDOW, "load", arguments.callee);
+        }
+        if(docReadyEvent && !Ext.isReady){
+            Ext.isReady = true;
+            docReadyEvent.fire();
+            docReadyEvent.listeners = [];
+        }
+
+    }
+
+    function initDocReady(){
+        docReadyEvent || (docReadyEvent = new Ext.util.Event());
+        if (DETECT_NATIVE) {
+            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
+        }
+        
+        if (Ext.isIE){
+            
+            
+            if(!checkReadyState()){
+                checkReadyState.bindIE = true;
+                DOC.attachEvent('onreadystatechange', checkReadyState);
+            }
+
+        }else if(Ext.isOpera ){
+            
+
+            
+            (DOC.readyState == COMPLETE && checkStyleSheets()) ||
+                DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
+
+        }else if (Ext.isWebKit){
+            
+            checkReadyState();
+        }
+        
+        E.on(WINDOW, "load", fireDocReady);
+    }
+
+    function createTargeted(h, o){
+        return function(){
+            var args = Ext.toArray(arguments);
+            if(o.target == Ext.EventObject.setEvent(args[0]).target){
+                h.apply(this, args);
+            }
+        };
+    }
+
+    function createBuffered(h, o, task){
+        return function(e){
+            
+            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
+        };
+    }
+
+    function createSingle(h, el, ename, fn, scope){
+        return function(e){
+            Ext.EventManager.removeListener(el, ename, fn, scope);
+            h(e);
+        };
+    }
+
+    function createDelayed(h, o, fn){
+        return function(e){
+            var task = new Ext.util.DelayedTask(h);
+            if(!fn.tasks) {
+                fn.tasks = [];
+            }
+            fn.tasks.push(task);
+            task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
+        };
+    }
+
+    function listen(element, ename, opt, fn, scope){
+        var o = (!opt || typeof opt == "boolean") ? {} : opt,
+            el = Ext.getDom(element), task;
+
+        fn = fn || o.fn;
+        scope = scope || o.scope;
+
+        if(!el){
+            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
+        }
+        function h(e){
+            
+            if(!Ext){
+                return;
+            }
+            e = Ext.EventObject.setEvent(e);
+            var t;
+            if (o.delegate) {
+                if(!(t = e.getTarget(o.delegate, el))){
+                    return;
+                }
+            } else {
+                t = e.target;
+            }
+            if (o.stopEvent) {
+                e.stopEvent();
+            }
+            if (o.preventDefault) {
+               e.preventDefault();
+            }
+            if (o.stopPropagation) {
+                e.stopPropagation();
+            }
+            if (o.normalized === false) {
+                e = e.browserEvent;
+            }
+
+            fn.call(scope || el, e, t, o);
+        }
+        if(o.target){
+            h = createTargeted(h, o);
+        }
+        if(o.delay){
+            h = createDelayed(h, o, fn);
+        }
+        if(o.single){
+            h = createSingle(h, el, ename, fn, scope);
+        }
+        if(o.buffer){
+            task = new Ext.util.DelayedTask(h);
+            h = createBuffered(h, o, task);
+        }
+
+        addListener(el, ename, fn, task, h, scope);
+        return h;
+    }
+
+    var pub = {
+        
+        addListener : function(element, eventName, fn, scope, options){
+            if(typeof eventName == 'object'){
+                var o = eventName, e, val;
+                for(e in o){
+                    val = o[e];
+                    if(!propRe.test(e)){
+                        if(Ext.isFunction(val)){
+                            
+                            listen(element, e, o, val, o.scope);
+                        }else{
+                            
+                            listen(element, e, val);
+                        }
+                    }
+                }
+            } else {
+                listen(element, eventName, options, fn, scope);
+            }
+        },
+
+        
+        removeListener : function(el, eventName, fn, scope){
+            el = Ext.getDom(el);
+            var id = getId(el),
+                f = el && (Ext.elCache[id].events)[eventName] || [],
+                wrap, i, l, k, len, fnc;
+
+            for (i = 0, len = f.length; i < len; i++) {
+
+                
+                if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
+                    if(fnc[4]) {
+                        fnc[4].cancel();
+                    }
+                    k = fn.tasks && fn.tasks.length;
+                    if(k) {
+                        while(k--) {
+                            fn.tasks[k].cancel();
+                        }
+                        delete fn.tasks;
+                    }
+                    wrap = fnc[1];
+                    E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
+
+                    
+                    if(wrap && el.addEventListener && eventName == "mousewheel"){
+                        el.removeEventListener("DOMMouseScroll", wrap, false);
+                    }
+
+                    
+                    if(wrap && el == DOC && eventName == "mousedown"){
+                        Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
+                    }
+
+                    f.splice(i, 1);
+                    if (f.length === 0) {
+                        delete Ext.elCache[id].events[eventName];
+                    }
+                    for (k in Ext.elCache[id].events) {
+                        return false;
+                    }
+                    Ext.elCache[id].events = {};
+                    return false;
+                }
+            }
+        },
+
+        
+        removeAll : function(el){
+            el = Ext.getDom(el);
+            var id = getId(el),
+                ec = Ext.elCache[id] || {},
+                es = ec.events || {},
+                f, i, len, ename, fn, k, wrap;
+
+            for(ename in es){
+                if(es.hasOwnProperty(ename)){
+                    f = es[ename];
+                    
+                    for (i = 0, len = f.length; i < len; i++) {
+                        fn = f[i];
+                        if(fn[4]) {
+                            fn[4].cancel();
+                        }
+                        if(fn[0].tasks && (k = fn[0].tasks.length)) {
+                            while(k--) {
+                                fn[0].tasks[k].cancel();
+                            }
+                            delete fn.tasks;
+                        }
+                        wrap =  fn[1];
+                        E.un(el, ename, E.extAdapter ? fn[3] : wrap);
+
+                        
+                        if(el.addEventListener && wrap && ename == "mousewheel"){
+                            el.removeEventListener("DOMMouseScroll", wrap, false);
+                        }
+
+                        
+                        if(wrap && el == DOC &&  ename == "mousedown"){
+                            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
+                        }
+                    }
+                }
+            }
+            if (Ext.elCache[id]) {
+                Ext.elCache[id].events = {};
+            }
+        },
+
+        getListeners : function(el, eventName) {
+            el = Ext.getDom(el);
+            var id = getId(el),
+                ec = Ext.elCache[id] || {},
+                es = ec.events || {},
+                results = [];
+            if (es && es[eventName]) {
+                return es[eventName];
+            } else {
+                return null;
+            }
+        },
+
+        purgeElement : function(el, recurse, eventName) {
+            el = Ext.getDom(el);
+            var id = getId(el),
+                ec = Ext.elCache[id] || {},
+                es = ec.events || {},
+                i, f, len;
+            if (eventName) {
+                if (es && es.hasOwnProperty(eventName)) {
+                    f = es[eventName];
+                    for (i = 0, len = f.length; i < len; i++) {
+                        Ext.EventManager.removeListener(el, eventName, f[i][0]);
+                    }
+                }
+            } else {
+                Ext.EventManager.removeAll(el);
+            }
+            if (recurse && el && el.childNodes) {
+                for (i = 0, len = el.childNodes.length; i < len; i++) {
+                    Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
+                }
+            }
+        },
+
+        _unload : function() {
+            var el;
+            for (el in Ext.elCache) {
+                Ext.EventManager.removeAll(el);
+            }
+            delete Ext.elCache;
+            delete Ext.Element._flyweights;
+
+            
+            var c,
+                conn,
+                tid,
+                ajax = Ext.lib.Ajax;
+            (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
+            for (tid in conn) {
+                c = conn[tid];
+                if (c) {
+                    ajax.abort({conn: c, tId: tid});
+                }
+            }
+        },
+        
+        onDocumentReady : function(fn, scope, options){
+            if (Ext.isReady) { 
+                docReadyEvent || (docReadyEvent = new Ext.util.Event());
+                docReadyEvent.addListener(fn, scope, options);
+                docReadyEvent.fire();
+                docReadyEvent.listeners = [];
+            } else {
+                if (!docReadyEvent) {
+                    initDocReady();
+                }
+                options = options || {};
+                options.delay = options.delay || 1;
+                docReadyEvent.addListener(fn, scope, options);
+            }
+        },
+
+        
+        fireDocReady  : fireDocReady
+    };
+     
+    pub.on = pub.addListener;
+    
+    pub.un = pub.removeListener;
+
+    pub.stoppedMouseDownEvent = new Ext.util.Event();
+    return pub;
+}();
+
+Ext.onReady = Ext.EventManager.onDocumentReady;
+
+
+
+(function(){
+    var initExtCss = function() {
+        
+        var bd = document.body || document.getElementsByTagName('body')[0];
+        if (!bd) {
+            return false;
+        }
+
+        var cls = [' ',
+                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : (Ext.isIE8 ? 'ext-ie8' : 'ext-ie9')))
+                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
+                : Ext.isOpera ? "ext-opera"
+                : Ext.isWebKit ? "ext-webkit" : ""];
+
+        if (Ext.isSafari) {
+            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
+        } else if(Ext.isChrome) {
+            cls.push("ext-chrome");
+        }
+
+        if (Ext.isMac) {
+            cls.push("ext-mac");
+        }
+        if (Ext.isLinux) {
+            cls.push("ext-linux");
+        }
+
+        
+        if (Ext.isStrict || Ext.isBorderBox) {
+            var p = bd.parentNode;
+            if (p) {
+                if (!Ext.isStrict) {
+                    Ext.fly(p, '_internal').addClass('x-quirks');
+                    if (Ext.isIE && !Ext.isStrict) {
+                        Ext.isIEQuirks = true;
+                    }
+                }
+                Ext.fly(p, '_internal').addClass(((Ext.isStrict && Ext.isIE ) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? ' ext-strict' : ' ext-border-box');
+            }
+        }
+        
+        
+        if (Ext.enableForcedBoxModel && !Ext.isIE) {
+            Ext.isForcedBorderBox = true;
+            cls.push("ext-forced-border-box");
+        }
+        
+        Ext.fly(bd, '_internal').addClass(cls);
+        return true;
+    };
+    
+    if (!initExtCss()) {
+        Ext.onReady(initExtCss);
+    }
+})();
+
+
+(function(){
+    var supports = Ext.apply(Ext.supports, {
+        
+        correctRightMargin: true,
+        
+        
+        correctTransparentColor: true,
+        
+        
+        cssFloat: true
+    });
+    
+    var supportTests = function(){
+            var div = document.createElement('div'),
+                doc = document,
+                view,
+                last;
+                
+            div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
+            doc.body.appendChild(div);
+            last = div.lastChild;
+            
+            if((view = doc.defaultView)){
+                if(view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'){
+                    supports.correctRightMargin = false;
+                }
+                if(view.getComputedStyle(last, null).backgroundColor != 'transparent'){
+                    supports.correctTransparentColor = false;
+                }
+            }
+            supports.cssFloat = !!last.style.cssFloat;
+            doc.body.removeChild(div);
+    };
+    
+    if (Ext.isReady) {
+        supportTests();    
+    } else {
+        Ext.onReady(supportTests);
+    }
+})();
+
+
+
+Ext.EventObject = function(){
+    var E = Ext.lib.Event,
+        clickRe = /(dbl)?click/,
+        
+        safariKeys = {
+            3 : 13, 
+            63234 : 37, 
+            63235 : 39, 
+            63232 : 38, 
+            63233 : 40, 
+            63276 : 33, 
+            63277 : 34, 
+            63272 : 46, 
+            63273 : 36, 
+            63275 : 35  
+        },
+        
+        btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};
+
+    Ext.EventObjectImpl = function(e){
+        if(e){
+            this.setEvent(e.browserEvent || e);
+        }
+    };
+
+    Ext.EventObjectImpl.prototype = {
+           
+        setEvent : function(e){
+            var me = this;
+            if(e == me || (e && e.browserEvent)){ 
+                return e;
+            }
+            me.browserEvent = e;
+            if(e){
+                
+                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
+                if(clickRe.test(e.type) && me.button == -1){
+                    me.button = 0;
+                }
+                me.type = e.type;
+                me.shiftKey = e.shiftKey;
+                
+                me.ctrlKey = e.ctrlKey || e.metaKey || false;
+                me.altKey = e.altKey;
+                
+                me.keyCode = e.keyCode;
+                me.charCode = e.charCode;
+                
+                me.target = E.getTarget(e);
+                
+                me.xy = E.getXY(e);
+            }else{
+                me.button = -1;
+                me.shiftKey = false;
+                me.ctrlKey = false;
+                me.altKey = false;
+                me.keyCode = 0;
+                me.charCode = 0;
+                me.target = null;
+                me.xy = [0, 0];
+            }
+            return me;
+        },
+
+        
+        stopEvent : function(){
+            var me = this;
+            if(me.browserEvent){
+                if(me.browserEvent.type == 'mousedown'){
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
+                }
+                E.stopEvent(me.browserEvent);
+            }
+        },
+
+        
+        preventDefault : function(){
+            if(this.browserEvent){
+                E.preventDefault(this.browserEvent);
+            }
+        },
+
+        
+        stopPropagation : function(){
+            var me = this;
+            if(me.browserEvent){
+                if(me.browserEvent.type == 'mousedown'){
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
+                }
+                E.stopPropagation(me.browserEvent);
+            }
+        },
+
+        
+        getCharCode : function(){
+            return this.charCode || this.keyCode;
+        },
+
+        
+        getKey : function(){
+            return this.normalizeKey(this.keyCode || this.charCode);
+        },
+
+        
+        normalizeKey: function(k){
+            return Ext.isSafari ? (safariKeys[k] || k) : k;
+        },
+
+        
+        getPageX : function(){
+            return this.xy[0];
+        },
+
+        
+        getPageY : function(){
+            return this.xy[1];
+        },
+
+        
+        getXY : function(){
+            return this.xy;
+        },
+
+        
+        getTarget : function(selector, maxDepth, returnEl){
+            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
+        },
+
+        
+        getRelatedTarget : function(){
+            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
+        },
+
+        
+        getWheelDelta : function(){
+            var e = this.browserEvent;
+            var delta = 0;
+            if(e.wheelDelta){ 
+                delta = e.wheelDelta/120;
+            }else if(e.detail){ 
+                delta = -e.detail/3;
+            }
+            return delta;
+        },
+
+        
+        within : function(el, related, allowEl){
+            if(el){
+                var t = this[related ? "getRelatedTarget" : "getTarget"]();
+                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
+            }
+            return false;
+        }
+     };
+
+    return new Ext.EventObjectImpl();
+}();
+Ext.Loader = Ext.apply({}, {
+    
+    load: function(fileList, callback, scope, preserveOrder) {
+        var scope       = scope || this,
+            head        = document.getElementsByTagName("head")[0],
+            fragment    = document.createDocumentFragment(),
+            numFiles    = fileList.length,
+            loadedFiles = 0,
+            me          = this;
+        
+        
+        var loadFileIndex = function(index) {
+            head.appendChild(
+                me.buildScriptTag(fileList[index], onFileLoaded)
+            );
+        };
+        
+        
+        var onFileLoaded = function() {
+            loadedFiles ++;
+            
+            
+            if (numFiles == loadedFiles && typeof callback == 'function') {
+                callback.call(scope);
+            } else {
+                if (preserveOrder === true) {
+                    loadFileIndex(loadedFiles);
+                }
+            }
+        };
+        
+        if (preserveOrder === true) {
+            loadFileIndex.call(this, 0);
+        } else {
+            
+            Ext.each(fileList, function(file, index) {
+                fragment.appendChild(
+                    this.buildScriptTag(file, onFileLoaded)
+                );  
+            }, this);
+            
+            head.appendChild(fragment);
+        }
+    },
+    
+    
+    buildScriptTag: function(filename, callback) {
+        var script  = document.createElement('script');
+        script.type = "text/javascript";
+        script.src  = filename;
+        
+        
+        if (script.readyState) {
+            script.onreadystatechange = function() {
+                if (script.readyState == "loaded" || script.readyState == "complete") {
+                    script.onreadystatechange = null;
+                    callback();
+                }
+            };
+        } else {
+            script.onload = callback;
+        }    
+        
+        return script;
+    }
+});
+
+
+Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
+       "Ext.state", "Ext.layout.boxOverflow", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct", "Ext.slider");
+    
+
+Ext.apply(Ext, function(){
+    var E = Ext,
+        idSeed = 0,
+        scrollWidth = null;
+
+    return {
+        
+        emptyFn : function(){},
+
+        
+        BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
+                            'http:/' + '/www.extjs.com/s.gif' :
+                            'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
+
+        extendX : function(supr, fn){
+            return Ext.extend(supr, fn(supr.prototype));
+        },
+
+        
+        getDoc : function(){
+            return Ext.get(document);
+        },
+
+        
+        num : function(v, defaultValue){
+            v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
+            return isNaN(v) ? defaultValue : v;
+        },
+
+        
+        value : function(v, defaultValue, allowBlank){
+            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
+        },
+
+        
+        escapeRe : function(s) {
+            return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
+        },
+
+        sequence : function(o, name, fn, scope){
+            o[name] = o[name].createSequence(fn, scope);
+        },
+
+        
+        addBehaviors : function(o){
+            if(!Ext.isReady){
+                Ext.onReady(function(){
+                    Ext.addBehaviors(o);
+                });
+            } else {
+                var cache = {}, 
+                    parts,
+                    b,
+                    s;
+                for (b in o) {
+                    if ((parts = b.split('@'))[1]) { 
+                        s = parts[0];
+                        if(!cache[s]){
+                            cache[s] = Ext.select(s);
+                        }
+                        cache[s].on(parts[1], o[b]);
+                    }
+                }
+                cache = null;
+            }
+        },
+
+        
+        getScrollBarWidth: function(force){
+            if(!Ext.isReady){
+                return 0;
+            }
+
+            if(force === true || scrollWidth === null){
+                    
+                var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
+                    child = div.child('div', true);
+                var w1 = child.offsetWidth;
+                div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
+                var w2 = child.offsetWidth;
+                div.remove();
+                
+                scrollWidth = w1 - w2 + 2;
+            }
+            return scrollWidth;
+        },
+
+
+        
+        combine : function(){
+            var as = arguments, l = as.length, r = [];
+            for(var i = 0; i < l; i++){
+                var a = as[i];
+                if(Ext.isArray(a)){
+                    r = r.concat(a);
+                }else if(a.length !== undefined && !a.substr){
+                    r = r.concat(Array.prototype.slice.call(a, 0));
+                }else{
+                    r.push(a);
+                }
+            }
+            return r;
+        },
+
+        
+        copyTo : function(dest, source, names){
+            if(typeof names == 'string'){
+                names = names.split(/[,;\s]/);
+            }
+            Ext.each(names, function(name){
+                if(source.hasOwnProperty(name)){
+                    dest[name] = source[name];
+                }
+            }, this);
+            return dest;
+        },
+
+        
+        destroy : function(){
+            Ext.each(arguments, function(arg){
+                if(arg){
+                    if(Ext.isArray(arg)){
+                        this.destroy.apply(this, arg);
+                    }else if(typeof arg.destroy == 'function'){
+                        arg.destroy();
+                    }else if(arg.dom){
+                        arg.remove();
+                    }
+                }
+            }, this);
+        },
+
+        
+        destroyMembers : function(o, arg1, arg2, etc){
+            for(var i = 1, a = arguments, len = a.length; i < len; i++) {
+                Ext.destroy(o[a[i]]);
+                delete o[a[i]];
+            }
+        },
+
+        
+        clean : function(arr){
+            var ret = [];
+            Ext.each(arr, function(v){
+                if(!!v){
+                    ret.push(v);
+                }
+            });
+            return ret;
+        },
+
+        
+        unique : function(arr){
+            var ret = [],
+                collect = {};
+
+            Ext.each(arr, function(v) {
+                if(!collect[v]){
+                    ret.push(v);
+                }
+                collect[v] = true;
+            });
+            return ret;
+        },
+
+        
+        flatten : function(arr){
+            var worker = [];
+            function rFlatten(a) {
+                Ext.each(a, function(v) {
+                    if(Ext.isArray(v)){
+                        rFlatten(v);
+                    }else{
+                        worker.push(v);
+                    }
+                });
+                return worker;
+            }
+            return rFlatten(arr);
+        },
+
+        
+        min : function(arr, comp){
+            var ret = arr[0];
+            comp = comp || function(a,b){ return a < b ? -1 : 1; };
+            Ext.each(arr, function(v) {
+                ret = comp(ret, v) == -1 ? ret : v;
+            });
+            return ret;
+        },
+
+        
+        max : function(arr, comp){
+            var ret = arr[0];
+            comp = comp || function(a,b){ return a > b ? 1 : -1; };
+            Ext.each(arr, function(v) {
+                ret = comp(ret, v) == 1 ? ret : v;
+            });
+            return ret;
+        },
+
+        
+        mean : function(arr){
+           return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
+        },
+
+        
+        sum : function(arr){
+           var ret = 0;
+           Ext.each(arr, function(v) {
+               ret += v;
+           });
+           return ret;
+        },
+
+        
+        partition : function(arr, truth){
+            var ret = [[],[]];
+            Ext.each(arr, function(v, i, a) {
+                ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
+            });
+            return ret;
+        },
+
+        
+        invoke : function(arr, methodName){
+            var ret = [],
+                args = Array.prototype.slice.call(arguments, 2);
+            Ext.each(arr, function(v,i) {
+                if (v && typeof v[methodName] == 'function') {
+                    ret.push(v[methodName].apply(v, args));
+                } else {
+                    ret.push(undefined);
+                }
+            });
+            return ret;
+        },
+
+        
+        pluck : function(arr, prop){
+            var ret = [];
+            Ext.each(arr, function(v) {
+                ret.push( v[prop] );
+            });
+            return ret;
+        },
+
+        
+        zip : function(){
+            var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
+                arrs = parts[0],
+                fn = parts[1][0],
+                len = Ext.max(Ext.pluck(arrs, "length")),
+                ret = [];
+
+            for (var i = 0; i < len; i++) {
+                ret[i] = [];
+                if(fn){
+                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
+                }else{
+                    for (var j = 0, aLen = arrs.length; j < aLen; j++){
+                        ret[i].push( arrs[j][i] );
+                    }
+                }
+            }
+            return ret;
+        },
+
+        
+        getCmp : function(id){
+            return Ext.ComponentMgr.get(id);
+        },
+
+        
+        useShims: E.isIE6 || (E.isMac && E.isGecko2),
+
+        
+        
+        type : function(o){
+            if(o === undefined || o === null){
+                return false;
+            }
+            if(o.htmlElement){
+                return 'element';
+            }
+            var t = typeof o;
+            if(t == 'object' && o.nodeName) {
+                switch(o.nodeType) {
+                    case 1: return 'element';
+                    case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
+                }
+            }
+            if(t == 'object' || t == 'function') {
+                switch(o.constructor) {
+                    case Array: return 'array';
+                    case RegExp: return 'regexp';
+                    case Date: return 'date';
+                }
+                if(typeof o.length == 'number' && typeof o.item == 'function') {
+                    return 'nodelist';
+                }
+            }
+            return t;
+        },
+
+        intercept : function(o, name, fn, scope){
+            o[name] = o[name].createInterceptor(fn, scope);
+        },
+
+        
+        callback : function(cb, scope, args, delay){
+            if(typeof cb == 'function'){
+                if(delay){
+                    cb.defer(delay, scope, args || []);
+                }else{
+                    cb.apply(scope, args || []);
+                }
+            }
+        }
+    };
+}());
+
+
+Ext.apply(Function.prototype, {
+    
+    createSequence : function(fcn, scope){
+        var method = this;
+        return (typeof fcn != 'function') ?
+                this :
+                function(){
+                    var retval = method.apply(this || window, arguments);
+                    fcn.apply(scope || this || window, arguments);
+                    return retval;
+                };
+    }
+});
+
+
+
+Ext.applyIf(String, {
+
+    
+    escape : function(string) {
+        return string.replace(/('|\\)/g, "\\$1");
+    },
+
+    
+    leftPad : function (val, size, ch) {
+        var result = String(val);
+        if(!ch) {
+            ch = " ";
+        }
+        while (result.length < size) {
+            result = ch + result;
+        }
+        return result;
+    }
+});
+
+
+String.prototype.toggle = function(value, other){
+    return this == value ? other : value;
+};
+
+
+String.prototype.trim = function(){
+    var re = /^\s+|\s+$/g;
+    return function(){ return this.replace(re, ""); };
+}();
+
+
+
+Date.prototype.getElapsed = function(date) {
+    return Math.abs((date || new Date()).getTime()-this.getTime());
+};
+
+
+
+Ext.applyIf(Number.prototype, {
+    
+    constrain : function(min, max){
+        return Math.min(Math.max(this, min), max);
+    }
+});
+Ext.lib.Dom.getRegion = function(el) {
+    return Ext.lib.Region.getRegion(el);
+};	Ext.lib.Region = function(t, r, b, l) {
+		var me = this;
+        me.top = t;
+        me[1] = t;
+        me.right = r;
+        me.bottom = b;
+        me.left = l;
+        me[0] = l;
+    };
+
+    Ext.lib.Region.prototype = {
+        contains : function(region) {
+	        var me = this;
+            return ( region.left >= me.left &&
+                     region.right <= me.right &&
+                     region.top >= me.top &&
+                     region.bottom <= me.bottom );
+
+        },
+
+        getArea : function() {
+	        var me = this;
+            return ( (me.bottom - me.top) * (me.right - me.left) );
+        },
+
+        intersect : function(region) {
+            var me = this,
+            	t = Math.max(me.top, region.top),
+            	r = Math.min(me.right, region.right),
+            	b = Math.min(me.bottom, region.bottom),
+            	l = Math.max(me.left, region.left);
+
+            if (b >= t && r >= l) {
+                return new Ext.lib.Region(t, r, b, l);
+            }
+        },
+        
+        union : function(region) {
+	        var me = this,
+            	t = Math.min(me.top, region.top),
+            	r = Math.max(me.right, region.right),
+            	b = Math.max(me.bottom, region.bottom),
+            	l = Math.min(me.left, region.left);
+
+            return new Ext.lib.Region(t, r, b, l);
+        },
+
+        constrainTo : function(r) {
+	        var me = this;
+            me.top = me.top.constrain(r.top, r.bottom);
+            me.bottom = me.bottom.constrain(r.top, r.bottom);
+            me.left = me.left.constrain(r.left, r.right);
+            me.right = me.right.constrain(r.left, r.right);
+            return me;
+        },
+
+        adjust : function(t, l, b, r) {
+	        var me = this;
+            me.top += t;
+            me.left += l;
+            me.right += r;
+            me.bottom += b;
+            return me;
+        }
+    };
+
+    Ext.lib.Region.getRegion = function(el) {
+        var p = Ext.lib.Dom.getXY(el),
+        	t = p[1],
+        	r = p[0] + el.offsetWidth,
+        	b = p[1] + el.offsetHeight,
+        	l = p[0];
+
+        return new Ext.lib.Region(t, r, b, l);
+    };	Ext.lib.Point = function(x, y) {
+        if (Ext.isArray(x)) {
+            y = x[1];
+            x = x[0];
+        }
+        var me = this;
+        me.x = me.right = me.left = me[0] = x;
+        me.y = me.top = me.bottom = me[1] = y;
+    };
+
+    Ext.lib.Point.prototype = new Ext.lib.Region();
+
+Ext.apply(Ext.DomHelper,
+function(){
+    var pub,
+        afterbegin = 'afterbegin',
+        afterend = 'afterend',
+        beforebegin = 'beforebegin',
+        beforeend = 'beforeend',
+        confRe = /tag|children|cn|html$/i;
+
+    
+    function doInsert(el, o, returnElement, pos, sibling, append){
+        el = Ext.getDom(el);
+        var newNode;
+        if (pub.useDom) {
+            newNode = createDom(o, null);
+            if (append) {
+                el.appendChild(newNode);
+            } else {
+                (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
+            }
+        } else {
+            newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
+        }
+        return returnElement ? Ext.get(newNode, true) : newNode;
+    }
+
+    
+    
+    function createDom(o, parentNode){
+        var el,
+            doc = document,
+            useSet,
+            attr,
+            val,
+            cn;
+
+        if (Ext.isArray(o)) {                       
+            el = doc.createDocumentFragment(); 
+            for (var i = 0, l = o.length; i < l; i++) {
+                createDom(o[i], el);
+            }
+        } else if (typeof o == 'string') {         
+            el = doc.createTextNode(o);
+        } else {
+            el = doc.createElement( o.tag || 'div' );
+            useSet = !!el.setAttribute; 
+            for (var attr in o) {
+                if(!confRe.test(attr)){
+                    val = o[attr];
+                    if(attr == 'cls'){
+                        el.className = val;
+                    }else{
+                        if(useSet){
+                            el.setAttribute(attr, val);
+                        }else{
+                            el[attr] = val;
+                        }
+                    }
+                }
+            }
+            Ext.DomHelper.applyStyles(el, o.style);
+
+            if ((cn = o.children || o.cn)) {
+                createDom(cn, el);
+            } else if (o.html) {
+                el.innerHTML = o.html;
+            }
+        }
+        if(parentNode){
+           parentNode.appendChild(el);
+        }
+        return el;
+    }
+
+    pub = {
+        
+        createTemplate : function(o){
+            var html = Ext.DomHelper.createHtml(o);
+            return new Ext.Template(html);
+        },
+
+        
+        useDom : false,
+
+        
+        insertBefore : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforebegin);
+        },
+
+        
+        insertAfter : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterend, 'nextSibling');
+        },
+
+        
+        insertFirst : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
+        },
+
+        
+        append: function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforeend, '', true);
+        },
+
+        
+        createDom: createDom
+    };
+    return pub;
+}());
+
+Ext.apply(Ext.Template.prototype, {
+    
+    disableFormats : false,
+    
+
+    
+    re : /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
+    argsRe : /^\s*['"](.*)["']\s*$/,
+    compileARe : /\\/g,
+    compileBRe : /(\r\n|\n)/g,
+    compileCRe : /'/g,
+
+    /**
+     * Returns an HTML fragment of this template with the specified values applied.
+     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
+     * @return {String} The HTML fragment
+     * @hide repeat doc
+     */
+    applyTemplate : function(values){
+        var me = this,
+            useF = me.disableFormats !== true,
+            fm = Ext.util.Format,
+            tpl = me;
+
+        if(me.compiled){
+            return me.compiled(values);
+        }
+        function fn(m, name, format, args){
+            if (format && useF) {
+                if (format.substr(0, 5) == "this.") {
+                    return tpl.call(format.substr(5), values[name], values);
+                } else {
+                    if (args) {
+                        // quoted values are required for strings in compiled templates,
+                        // but for non compiled we need to strip them
+                        // quoted reversed for jsmin
+                        var re = me.argsRe;
+                        args = args.split(',');
+                        for(var i = 0, len = args.length; i < len; i++){
+                            args[i] = args[i].replace(re, "$1");
+                        }
+                        args = [values[name]].concat(args);
+                    } else {
+                        args = [values[name]];
+                    }
+                    return fm[format].apply(fm, args);
+                }
+            } else {
+                return values[name] !== undefined ? values[name] : "";
+            }
+        }
+        return me.html.replace(me.re, fn);
+    },
+
+    /**
+     * Compiles the template into an internal function, eliminating the RegEx overhead.
+     * @return {Ext.Template} this
+     * @hide repeat doc
+     */
+    compile : function(){
+        var me = this,
+            fm = Ext.util.Format,
+            useF = me.disableFormats !== true,
+            sep = Ext.isGecko ? "+" : ",",
+            body;
+
+        function fn(m, name, format, args){
+            if(format && useF){
+                args = args ? ',' + args : "";
+                if(format.substr(0, 5) != "this."){
+                    format = "fm." + format + '(';
+                }else{
+                    format = 'this.call("'+ format.substr(5) + '", ';
+                    args = ", values";
+                }
+            }else{
+                args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
+            }
+            return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
+        }
+
+        // branched to use + in gecko and [].join() in others
+        if(Ext.isGecko){
+            body = "this.compiled = function(values){ return '" +
+                   me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
+                    "';};";
+        }else{
+            body = ["this.compiled = function(values){ return ['"];
+            body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
+            body.push("'].join('');};");
+            body = body.join('');
+        }
+        eval(body);
+        return me;
+    },
+
+    // private function used to call members
+    call : function(fnName, value, allValues){
+        return this[fnName](value, allValues);
+    }
+});
+Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
+/**
+ * @class Ext.util.Functions
+ * @singleton
+ */
+Ext.util.Functions = {
+    /**
+     * Creates an interceptor function. The passed function is called before the original one. If it returns false,
+     * the original one is not called. The resulting function returns the results of the original function.
+     * The passed function is called with the parameters of the original function. Example usage:
+     * <pre><code>
+var sayHi = function(name){
+    alert('Hi, ' + name);
+}
+
+sayHi('Fred'); // alerts "Hi, Fred"
+
+// create a new function that validates input without
+// directly modifying the original function:
+var sayHiToFriend = Ext.createInterceptor(sayHi, function(name){
+    return name == 'Brian';
+});
+
+sayHiToFriend('Fred');  // no alert
+sayHiToFriend('Brian'); // alerts "Hi, Brian"
+       </code></pre>
+     * @param {Function} origFn The original function.
+     * @param {Function} newFn The function to call before the original
+     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
+     * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
+     * @return {Function} The new function
+     */
+    createInterceptor: function(origFn, newFn, scope) { 
+        var method = origFn;
+        if (!Ext.isFunction(newFn)) {
+            return origFn;
+        }
+        else {
+            return function() {
+                var me = this,
+                    args = arguments;
+                newFn.target = me;
+                newFn.method = origFn;
+                return (newFn.apply(scope || me || window, args) !== false) ?
+                        origFn.apply(me || window, args) :
+                        null;
+            };
+        }
+    },
+
+    /**
+     * Creates a delegate (callback) that sets the scope to obj.
+     * Call directly on any function. Example: <code>Ext.createDelegate(this.myFunction, this, [arg1, arg2])</code>
+     * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
+     * callback points to obj. Example usage:
+     * <pre><code>
+var sayHi = function(name){
+    // Note this use of "this.text" here.  This function expects to
+    // execute within a scope that contains a text property.  In this
+    // example, the "this" variable is pointing to the btn object that
+    // was passed in createDelegate below.
+    alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
+}
+
+var btn = new Ext.Button({
+    text: 'Say Hi',
+    renderTo: Ext.getBody()
+});
+
+// This callback will execute in the scope of the
+// button instance. Clicking the button alerts
+// "Hi, Fred. You clicked the "Say Hi" button."
+btn.on('click', Ext.createDelegate(sayHi, btn, ['Fred']));
+       </code></pre>
+     * @param {Function} fn The function to delegate.
+     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
+     * <b>If omitted, defaults to the browser window.</b>
+     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
+     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
+     * if a number the args are inserted at the specified position
+     * @return {Function} The new function
+     */
+    createDelegate: function(fn, obj, args, appendArgs) {
+        if (!Ext.isFunction(fn)) {
+            return fn;
+        }
+        return function() {
+            var callArgs = args || arguments;
+            if (appendArgs === true) {
+                callArgs = Array.prototype.slice.call(arguments, 0);
+                callArgs = callArgs.concat(args);
+            }
+            else if (Ext.isNumber(appendArgs)) {
+                callArgs = Array.prototype.slice.call(arguments, 0);
+                // copy arguments first
+                var applyArgs = [appendArgs, 0].concat(args);
+                // create method call params
+                Array.prototype.splice.apply(callArgs, applyArgs);
+                // splice them in
+            }
+            return fn.apply(obj || window, callArgs);
+        };
+    },
+
+    /**
+     * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
+     * <pre><code>
+var sayHi = function(name){
+    alert('Hi, ' + name);
+}
+
+// executes immediately:
+sayHi('Fred');
+
+// executes after 2 seconds:
+Ext.defer(sayHi, 2000, this, ['Fred']);
+
+// this syntax is sometimes useful for deferring
+// execution of an anonymous function:
+Ext.defer(function(){
+    alert('Anonymous');
+}, 100);
+       </code></pre>
+     * @param {Function} fn The function to defer.
+     * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
+     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
+     * <b>If omitted, defaults to the browser window.</b>
+     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
+     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
+     * if a number the args are inserted at the specified position
+     * @return {Number} The timeout id that can be used with clearTimeout
+     */
+    defer: function(fn, millis, obj, args, appendArgs) {
+        fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
+        if (millis > 0) {
+            return setTimeout(fn, millis);
+        }
+        fn();
+        return 0;
+    },
+
+
+    /**
+     * Create a combined function call sequence of the original function + the passed function.
+     * The resulting function returns the results of the original function.
+     * The passed fcn is called with the parameters of the original function. Example usage:
+     * 
+
+var sayHi = function(name){
+    alert('Hi, ' + name);
+}
+
+sayHi('Fred'); // alerts "Hi, Fred"
+
+var sayGoodbye = Ext.createSequence(sayHi, function(name){
+    alert('Bye, ' + name);
+});
+
+sayGoodbye('Fred'); // both alerts show
+
+     * @param {Function} origFn The original function.
+     * @param {Function} newFn The function to sequence
+     * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
+     * If omitted, defaults to the scope in which the original function is called or the browser window.
+     * @return {Function} The new function
+     */
+    createSequence: function(origFn, newFn, scope) {
+        if (!Ext.isFunction(newFn)) {
+            return origFn;
+        }
+        else {
+            return function() {
+                var retval = origFn.apply(this || window, arguments);
+                newFn.apply(scope || this || window, arguments);
+                return retval;
+            };
+        }
+    }
+};
+
+/**
+ * Shorthand for {@link Ext.util.Functions#defer}   
+ * @param {Function} fn The function to defer.
+ * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
+ * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
+ * <b>If omitted, defaults to the browser window.</b>
+ * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
+ * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
+ * if a number the args are inserted at the specified position
+ * @return {Number} The timeout id that can be used with clearTimeout
+ * @member Ext
+ * @method defer
+ */
+
+Ext.defer = Ext.util.Functions.defer;
+
+/**
+ * Shorthand for {@link Ext.util.Functions#createInterceptor}   
+ * @param {Function} origFn The original function.
+ * @param {Function} newFn The function to call before the original
+ * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
+ * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
+ * @return {Function} The new function
+ * @member Ext
+ * @method defer
+ */
+
+Ext.createInterceptor = Ext.util.Functions.createInterceptor;
+
+/**
+ * Shorthand for {@link Ext.util.Functions#createSequence}
+ * @param {Function} origFn The original function.
+ * @param {Function} newFn The function to sequence
+ * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
+ * If omitted, defaults to the scope in which the original function is called or the browser window.
+ * @return {Function} The new function
+ * @member Ext
+ * @method defer
+ */
+
+Ext.createSequence = Ext.util.Functions.createSequence;
+
+/**
+ * Shorthand for {@link Ext.util.Functions#createDelegate}
+ * @param {Function} fn The function to delegate.
+ * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
+ * <b>If omitted, defaults to the browser window.</b>
+ * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
+ * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
+ * if a number the args are inserted at the specified position
+ * @return {Function} The new function
+ * @member Ext
+ * @method defer
+ */
+Ext.createDelegate = Ext.util.Functions.createDelegate;
+/**
+ * @class Ext.util.Observable
+ */
+Ext.apply(Ext.util.Observable.prototype, function(){
+    // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
+    // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
+    // private
+    function getMethodEvent(method){
+        var e = (this.methodEvents = this.methodEvents ||
+        {})[method], returnValue, v, cancel, obj = this;
+
+        if (!e) {
+            this.methodEvents[method] = e = {};
+            e.originalFn = this[method];
+            e.methodName = method;
+            e.before = [];
+            e.after = [];
+
+            var makeCall = function(fn, scope, args){
+                if((v = fn.apply(scope || obj, args)) !== undefined){
+                    if (typeof v == 'object') {
+                        if(v.returnValue !== undefined){
+                            returnValue = v.returnValue;
+                        }else{
+                            returnValue = v;
+                        }
+                        cancel = !!v.cancel;
+                    }
+                    else
+                        if (v === false) {
+                            cancel = true;
+                        }
+                        else {
+                            returnValue = v;
+                        }
+                }
+            };
+
+            this[method] = function(){
+                var args = Array.prototype.slice.call(arguments, 0),
+                    b;
+                returnValue = v = undefined;
+                cancel = false;
+
+                for(var i = 0, len = e.before.length; i < len; i++){
+                    b = e.before[i];
+                    makeCall(b.fn, b.scope, args);
+                    if (cancel) {
+                        return returnValue;
+                    }
+                }
+
+                if((v = e.originalFn.apply(obj, args)) !== undefined){
+                    returnValue = v;
+                }
+
+                for(var i = 0, len = e.after.length; i < len; i++){
+                    b = e.after[i];
+                    makeCall(b.fn, b.scope, args);
+                    if (cancel) {
+                        return returnValue;
+                    }
+                }
+                return returnValue;
+            };
+        }
+        return e;
+    }
+
+    return {
+        // these are considered experimental
+        // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
+        // adds an 'interceptor' called before the original method
+        beforeMethod : function(method, fn, scope){
+            getMethodEvent.call(this, method).before.push({
+                fn: fn,
+                scope: scope
+            });
+        },
+
+        // adds a 'sequence' called after the original method
+        afterMethod : function(method, fn, scope){
+            getMethodEvent.call(this, method).after.push({
+                fn: fn,
+                scope: scope
+            });
+        },
+
+        removeMethodListener: function(method, fn, scope){
+            var e = this.getMethodEvent(method);
+            for(var i = 0, len = e.before.length; i < len; i++){
+                if(e.before[i].fn == fn && e.before[i].scope == scope){
+                    e.before.splice(i, 1);
+                    return;
+                }
+            }
+            for(var i = 0, len = e.after.length; i < len; i++){
+                if(e.after[i].fn == fn && e.after[i].scope == scope){
+                    e.after.splice(i, 1);
+                    return;
+                }
+            }
+        },
+
+        /**
+         * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
+         * @param {Object} o The Observable whose events this object is to relay.
+         * @param {Array} events Array of event names to relay.
+         */
+        relayEvents : function(o, events){
+            var me = this;
+            function createHandler(ename){
+                return function(){
+                    return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
+                };
+            }
+            for(var i = 0, len = events.length; i < len; i++){
+                var ename = events[i];
+                me.events[ename] = me.events[ename] || true;
+                o.on(ename, createHandler(ename), me);
+            }
+        },
+
+        /**
+         * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
+         * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
+         * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
+         * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
+         * access the required target more quickly.</p>
+         * <p>Example:</p><pre><code>
+Ext.override(Ext.form.Field, {
+    
+    initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
+        this.enableBubble('change');
+    }),
+
+    
+    getBubbleTarget : function() {
+        if (!this.formPanel) {
+            this.formPanel = this.findParentByType('form');
+        }
+        return this.formPanel;
+    }
+});
+
+var myForm = new Ext.formPanel({
+    title: 'User Details',
+    items: [{
+        ...
+    }],
+    listeners: {
+        change: function() {
+            
+            myForm.header.setStyle('color', 'red');
+        }
+    }
+});
+</code></pre>
+         * @param {String/Array} events The event name to bubble, or an Array of event names.
+         */
+        enableBubble : function(events){
+            var me = this;
+            if(!Ext.isEmpty(events)){
+                events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
+                for(var i = 0, len = events.length; i < len; i++){
+                    var ename = events[i];
+                    ename = ename.toLowerCase();
+                    var ce = me.events[ename] || true;
+                    if (typeof ce == 'boolean') {
+                        ce = new Ext.util.Event(me, ename);
+                        me.events[ename] = ce;
+                    }
+                    ce.bubble = true;
+                }
+            }
+        }
+    };
+}());
+
+
+
+Ext.util.Observable.capture = function(o, fn, scope){
+    o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
+};
+
+
+
+Ext.util.Observable.observeClass = function(c, listeners){
+    if(c){
+      if(!c.fireEvent){
+          Ext.apply(c, new Ext.util.Observable());
+          Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
+      }
+      if(typeof listeners == 'object'){
+          c.on(listeners);
+      }
+      return c;
+   }
+};
+
+Ext.apply(Ext.EventManager, function(){
+   var resizeEvent,
+       resizeTask,
+       textEvent,
+       textSize,
+       D = Ext.lib.Dom,
+       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
+       unload = Ext.EventManager._unload,
+       curWidth = 0,
+       curHeight = 0,
+       
+       
+       
+       useKeydown = Ext.isWebKit ?
+                   Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
+                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
+
+   return {
+       _unload: function(){
+           Ext.EventManager.un(window, "resize", this.fireWindowResize, this);
+           unload.call(Ext.EventManager);    
+       },
+       
+       
+       doResizeEvent: function(){
+           var h = D.getViewHeight(),
+               w = D.getViewWidth();
+
+            
+            if(curHeight != h || curWidth != w){
+               resizeEvent.fire(curWidth = w, curHeight = h);
+            }
+       },
+
+       
+       onWindowResize : function(fn, scope, options){
+           if(!resizeEvent){
+               resizeEvent = new Ext.util.Event();
+               resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
+               Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
+           }
+           resizeEvent.addListener(fn, scope, options);
+       },
+
+       
+       fireWindowResize : function(){
+           if(resizeEvent){
+               resizeTask.delay(100);
+           }
+       },
+
+       
+       onTextResize : function(fn, scope, options){
+           if(!textEvent){
+               textEvent = new Ext.util.Event();
+               var textEl = new Ext.Element(document.createElement('div'));
+               textEl.dom.className = 'x-text-resize';
+               textEl.dom.innerHTML = 'X';
+               textEl.appendTo(document.body);
+               textSize = textEl.dom.offsetHeight;
+               setInterval(function(){
+                   if(textEl.dom.offsetHeight != textSize){
+                       textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
+                   }
+               }, this.textResizeInterval);
+           }
+           textEvent.addListener(fn, scope, options);
+       },
+
+       
+       removeResizeListener : function(fn, scope){
+           if(resizeEvent){
+               resizeEvent.removeListener(fn, scope);
+           }
+       },
+
+       
+       fireResize : function(){
+           if(resizeEvent){
+               resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
+           }
+       },
+
+        
+       textResizeInterval : 50,
+
+       
+       ieDeferSrc : false,
+       
+       
+       getKeyEvent : function(){
+           return useKeydown ? 'keydown' : 'keypress';
+       },
+
+       
+       
+       useKeydown: useKeydown
+   };
+}());
+
+Ext.EventManager.on = Ext.EventManager.addListener;
+
+
+Ext.apply(Ext.EventObjectImpl.prototype, {
+   
+   BACKSPACE: 8,
+   
+   TAB: 9,
+   
+   NUM_CENTER: 12,
+   
+   ENTER: 13,
+   
+   RETURN: 13,
+   
+   SHIFT: 16,
+   
+   CTRL: 17,
+   CONTROL : 17, 
+   
+   ALT: 18,
+   
+   PAUSE: 19,
+   
+   CAPS_LOCK: 20,
+   
+   ESC: 27,
+   
+   SPACE: 32,
+   
+   PAGE_UP: 33,
+   PAGEUP : 33, 
+   
+   PAGE_DOWN: 34,
+   PAGEDOWN : 34, 
+   
+   END: 35,
+   
+   HOME: 36,
+   
+   LEFT: 37,
+   
+   UP: 38,
+   
+   RIGHT: 39,
+   
+   DOWN: 40,
+   
+   PRINT_SCREEN: 44,
+   
+   INSERT: 45,
+   
+   DELETE: 46,
+   
+   ZERO: 48,
+   
+   ONE: 49,
+   
+   TWO: 50,
+   
+   THREE: 51,
+   
+   FOUR: 52,
+   
+   FIVE: 53,
+   
+   SIX: 54,
+   
+   SEVEN: 55,
+   
+   EIGHT: 56,
+   
+   NINE: 57,
+   
+   A: 65,
+   
+   B: 66,
+   
+   C: 67,
+   
+   D: 68,
+   
+   E: 69,
+   
+   F: 70,
+   
+   G: 71,
+   
+   H: 72,
+   
+   I: 73,
+   
+   J: 74,
+   
+   K: 75,
+   
+   L: 76,
+   
+   M: 77,
+   
+   N: 78,
+   
+   O: 79,
+   
+   P: 80,
+   
+   Q: 81,
+   
+   R: 82,
+   
+   S: 83,
+   
+   T: 84,
+   
+   U: 85,
+   
+   V: 86,
+   
+   W: 87,
+   
+   X: 88,
+   
+   Y: 89,
+   
+   Z: 90,
+   
+   CONTEXT_MENU: 93,
+   
+   NUM_ZERO: 96,
+   
+   NUM_ONE: 97,
+   
+   NUM_TWO: 98,
+   
+   NUM_THREE: 99,
+   
+   NUM_FOUR: 100,
+   
+   NUM_FIVE: 101,
+   
+   NUM_SIX: 102,
+   
+   NUM_SEVEN: 103,
+   
+   NUM_EIGHT: 104,
+   
+   NUM_NINE: 105,
+   
+   NUM_MULTIPLY: 106,
+   
+   NUM_PLUS: 107,
+   
+   NUM_MINUS: 109,
+   
+   NUM_PERIOD: 110,
+   
+   NUM_DIVISION: 111,
+   
+   F1: 112,
+   
+   F2: 113,
+   
+   F3: 114,
+   
+   F4: 115,
+   
+   F5: 116,
+   
+   F6: 117,
+   
+   F7: 118,
+   
+   F8: 119,
+   
+   F9: 120,
+   
+   F10: 121,
+   
+   F11: 122,
+   
+   F12: 123,
+
+   
+   isNavKeyPress : function(){
+       var me = this,
+           k = this.normalizeKey(me.keyCode);
+       return (k >= 33 && k <= 40) ||  
+       k == me.RETURN ||
+       k == me.TAB ||
+       k == me.ESC;
+   },
+
+   isSpecialKey : function(){
+       var k = this.normalizeKey(this.keyCode);
+       return (this.type == 'keypress' && this.ctrlKey) ||
+       this.isNavKeyPress() ||
+       (k == this.BACKSPACE) || 
+       (k >= 16 && k <= 20) || 
+       (k >= 44 && k <= 46);   
+   },
+
+   getPoint : function(){
+       return new Ext.lib.Point(this.xy[0], this.xy[1]);
+   },
+
+   
+   hasModifier : function(){
+       return ((this.ctrlKey || this.altKey) || this.shiftKey);
+   }
+});
+Ext.Element.addMethods({
+    
+    swallowEvent : function(eventName, preventDefault) {
+        var me = this;
+        function fn(e) {
+            e.stopPropagation();
+            if (preventDefault) {
+                e.preventDefault();
+            }
+        }
+        
+        if (Ext.isArray(eventName)) {
+            Ext.each(eventName, function(e) {
+                 me.on(e, fn);
+            });
+            return me;
+        }
+        me.on(eventName, fn);
+        return me;
+    },
+
+    
+    relayEvent : function(eventName, observable) {
+        this.on(eventName, function(e) {
+            observable.fireEvent(eventName, e);
+        });
+    },
+
+    
+    clean : function(forceReclean) {
+        var me  = this,
+            dom = me.dom,
+            n   = dom.firstChild,
+            ni  = -1;
+
+        if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
+            return me;
+        }
+
+        while (n) {
+            var nx = n.nextSibling;
+            if (n.nodeType == 3 && !(/\S/.test(n.nodeValue))) {
+                dom.removeChild(n);
+            } else {
+                n.nodeIndex = ++ni;
+            }
+            n = nx;
+        }
+        
+        Ext.Element.data(dom, 'isCleaned', true);
+        return me;
+    },
+
+    
+    load : function() {
+        var updateManager = this.getUpdater();
+        updateManager.update.apply(updateManager, arguments);
+        
+        return this;
+    },
+
+    
+    getUpdater : function() {
+        return this.updateManager || (this.updateManager = new Ext.Updater(this));
+    },
+
+    
+    update : function(html, loadScripts, callback) {
+        if (!this.dom) {
+            return this;
+        }
+        html = html || "";
+
+        if (loadScripts !== true) {
+            this.dom.innerHTML = html;
+            if (typeof callback == 'function') {
+                callback();
+            }
+            return this;
+        }
+
+        var id  = Ext.id(),
+            dom = this.dom;
+
+        html += '<span id="' + id + '"></span>';
+
+        Ext.lib.Event.onAvailable(id, function() {
+            var DOC    = document,
+                hd     = DOC.getElementsByTagName("head")[0],
+                re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
+                srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
+                typeRe = /\stype=([\'\"])(.*?)\1/i,
+                match,
+                attrs,
+                srcMatch,
+                typeMatch,
+                el,
+                s;
+
+            while ((match = re.exec(html))) {
+                attrs = match[1];
+                srcMatch = attrs ? attrs.match(srcRe) : false;
+                if (srcMatch && srcMatch[2]) {
+                   s = DOC.createElement("script");
+                   s.src = srcMatch[2];
+                   typeMatch = attrs.match(typeRe);
+                   if (typeMatch && typeMatch[2]) {
+                       s.type = typeMatch[2];
+                   }
+                   hd.appendChild(s);
+                } else if (match[2] && match[2].length > 0) {
+                    if (window.execScript) {
+                       window.execScript(match[2]);
+                    } else {
+                       window.eval(match[2]);
+                    }
+                }
+            }
+            
+            el = DOC.getElementById(id);
+            if (el) {
+                Ext.removeNode(el);
+            }
+            
+            if (typeof callback == 'function') {
+                callback();
+            }
+        });
+        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
+        return this;
+    },
+
+    
+    removeAllListeners : function() {
+        this.removeAnchor();
+        Ext.EventManager.removeAll(this.dom);
+        return this;
+    },
+
+    
+    createProxy : function(config, renderTo, matchBox) {
+        config = (typeof config == 'object') ? config : {tag : "div", cls: config};
+
+        var me = this,
+            proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
+                               Ext.DomHelper.insertBefore(me.dom, config, true);
+
+        if (matchBox && me.setBox && me.getBox) { 
+           proxy.setBox(me.getBox());
+        }
+        return proxy;
+    }
+});
+
+Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
+
+Ext.Element.addMethods({
+    
+    getAnchorXY : function(anchor, local, s){
+        
+        
+		anchor = (anchor || "tl").toLowerCase();
+        s = s || {};
+        
+        var me = this,        
+        	vp = me.dom == document.body || me.dom == document,
+        	w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
+        	h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),         	        	
+        	xy,       	
+        	r = Math.round,
+        	o = me.getXY(),
+        	scroll = me.getScroll(),
+        	extraX = vp ? scroll.left : !local ? o[0] : 0,
+        	extraY = vp ? scroll.top : !local ? o[1] : 0,
+        	hash = {
+	        	c  : [r(w * 0.5), r(h * 0.5)],
+	        	t  : [r(w * 0.5), 0],
+	        	l  : [0, r(h * 0.5)],
+	        	r  : [w, r(h * 0.5)],
+	        	b  : [r(w * 0.5), h],
+	        	tl : [0, 0],	
+	        	bl : [0, h],
+	        	br : [w, h],
+	        	tr : [w, 0]
+        	};
+        
+        xy = hash[anchor];	
+        return [xy[0] + extraX, xy[1] + extraY]; 
+    },
+
+    
+    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
+	    var me = this,
+            dom = me.dom,
+            scroll = !Ext.isEmpty(monitorScroll),
+            action = function(){
+                Ext.fly(dom).alignTo(el, alignment, offsets, animate);
+                Ext.callback(callback, Ext.fly(dom));
+            },
+            anchor = this.getAnchor();
+            
+        
+        this.removeAnchor();
+        Ext.apply(anchor, {
+            fn: action,
+            scroll: scroll
+        });
+
+        Ext.EventManager.onWindowResize(action, null);
+        
+        if(scroll){
+            Ext.EventManager.on(window, 'scroll', action, null,
+                {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
+        }
+        action.call(me); 
+        return me;
+    },
+    
+    
+    removeAnchor : function(){
+        var me = this,
+            anchor = this.getAnchor();
+            
+        if(anchor && anchor.fn){
+            Ext.EventManager.removeResizeListener(anchor.fn);
+            if(anchor.scroll){
+                Ext.EventManager.un(window, 'scroll', anchor.fn);
+            }
+            delete anchor.fn;
+        }
+        return me;
+    },
+    
+    
+    getAnchor : function(){
+        var data = Ext.Element.data,
+            dom = this.dom;
+            if (!dom) {
+                return;
+            }
+            var anchor = data(dom, '_anchor');
+            
+        if(!anchor){
+            anchor = data(dom, '_anchor', {});
+        }
+        return anchor;
+    },
+
+    
+    getAlignToXY : function(el, p, o){	    
+        el = Ext.get(el);
+        
+        if(!el || !el.dom){
+            throw "Element.alignToXY with an element that doesn't exist";
+        }
+        
+        o = o || [0,0];
+        p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
+                
+        var me = this,
+        	d = me.dom,
+        	a1,
+        	a2,
+        	x,
+        	y,
+        	
+        	w,
+        	h,
+        	r,
+        	dw = Ext.lib.Dom.getViewWidth() -10, 
+        	dh = Ext.lib.Dom.getViewHeight()-10, 
+        	p1y,
+        	p1x,        	
+        	p2y,
+        	p2x,
+        	swapY,
+        	swapX,
+        	doc = document,
+        	docElement = doc.documentElement,
+        	docBody = doc.body,
+        	scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
+        	scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
+        	c = false, 
+        	p1 = "", 
+        	p2 = "",
+        	m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+        
+        if(!m){
+           throw "Element.alignTo with an invalid alignment " + p;
+        }
+        
+        p1 = m[1]; 
+        p2 = m[2]; 
+        c = !!m[3];
+
+        
+        
+        a1 = me.getAnchorXY(p1, true);
+        a2 = el.getAnchorXY(p2, false);
+
+        x = a2[0] - a1[0] + o[0];
+        y = a2[1] - a1[1] + o[1];
+
+        if(c){    
+	       w = me.getWidth();
+           h = me.getHeight();
+           r = el.getRegion();       
+           
+           
+           
+           p1y = p1.charAt(0);
+           p1x = p1.charAt(p1.length-1);
+           p2y = p2.charAt(0);
+           p2x = p2.charAt(p2.length-1);
+           swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
+           swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
+           
+
+           if (x + w > dw + scrollX) {
+                x = swapX ? r.left-w : dw+scrollX-w;
+           }
+           if (x < scrollX) {
+               x = swapX ? r.right : scrollX;
+           }
+           if (y + h > dh + scrollY) {
+                y = swapY ? r.top-h : dh+scrollY-h;
+            }
+           if (y < scrollY){
+               y = swapY ? r.bottom : scrollY;
+           }
+        }
+        return [x,y];
+    },
+
+    
+    alignTo : function(element, position, offsets, animate){
+	    var me = this;
+        return me.setXY(me.getAlignToXY(element, position, offsets),
+          		        me.preanim && !!animate ? me.preanim(arguments, 3) : false);
+    },
+    
+    
+    adjustForConstraints : function(xy, parent, offsets){
+        return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
+    },
+
+    
+    getConstrainToXY : function(el, local, offsets, proposedXY){   
+	    var os = {top:0, left:0, bottom:0, right: 0};
+
+        return function(el, local, offsets, proposedXY){
+            el = Ext.get(el);
+            offsets = offsets ? Ext.applyIf(offsets, os) : os;
+
+            var vw, vh, vx = 0, vy = 0;
+            if(el.dom == document.body || el.dom == document){
+                vw =Ext.lib.Dom.getViewWidth();
+                vh = Ext.lib.Dom.getViewHeight();
+            }else{
+                vw = el.dom.clientWidth;
+                vh = el.dom.clientHeight;
+                if(!local){
+                    var vxy = el.getXY();
+                    vx = vxy[0];
+                    vy = vxy[1];
+                }
+            }
+
+            var s = el.getScroll();
+
+            vx += offsets.left + s.left;
+            vy += offsets.top + s.top;
+
+            vw -= offsets.right;
+            vh -= offsets.bottom;
+
+            var vr = vx + vw,
+                vb = vy + vh,
+                xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
+                x = xy[0], y = xy[1],
+                offset = this.getConstrainOffset(),
+                w = this.dom.offsetWidth + offset, 
+                h = this.dom.offsetHeight + offset;
+
+            
+            var moved = false;
+
+            
+            if((x + w) > vr){
+                x = vr - w;
+                moved = true;
+            }
+            if((y + h) > vb){
+                y = vb - h;
+                moved = true;
+            }
+            
+            if(x < vx){
+                x = vx;
+                moved = true;
+            }
+            if(y < vy){
+                y = vy;
+                moved = true;
+            }
+            return moved ? [x, y] : false;
+        };
+    }(),
+	    
+	    
+	        
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    getConstrainOffset : function(){
+        return 0;
+    },
+    
+    
+    getCenterXY : function(){
+        return this.getAlignToXY(document, 'c-c');
+    },
+
+    
+    center : function(centerIn){
+        return this.alignTo(centerIn || document, 'c-c');        
+    }    
+});
+
+Ext.Element.addMethods({
+    
+    select : function(selector, unique){
+        return Ext.Element.select(selector, unique, this.dom);
+    }
+});
+Ext.apply(Ext.Element.prototype, function() {
+	var GETDOM = Ext.getDom,
+		GET = Ext.get,
+		DH = Ext.DomHelper;
+	
+	return {	
+		
+	    insertSibling: function(el, where, returnDom){
+	        var me = this,
+	        	rt,
+                isAfter = (where || 'before').toLowerCase() == 'after',
+                insertEl;
+	        	
+	        if(Ext.isArray(el)){
+                insertEl = me;
+	            Ext.each(el, function(e) {
+		            rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
+                    if(isAfter){
+                        insertEl = rt;
+                    }
+	            });
+	            return rt;
+	        }
+	                
+	        el = el || {};
+	       	
+            if(el.nodeType || el.dom){
+                rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
+                if (!returnDom) {
+                    rt = GET(rt);
+                }
+            }else{
+                if (isAfter && !me.dom.nextSibling) {
+                    rt = DH.append(me.dom.parentNode, el, !returnDom);
+                } else {                    
+                    rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
+                }
+            }
+	        return rt;
+	    }
+    };
+}());
+
+
+Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
+
+Ext.Element.addMethods(function(){
+    var INTERNAL = "_internal",
+        pxMatch = /(\d+\.?\d+)px/;
+    return {
+        
+        applyStyles : function(style){
+            Ext.DomHelper.applyStyles(this.dom, style);
+            return this;
+        },
+
+        
+        getStyles : function(){
+            var ret = {};
+            Ext.each(arguments, function(v) {
+               ret[v] = this.getStyle(v);
+            },
+            this);
+            return ret;
+        },
+
+        
+        setOverflow : function(v){
+            var dom = this.dom;
+            if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
+                dom.style.overflow = 'hidden';
+                (function(){dom.style.overflow = 'auto';}).defer(1);
+            }else{
+                dom.style.overflow = v;
+            }
+        },
+
+       
+        boxWrap : function(cls){
+            cls = cls || 'x-box';
+            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
+            Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
+            return el;
+        },
+
+        
+        setSize : function(width, height, animate){
+            var me = this;
+            if(typeof width == 'object'){ 
+                height = width.height;
+                width = width.width;
+            }
+            width = me.adjustWidth(width);
+            height = me.adjustHeight(height);
+            if(!animate || !me.anim){
+                me.dom.style.width = me.addUnits(width);
+                me.dom.style.height = me.addUnits(height);
+            }else{
+                me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
+            }
+            return me;
+        },
+
+        
+        getComputedHeight : function(){
+            var me = this,
+                h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
+            if(!h){
+                h = parseFloat(me.getStyle('height')) || 0;
+                if(!me.isBorderBox()){
+                    h += me.getFrameWidth('tb');
+                }
+            }
+            return h;
+        },
+
+        
+        getComputedWidth : function(){
+            var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
+            if(!w){
+                w = parseFloat(this.getStyle('width')) || 0;
+                if(!this.isBorderBox()){
+                    w += this.getFrameWidth('lr');
+                }
+            }
+            return w;
+        },
+
+        
+        getFrameWidth : function(sides, onlyContentBox){
+            return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
+        },
+
+        
+        addClassOnOver : function(className){
+            this.hover(
+                function(){
+                    Ext.fly(this, INTERNAL).addClass(className);
+                },
+                function(){
+                    Ext.fly(this, INTERNAL).removeClass(className);
+                }
+            );
+            return this;
+        },
+
+        
+        addClassOnFocus : function(className){
+            this.on("focus", function(){
+                Ext.fly(this, INTERNAL).addClass(className);
+            }, this.dom);
+            this.on("blur", function(){
+                Ext.fly(this, INTERNAL).removeClass(className);
+            }, this.dom);
+            return this;
+        },
+
+        
+        addClassOnClick : function(className){
+            var dom = this.dom;
+            this.on("mousedown", function(){
+                Ext.fly(dom, INTERNAL).addClass(className);
+                var d = Ext.getDoc(),
+                    fn = function(){
+                        Ext.fly(dom, INTERNAL).removeClass(className);
+                        d.removeListener("mouseup", fn);
+                    };
+                d.on("mouseup", fn);
+            });
+            return this;
+        },
+
+        
+
+        getViewSize : function(){
+            var doc = document,
+                d = this.dom,
+                isDoc = (d == doc || d == doc.body);
+
+            
+            if (isDoc) {
+                var extdom = Ext.lib.Dom;
+                return {
+                    width : extdom.getViewWidth(),
+                    height : extdom.getViewHeight()
+                };
+
+            
+            } else {
+                return {
+                    width : d.clientWidth,
+                    height : d.clientHeight
+                };
+            }
+        },
+
+        
+
+        getStyleSize : function(){
+            var me = this,
+                w, h,
+                doc = document,
+                d = this.dom,
+                isDoc = (d == doc || d == doc.body),
+                s = d.style;
+
+            
+            if (isDoc) {
+                var extdom = Ext.lib.Dom;
+                return {
+                    width : extdom.getViewWidth(),
+                    height : extdom.getViewHeight()
+                };
+            }
+            
+            if(s.width && s.width != 'auto'){
+                w = parseFloat(s.width);
+                if(me.isBorderBox()){
+                   w -= me.getFrameWidth('lr');
+                }
+            }
+            
+            if(s.height && s.height != 'auto'){
+                h = parseFloat(s.height);
+                if(me.isBorderBox()){
+                   h -= me.getFrameWidth('tb');
+                }
+            }
+            
+            return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
+        },
+
+        
+        getSize : function(contentSize){
+            return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
+        },
+
+        
+        repaint : function(){
+            var dom = this.dom;
+            this.addClass("x-repaint");
+            setTimeout(function(){
+                Ext.fly(dom).removeClass("x-repaint");
+            }, 1);
+            return this;
+        },
+
+        
+        unselectable : function(){
+            this.dom.unselectable = "on";
+            return this.swallowEvent("selectstart", true).
+                        applyStyles("-moz-user-select:none;-khtml-user-select:none;").
+                        addClass("x-unselectable");
+        },
+
+        
+        getMargins : function(side){
+            var me = this,
+                key,
+                hash = {t:"top", l:"left", r:"right", b: "bottom"},
+                o = {};
+
+            if (!side) {
+                for (key in me.margins){
+                    o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
+                }
+                return o;
+            } else {
+                return me.addStyles.call(me, side, me.margins);
+            }
+        }
+    };
+}());
+
+Ext.Element.addMethods({
+    
+    setBox : function(box, adjust, animate){
+        var me = this,
+        	w = box.width, 
+        	h = box.height;
+        if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
+           w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+           h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+        }
+        me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
+        return me;
+    },
+
+    
+	getBox : function(contentBox, local) {	    
+	    var me = this,
+        	xy,
+        	left,
+        	top,
+        	getBorderWidth = me.getBorderWidth,
+        	getPadding = me.getPadding, 
+        	l,
+        	r,
+        	t,
+        	b;
+        if(!local){
+            xy = me.getXY();
+        }else{
+            left = parseInt(me.getStyle("left"), 10) || 0;
+            top = parseInt(me.getStyle("top"), 10) || 0;
+            xy = [left, top];
+        }
+        var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
+        if(!contentBox){
+            bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
+        }else{
+            l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
+            r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
+            t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
+            b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
+            bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
+        }
+        bx.right = bx.x + bx.width;
+        bx.bottom = bx.y + bx.height;
+        return bx;
+	},
+	
+    
+     move : function(direction, distance, animate){
+        var me = this,        	
+        	xy = me.getXY(),
+        	x = xy[0],
+        	y = xy[1],        	
+        	left = [x - distance, y],
+        	right = [x + distance, y],
+        	top = [x, y - distance],
+        	bottom = [x, y + distance],
+	       	hash = {
+	        	l :	left,
+	        	left : left,
+	        	r : right,
+	        	right : right,
+	        	t : top,
+	        	top : top,
+	        	up : top,
+	        	b : bottom, 
+	        	bottom : bottom,
+	        	down : bottom	        		
+	        };
+        
+ 	    direction = direction.toLowerCase();    
+ 	    me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
+    },
+    
+    
+     setLeftTop : function(left, top){
+	    var me = this,
+	    	style = me.dom.style;
+        style.left = me.addUnits(left);
+        style.top = me.addUnits(top);
+        return me;
+    },
+    
+    
+    getRegion : function(){
+        return Ext.lib.Dom.getRegion(this.dom);
+    },
+    
+    
+    setBounds : function(x, y, width, height, animate){
+	    var me = this;
+        if (!animate || !me.anim) {
+            me.setSize(width, height);
+            me.setLocation(x, y);
+        } else {
+            me.anim({points: {to: [x, y]}, 
+            		 width: {to: me.adjustWidth(width)}, 
+            		 height: {to: me.adjustHeight(height)}},
+                     me.preanim(arguments, 4), 
+                     'motion');
+        }
+        return me;
+    },
+
+    
+    setRegion : function(region, animate) {
+        return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
+    }
+});
+Ext.Element.addMethods({
+    
+    scrollTo : function(side, value, animate) {
+        
+        var top = /top/i.test(side),
+            me = this,
+            dom = me.dom,
+            prop;
+        if (!animate || !me.anim) {
+            
+            prop = 'scroll' + (top ? 'Top' : 'Left');
+            dom[prop] = value;
+        }
+        else {
+            
+            prop = 'scroll' + (top ? 'Left' : 'Top');
+            me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}}, me.preanim(arguments, 2), 'scroll');
+        }
+        return me;
+    },
+    
+    
+    scrollIntoView : function(container, hscroll) {
+        var c = Ext.getDom(container) || Ext.getBody().dom,
+            el = this.dom,
+            o = this.getOffsetsTo(c),
+            l = o[0] + c.scrollLeft,
+            t = o[1] + c.scrollTop,
+            b = t + el.offsetHeight,
+            r = l + el.offsetWidth,
+            ch = c.clientHeight,
+            ct = parseInt(c.scrollTop, 10),
+            cl = parseInt(c.scrollLeft, 10),
+            cb = ct + ch,
+            cr = cl + c.clientWidth;
+
+        if (el.offsetHeight > ch || t < ct) {
+            c.scrollTop = t;
+        }
+        else if (b > cb) {
+            c.scrollTop = b-ch;
+        }
+        
+        c.scrollTop = c.scrollTop;
+
+        if (hscroll !== false) {
+            if (el.offsetWidth > c.clientWidth || l < cl) {
+                c.scrollLeft = l;
+            }
+            else if (r > cr) {
+                c.scrollLeft = r - c.clientWidth;
+            }
+            c.scrollLeft = c.scrollLeft;
+        }
+        return this;
+    },
+
+    
+    scrollChildIntoView : function(child, hscroll) {
+        Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
+    },
+    
+    
+     scroll : function(direction, distance, animate) {
+        if (!this.isScrollable()) {
+            return false;
+        }
+        var el = this.dom,
+            l = el.scrollLeft, t = el.scrollTop,
+            w = el.scrollWidth, h = el.scrollHeight,
+            cw = el.clientWidth, ch = el.clientHeight,
+            scrolled = false, v,
+            hash = {
+                l: Math.min(l + distance, w-cw),
+                r: v = Math.max(l - distance, 0),
+                t: Math.max(t - distance, 0),
+                b: Math.min(t + distance, h-ch)
+            };
+            hash.d = hash.b;
+            hash.u = hash.t;
+        
+        direction = direction.substr(0, 1);
+        if ((v = hash[direction]) > -1) {
+            scrolled = true;
+            this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
+        }
+        return scrolled;
+    }
+});
+Ext.Element.addMethods(
+    function() {
+        var VISIBILITY      = "visibility",
+            DISPLAY         = "display",
+            HIDDEN          = "hidden",
+            NONE            = "none",
+            XMASKED         = "x-masked",
+            XMASKEDRELATIVE = "x-masked-relative",
+            data            = Ext.Element.data;
+
+        return {
+            
+            isVisible : function(deep) {
+                var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
+                    p   = this.dom.parentNode;
+                
+                if (deep !== true || !vis) {
+                    return vis;
+                }
+                
+                while (p && !(/^body/i.test(p.tagName))) {
+                    if (!Ext.fly(p, '_isVisible').isVisible()) {
+                        return false;
+                    }
+                    p = p.parentNode;
+                }
+                return true;
+            },
+
+            
+            isDisplayed : function() {
+                return !this.isStyle(DISPLAY, NONE);
+            },
+
+            
+            enableDisplayMode : function(display) {
+                this.setVisibilityMode(Ext.Element.DISPLAY);
+                
+                if (!Ext.isEmpty(display)) {
+                    data(this.dom, 'originalDisplay', display);
+                }
+                
+                return this;
+            },
+
+            
+            mask : function(msg, msgCls) {
+                var me  = this,
+                    dom = me.dom,
+                    dh  = Ext.DomHelper,
+                    EXTELMASKMSG = "ext-el-mask-msg",
+                    el,
+                    mask;
+
+                if (!/^body/i.test(dom.tagName) && me.getStyle('position') == 'static') {
+                    me.addClass(XMASKEDRELATIVE);
+                }
+                if (el = data(dom, 'maskMsg')) {
+                    el.remove();
+                }
+                if (el = data(dom, 'mask')) {
+                    el.remove();
+                }
+
+                mask = dh.append(dom, {cls : "ext-el-mask"}, true);
+                data(dom, 'mask', mask);
+
+                me.addClass(XMASKED);
+                mask.setDisplayed(true);
+                
+                if (typeof msg == 'string') {
+                    var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
+                    data(dom, 'maskMsg', mm);
+                    mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
+                    mm.dom.firstChild.innerHTML = msg;
+                    mm.setDisplayed(true);
+                    mm.center(me);
+                }
+                
+                
+                if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
+                    mask.setSize(undefined, me.getHeight());
+                }
+                
+                return mask;
+            },
+
+            
+            unmask : function() {
+                var me      = this,
+                    dom     = me.dom,
+                    mask    = data(dom, 'mask'),
+                    maskMsg = data(dom, 'maskMsg');
+
+                if (mask) {
+                    if (maskMsg) {
+                        maskMsg.remove();
+                        data(dom, 'maskMsg', undefined);
+                    }
+                    
+                    mask.remove();
+                    data(dom, 'mask', undefined);
+                    me.removeClass([XMASKED, XMASKEDRELATIVE]);
+                }
+            },
+
+            
+            isMasked : function() {
+                var m = data(this.dom, 'mask');
+                return m && m.isVisible();
+            },
+
+            
+            createShim : function() {
+                var el = document.createElement('iframe'),
+                    shim;
+                
+                el.frameBorder = '0';
+                el.className = 'ext-shim';
+                el.src = Ext.SSL_SECURE_URL;
+                shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
+                shim.autoBoxAdjust = false;
+                return shim;
+            }
+        };
+    }()
+);
+Ext.Element.addMethods({
+    
+    addKeyListener : function(key, fn, scope){
+        var config;
+        if(typeof key != 'object' || Ext.isArray(key)){
+            config = {
+                key: key,
+                fn: fn,
+                scope: scope
+            };
+        }else{
+            config = {
+                key : key.key,
+                shift : key.shift,
+                ctrl : key.ctrl,
+                alt : key.alt,
+                fn: fn,
+                scope: scope
+            };
+        }
+        return new Ext.KeyMap(this, config);
+    },
+
+    
+    addKeyMap : function(config){
+        return new Ext.KeyMap(this, config);
+    }
+});
+
+
+
+Ext.CompositeElementLite.importElementMethods();
+Ext.apply(Ext.CompositeElementLite.prototype, {
+    addElements : function(els, root){
+        if(!els){
+            return this;
+        }
+        if(typeof els == "string"){
+            els = Ext.Element.selectorFunction(els, root);
+        }
+        var yels = this.elements;
+        Ext.each(els, function(e) {
+            yels.push(Ext.get(e));
+        });
+        return this;
+    },
+
+    
+    first : function(){
+        return this.item(0);
+    },
+
+    
+    last : function(){
+        return this.item(this.getCount()-1);
+    },
+
+    
+    contains : function(el){
+        return this.indexOf(el) != -1;
+    },
+
+    
+    removeElement : function(keys, removeDom){
+        var me = this,
+            els = this.elements,
+            el;
+        Ext.each(keys, function(val){
+            if ((el = (els[val] || els[val = me.indexOf(val)]))) {
+                if(removeDom){
+                    if(el.dom){
+                        el.remove();
+                    }else{
+                        Ext.removeNode(el);
+                    }
+                }
+                els.splice(val, 1);
+            }
+        });
+        return this;
+    }
+});
+
+Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
+    
+    constructor : function(els, root){
+        this.elements = [];
+        this.add(els, root);
+    },
+    
+    
+    getElement : function(el){
+        
+        return el;
+    },
+    
+    
+    transformElement : function(el){
+        return Ext.get(el);
+    }
+
+    
+
+    
+
+    
+});
+
+
+Ext.Element.select = function(selector, unique, root){
+    var els;
+    if(typeof selector == "string"){
+        els = Ext.Element.selectorFunction(selector, root);
+    }else if(selector.length !== undefined){
+        els = selector;
+    }else{
+        throw "Invalid selector";
+    }
+
+    return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
+};
+
+
+Ext.select = Ext.Element.select;
+Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
+function() {
+    var BEFOREUPDATE = "beforeupdate",
+        UPDATE = "update",
+        FAILURE = "failure";
+
+    
+    function processSuccess(response){
+        var me = this;
+        me.transaction = null;
+        if (response.argument.form && response.argument.reset) {
+            try { 
+                response.argument.form.reset();
+            } catch(e){}
+        }
+        if (me.loadScripts) {
+            me.renderer.render(me.el, response, me,
+               updateComplete.createDelegate(me, [response]));
+        } else {
+            me.renderer.render(me.el, response, me);
+            updateComplete.call(me, response);
+        }
+    }
+
+    
+    function updateComplete(response, type, success){
+        this.fireEvent(type || UPDATE, this.el, response);
+        if(Ext.isFunction(response.argument.callback)){
+            response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
+        }
+    }
+
+    
+    function processFailure(response){
+        updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
+    }
+
+    return {
+        constructor: function(el, forceNew){
+            var me = this;
+            el = Ext.get(el);
+            if(!forceNew && el.updateManager){
+                return el.updateManager;
+            }
+            
+            me.el = el;
+            
+            me.defaultUrl = null;
+
+            me.addEvents(
+                
+                BEFOREUPDATE,
+                
+                UPDATE,
+                
+                FAILURE
+            );
+
+            Ext.apply(me, Ext.Updater.defaults);
+            
+            
+            
+            
+            
+            
+
+            
+            me.transaction = null;
+            
+            me.refreshDelegate = me.refresh.createDelegate(me);
+            
+            me.updateDelegate = me.update.createDelegate(me);
+            
+            me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
+
+            
+            me.renderer = me.renderer || me.getDefaultRenderer();
+
+            Ext.Updater.superclass.constructor.call(me);
+        },
+
+        
+        setRenderer : function(renderer){
+            this.renderer = renderer;
+        },
+
+        
+        getRenderer : function(){
+           return this.renderer;
+        },
+
+        
+        getDefaultRenderer: function() {
+            return new Ext.Updater.BasicRenderer();
+        },
+
+        
+        setDefaultUrl : function(defaultUrl){
+            this.defaultUrl = defaultUrl;
+        },
+
+        
+        getEl : function(){
+            return this.el;
+        },
+
+        
+        update : function(url, params, callback, discardUrl){
+            var me = this,
+                cfg,
+                callerScope;
+
+            if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
+                if(Ext.isObject(url)){ 
+                    cfg = url;
+                    url = cfg.url;
+                    params = params || cfg.params;
+                    callback = callback || cfg.callback;
+                    discardUrl = discardUrl || cfg.discardUrl;
+                    callerScope = cfg.scope;
+                    if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
+                    if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
+                    if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
+                    if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
+                }
+                me.showLoading();
+
+                if(!discardUrl){
+                    me.defaultUrl = url;
+                }
+                if(Ext.isFunction(url)){
+                    url = url.call(me);
+                }
+
+                var o = Ext.apply({}, {
+                    url : url,
+                    params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
+                    success: processSuccess,
+                    failure: processFailure,
+                    scope: me,
+                    callback: undefined,
+                    timeout: (me.timeout*1000),
+                    disableCaching: me.disableCaching,
+                    argument: {
+                        "options": cfg,
+                        "url": url,
+                        "form": null,
+                        "callback": callback,
+                        "scope": callerScope || window,
+                        "params": params
+                    }
+                }, cfg);
+
+                me.transaction = Ext.Ajax.request(o);
+            }
+        },
+
+        
+        formUpdate : function(form, url, reset, callback){
+            var me = this;
+            if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
+                if(Ext.isFunction(url)){
+                    url = url.call(me);
+                }
+                form = Ext.getDom(form);
+                me.transaction = Ext.Ajax.request({
+                    form: form,
+                    url:url,
+                    success: processSuccess,
+                    failure: processFailure,
+                    scope: me,
+                    timeout: (me.timeout*1000),
+                    argument: {
+                        "url": url,
+                        "form": form,
+                        "callback": callback,
+                        "reset": reset
+                    }
+                });
+                me.showLoading.defer(1, me);
+            }
+        },
+
+        
+        startAutoRefresh : function(interval, url, params, callback, refreshNow){
+            var me = this;
+            if(refreshNow){
+                me.update(url || me.defaultUrl, params, callback, true);
+            }
+            if(me.autoRefreshProcId){
+                clearInterval(me.autoRefreshProcId);
+            }
+            me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
+        },
+
+        
+        stopAutoRefresh : function(){
+            if(this.autoRefreshProcId){
+                clearInterval(this.autoRefreshProcId);
+                delete this.autoRefreshProcId;
+            }
+        },
+
+        
+        isAutoRefreshing : function(){
+           return !!this.autoRefreshProcId;
+        },
+
+        
+        showLoading : function(){
+            if(this.showLoadIndicator){
+                this.el.dom.innerHTML = this.indicatorText;
+            }
+        },
+
+        
+        abort : function(){
+            if(this.transaction){
+                Ext.Ajax.abort(this.transaction);
+            }
+        },
+
+        
+        isUpdating : function(){
+            return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
+        },
+
+        
+        refresh : function(callback){
+            if(this.defaultUrl){
+                this.update(this.defaultUrl, null, callback, true);
+            }
+        }
+    };
+}());
+
+
+Ext.Updater.defaults = {
+   
+    timeout : 30,
+    
+    disableCaching : false,
+    
+    showLoadIndicator : true,
+    
+    indicatorText : '<div class="loading-indicator">Loading...</div>',
+     
+    loadScripts : false,
+    
+    sslBlankUrl : Ext.SSL_SECURE_URL
+};
+
+
+
+Ext.Updater.updateElement = function(el, url, params, options){
+    var um = Ext.get(el).getUpdater();
+    Ext.apply(um, options);
+    um.update(url, params, options ? options.callback : null);
+};
+
+
+Ext.Updater.BasicRenderer = function(){};
+
+Ext.Updater.BasicRenderer.prototype = {
+    
+     render : function(el, response, updateManager, callback){
+        el.update(response.responseText, updateManager.loadScripts, callback);
+    }
+};
+
+
+
+(function() {
+
+
+Date.useStrict = false;
+
+
+
+
+
+function xf(format) {
+    var args = Array.prototype.slice.call(arguments, 1);
+    return format.replace(/\{(\d+)\}/g, function(m, i) {
+        return args[i];
+    });
+}
+
+
+
+Date.formatCodeToRegex = function(character, currentGroup) {
+    
+    var p = Date.parseCodes[character];
+
+    if (p) {
+      p = typeof p == 'function'? p() : p;
+      Date.parseCodes[character] = p; 
+    }
+
+    return p ? Ext.applyIf({
+      c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
+    }, p) : {
+        g:0,
+        c:null,
+        s:Ext.escapeRe(character) 
+    };
+};
+
+
+var $f = Date.formatCodeToRegex;
+
+Ext.apply(Date, {
+    
+    parseFunctions: {
+        "M$": function(input, strict) {
+            
+            
+            var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
+            var r = (input || '').match(re);
+            return r? new Date(((r[1] || '') + r[2]) * 1) : null;
+        }
+    },
+    parseRegexes: [],
+
+    
+    formatFunctions: {
+        "M$": function() {
+            
+            return '\\/Date(' + this.getTime() + ')\\/';
+        }
+    },
+
+    y2kYear : 50,
+
+    
+    MILLI : "ms",
+
+    
+    SECOND : "s",
+
+    
+    MINUTE : "mi",
+
+    
+    HOUR : "h",
+
+    
+    DAY : "d",
+
+    
+    MONTH : "mo",
+
+    
+    YEAR : "y",
+
+    
+    defaults: {},
+
+    
+    dayNames : [
+        "Sunday",
+        "Monday",
+        "Tuesday",
+        "Wednesday",
+        "Thursday",
+        "Friday",
+        "Saturday"
+    ],
+
+    
+    monthNames : [
+        "January",
+        "February",
+        "March",
+        "April",
+        "May",
+        "June",
+        "July",
+        "August",
+        "September",
+        "October",
+        "November",
+        "December"
+    ],
+
+    
+    monthNumbers : {
+        Jan:0,
+        Feb:1,
+        Mar:2,
+        Apr:3,
+        May:4,
+        Jun:5,
+        Jul:6,
+        Aug:7,
+        Sep:8,
+        Oct:9,
+        Nov:10,
+        Dec:11
+    },
+
+    
+    getShortMonthName : function(month) {
+        return Date.monthNames[month].substring(0, 3);
+    },
+
+    
+    getShortDayName : function(day) {
+        return Date.dayNames[day].substring(0, 3);
+    },
+
+    
+    getMonthNumber : function(name) {
+        
+        return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
+    },
+    
+    
+    formatContainsHourInfo : (function(){
+        var stripEscapeRe = /(\\.)/g,
+            hourInfoRe = /([gGhHisucUOPZ]|M\$)/;
+        return function(format){
+            return hourInfoRe.test(format.replace(stripEscapeRe, ''));
+        };
+    })(),
+
+    
+    formatCodes : {
+        d: "String.leftPad(this.getDate(), 2, '0')",
+        D: "Date.getShortDayName(this.getDay())", 
+        j: "this.getDate()",
+        l: "Date.dayNames[this.getDay()]",
+        N: "(this.getDay() ? this.getDay() : 7)",
+        S: "this.getSuffix()",
+        w: "this.getDay()",
+        z: "this.getDayOfYear()",
+        W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
+        F: "Date.monthNames[this.getMonth()]",
+        m: "String.leftPad(this.getMonth() + 1, 2, '0')",
+        M: "Date.getShortMonthName(this.getMonth())", 
+        n: "(this.getMonth() + 1)",
+        t: "this.getDaysInMonth()",
+        L: "(this.isLeapYear() ? 1 : 0)",
+        o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
+        Y: "String.leftPad(this.getFullYear(), 4, '0')",
+        y: "('' + this.getFullYear()).substring(2, 4)",
+        a: "(this.getHours() < 12 ? 'am' : 'pm')",
+        A: "(this.getHours() < 12 ? 'AM' : 'PM')",
+        g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
+        G: "this.getHours()",
+        h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
+        H: "String.leftPad(this.getHours(), 2, '0')",
+        i: "String.leftPad(this.getMinutes(), 2, '0')",
+        s: "String.leftPad(this.getSeconds(), 2, '0')",
+        u: "String.leftPad(this.getMilliseconds(), 3, '0')",
+        O: "this.getGMTOffset()",
+        P: "this.getGMTOffset(true)",
+        T: "this.getTimezone()",
+        Z: "(this.getTimezoneOffset() * -60)",
+
+        c: function() { 
+            for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
+                var e = c.charAt(i);
+                code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
+            }
+            return code.join(" + ");
+        },
+        
+
+        U: "Math.round(this.getTime() / 1000)"
+    },
+
+    
+    isValid : function(y, m, d, h, i, s, ms) {
+        
+        h = h || 0;
+        i = i || 0;
+        s = s || 0;
+        ms = ms || 0;
+
+        
+        var dt = new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);
+
+        return y == dt.getFullYear() &&
+            m == dt.getMonth() + 1 &&
+            d == dt.getDate() &&
+            h == dt.getHours() &&
+            i == dt.getMinutes() &&
+            s == dt.getSeconds() &&
+            ms == dt.getMilliseconds();
+    },
+
+    
+    parseDate : function(input, format, strict) {
+        var p = Date.parseFunctions;
+        if (p[format] == null) {
+            Date.createParser(format);
+        }
+        return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
+    },
+
+    
+    getFormatCode : function(character) {
+        var f = Date.formatCodes[character];
+
+        if (f) {
+          f = typeof f == 'function'? f() : f;
+          Date.formatCodes[character] = f; 
+        }
+
+        
+        return f || ("'" + String.escape(character) + "'");
+    },
+
+    
+    createFormat : function(format) {
+        var code = [],
+            special = false,
+            ch = '';
+
+        for (var i = 0; i < format.length; ++i) {
+            ch = format.charAt(i);
+            if (!special && ch == "\\") {
+                special = true;
+            } else if (special) {
+                special = false;
+                code.push("'" + String.escape(ch) + "'");
+            } else {
+                code.push(Date.getFormatCode(ch));
+            }
+        }
+        Date.formatFunctions[format] = new Function("return " + code.join('+'));
+    },
+
+    
+    createParser : function() {
+        var code = [
+            "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
+                "def = Date.defaults,",
+                "results = String(input).match(Date.parseRegexes[{0}]);", 
+
+            "if(results){",
+                "{1}",
+
+                "if(u != null){", 
+                    "v = new Date(u * 1000);", 
+                "}else{",
+                    
+                    
+                    
+                    "dt = (new Date()).clearTime();",
+
+                    
+                    "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
+                    "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
+                    "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
+
+                    
+                    "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
+                    "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
+                    "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
+                    "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
+
+                    "if(z >= 0 && y >= 0){",
+                        
+                        
+
+                        
+                        
+                        "v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
+
+                        
+                        "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
+                    "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
+                        "v = null;", 
+                    "}else{",
+                        
+                        
+                        "v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
+                    "}",
+                "}",
+            "}",
+
+            "if(v){",
+                
+                "if(zz != null){",
+                    
+                    "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
+                "}else if(o){",
+                    
+                    "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
+                "}",
+            "}",
+
+            "return v;"
+        ].join('\n');
+
+        return function(format) {
+            var regexNum = Date.parseRegexes.length,
+                currentGroup = 1,
+                calc = [],
+                regex = [],
+                special = false,
+                ch = "",
+                i = 0,
+                obj,
+                last;
+
+            for (; i < format.length; ++i) {
+                ch = format.charAt(i);
+                if (!special && ch == "\\") {
+                    special = true;
+                } else if (special) {
+                    special = false;
+                    regex.push(String.escape(ch));
+                } else {
+                    obj = $f(ch, currentGroup);
+                    currentGroup += obj.g;
+                    regex.push(obj.s);
+                    if (obj.g && obj.c) {
+                        if (obj.calcLast) {
+                            last = obj.c;
+                        } else {
+                            calc.push(obj.c);
+                        }
+                    }
+                }
+            }
+            
+            if (last) {
+                calc.push(last);
+            }
+
+            Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
+            Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
+        };
+    }(),
+
+    
+    parseCodes : {
+        
+        d: {
+            g:1,
+            c:"d = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        j: {
+            g:1,
+            c:"d = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,2})" 
+        },
+        D: function() {
+            for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
+            return {
+                g:0,
+                c:null,
+                s:"(?:" + a.join("|") +")"
+            };
+        },
+        l: function() {
+            return {
+                g:0,
+                c:null,
+                s:"(?:" + Date.dayNames.join("|") + ")"
+            };
+        },
+        N: {
+            g:0,
+            c:null,
+            s:"[1-7]" 
+        },
+        S: {
+            g:0,
+            c:null,
+            s:"(?:st|nd|rd|th)"
+        },
+        w: {
+            g:0,
+            c:null,
+            s:"[0-6]" 
+        },
+        z: {
+            g:1,
+            c:"z = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,3})" 
+        },
+        W: {
+            g:0,
+            c:null,
+            s:"(?:\\d{2})" 
+        },
+        F: function() {
+            return {
+                g:1,
+                c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
+                s:"(" + Date.monthNames.join("|") + ")"
+            };
+        },
+        M: function() {
+            for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
+            return Ext.applyIf({
+                s:"(" + a.join("|") + ")"
+            }, $f("F"));
+        },
+        m: {
+            g:1,
+            c:"m = parseInt(results[{0}], 10) - 1;\n",
+            s:"(\\d{2})" 
+        },
+        n: {
+            g:1,
+            c:"m = parseInt(results[{0}], 10) - 1;\n",
+            s:"(\\d{1,2})" 
+        },
+        t: {
+            g:0,
+            c:null,
+            s:"(?:\\d{2})" 
+        },
+        L: {
+            g:0,
+            c:null,
+            s:"(?:1|0)"
+        },
+        o: function() {
+            return $f("Y");
+        },
+        Y: {
+            g:1,
+            c:"y = parseInt(results[{0}], 10);\n",
+            s:"(\\d{4})" 
+        },
+        y: {
+            g:1,
+            c:"var ty = parseInt(results[{0}], 10);\n"
+                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
+            s:"(\\d{1,2})"
+        },
+        
+        a: function(){
+            return $f("A");
+        },
+        A: {
+            
+            calcLast: true,
+            g:1,
+            c:"if (/(am)/i.test(results[{0}])) {\n"
+                + "if (!h || h == 12) { h = 0; }\n"
+                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
+            s:"(AM|PM|am|pm)"
+        },
+        g: function() {
+            return $f("G");
+        },
+        G: {
+            g:1,
+            c:"h = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,2})" 
+        },
+        h: function() {
+            return $f("H");
+        },
+        H: {
+            g:1,
+            c:"h = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        i: {
+            g:1,
+            c:"i = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        s: {
+            g:1,
+            c:"s = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        u: {
+            g:1,
+            c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
+            s:"(\\d+)" 
+        },
+        O: {
+            g:1,
+            c:[
+                "o = results[{0}];",
+                "var sn = o.substring(0,1),", 
+                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
+                    "mn = o.substring(3,5) % 60;", 
+                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
+            ].join("\n"),
+            s: "([+\-]\\d{4})" 
+        },
+        P: {
+            g:1,
+            c:[
+                "o = results[{0}];",
+                "var sn = o.substring(0,1),", 
+                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
+                    "mn = o.substring(4,6) % 60;", 
+                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
+            ].join("\n"),
+            s: "([+\-]\\d{2}:\\d{2})" 
+        },
+        T: {
+            g:0,
+            c:null,
+            s:"[A-Z]{1,4}" 
+        },
+        Z: {
+            g:1,
+            c:"zz = results[{0}] * 1;\n" 
+                  + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
+            s:"([+\-]?\\d{1,5})" 
+        },
+        c: function() {
+            var calc = [],
+                arr = [
+                    $f("Y", 1), 
+                    $f("m", 2), 
+                    $f("d", 3), 
+                    $f("h", 4), 
+                    $f("i", 5), 
+                    $f("s", 6), 
+                    {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
+                    {c:[ 
+                        "if(results[8]) {", 
+                            "if(results[8] == 'Z'){",
+                                "zz = 0;", 
+                            "}else if (results[8].indexOf(':') > -1){",
+                                $f("P", 8).c, 
+                            "}else{",
+                                $f("O", 8).c, 
+                            "}",
+                        "}"
+                    ].join('\n')}
+                ];
+
+            for (var i = 0, l = arr.length; i < l; ++i) {
+                calc.push(arr[i].c);
+            }
+
+            return {
+                g:1,
+                c:calc.join(""),
+                s:[
+                    arr[0].s, 
+                    "(?:", "-", arr[1].s, 
+                        "(?:", "-", arr[2].s, 
+                            "(?:",
+                                "(?:T| )?", 
+                                arr[3].s, ":", arr[4].s,  
+                                "(?::", arr[5].s, ")?", 
+                                "(?:(?:\\.|,)(\\d+))?", 
+                                "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
+                            ")?",
+                        ")?",
+                    ")?"
+                ].join("")
+            };
+        },
+        U: {
+            g:1,
+            c:"u = parseInt(results[{0}], 10);\n",
+            s:"(-?\\d+)" 
+        }
+    }
+});
+
+}());
+
+Ext.apply(Date.prototype, {
+    
+    dateFormat : function(format) {
+        if (Date.formatFunctions[format] == null) {
+            Date.createFormat(format);
+        }
+        return Date.formatFunctions[format].call(this);
+    },
+
+    
+    getTimezone : function() {
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
+    },
+
+    
+    getGMTOffset : function(colon) {
+        return (this.getTimezoneOffset() > 0 ? "-" : "+")
+            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
+            + (colon ? ":" : "")
+            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
+    },
+
+    
+    getDayOfYear: function() {
+        var num = 0,
+            d = this.clone(),
+            m = this.getMonth(),
+            i;
+
+        for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
+            num += d.getDaysInMonth();
+        }
+        return num + this.getDate() - 1;
+    },
+
+    
+    getWeekOfYear : function() {
+        
+        var ms1d = 864e5, 
+            ms7d = 7 * ms1d; 
+
+        return function() { 
+            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
+                AWN = Math.floor(DC3 / 7), 
+                Wyr = new Date(AWN * ms7d).getUTCFullYear();
+
+            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
+        };
+    }(),
+
+    
+    isLeapYear : function() {
+        var year = this.getFullYear();
+        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
+    },
+
+    
+    getFirstDayOfMonth : function() {
+        var day = (this.getDay() - (this.getDate() - 1)) % 7;
+        return (day < 0) ? (day + 7) : day;
+    },
+
+    
+    getLastDayOfMonth : function() {
+        return this.getLastDateOfMonth().getDay();
+    },
+
+
+    
+    getFirstDateOfMonth : function() {
+        return new Date(this.getFullYear(), this.getMonth(), 1);
+    },
+
+    
+    getLastDateOfMonth : function() {
+        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
+    },
+
+    
+    getDaysInMonth: function() {
+        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+        return function() { 
+            var m = this.getMonth();
+
+            return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
+        };
+    }(),
+
+    
+    getSuffix : function() {
+        switch (this.getDate()) {
+            case 1:
+            case 21:
+            case 31:
+                return "st";
+            case 2:
+            case 22:
+                return "nd";
+            case 3:
+            case 23:
+                return "rd";
+            default:
+                return "th";
+        }
+    },
+
+    
+    clone : function() {
+        return new Date(this.getTime());
+    },
+
+    
+    isDST : function() {
+        
+        
+        return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
+    },
+
+    
+    clearTime : function(clone) {
+        if (clone) {
+            return this.clone().clearTime();
+        }
+
+        
+        var d = this.getDate();
+
+        
+        this.setHours(0);
+        this.setMinutes(0);
+        this.setSeconds(0);
+        this.setMilliseconds(0);
+
+        if (this.getDate() != d) { 
+            
+            
+
+            
+            for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
+
+            this.setDate(d);
+            this.setHours(c.getHours());
+        }
+
+        return this;
+    },
+
+    
+    add : function(interval, value) {
+        var d = this.clone();
+        if (!interval || value === 0) return d;
+
+        switch(interval.toLowerCase()) {
+            case Date.MILLI:
+                d.setMilliseconds(this.getMilliseconds() + value);
+                break;
+            case Date.SECOND:
+                d.setSeconds(this.getSeconds() + value);
+                break;
+            case Date.MINUTE:
+                d.setMinutes(this.getMinutes() + value);
+                break;
+            case Date.HOUR:
+                d.setHours(this.getHours() + value);
+                break;
+            case Date.DAY:
+                d.setDate(this.getDate() + value);
+                break;
+            case Date.MONTH:
+                var day = this.getDate();
+                if (day > 28) {
+                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
+                }
+                d.setDate(day);
+                d.setMonth(this.getMonth() + value);
+                break;
+            case Date.YEAR:
+                d.setFullYear(this.getFullYear() + value);
+                break;
+        }
+        return d;
+    },
+
+    
+    between : function(start, end) {
+        var t = this.getTime();
+        return start.getTime() <= t && t <= end.getTime();
+    }
+});
+
+
+
+Date.prototype.format = Date.prototype.dateFormat;
+
+
+
+if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
+    Ext.apply(Date.prototype, {
+        _xMonth : Date.prototype.setMonth,
+        _xDate  : Date.prototype.setDate,
+
+        
+        
+        setMonth : function(num) {
+            if (num <= -1) {
+                var n = Math.ceil(-num),
+                    back_year = Math.ceil(n / 12),
+                    month = (n % 12) ? 12 - n % 12 : 0;
+
+                this.setFullYear(this.getFullYear() - back_year);
+
+                return this._xMonth(month);
+            } else {
+                return this._xMonth(num);
+            }
+        },
+
+        
+        
+        
+        setDate : function(d) {
+            
+            
+            return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
+        }
+    });
+}
+
+
+
+
+
+Ext.util.MixedCollection = function(allowFunctions, keyFn){
+    this.items = [];
+    this.map = {};
+    this.keys = [];
+    this.length = 0;
+    this.addEvents(
+        
+        'clear',
+        
+        'add',
+        
+        'replace',
+        
+        'remove',
+        'sort'
+    );
+    this.allowFunctions = allowFunctions === true;
+    if(keyFn){
+        this.getKey = keyFn;
+    }
+    Ext.util.MixedCollection.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
+
+    
+    allowFunctions : false,
+
+    
+    add : function(key, o){
+        if(arguments.length == 1){
+            o = arguments[0];
+            key = this.getKey(o);
+        }
+        if(typeof key != 'undefined' && key !== null){
+            var old = this.map[key];
+            if(typeof old != 'undefined'){
+                return this.replace(key, o);
+            }
+            this.map[key] = o;
+        }
+        this.length++;
+        this.items.push(o);
+        this.keys.push(key);
+        this.fireEvent('add', this.length-1, o, key);
+        return o;
+    },
+
+    
+    getKey : function(o){
+         return o.id;
+    },
+
+    
+    replace : function(key, o){
+        if(arguments.length == 1){
+            o = arguments[0];
+            key = this.getKey(o);
+        }
+        var old = this.map[key];
+        if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
+             return this.add(key, o);
+        }
+        var index = this.indexOfKey(key);
+        this.items[index] = o;
+        this.map[key] = o;
+        this.fireEvent('replace', key, old, o);
+        return o;
+    },
+
+    
+    addAll : function(objs){
+        if(arguments.length > 1 || Ext.isArray(objs)){
+            var args = arguments.length > 1 ? arguments : objs;
+            for(var i = 0, len = args.length; i < len; i++){
+                this.add(args[i]);
+            }
+        }else{
+            for(var key in objs){
+                if(this.allowFunctions || typeof objs[key] != 'function'){
+                    this.add(key, objs[key]);
+                }
+            }
+        }
+    },
+
+    
+    each : function(fn, scope){
+        var items = [].concat(this.items); 
+        for(var i = 0, len = items.length; i < len; i++){
+            if(fn.call(scope || items[i], items[i], i, len) === false){
+                break;
+            }
+        }
+    },
+
+    
+    eachKey : function(fn, scope){
+        for(var i = 0, len = this.keys.length; i < len; i++){
+            fn.call(scope || window, this.keys[i], this.items[i], i, len);
+        }
+    },
+
+    
+    find : function(fn, scope){
+        for(var i = 0, len = this.items.length; i < len; i++){
+            if(fn.call(scope || window, this.items[i], this.keys[i])){
+                return this.items[i];
+            }
+        }
+        return null;
+    },
+
+    
+    insert : function(index, key, o){
+        if(arguments.length == 2){
+            o = arguments[1];
+            key = this.getKey(o);
+        }
+        if(this.containsKey(key)){
+            this.suspendEvents();
+            this.removeKey(key);
+            this.resumeEvents();
+        }
+        if(index >= this.length){
+            return this.add(key, o);
+        }
+        this.length++;
+        this.items.splice(index, 0, o);
+        if(typeof key != 'undefined' && key !== null){
+            this.map[key] = o;
+        }
+        this.keys.splice(index, 0, key);
+        this.fireEvent('add', index, o, key);
+        return o;
+    },
+
+    
+    remove : function(o){
+        return this.removeAt(this.indexOf(o));
+    },
+
+    
+    removeAt : function(index){
+        if(index < this.length && index >= 0){
+            this.length--;
+            var o = this.items[index];
+            this.items.splice(index, 1);
+            var key = this.keys[index];
+            if(typeof key != 'undefined'){
+                delete this.map[key];
+            }
+            this.keys.splice(index, 1);
+            this.fireEvent('remove', o, key);
+            return o;
+        }
+        return false;
+    },
+
+    
+    removeKey : function(key){
+        return this.removeAt(this.indexOfKey(key));
+    },
+
+    
+    getCount : function(){
+        return this.length;
+    },
+
+    
+    indexOf : function(o){
+        return this.items.indexOf(o);
+    },
+
+    
+    indexOfKey : function(key){
+        return this.keys.indexOf(key);
+    },
+
+    
+    item : function(key){
+        var mk = this.map[key],
+            item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
+        return typeof item != 'function' || this.allowFunctions ? item : null; 
+    },
+
+    
+    itemAt : function(index){
+        return this.items[index];
+    },
+
+    
+    key : function(key){
+        return this.map[key];
+    },
+
+    
+    contains : function(o){
+        return this.indexOf(o) != -1;
+    },
+
+    
+    containsKey : function(key){
+        return typeof this.map[key] != 'undefined';
+    },
+
+    
+    clear : function(){
+        this.length = 0;
+        this.items = [];
+        this.keys = [];
+        this.map = {};
+        this.fireEvent('clear');
+    },
+
+    
+    first : function(){
+        return this.items[0];
+    },
+
+    
+    last : function(){
+        return this.items[this.length-1];
+    },
+
+    
+    _sort : function(property, dir, fn){
+        var i, len,
+            dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
+
+            
+            c     = [],
+            keys  = this.keys,
+            items = this.items;
+
+        
+        fn = fn || function(a, b) {
+            return a - b;
+        };
+
+        
+        for(i = 0, len = items.length; i < len; i++){
+            c[c.length] = {
+                key  : keys[i],
+                value: items[i],
+                index: i
+            };
+        }
+
+        
+        c.sort(function(a, b){
+            var v = fn(a[property], b[property]) * dsc;
+            if(v === 0){
+                v = (a.index < b.index ? -1 : 1);
+            }
+            return v;
+        });
+
+        
+        for(i = 0, len = c.length; i < len; i++){
+            items[i] = c[i].value;
+            keys[i]  = c[i].key;
+        }
+
+        this.fireEvent('sort', this);
+    },
+
+    
+    sort : function(dir, fn){
+        this._sort('value', dir, fn);
+    },
+
+    
+    reorder: function(mapping) {
+        this.suspendEvents();
+
+        var items = this.items,
+            index = 0,
+            length = items.length,
+            order = [],
+            remaining = [],
+            oldIndex;
+
+        
+        for (oldIndex in mapping) {
+            order[mapping[oldIndex]] = items[oldIndex];
+        }
+
+        for (index = 0; index < length; index++) {
+            if (mapping[index] == undefined) {
+                remaining.push(items[index]);
+            }
+        }
+
+        for (index = 0; index < length; index++) {
+            if (order[index] == undefined) {
+                order[index] = remaining.shift();
+            }
+        }
+
+        this.clear();
+        this.addAll(order);
+
+        this.resumeEvents();
+        this.fireEvent('sort', this);
+    },
+
+    
+    keySort : function(dir, fn){
+        this._sort('key', dir, fn || function(a, b){
+            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
+            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
+        });
+    },
+
+    
+    getRange : function(start, end){
+        var items = this.items;
+        if(items.length < 1){
+            return [];
+        }
+        start = start || 0;
+        end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
+        var i, r = [];
+        if(start <= end){
+            for(i = start; i <= end; i++) {
+                r[r.length] = items[i];
+            }
+        }else{
+            for(i = start; i >= end; i--) {
+                r[r.length] = items[i];
+            }
+        }
+        return r;
+    },
+
+    
+    filter : function(property, value, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return this.clone();
+        }
+        value = this.createValueMatcher(value, anyMatch, caseSensitive);
+        return this.filterBy(function(o){
+            return o && value.test(o[property]);
+        });
+    },
+
+    
+    filterBy : function(fn, scope){
+        var r = new Ext.util.MixedCollection();
+        r.getKey = this.getKey;
+        var k = this.keys, it = this.items;
+        for(var i = 0, len = it.length; i < len; i++){
+            if(fn.call(scope||this, it[i], k[i])){
+                r.add(k[i], it[i]);
+            }
+        }
+        return r;
+    },
+
+    
+    findIndex : function(property, value, start, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return -1;
+        }
+        value = this.createValueMatcher(value, anyMatch, caseSensitive);
+        return this.findIndexBy(function(o){
+            return o && value.test(o[property]);
+        }, null, start);
+    },
+
+    
+    findIndexBy : function(fn, scope, start){
+        var k = this.keys, it = this.items;
+        for(var i = (start||0), len = it.length; i < len; i++){
+            if(fn.call(scope||this, it[i], k[i])){
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    
+    createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
+        if (!value.exec) { 
+            var er = Ext.escapeRe;
+            value = String(value);
+
+            if (anyMatch === true) {
+                value = er(value);
+            } else {
+                value = '^' + er(value);
+                if (exactMatch === true) {
+                    value += '$';
+                }
+            }
+            value = new RegExp(value, caseSensitive ? '' : 'i');
+         }
+         return value;
+    },
+
+    
+    clone : function(){
+        var r = new Ext.util.MixedCollection();
+        var k = this.keys, it = this.items;
+        for(var i = 0, len = it.length; i < len; i++){
+            r.add(k[i], it[i]);
+        }
+        r.getKey = this.getKey;
+        return r;
+    }
+});
+
+Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
+
+Ext.AbstractManager = Ext.extend(Object, {
+    typeName: 'type',
+    
+    constructor: function(config) {
+        Ext.apply(this, config || {});
+        
+        
+        this.all = new Ext.util.MixedCollection();
+        
+        this.types = {};
+    },
+    
+    
+    get : function(id){
+        return this.all.get(id);
+    },
+    
+    
+    register: function(item) {
+        this.all.add(item);
+    },
+    
+    
+    unregister: function(item) {
+        this.all.remove(item);        
+    },
+    
+    
+    registerType : function(type, cls){
+        this.types[type] = cls;
+        cls[this.typeName] = type;
+    },
+    
+    
+    isRegistered : function(type){
+        return this.types[type] !== undefined;    
+    },
+    
+    
+    create: function(config, defaultType) {
+        var type        = config[this.typeName] || config.type || defaultType,
+            Constructor = this.types[type];
+        
+        if (Constructor == undefined) {
+            throw new Error(String.format("The '{0}' type has not been registered with this manager", type));
+        }
+        
+        return new Constructor(config);
+    },
+    
+    
+    onAvailable : function(id, fn, scope){
+        var all = this.all;
+        
+        all.on("add", function(index, o){
+            if (o.id == id) {
+                fn.call(scope || o, o);
+                all.un("add", fn, scope);
+            }
+        });
+    }
+});
+Ext.util.Format = function() {
+    var trimRe         = /^\s+|\s+$/g,
+        stripTagsRE    = /<\/?[^>]+>/gi,
+        stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
+        nl2brRe        = /\r?\n/g;
+
+    return {
+        
+        ellipsis : function(value, len, word) {
+            if (value && value.length > len) {
+                if (word) {
+                    var vs    = value.substr(0, len - 2),
+                        index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
+                    if (index == -1 || index < (len - 15)) {
+                        return value.substr(0, len - 3) + "...";
+                    } else {
+                        return vs.substr(0, index) + "...";
+                    }
+                } else {
+                    return value.substr(0, len - 3) + "...";
+                }
+            }
+            return value;
+        },
+
+        
+        undef : function(value) {
+            return value !== undefined ? value : "";
+        },
+
+        
+        defaultValue : function(value, defaultValue) {
+            return value !== undefined && value !== '' ? value : defaultValue;
+        },
+
+        
+        htmlEncode : function(value) {
+            return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
+        },
+
+        
+        htmlDecode : function(value) {
+            return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
+        },
+
+        
+        trim : function(value) {
+            return String(value).replace(trimRe, "");
+        },
+
+        
+        substr : function(value, start, length) {
+            return String(value).substr(start, length);
+        },
+
+        
+        lowercase : function(value) {
+            return String(value).toLowerCase();
+        },
+
+        
+        uppercase : function(value) {
+            return String(value).toUpperCase();
+        },
+
+        
+        capitalize : function(value) {
+            return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
+        },
+
+        
+        call : function(value, fn) {
+            if (arguments.length > 2) {
+                var args = Array.prototype.slice.call(arguments, 2);
+                args.unshift(value);
+                return eval(fn).apply(window, args);
+            } else {
+                return eval(fn).call(window, value);
+            }
+        },
+
+        
+        usMoney : function(v) {
+            v = (Math.round((v-0)*100))/100;
+            v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
+            v = String(v);
+            var ps = v.split('.'),
+                whole = ps[0],
+                sub = ps[1] ? '.'+ ps[1] : '.00',
+                r = /(\d+)(\d{3})/;
+            while (r.test(whole)) {
+                whole = whole.replace(r, '$1' + ',' + '$2');
+            }
+            v = whole + sub;
+            if (v.charAt(0) == '-') {
+                return '-$' + v.substr(1);
+            }
+            return "$" +  v;
+        },
+
+        
+        date : function(v, format) {
+            if (!v) {
+                return "";
+            }
+            if (!Ext.isDate(v)) {
+                v = new Date(Date.parse(v));
+            }
+            return v.dateFormat(format || "m/d/Y");
+        },
+
+        
+        dateRenderer : function(format) {
+            return function(v) {
+                return Ext.util.Format.date(v, format);
+            };
+        },
+
+        
+        stripTags : function(v) {
+            return !v ? v : String(v).replace(stripTagsRE, "");
+        },
+
+        
+        stripScripts : function(v) {
+            return !v ? v : String(v).replace(stripScriptsRe, "");
+        },
+
+        
+        fileSize : function(size) {
+            if (size < 1024) {
+                return size + " bytes";
+            } else if (size < 1048576) {
+                return (Math.round(((size*10) / 1024))/10) + " KB";
+            } else {
+                return (Math.round(((size*10) / 1048576))/10) + " MB";
+            }
+        },
+
+        
+        math : function(){
+            var fns = {};
+            
+            return function(v, a){
+                if (!fns[a]) {
+                    fns[a] = new Function('v', 'return v ' + a + ';');
+                }
+                return fns[a](v);
+            };
+        }(),
+
+        
+        round : function(value, precision) {
+            var result = Number(value);
+            if (typeof precision == 'number') {
+                precision = Math.pow(10, precision);
+                result = Math.round(value * precision) / precision;
+            }
+            return result;
+        },
+
+        
+        number: function(v, format) {
+            if (!format) {
+                return v;
+            }
+            v = Ext.num(v, NaN);
+            if (isNaN(v)) {
+                return '';
+            }
+            var comma = ',',
+                dec   = '.',
+                i18n  = false,
+                neg   = v < 0;
+
+            v = Math.abs(v);
+            if (format.substr(format.length - 2) == '/i') {
+                format = format.substr(0, format.length - 2);
+                i18n   = true;
+                comma  = '.';
+                dec    = ',';
+            }
+
+            var hasComma = format.indexOf(comma) != -1,
+                psplit   = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
+
+            if (1 < psplit.length) {
+                v = v.toFixed(psplit[1].length);
+            } else if(2 < psplit.length) {
+                throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
+            } else {
+                v = v.toFixed(0);
+            }
+
+            var fnum = v.toString();
+
+            psplit = fnum.split('.');
+
+            if (hasComma) {
+                var cnum = psplit[0], 
+                    parr = [], 
+                    j    = cnum.length, 
+                    m    = Math.floor(j / 3),
+                    n    = cnum.length % 3 || 3,
+                    i;
+
+                for (i = 0; i < j; i += n) {
+                    if (i != 0) {
+                        n = 3;
+                    }
+                    
+                    parr[parr.length] = cnum.substr(i, n);
+                    m -= 1;
+                }
+                fnum = parr.join(comma);
+                if (psplit[1]) {
+                    fnum += dec + psplit[1];
+                }
+            } else {
+                if (psplit[1]) {
+                    fnum = psplit[0] + dec + psplit[1];
+                }
+            }
+
+            return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
+        },
+
+        
+        numberRenderer : function(format) {
+            return function(v) {
+                return Ext.util.Format.number(v, format);
+            };
+        },
+
+        
+        plural : function(v, s, p) {
+            return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
+        },
+
+        
+        nl2br : function(v) {
+            return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
+        }
+    };
+}();
+
+Ext.XTemplate = function(){
+    Ext.XTemplate.superclass.constructor.apply(this, arguments);
+
+    var me = this,
+        s = me.html,
+        re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
+        nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
+        ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
+        execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
+        m,
+        id = 0,
+        tpls = [],
+        VALUES = 'values',
+        PARENT = 'parent',
+        XINDEX = 'xindex',
+        XCOUNT = 'xcount',
+        RETURN = 'return ',
+        WITHVALUES = 'with(values){ ';
+
+    s = ['<tpl>', s, '</tpl>'].join('');
+
+    while((m = s.match(re))){
+        var m2 = m[0].match(nameRe),
+            m3 = m[0].match(ifRe),
+            m4 = m[0].match(execRe),
+            exp = null,
+            fn = null,
+            exec = null,
+            name = m2 && m2[1] ? m2[1] : '';
+
+       if (m3) {
+           exp = m3 && m3[1] ? m3[1] : null;
+           if(exp){
+               fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
+           }
+       }
+       if (m4) {
+           exp = m4 && m4[1] ? m4[1] : null;
+           if(exp){
+               exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
+           }
+       }
+       if(name){
+           switch(name){
+               case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
+               case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
+               default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
+           }
+       }
+       tpls.push({
+            id: id,
+            target: name,
+            exec: exec,
+            test: fn,
+            body: m[1]||''
+        });
+       s = s.replace(m[0], '{xtpl'+ id + '}');
+       ++id;
+    }
+    for(var i = tpls.length-1; i >= 0; --i){
+        me.compileTpl(tpls[i]);
+    }
+    me.master = tpls[tpls.length-1];
+    me.tpls = tpls;
+};
+Ext.extend(Ext.XTemplate, Ext.Template, {
+    
+    re : /\{([\w\-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
+    
+    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+
+    
+    applySubTemplate : function(id, values, parent, xindex, xcount){
+        var me = this,
+            len,
+            t = me.tpls[id],
+            vs,
+            buf = [];
+        if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
+            (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
+            return '';
+        }
+        vs = t.target ? t.target.call(me, values, parent) : values;
+        len = vs.length;
+        parent = t.target ? values : parent;
+        if(t.target && Ext.isArray(vs)){
+            for(var i = 0, len = vs.length; i < len; i++){
+                buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
+            }
+            return buf.join('');
+        }
+        return t.compiled.call(me, vs, parent, xindex, xcount);
+    },
+
+    
+    compileTpl : function(tpl){
+        var fm = Ext.util.Format,
+            useF = this.disableFormats !== true,
+            sep = Ext.isGecko ? "+" : ",",
+            body;
+
+        function fn(m, name, format, args, math){
+            if(name.substr(0, 4) == 'xtpl'){
+                return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
+            }
+            var v;
+            if(name === '.'){
+                v = 'values';
+            }else if(name === '#'){
+                v = 'xindex';
+            }else if(name.indexOf('.') != -1){
+                v = name;
+            }else{
+                v = "values['" + name + "']";
+            }
+            if(math){
+                v = '(' + v + math + ')';
+            }
+            if (format && useF) {
+                args = args ? ',' + args : "";
+                if(format.substr(0, 5) != "this."){
+                    format = "fm." + format + '(';
+                }else{
+                    format = 'this.call("'+ format.substr(5) + '", ';
+                    args = ", values";
+                }
+            } else {
+                args= ''; format = "("+v+" === undefined ? '' : ";
+            }
+            return "'"+ sep + format + v + args + ")"+sep+"'";
+        }
+
+        function codeFn(m, code){
+            
+            return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
+        }
+
+        
+        if(Ext.isGecko){
+            body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
+                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
+                    "';};";
+        }else{
+            body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
+            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
+            body.push("'].join('');};");
+            body = body.join('');
+        }
+        eval(body);
+        return this;
+    },
+
+    
+    applyTemplate : function(values){
+        return this.master.compiled.call(this, values, {}, 1, 1);
+    },
+
+    
+    compile : function(){return this;}
+
+    
+    
+    
+
+});
+
+Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
+
+
+Ext.XTemplate.from = function(el){
+    el = Ext.getDom(el);
+    return new Ext.XTemplate(el.value || el.innerHTML);
+};
+
+Ext.util.CSS = function(){
+	var rules = null;
+   	var doc = document;
+
+    var camelRe = /(-[a-z])/gi;
+    var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
+
+   return {
+   
+   createStyleSheet : function(cssText, id){
+       var ss;
+       var head = doc.getElementsByTagName("head")[0];
+       var rules = doc.createElement("style");
+       rules.setAttribute("type", "text/css");
+       if(id){
+           rules.setAttribute("id", id);
+       }
+       if(Ext.isIE){
+           head.appendChild(rules);
+           ss = rules.styleSheet;
+           ss.cssText = cssText;
+       }else{
+           try{
+                rules.appendChild(doc.createTextNode(cssText));
+           }catch(e){
+               rules.cssText = cssText;
+           }
+           head.appendChild(rules);
+           ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
+       }
+       this.cacheStyleSheet(ss);
+       return ss;
+   },
+
+   
+   removeStyleSheet : function(id){
+       var existing = doc.getElementById(id);
+       if(existing){
+           existing.parentNode.removeChild(existing);
+       }
+   },
+
+   
+   swapStyleSheet : function(id, url){
+       this.removeStyleSheet(id);
+       var ss = doc.createElement("link");
+       ss.setAttribute("rel", "stylesheet");
+       ss.setAttribute("type", "text/css");
+       ss.setAttribute("id", id);
+       ss.setAttribute("href", url);
+       doc.getElementsByTagName("head")[0].appendChild(ss);
+   },
+   
+   
+   refreshCache : function(){
+       return this.getRules(true);
+   },
+
+   
+   cacheStyleSheet : function(ss){
+       if(!rules){
+           rules = {};
+       }
+       try{
+           var ssRules = ss.cssRules || ss.rules;
+           for(var j = ssRules.length-1; j >= 0; --j){
+               rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
+           }
+       }catch(e){}
+   },
+   
+   
+   getRules : function(refreshCache){
+   		if(rules === null || refreshCache){
+   			rules = {};
+   			var ds = doc.styleSheets;
+   			for(var i =0, len = ds.length; i < len; i++){
+   			    try{
+    		        this.cacheStyleSheet(ds[i]);
+    		    }catch(e){} 
+	        }
+   		}
+   		return rules;
+   	},
+   	
+   	
+   getRule : function(selector, refreshCache){
+   		var rs = this.getRules(refreshCache);
+   		if(!Ext.isArray(selector)){
+   		    return rs[selector.toLowerCase()];
+   		}
+   		for(var i = 0; i < selector.length; i++){
+			if(rs[selector[i]]){
+				return rs[selector[i].toLowerCase()];
+			}
+		}
+		return null;
+   	},
+   	
+   	
+   	
+   updateRule : function(selector, property, value){
+   		if(!Ext.isArray(selector)){
+   			var rule = this.getRule(selector);
+   			if(rule){
+   				rule.style[property.replace(camelRe, camelFn)] = value;
+   				return true;
+   			}
+   		}else{
+   			for(var i = 0; i < selector.length; i++){
+   				if(this.updateRule(selector[i], property, value)){
+   					return true;
+   				}
+   			}
+   		}
+   		return false;
+   	}
+   };	
+}();
+Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(el, config){
+        this.el = Ext.get(el);
+        this.el.unselectable();
+
+        Ext.apply(this, config);
+
+        this.addEvents(
+        
+        "mousedown",
+        
+        "click",
+        
+        "mouseup"
+        );
+
+        if(!this.disabled){
+            this.disabled = true;
+            this.enable();
+        }
+
+        
+        if(this.handler){
+            this.on("click", this.handler,  this.scope || this);
+        }
+
+        Ext.util.ClickRepeater.superclass.constructor.call(this);        
+    },
+    
+    interval : 20,
+    delay: 250,
+    preventDefault : true,
+    stopDefault : false,
+    timer : 0,
+
+    
+    enable: function(){
+        if(this.disabled){
+            this.el.on('mousedown', this.handleMouseDown, this);
+            if (Ext.isIE){
+                this.el.on('dblclick', this.handleDblClick, this);
+            }
+            if(this.preventDefault || this.stopDefault){
+                this.el.on('click', this.eventOptions, this);
+            }
+        }
+        this.disabled = false;
+    },
+
+    
+    disable: function( force){
+        if(force || !this.disabled){
+            clearTimeout(this.timer);
+            if(this.pressClass){
+                this.el.removeClass(this.pressClass);
+            }
+            Ext.getDoc().un('mouseup', this.handleMouseUp, this);
+            this.el.removeAllListeners();
+        }
+        this.disabled = true;
+    },
+
+    
+    setDisabled: function(disabled){
+        this[disabled ? 'disable' : 'enable']();
+    },
+
+    eventOptions: function(e){
+        if(this.preventDefault){
+            e.preventDefault();
+        }
+        if(this.stopDefault){
+            e.stopEvent();
+        }
+    },
+
+    
+    destroy : function() {
+        this.disable(true);
+        Ext.destroy(this.el);
+        this.purgeListeners();
+    },
+
+    handleDblClick : function(e){
+        clearTimeout(this.timer);
+        this.el.blur();
+
+        this.fireEvent("mousedown", this, e);
+        this.fireEvent("click", this, e);
+    },
+
+    
+    handleMouseDown : function(e){
+        clearTimeout(this.timer);
+        this.el.blur();
+        if(this.pressClass){
+            this.el.addClass(this.pressClass);
+        }
+        this.mousedownTime = new Date();
+
+        Ext.getDoc().on("mouseup", this.handleMouseUp, this);
+        this.el.on("mouseout", this.handleMouseOut, this);
+
+        this.fireEvent("mousedown", this, e);
+        this.fireEvent("click", this, e);
+
+        
+        if (this.accelerate) {
+            this.delay = 400;
+        }
+        this.timer = this.click.defer(this.delay || this.interval, this, [e]);
+    },
+
+    
+    click : function(e){
+        this.fireEvent("click", this, e);
+        this.timer = this.click.defer(this.accelerate ?
+            this.easeOutExpo(this.mousedownTime.getElapsed(),
+                400,
+                -390,
+                12000) :
+            this.interval, this, [e]);
+    },
+
+    easeOutExpo : function (t, b, c, d) {
+        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+    },
+
+    
+    handleMouseOut : function(){
+        clearTimeout(this.timer);
+        if(this.pressClass){
+            this.el.removeClass(this.pressClass);
+        }
+        this.el.on("mouseover", this.handleMouseReturn, this);
+    },
+
+    
+    handleMouseReturn : function(){
+        this.el.un("mouseover", this.handleMouseReturn, this);
+        if(this.pressClass){
+            this.el.addClass(this.pressClass);
+        }
+        this.click();
+    },
+
+    
+    handleMouseUp : function(e){
+        clearTimeout(this.timer);
+        this.el.un("mouseover", this.handleMouseReturn, this);
+        this.el.un("mouseout", this.handleMouseOut, this);
+        Ext.getDoc().un("mouseup", this.handleMouseUp, this);
+        this.el.removeClass(this.pressClass);
+        this.fireEvent("mouseup", this, e);
+    }
+});
+Ext.KeyNav = function(el, config){
+    this.el = Ext.get(el);
+    Ext.apply(this, config);
+    if(!this.disabled){
+        this.disabled = true;
+        this.enable();
+    }
+};
+
+Ext.KeyNav.prototype = {
+    
+    disabled : false,
+    
+    defaultEventAction: "stopEvent",
+    
+    forceKeyDown : false,
+
+    
+    relay : function(e){
+        var k = e.getKey(),
+            h = this.keyToHandler[k];
+        if(h && this[h]){
+            if(this.doRelay(e, this[h], h) !== true){
+                e[this.defaultEventAction]();
+            }
+        }
+    },
+
+    
+    doRelay : function(e, h, hname){
+        return h.call(this.scope || this, e, hname);
+    },
+
+    
+    enter : false,
+    left : false,
+    right : false,
+    up : false,
+    down : false,
+    tab : false,
+    esc : false,
+    pageUp : false,
+    pageDown : false,
+    del : false,
+    home : false,
+    end : false,
+    space : false,
+
+    
+    keyToHandler : {
+        37 : "left",
+        39 : "right",
+        38 : "up",
+        40 : "down",
+        33 : "pageUp",
+        34 : "pageDown",
+        46 : "del",
+        36 : "home",
+        35 : "end",
+        13 : "enter",
+        27 : "esc",
+        9  : "tab",
+        32 : "space"
+    },
+    
+    stopKeyUp: function(e) {
+        var k = e.getKey();
+
+        if (k >= 37 && k <= 40) {
+            
+            
+            e.stopEvent();
+        }
+    },
+    
+    
+    destroy: function(){
+        this.disable();    
+    },
+
+	
+	enable: function() {
+        if (this.disabled) {
+            if (Ext.isSafari2) {
+                
+                this.el.on('keyup', this.stopKeyUp, this);
+            }
+
+            this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
+            this.disabled = false;
+        }
+    },
+
+	
+	disable: function() {
+        if (!this.disabled) {
+            if (Ext.isSafari2) {
+                
+                this.el.un('keyup', this.stopKeyUp, this);
+            }
+
+            this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
+            this.disabled = true;
+        }
+    },
+    
+    
+    setDisabled : function(disabled){
+        this[disabled ? "disable" : "enable"]();
+    },
+    
+    
+    isKeydown: function(){
+        return this.forceKeyDown || Ext.EventManager.useKeydown;
+    }
+};
+
+Ext.KeyMap = function(el, config, eventName){
+    this.el  = Ext.get(el);
+    this.eventName = eventName || "keydown";
+    this.bindings = [];
+    if(config){
+        this.addBinding(config);
+    }
+    this.enable();
+};
+
+Ext.KeyMap.prototype = {
+    
+    stopEvent : false,
+
+    
+	addBinding : function(config){
+        if(Ext.isArray(config)){
+            Ext.each(config, function(c){
+                this.addBinding(c);
+            }, this);
+            return;
+        }
+        var keyCode = config.key,
+            fn = config.fn || config.handler,
+            scope = config.scope;
+
+	if (config.stopEvent) {
+	    this.stopEvent = config.stopEvent;    
+	}	
+
+        if(typeof keyCode == "string"){
+            var ks = [];
+            var keyString = keyCode.toUpperCase();
+            for(var j = 0, len = keyString.length; j < len; j++){
+                ks.push(keyString.charCodeAt(j));
+            }
+            keyCode = ks;
+        }
+        var keyArray = Ext.isArray(keyCode);
+        
+        var handler = function(e){
+            if(this.checkModifiers(config, e)){
+                var k = e.getKey();
+                if(keyArray){
+                    for(var i = 0, len = keyCode.length; i < len; i++){
+                        if(keyCode[i] == k){
+                          if(this.stopEvent){
+                              e.stopEvent();
+                          }
+                          fn.call(scope || window, k, e);
+                          return;
+                        }
+                    }
+                }else{
+                    if(k == keyCode){
+                        if(this.stopEvent){
+                           e.stopEvent();
+                        }
+                        fn.call(scope || window, k, e);
+                    }
+                }
+            }
+        };
+        this.bindings.push(handler);
+	},
+    
+    
+    checkModifiers: function(config, e){
+        var val, key, keys = ['shift', 'ctrl', 'alt'];
+        for (var i = 0, len = keys.length; i < len; ++i){
+            key = keys[i];
+            val = config[key];
+            if(!(val === undefined || (val === e[key + 'Key']))){
+                return false;
+            }
+        }
+        return true;
+    },
+
+    
+    on : function(key, fn, scope){
+        var keyCode, shift, ctrl, alt;
+        if(typeof key == "object" && !Ext.isArray(key)){
+            keyCode = key.key;
+            shift = key.shift;
+            ctrl = key.ctrl;
+            alt = key.alt;
+        }else{
+            keyCode = key;
+        }
+        this.addBinding({
+            key: keyCode,
+            shift: shift,
+            ctrl: ctrl,
+            alt: alt,
+            fn: fn,
+            scope: scope
+        });
+    },
+
+    
+    handleKeyDown : function(e){
+	    if(this.enabled){ 
+    	    var b = this.bindings;
+    	    for(var i = 0, len = b.length; i < len; i++){
+    	        b[i].call(this, e);
+    	    }
+	    }
+	},
+
+	
+	isEnabled : function(){
+	    return this.enabled;
+	},
+
+	
+	enable: function(){
+		if(!this.enabled){
+		    this.el.on(this.eventName, this.handleKeyDown, this);
+		    this.enabled = true;
+		}
+	},
+
+	
+	disable: function(){
+		if(this.enabled){
+		    this.el.removeListener(this.eventName, this.handleKeyDown, this);
+		    this.enabled = false;
+		}
+	},
+    
+    
+    setDisabled : function(disabled){
+        this[disabled ? "disable" : "enable"]();
+    }
+};
+Ext.util.TextMetrics = function(){
+    var shared;
+    return {
+        
+        measure : function(el, text, fixedWidth){
+            if(!shared){
+                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
+            }
+            shared.bind(el);
+            shared.setFixedWidth(fixedWidth || 'auto');
+            return shared.getSize(text);
+        },
+
+        
+        createInstance : function(el, fixedWidth){
+            return Ext.util.TextMetrics.Instance(el, fixedWidth);
+        }
+    };
+}();
+
+Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
+    var ml = new Ext.Element(document.createElement('div'));
+    document.body.appendChild(ml.dom);
+    ml.position('absolute');
+    ml.setLeftTop(-1000, -1000);
+    ml.hide();
+
+    if(fixedWidth){
+        ml.setWidth(fixedWidth);
+    }
+
+    var instance = {
+        
+        getSize : function(text){
+            ml.update(text);
+            var s = ml.getSize();
+            ml.update('');
+            return s;
+        },
+
+        
+        bind : function(el){
+            ml.setStyle(
+                Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
+            );
+        },
+
+        
+        setFixedWidth : function(width){
+            ml.setWidth(width);
+        },
+
+        
+        getWidth : function(text){
+            ml.dom.style.width = 'auto';
+            return this.getSize(text).width;
+        },
+
+        
+        getHeight : function(text){
+            return this.getSize(text).height;
+        }
+    };
+
+    instance.bind(bindTo);
+
+    return instance;
+};
+
+Ext.Element.addMethods({
+    
+    getTextWidth : function(text, min, max){
+        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
+    }
+});
+
+Ext.util.Cookies = {
+    
+    set : function(name, value){
+        var argv = arguments;
+        var argc = arguments.length;
+        var expires = (argc > 2) ? argv[2] : null;
+        var path = (argc > 3) ? argv[3] : '/';
+        var domain = (argc > 4) ? argv[4] : null;
+        var secure = (argc > 5) ? argv[5] : false;
+        document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
+    },
+
+    
+    get : function(name){
+        var arg = name + "=";
+        var alen = arg.length;
+        var clen = document.cookie.length;
+        var i = 0;
+        var j = 0;
+        while(i < clen){
+            j = i + alen;
+            if(document.cookie.substring(i, j) == arg){
+                return Ext.util.Cookies.getCookieVal(j);
+            }
+            i = document.cookie.indexOf(" ", i) + 1;
+            if(i === 0){
+                break;
+            }
+        }
+        return null;
+    },
+
+    
+    clear : function(name){
+        if(Ext.util.Cookies.get(name)){
+            document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
+        }
+    },
+    
+    getCookieVal : function(offset){
+        var endstr = document.cookie.indexOf(";", offset);
+        if(endstr == -1){
+            endstr = document.cookie.length;
+        }
+        return unescape(document.cookie.substring(offset, endstr));
+    }
+};
+Ext.handleError = function(e) {
+    throw e;
+};
+
+
+Ext.Error = function(message) {
+    
+    this.message = (this.lang[message]) ? this.lang[message] : message;
+};
+
+Ext.Error.prototype = new Error();
+Ext.apply(Ext.Error.prototype, {
+    
+    lang: {},
+
+    name: 'Ext.Error',
+    
+    getName : function() {
+        return this.name;
+    },
+    
+    getMessage : function() {
+        return this.message;
+    },
+    
+    toJson : function() {
+        return Ext.encode(this);
+    }
+});
+
+Ext.ComponentMgr = function(){
+    var all = new Ext.util.MixedCollection();
+    var types = {};
+    var ptypes = {};
+
+    return {
+        
+        register : function(c){
+            all.add(c);
+        },
+
+        
+        unregister : function(c){
+            all.remove(c);
+        },
+
+        
+        get : function(id){
+            return all.get(id);
+        },
+
+        
+        onAvailable : function(id, fn, scope){
+            all.on("add", function(index, o){
+                if(o.id == id){
+                    fn.call(scope || o, o);
+                    all.un("add", fn, scope);
+                }
+            });
+        },
+
+        
+        all : all,
+        
+        
+        types : types,
+        
+        
+        ptypes: ptypes,
+        
+        
+        isRegistered : function(xtype){
+            return types[xtype] !== undefined;    
+        },
+        
+        
+        isPluginRegistered : function(ptype){
+            return ptypes[ptype] !== undefined;    
+        },        
+
+        
+        registerType : function(xtype, cls){
+            types[xtype] = cls;
+            cls.xtype = xtype;
+        },
+
+        
+        create : function(config, defaultType){
+            return config.render ? config : new types[config.xtype || defaultType](config);
+        },
+
+        
+        registerPlugin : function(ptype, cls){
+            ptypes[ptype] = cls;
+            cls.ptype = ptype;
+        },
+
+        
+        createPlugin : function(config, defaultType){
+            var PluginCls = ptypes[config.ptype || defaultType];
+            if (PluginCls.init) {
+                return PluginCls;                
+            } else {
+                return new PluginCls(config);
+            }            
+        }
+    };
+}();
+
+
+Ext.reg = Ext.ComponentMgr.registerType; 
+
+Ext.preg = Ext.ComponentMgr.registerPlugin;
+
+Ext.create = Ext.ComponentMgr.create;
+Ext.Component = function(config){
+    config = config || {};
+    if(config.initialConfig){
+        if(config.isAction){           
+            this.baseAction = config;
+        }
+        config = config.initialConfig; 
+    }else if(config.tagName || config.dom || Ext.isString(config)){ 
+        config = {applyTo: config, id: config.id || config};
+    }
+
+    
+    this.initialConfig = config;
+
+    Ext.apply(this, config);
+    this.addEvents(
+        
+        'added',
+        
+        'disable',
+        
+        'enable',
+        
+        'beforeshow',
+        
+        'show',
+        
+        'beforehide',
+        
+        'hide',
+        
+        'removed',
+        
+        'beforerender',
+        
+        'render',
+        
+        'afterrender',
+        
+        'beforedestroy',
+        
+        'destroy',
+        
+        'beforestaterestore',
+        
+        'staterestore',
+        
+        'beforestatesave',
+        
+        'statesave'
+    );
+    this.getId();
+    Ext.ComponentMgr.register(this);
+    Ext.Component.superclass.constructor.call(this);
+
+    if(this.baseAction){
+        this.baseAction.addComponent(this);
+    }
+
+    this.initComponent();
+
+    if(this.plugins){
+        if(Ext.isArray(this.plugins)){
+            for(var i = 0, len = this.plugins.length; i < len; i++){
+                this.plugins[i] = this.initPlugin(this.plugins[i]);
+            }
+        }else{
+            this.plugins = this.initPlugin(this.plugins);
+        }
+    }
+
+    if(this.stateful !== false){
+        this.initState();
+    }
+
+    if(this.applyTo){
+        this.applyToMarkup(this.applyTo);
+        delete this.applyTo;
+    }else if(this.renderTo){
+        this.render(this.renderTo);
+        delete this.renderTo;
+    }
+};
+
+
+Ext.Component.AUTO_ID = 1000;
+
+Ext.extend(Ext.Component, Ext.util.Observable, {
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    disabled : false,
+    
+    hidden : false,
+    
+    
+    
+    
+    
+    
+    
+    autoEl : 'div',
+
+    
+    disabledClass : 'x-item-disabled',
+    
+    allowDomMove : true,
+    
+    autoShow : false,
+    
+    hideMode : 'display',
+    
+    hideParent : false,
+    
+    
+    
+    
+    
+    rendered : false,
+
+    
+    
+
+    
+
+    
+    tplWriteMode : 'overwrite',
+
+    
+    
+    
+    bubbleEvents: [],
+
+
+    
+    ctype : 'Ext.Component',
+
+    
+    actionMode : 'el',
+
+    
+    getActionEl : function(){
+        return this[this.actionMode];
+    },
+
+    initPlugin : function(p){
+        if(p.ptype && !Ext.isFunction(p.init)){
+            p = Ext.ComponentMgr.createPlugin(p);
+        }else if(Ext.isString(p)){
+            p = Ext.ComponentMgr.createPlugin({
+                ptype: p
+            });
+        }
+        p.init(this);
+        return p;
+    },
+
+    
+    initComponent : function(){
+        
+        if(this.listeners){
+            this.on(this.listeners);
+            delete this.listeners;
+        }
+        this.enableBubble(this.bubbleEvents);
+    },
+
+    
+    render : function(container, position){
+        if(!this.rendered && this.fireEvent('beforerender', this) !== false){
+            if(!container && this.el){
+                this.el = Ext.get(this.el);
+                container = this.el.dom.parentNode;
+                this.allowDomMove = false;
+            }
+            this.container = Ext.get(container);
+            if(this.ctCls){
+                this.container.addClass(this.ctCls);
+            }
+            this.rendered = true;
+            if(position !== undefined){
+                if(Ext.isNumber(position)){
+                    position = this.container.dom.childNodes[position];
+                }else{
+                    position = Ext.getDom(position);
+                }
+            }
+            this.onRender(this.container, position || null);
+            if(this.autoShow){
+                this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
+            }
+            if(this.cls){
+                this.el.addClass(this.cls);
+                delete this.cls;
+            }
+            if(this.style){
+                this.el.applyStyles(this.style);
+                delete this.style;
+            }
+            if(this.overCls){
+                this.el.addClassOnOver(this.overCls);
+            }
+            this.fireEvent('render', this);
+
+
+            
+            
+            var contentTarget = this.getContentTarget();
+            if (this.html){
+                contentTarget.update(Ext.DomHelper.markup(this.html));
+                delete this.html;
+            }
+            if (this.contentEl){
+                var ce = Ext.getDom(this.contentEl);
+                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
+                contentTarget.appendChild(ce);
+            }
+            if (this.tpl) {
+                if (!this.tpl.compile) {
+                    this.tpl = new Ext.XTemplate(this.tpl);
+                }
+                if (this.data) {
+                    this.tpl[this.tplWriteMode](contentTarget, this.data);
+                    delete this.data;
+                }
+            }
+            this.afterRender(this.container);
+
+
+            if(this.hidden){
+                
+                this.doHide();
+            }
+            if(this.disabled){
+                
+                this.disable(true);
+            }
+
+            if(this.stateful !== false){
+                this.initStateEvents();
+            }
+            this.fireEvent('afterrender', this);
+        }
+        return this;
+    },
+
+
+    
+    update: function(htmlOrData, loadScripts, cb) {
+        var contentTarget = this.getContentTarget();
+        if (this.tpl && typeof htmlOrData !== "string") {
+            this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
+        } else {
+            var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
+            contentTarget.update(html, loadScripts, cb);
+        }
+    },
+
+
+    
+    onAdded : function(container, pos) {
+        this.ownerCt = container;
+        this.initRef();
+        this.fireEvent('added', this, container, pos);
+    },
+
+    
+    onRemoved : function() {
+        this.removeRef();
+        this.fireEvent('removed', this, this.ownerCt);
+        delete this.ownerCt;
+    },
+
+    
+    initRef : function() {
+        
+        if(this.ref && !this.refOwner){
+            var levels = this.ref.split('/'),
+                last = levels.length,
+                i = 0,
+                t = this;
+
+            while(t && i < last){
+                t = t.ownerCt;
+                ++i;
+            }
+            if(t){
+                t[this.refName = levels[--i]] = this;
+                
+                this.refOwner = t;
+            }
+        }
+    },
+
+    removeRef : function() {
+        if (this.refOwner && this.refName) {
+            delete this.refOwner[this.refName];
+            delete this.refOwner;
+        }
+    },
+
+    
+    initState : function(){
+        if(Ext.state.Manager){
+            var id = this.getStateId();
+            if(id){
+                var state = Ext.state.Manager.get(id);
+                if(state){
+                    if(this.fireEvent('beforestaterestore', this, state) !== false){
+                        this.applyState(Ext.apply({}, state));
+                        this.fireEvent('staterestore', this, state);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    getStateId : function(){
+        return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
+    },
+
+    
+    initStateEvents : function(){
+        if(this.stateEvents){
+            for(var i = 0, e; e = this.stateEvents[i]; i++){
+                this.on(e, this.saveState, this, {delay:100});
+            }
+        }
+    },
+
+    
+    applyState : function(state){
+        if(state){
+            Ext.apply(this, state);
+        }
+    },
+
+    
+    getState : function(){
+        return null;
+    },
+
+    
+    saveState : function(){
+        if(Ext.state.Manager && this.stateful !== false){
+            var id = this.getStateId();
+            if(id){
+                var state = this.getState();
+                if(this.fireEvent('beforestatesave', this, state) !== false){
+                    Ext.state.Manager.set(id, state);
+                    this.fireEvent('statesave', this, state);
+                }
+            }
+        }
+    },
+
+    
+    applyToMarkup : function(el){
+        this.allowDomMove = false;
+        this.el = Ext.get(el);
+        this.render(this.el.dom.parentNode);
+    },
+
+    
+    addClass : function(cls){
+        if(this.el){
+            this.el.addClass(cls);
+        }else{
+            this.cls = this.cls ? this.cls + ' ' + cls : cls;
+        }
+        return this;
+    },
+
+    
+    removeClass : function(cls){
+        if(this.el){
+            this.el.removeClass(cls);
+        }else if(this.cls){
+            this.cls = this.cls.split(' ').remove(cls).join(' ');
+        }
+        return this;
+    },
+
+    
+    
+    onRender : function(ct, position){
+        if(!this.el && this.autoEl){
+            if(Ext.isString(this.autoEl)){
+                this.el = document.createElement(this.autoEl);
+            }else{
+                var div = document.createElement('div');
+                Ext.DomHelper.overwrite(div, this.autoEl);
+                this.el = div.firstChild;
+            }
+            if (!this.el.id) {
+                this.el.id = this.getId();
+            }
+        }
+        if(this.el){
+            this.el = Ext.get(this.el);
+            if(this.allowDomMove !== false){
+                ct.dom.insertBefore(this.el.dom, position);
+                if (div) {
+                    Ext.removeNode(div);
+                    div = null;
+                }
+            }
+        }
+    },
+
+    
+    getAutoCreate : function(){
+        var cfg = Ext.isObject(this.autoCreate) ?
+                      this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
+        if(this.id && !cfg.id){
+            cfg.id = this.id;
+        }
+        return cfg;
+    },
+
+    
+    afterRender : Ext.emptyFn,
+
+    
+    destroy : function(){
+        if(!this.isDestroyed){
+            if(this.fireEvent('beforedestroy', this) !== false){
+                this.destroying = true;
+                this.beforeDestroy();
+                if(this.ownerCt && this.ownerCt.remove){
+                    this.ownerCt.remove(this, false);
+                }
+                if(this.rendered){
+                    this.el.remove();
+                    if(this.actionMode == 'container' || this.removeMode == 'container'){
+                        this.container.remove();
+                    }
+                }
+                
+                if(this.focusTask && this.focusTask.cancel){
+                    this.focusTask.cancel();
+                }
+                this.onDestroy();
+                Ext.ComponentMgr.unregister(this);
+                this.fireEvent('destroy', this);
+                this.purgeListeners();
+                this.destroying = false;
+                this.isDestroyed = true;
+            }
+        }
+    },
+
+    deleteMembers : function(){
+        var args = arguments;
+        for(var i = 0, len = args.length; i < len; ++i){
+            delete this[args[i]];
+        }
+    },
+
+    
+    beforeDestroy : Ext.emptyFn,
+
+    
+    onDestroy  : Ext.emptyFn,
+
+    
+    getEl : function(){
+        return this.el;
+    },
+
+    
+    getContentTarget : function(){
+        return this.el;
+    },
+
+    
+    getId : function(){
+        return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
+    },
+
+    
+    getItemId : function(){
+        return this.itemId || this.getId();
+    },
+
+    
+    focus : function(selectText, delay){
+        if(delay){
+            this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
+            this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
+            return this;
+        }
+        if(this.rendered && !this.isDestroyed){
+            this.el.focus();
+            if(selectText === true){
+                this.el.dom.select();
+            }
+        }
+        return this;
+    },
+
+    
+    blur : function(){
+        if(this.rendered){
+            this.el.blur();
+        }
+        return this;
+    },
+
+    
+    disable : function( silent){
+        if(this.rendered){
+            this.onDisable();
+        }
+        this.disabled = true;
+        if(silent !== true){
+            this.fireEvent('disable', this);
+        }
+        return this;
+    },
+
+    
+    onDisable : function(){
+        this.getActionEl().addClass(this.disabledClass);
+        this.el.dom.disabled = true;
+    },
+
+    
+    enable : function(){
+        if(this.rendered){
+            this.onEnable();
+        }
+        this.disabled = false;
+        this.fireEvent('enable', this);
+        return this;
+    },
+
+    
+    onEnable : function(){
+        this.getActionEl().removeClass(this.disabledClass);
+        this.el.dom.disabled = false;
+    },
+
+    
+    setDisabled : function(disabled){
+        return this[disabled ? 'disable' : 'enable']();
+    },
+
+    
+    show : function(){
+        if(this.fireEvent('beforeshow', this) !== false){
+            this.hidden = false;
+            if(this.autoRender){
+                this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
+            }
+            if(this.rendered){
+                this.onShow();
+            }
+            this.fireEvent('show', this);
+        }
+        return this;
+    },
+
+    
+    onShow : function(){
+        this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
+    },
+
+    
+    hide : function(){
+        if(this.fireEvent('beforehide', this) !== false){
+            this.doHide();
+            this.fireEvent('hide', this);
+        }
+        return this;
+    },
+
+    
+    doHide: function(){
+        this.hidden = true;
+        if(this.rendered){
+            this.onHide();
+        }
+    },
+
+    
+    onHide : function(){
+        this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
+    },
+
+    
+    getVisibilityEl : function(){
+        return this.hideParent ? this.container : this.getActionEl();
+    },
+
+    
+    setVisible : function(visible){
+        return this[visible ? 'show' : 'hide']();
+    },
+
+    
+    isVisible : function(){
+        return this.rendered && this.getVisibilityEl().isVisible();
+    },
+
+    
+    cloneConfig : function(overrides){
+        overrides = overrides || {};
+        var id = overrides.id || Ext.id();
+        var cfg = Ext.applyIf(overrides, this.initialConfig);
+        cfg.id = id; 
+        return new this.constructor(cfg);
+    },
+
+    
+    getXType : function(){
+        return this.constructor.xtype;
+    },
+
+    
+    isXType : function(xtype, shallow){
+        
+        if (Ext.isFunction(xtype)){
+            xtype = xtype.xtype; 
+        }else if (Ext.isObject(xtype)){
+            xtype = xtype.constructor.xtype; 
+        }
+
+        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
+    },
+
+    
+    getXTypes : function(){
+        var tc = this.constructor;
+        if(!tc.xtypes){
+            var c = [], sc = this;
+            while(sc && sc.constructor.xtype){
+                c.unshift(sc.constructor.xtype);
+                sc = sc.constructor.superclass;
+            }
+            tc.xtypeChain = c;
+            tc.xtypes = c.join('/');
+        }
+        return tc.xtypes;
+    },
+
+    
+    findParentBy : function(fn) {
+        for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
+        return p || null;
+    },
+
+    
+    findParentByType : function(xtype, shallow){
+        return this.findParentBy(function(c){
+            return c.isXType(xtype, shallow);
+        });
+    },
+    
+    
+    bubble : function(fn, scope, args){
+        var p = this;
+        while(p){
+            if(fn.apply(scope || p, args || [p]) === false){
+                break;
+            }
+            p = p.ownerCt;
+        }
+        return this;
+    },
+
+    
+    getPositionEl : function(){
+        return this.positionEl || this.el;
+    },
+
+    
+    purgeListeners : function(){
+        Ext.Component.superclass.purgeListeners.call(this);
+        if(this.mons){
+            this.on('beforedestroy', this.clearMons, this, {single: true});
+        }
+    },
+
+    
+    clearMons : function(){
+        Ext.each(this.mons, function(m){
+            m.item.un(m.ename, m.fn, m.scope);
+        }, this);
+        this.mons = [];
+    },
+
+    
+    createMons: function(){
+        if(!this.mons){
+            this.mons = [];
+            this.on('beforedestroy', this.clearMons, this, {single: true});
+        }
+    },
+
+    
+    mon : function(item, ename, fn, scope, opt){
+        this.createMons();
+        if(Ext.isObject(ename)){
+            var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
+
+            var o = ename;
+            for(var e in o){
+                if(propRe.test(e)){
+                    continue;
+                }
+                if(Ext.isFunction(o[e])){
+                    
+                    this.mons.push({
+                        item: item, ename: e, fn: o[e], scope: o.scope
+                    });
+                    item.on(e, o[e], o.scope, o);
+                }else{
+                    
+                    this.mons.push({
+                        item: item, ename: e, fn: o[e], scope: o.scope
+                    });
+                    item.on(e, o[e]);
+                }
+            }
+            return;
+        }
+
+        this.mons.push({
+            item: item, ename: ename, fn: fn, scope: scope
+        });
+        item.on(ename, fn, scope, opt);
+    },
+
+    
+    mun : function(item, ename, fn, scope){
+        var found, mon;
+        this.createMons();
+        for(var i = 0, len = this.mons.length; i < len; ++i){
+            mon = this.mons[i];
+            if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
+                this.mons.splice(i, 1);
+                item.un(ename, fn, scope);
+                found = true;
+                break;
+            }
+        }
+        return found;
+    },
+
+    
+    nextSibling : function(){
+        if(this.ownerCt){
+            var index = this.ownerCt.items.indexOf(this);
+            if(index != -1 && index+1 < this.ownerCt.items.getCount()){
+                return this.ownerCt.items.itemAt(index+1);
+            }
+        }
+        return null;
+    },
+
+    
+    previousSibling : function(){
+        if(this.ownerCt){
+            var index = this.ownerCt.items.indexOf(this);
+            if(index > 0){
+                return this.ownerCt.items.itemAt(index-1);
+            }
+        }
+        return null;
+    },
+
+    
+    getBubbleTarget : function(){
+        return this.ownerCt;
+    }
+});
+
+Ext.reg('component', Ext.Component);
+
+Ext.Action = Ext.extend(Object, {
+    
+    
+    
+    
+    
+    
+    
+
+    constructor : function(config){
+        this.initialConfig = config;
+        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
+        this.items = [];
+    },
+    
+    
+    isAction : true,
+
+    
+    setText : function(text){
+        this.initialConfig.text = text;
+        this.callEach('setText', [text]);
+    },
+
+    
+    getText : function(){
+        return this.initialConfig.text;
+    },
+
+    
+    setIconClass : function(cls){
+        this.initialConfig.iconCls = cls;
+        this.callEach('setIconClass', [cls]);
+    },
+
+    
+    getIconClass : function(){
+        return this.initialConfig.iconCls;
+    },
+
+    
+    setDisabled : function(v){
+        this.initialConfig.disabled = v;
+        this.callEach('setDisabled', [v]);
+    },
+
+    
+    enable : function(){
+        this.setDisabled(false);
+    },
+
+    
+    disable : function(){
+        this.setDisabled(true);
+    },
+
+    
+    isDisabled : function(){
+        return this.initialConfig.disabled;
+    },
+
+    
+    setHidden : function(v){
+        this.initialConfig.hidden = v;
+        this.callEach('setVisible', [!v]);
+    },
+
+    
+    show : function(){
+        this.setHidden(false);
+    },
+
+    
+    hide : function(){
+        this.setHidden(true);
+    },
+
+    
+    isHidden : function(){
+        return this.initialConfig.hidden;
+    },
+
+    
+    setHandler : function(fn, scope){
+        this.initialConfig.handler = fn;
+        this.initialConfig.scope = scope;
+        this.callEach('setHandler', [fn, scope]);
+    },
+
+    
+    each : function(fn, scope){
+        Ext.each(this.items, fn, scope);
+    },
+
+    
+    callEach : function(fnName, args){
+        var cs = this.items;
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i][fnName].apply(cs[i], args);
+        }
+    },
+
+    
+    addComponent : function(comp){
+        this.items.push(comp);
+        comp.on('destroy', this.removeComponent, this);
+    },
+
+    
+    removeComponent : function(comp){
+        this.items.remove(comp);
+    },
+
+    
+    execute : function(){
+        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
+    }
+});
+
+(function(){
+Ext.Layer = function(config, existingEl){
+    config = config || {};
+    var dh = Ext.DomHelper,
+        cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
+        
+    if (existingEl) {
+        this.dom = Ext.getDom(existingEl);
+    }
+    if(!this.dom){
+        var o = config.dh || {tag: 'div', cls: 'x-layer'};
+        this.dom = dh.append(pel, o);
+    }
+    if(config.cls){
+        this.addClass(config.cls);
+    }
+    this.constrain = config.constrain !== false;
+    this.setVisibilityMode(Ext.Element.VISIBILITY);
+    if(config.id){
+        this.id = this.dom.id = config.id;
+    }else{
+        this.id = Ext.id(this.dom);
+    }
+    this.zindex = config.zindex || this.getZIndex();
+    this.position('absolute', this.zindex);
+    if(config.shadow){
+        this.shadowOffset = config.shadowOffset || 4;
+        this.shadow = new Ext.Shadow({
+            offset : this.shadowOffset,
+            mode : config.shadow
+        });
+    }else{
+        this.shadowOffset = 0;
+    }
+    this.useShim = config.shim !== false && Ext.useShims;
+    this.useDisplay = config.useDisplay;
+    this.hide();
+};
+
+var supr = Ext.Element.prototype;
+
+
+var shims = [];
+
+Ext.extend(Ext.Layer, Ext.Element, {
+
+    getZIndex : function(){
+        return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
+    },
+
+    getShim : function(){
+        if(!this.useShim){
+            return null;
+        }
+        if(this.shim){
+            return this.shim;
+        }
+        var shim = shims.shift();
+        if(!shim){
+            shim = this.createShim();
+            shim.enableDisplayMode('block');
+            shim.dom.style.display = 'none';
+            shim.dom.style.visibility = 'visible';
+        }
+        var pn = this.dom.parentNode;
+        if(shim.dom.parentNode != pn){
+            pn.insertBefore(shim.dom, this.dom);
+        }
+        shim.setStyle('z-index', this.getZIndex()-2);
+        this.shim = shim;
+        return shim;
+    },
+
+    hideShim : function(){
+        if(this.shim){
+            this.shim.setDisplayed(false);
+            shims.push(this.shim);
+            delete this.shim;
+        }
+    },
+
+    disableShadow : function(){
+        if(this.shadow){
+            this.shadowDisabled = true;
+            this.shadow.hide();
+            this.lastShadowOffset = this.shadowOffset;
+            this.shadowOffset = 0;
+        }
+    },
+
+    enableShadow : function(show){
+        if(this.shadow){
+            this.shadowDisabled = false;
+            if(Ext.isDefined(this.lastShadowOffset)) {
+                this.shadowOffset = this.lastShadowOffset;
+                delete this.lastShadowOffset;
+            }
+            if(show){
+                this.sync(true);
+            }
+        }
+    },
+
+    
+    
+    
+    sync : function(doShow){
+        var shadow = this.shadow;
+        if(!this.updating && this.isVisible() && (shadow || this.useShim)){
+            var shim = this.getShim(),
+                w = this.getWidth(),
+                h = this.getHeight(),
+                l = this.getLeft(true),
+                t = this.getTop(true);
+
+            if(shadow && !this.shadowDisabled){
+                if(doShow && !shadow.isVisible()){
+                    shadow.show(this);
+                }else{
+                    shadow.realign(l, t, w, h);
+                }
+                if(shim){
+                    if(doShow){
+                       shim.show();
+                    }
+                    
+                    var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
+                        shadowSize = shadow.el.getSize();
+                    shimStyle.left = (shadowAdj[0])+'px';
+                    shimStyle.top = (shadowAdj[1])+'px';
+                    shimStyle.width = (shadowSize.width)+'px';
+                    shimStyle.height = (shadowSize.height)+'px';
+                }
+            }else if(shim){
+                if(doShow){
+                   shim.show();
+                }
+                shim.setSize(w, h);
+                shim.setLeftTop(l, t);
+            }
+        }
+    },
+
+    
+    destroy : function(){
+        this.hideShim();
+        if(this.shadow){
+            this.shadow.hide();
+        }
+        this.removeAllListeners();
+        Ext.removeNode(this.dom);
+        delete this.dom;
+    },
+
+    remove : function(){
+        this.destroy();
+    },
+
+    
+    beginUpdate : function(){
+        this.updating = true;
+    },
+
+    
+    endUpdate : function(){
+        this.updating = false;
+        this.sync(true);
+    },
+
+    
+    hideUnders : function(negOffset){
+        if(this.shadow){
+            this.shadow.hide();
+        }
+        this.hideShim();
+    },
+
+    
+    constrainXY : function(){
+        if(this.constrain){
+            var vw = Ext.lib.Dom.getViewWidth(),
+                vh = Ext.lib.Dom.getViewHeight();
+            var s = Ext.getDoc().getScroll();
+
+            var xy = this.getXY();
+            var x = xy[0], y = xy[1];
+            var so = this.shadowOffset;
+            var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
+            
+            var moved = false;
+            
+            if((x + w) > vw+s.left){
+                x = vw - w - so;
+                moved = true;
+            }
+            if((y + h) > vh+s.top){
+                y = vh - h - so;
+                moved = true;
+            }
+            
+            if(x < s.left){
+                x = s.left;
+                moved = true;
+            }
+            if(y < s.top){
+                y = s.top;
+                moved = true;
+            }
+            if(moved){
+                if(this.avoidY){
+                    var ay = this.avoidY;
+                    if(y <= ay && (y+h) >= ay){
+                        y = ay-h-5;
+                    }
+                }
+                xy = [x, y];
+                this.storeXY(xy);
+                supr.setXY.call(this, xy);
+                this.sync();
+            }
+        }
+        return this;
+    },
+    
+    getConstrainOffset : function(){
+        return this.shadowOffset;    
+    },
+
+    isVisible : function(){
+        return this.visible;
+    },
+
+    
+    showAction : function(){
+        this.visible = true; 
+        if(this.useDisplay === true){
+            this.setDisplayed('');
+        }else if(this.lastXY){
+            supr.setXY.call(this, this.lastXY);
+        }else if(this.lastLT){
+            supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
+        }
+    },
+
+    
+    hideAction : function(){
+        this.visible = false;
+        if(this.useDisplay === true){
+            this.setDisplayed(false);
+        }else{
+            this.setLeftTop(-10000,-10000);
+        }
+    },
+
+    
+    setVisible : function(v, a, d, c, e){
+        if(v){
+            this.showAction();
+        }
+        if(a && v){
+            var cb = function(){
+                this.sync(true);
+                if(c){
+                    c();
+                }
+            }.createDelegate(this);
+            supr.setVisible.call(this, true, true, d, cb, e);
+        }else{
+            if(!v){
+                this.hideUnders(true);
+            }
+            var cb = c;
+            if(a){
+                cb = function(){
+                    this.hideAction();
+                    if(c){
+                        c();
+                    }
+                }.createDelegate(this);
+            }
+            supr.setVisible.call(this, v, a, d, cb, e);
+            if(v){
+                this.sync(true);
+            }else if(!a){
+                this.hideAction();
+            }
+        }
+        return this;
+    },
+
+    storeXY : function(xy){
+        delete this.lastLT;
+        this.lastXY = xy;
+    },
+
+    storeLeftTop : function(left, top){
+        delete this.lastXY;
+        this.lastLT = [left, top];
+    },
+
+    
+    beforeFx : function(){
+        this.beforeAction();
+        return Ext.Layer.superclass.beforeFx.apply(this, arguments);
+    },
+
+    
+    afterFx : function(){
+        Ext.Layer.superclass.afterFx.apply(this, arguments);
+        this.sync(this.isVisible());
+    },
+
+    
+    beforeAction : function(){
+        if(!this.updating && this.shadow){
+            this.shadow.hide();
+        }
+    },
+
+    
+    setLeft : function(left){
+        this.storeLeftTop(left, this.getTop(true));
+        supr.setLeft.apply(this, arguments);
+        this.sync();
+        return this;
+    },
+
+    setTop : function(top){
+        this.storeLeftTop(this.getLeft(true), top);
+        supr.setTop.apply(this, arguments);
+        this.sync();
+        return this;
+    },
+
+    setLeftTop : function(left, top){
+        this.storeLeftTop(left, top);
+        supr.setLeftTop.apply(this, arguments);
+        this.sync();
+        return this;
+    },
+
+    setXY : function(xy, a, d, c, e){
+        this.fixDisplay();
+        this.beforeAction();
+        this.storeXY(xy);
+        var cb = this.createCB(c);
+        supr.setXY.call(this, xy, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+        return this;
+    },
+
+    
+    createCB : function(c){
+        var el = this;
+        return function(){
+            el.constrainXY();
+            el.sync(true);
+            if(c){
+                c();
+            }
+        };
+    },
+
+    
+    setX : function(x, a, d, c, e){
+        this.setXY([x, this.getY()], a, d, c, e);
+        return this;
+    },
+
+    
+    setY : function(y, a, d, c, e){
+        this.setXY([this.getX(), y], a, d, c, e);
+        return this;
+    },
+
+    
+    setSize : function(w, h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setSize.call(this, w, h, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+        return this;
+    },
+
+    
+    setWidth : function(w, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setWidth.call(this, w, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+        return this;
+    },
+
+    
+    setHeight : function(h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setHeight.call(this, h, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+        return this;
+    },
+
+    
+    setBounds : function(x, y, w, h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        if(!a){
+            this.storeXY([x, y]);
+            supr.setXY.call(this, [x, y]);
+            supr.setSize.call(this, w, h, a, d, cb, e);
+            cb();
+        }else{
+            supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
+        }
+        return this;
+    },
+
+    
+    setZIndex : function(zindex){
+        this.zindex = zindex;
+        this.setStyle('z-index', zindex + 2);
+        if(this.shadow){
+            this.shadow.setZIndex(zindex + 1);
+        }
+        if(this.shim){
+            this.shim.setStyle('z-index', zindex);
+        }
+        return this;
+    }
+});
+})();
+
+Ext.Shadow = function(config) {
+    Ext.apply(this, config);
+    if (typeof this.mode != "string") {
+        this.mode = this.defaultMode;
+    }
+    var o = this.offset,
+        a = {
+            h: 0
+        },
+        rad = Math.floor(this.offset / 2);
+    switch (this.mode.toLowerCase()) {
+        
+        case "drop":
+            a.w = 0;
+            a.l = a.t = o;
+            a.t -= 1;
+            if (Ext.isIE) {
+                a.l -= this.offset + rad;
+                a.t -= this.offset + rad;
+                a.w -= rad;
+                a.h -= rad;
+                a.t += 1;
+            }
+        break;
+        case "sides":
+            a.w = (o * 2);
+            a.l = -o;
+            a.t = o - 1;
+            if (Ext.isIE) {
+                a.l -= (this.offset - rad);
+                a.t -= this.offset + rad;
+                a.l += 1;
+                a.w -= (this.offset - rad) * 2;
+                a.w -= rad + 1;
+                a.h -= 1;
+            }
+        break;
+        case "frame":
+            a.w = a.h = (o * 2);
+            a.l = a.t = -o;
+            a.t += 1;
+            a.h -= 2;
+            if (Ext.isIE) {
+                a.l -= (this.offset - rad);
+                a.t -= (this.offset - rad);
+                a.l += 1;
+                a.w -= (this.offset + rad + 1);
+                a.h -= (this.offset + rad);
+                a.h += 1;
+            }
+        break;
+    };
+
+    this.adjusts = a;
+};
+
+Ext.Shadow.prototype = {
+    
+    
+    offset: 4,
+
+    
+    defaultMode: "drop",
+
+    
+    show: function(target) {
+        target = Ext.get(target);
+        if (!this.el) {
+            this.el = Ext.Shadow.Pool.pull();
+            if (this.el.dom.nextSibling != target.dom) {
+                this.el.insertBefore(target);
+            }
+        }
+        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
+        if (Ext.isIE) {
+            this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
+        }
+        this.realign(
+        target.getLeft(true),
+        target.getTop(true),
+        target.getWidth(),
+        target.getHeight()
+        );
+        this.el.dom.style.display = "block";
+    },
+
+    
+    isVisible: function() {
+        return this.el ? true: false;
+    },
+
+    
+    realign: function(l, t, w, h) {
+        if (!this.el) {
+            return;
+        }
+        var a = this.adjusts,
+            d = this.el.dom,
+            s = d.style,
+            iea = 0,
+            sw = (w + a.w),
+            sh = (h + a.h),
+            sws = sw + "px",
+            shs = sh + "px",
+            cn,
+            sww;
+        s.left = (l + a.l) + "px";
+        s.top = (t + a.t) + "px";
+        if (s.width != sws || s.height != shs) {
+            s.width = sws;
+            s.height = shs;
+            if (!Ext.isIE) {
+                cn = d.childNodes;
+                sww = Math.max(0, (sw - 12)) + "px";
+                cn[0].childNodes[1].style.width = sww;
+                cn[1].childNodes[1].style.width = sww;
+                cn[2].childNodes[1].style.width = sww;
+                cn[1].style.height = Math.max(0, (sh - 12)) + "px";
+            }
+        }
+    },
+
+    
+    hide: function() {
+        if (this.el) {
+            this.el.dom.style.display = "none";
+            Ext.Shadow.Pool.push(this.el);
+            delete this.el;
+        }
+    },
+
+    
+    setZIndex: function(z) {
+        this.zIndex = z;
+        if (this.el) {
+            this.el.setStyle("z-index", z);
+        }
+    }
+};
+
+
+Ext.Shadow.Pool = function() {
+    var p = [],
+        markup = Ext.isIE ?
+            '<div class="x-ie-shadow"></div>':
+            '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
+    return {
+        pull: function() {
+            var sh = p.shift();
+            if (!sh) {
+                sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
+                sh.autoBoxAdjust = false;
+            }
+            return sh;
+        },
+
+        push: function(sh) {
+            p.push(sh);
+        }
+    };
+}();
+Ext.BoxComponent = Ext.extend(Ext.Component, {
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+
+    
+    initComponent : function(){
+        Ext.BoxComponent.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'resize',
+            
+            'move'
+        );
+    },
+
+    
+    boxReady : false,
+    
+    deferHeight: false,
+
+    
+    setSize : function(w, h){
+
+        
+        if(typeof w == 'object'){
+            h = w.height;
+            w = w.width;
+        }
+        if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
+            w = this.boxMinWidth;
+        }
+        if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
+            h = this.boxMinHeight;
+        }
+        if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
+            w = this.boxMaxWidth;
+        }
+        if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
+            h = this.boxMaxHeight;
+        }
+        
+        if(!this.boxReady){
+            this.width  = w;
+            this.height = h;
+            return this;
+        }
+
+        
+        if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
+            return this;
+        }
+        this.lastSize = {width: w, height: h};
+        var adj = this.adjustSize(w, h),
+            aw = adj.width,
+            ah = adj.height,
+            rz;
+        if(aw !== undefined || ah !== undefined){ 
+            rz = this.getResizeEl();
+            if(!this.deferHeight && aw !== undefined && ah !== undefined){
+                rz.setSize(aw, ah);
+            }else if(!this.deferHeight && ah !== undefined){
+                rz.setHeight(ah);
+            }else if(aw !== undefined){
+                rz.setWidth(aw);
+            }
+            this.onResize(aw, ah, w, h);
+            this.fireEvent('resize', this, aw, ah, w, h);
+        }
+        return this;
+    },
+
+    
+    setWidth : function(width){
+        return this.setSize(width);
+    },
+
+    
+    setHeight : function(height){
+        return this.setSize(undefined, height);
+    },
+
+    
+    getSize : function(){
+        return this.getResizeEl().getSize();
+    },
+
+    
+    getWidth : function(){
+        return this.getResizeEl().getWidth();
+    },
+
+    
+    getHeight : function(){
+        return this.getResizeEl().getHeight();
+    },
+
+    
+    getOuterSize : function(){
+        var el = this.getResizeEl();
+        return {width: el.getWidth() + el.getMargins('lr'),
+                height: el.getHeight() + el.getMargins('tb')};
+    },
+
+    
+    getPosition : function(local){
+        var el = this.getPositionEl();
+        if(local === true){
+            return [el.getLeft(true), el.getTop(true)];
+        }
+        return this.xy || el.getXY();
+    },
+
+    
+    getBox : function(local){
+        var pos = this.getPosition(local);
+        var s = this.getSize();
+        s.x = pos[0];
+        s.y = pos[1];
+        return s;
+    },
+
+    
+    updateBox : function(box){
+        this.setSize(box.width, box.height);
+        this.setPagePosition(box.x, box.y);
+        return this;
+    },
+
+    
+    getResizeEl : function(){
+        return this.resizeEl || this.el;
+    },
+
+    
+    setAutoScroll : function(scroll){
+        if(this.rendered){
+            this.getContentTarget().setOverflow(scroll ? 'auto' : '');
+        }
+        this.autoScroll = scroll;
+        return this;
+    },
+
+    
+    setPosition : function(x, y){
+        if(x && typeof x[1] == 'number'){
+            y = x[1];
+            x = x[0];
+        }
+        this.x = x;
+        this.y = y;
+        if(!this.boxReady){
+            return this;
+        }
+        var adj = this.adjustPosition(x, y);
+        var ax = adj.x, ay = adj.y;
+
+        var el = this.getPositionEl();
+        if(ax !== undefined || ay !== undefined){
+            if(ax !== undefined && ay !== undefined){
+                el.setLeftTop(ax, ay);
+            }else if(ax !== undefined){
+                el.setLeft(ax);
+            }else if(ay !== undefined){
+                el.setTop(ay);
+            }
+            this.onPosition(ax, ay);
+            this.fireEvent('move', this, ax, ay);
+        }
+        return this;
+    },
+
+    
+    setPagePosition : function(x, y){
+        if(x && typeof x[1] == 'number'){
+            y = x[1];
+            x = x[0];
+        }
+        this.pageX = x;
+        this.pageY = y;
+        if(!this.boxReady){
+            return;
+        }
+        if(x === undefined || y === undefined){ 
+            return;
+        }
+        var p = this.getPositionEl().translatePoints(x, y);
+        this.setPosition(p.left, p.top);
+        return this;
+    },
+
+    
+    afterRender : function(){
+        Ext.BoxComponent.superclass.afterRender.call(this);
+        if(this.resizeEl){
+            this.resizeEl = Ext.get(this.resizeEl);
+        }
+        if(this.positionEl){
+            this.positionEl = Ext.get(this.positionEl);
+        }
+        this.boxReady = true;
+        Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
+        this.setSize(this.width, this.height);
+        if(this.x || this.y){
+            this.setPosition(this.x, this.y);
+        }else if(this.pageX || this.pageY){
+            this.setPagePosition(this.pageX, this.pageY);
+        }
+    },
+
+    
+    syncSize : function(){
+        delete this.lastSize;
+        this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
+        return this;
+    },
+
+    
+    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
+    },
+
+    
+    onPosition : function(x, y){
+
+    },
+
+    
+    adjustSize : function(w, h){
+        if(this.autoWidth){
+            w = 'auto';
+        }
+        if(this.autoHeight){
+            h = 'auto';
+        }
+        return {width : w, height: h};
+    },
+
+    
+    adjustPosition : function(x, y){
+        return {x : x, y: y};
+    }
+});
+Ext.reg('box', Ext.BoxComponent);
+
+
+
+Ext.Spacer = Ext.extend(Ext.BoxComponent, {
+    autoEl:'div'
+});
+Ext.reg('spacer', Ext.Spacer);
+Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
+
+    
+    this.el = Ext.get(dragElement, true);
+    this.el.dom.unselectable = "on";
+    
+    this.resizingEl = Ext.get(resizingElement, true);
+
+    
+    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
+
+    
+    
+    this.minSize = 0;
+
+    
+    this.maxSize = 2000;
+
+    
+    this.animate = false;
+
+    
+    this.useShim = false;
+
+    
+    this.shim = null;
+
+    if(!existingProxy){
+        
+        this.proxy = Ext.SplitBar.createProxy(this.orientation);
+    }else{
+        this.proxy = Ext.get(existingProxy).dom;
+    }
+    
+    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
+
+    
+    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
+
+    
+    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
+
+    
+    this.dragSpecs = {};
+
+    
+    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
+    this.adapter.init(this);
+
+    if(this.orientation == Ext.SplitBar.HORIZONTAL){
+        
+        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
+        this.el.addClass("x-splitbar-h");
+    }else{
+        
+        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
+        this.el.addClass("x-splitbar-v");
+    }
+
+    this.addEvents(
+        
+        "resize",
+        
+        "moved",
+        
+        "beforeresize",
+
+        "beforeapply"
+    );
+
+    Ext.SplitBar.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.SplitBar, Ext.util.Observable, {
+    onStartProxyDrag : function(x, y){
+        this.fireEvent("beforeresize", this);
+        this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
+        this.overlay.unselectable();
+        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
+        this.overlay.show();
+        Ext.get(this.proxy).setDisplayed("block");
+        var size = this.adapter.getElementSize(this);
+        this.activeMinSize = this.getMinimumSize();
+        this.activeMaxSize = this.getMaximumSize();
+        var c1 = size - this.activeMinSize;
+        var c2 = Math.max(this.activeMaxSize - size, 0);
+        if(this.orientation == Ext.SplitBar.HORIZONTAL){
+            this.dd.resetConstraints();
+            this.dd.setXConstraint(
+                this.placement == Ext.SplitBar.LEFT ? c1 : c2,
+                this.placement == Ext.SplitBar.LEFT ? c2 : c1,
+                this.tickSize
+            );
+            this.dd.setYConstraint(0, 0);
+        }else{
+            this.dd.resetConstraints();
+            this.dd.setXConstraint(0, 0);
+            this.dd.setYConstraint(
+                this.placement == Ext.SplitBar.TOP ? c1 : c2,
+                this.placement == Ext.SplitBar.TOP ? c2 : c1,
+                this.tickSize
+            );
+         }
+        this.dragSpecs.startSize = size;
+        this.dragSpecs.startPoint = [x, y];
+        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
+    },
+
+    
+    onEndProxyDrag : function(e){
+        Ext.get(this.proxy).setDisplayed(false);
+        var endPoint = Ext.lib.Event.getXY(e);
+        if(this.overlay){
+            Ext.destroy(this.overlay);
+            delete this.overlay;
+        }
+        var newSize;
+        if(this.orientation == Ext.SplitBar.HORIZONTAL){
+            newSize = this.dragSpecs.startSize +
+                (this.placement == Ext.SplitBar.LEFT ?
+                    endPoint[0] - this.dragSpecs.startPoint[0] :
+                    this.dragSpecs.startPoint[0] - endPoint[0]
+                );
+        }else{
+            newSize = this.dragSpecs.startSize +
+                (this.placement == Ext.SplitBar.TOP ?
+                    endPoint[1] - this.dragSpecs.startPoint[1] :
+                    this.dragSpecs.startPoint[1] - endPoint[1]
+                );
+        }
+        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
+        if(newSize != this.dragSpecs.startSize){
+            if(this.fireEvent('beforeapply', this, newSize) !== false){
+                this.adapter.setElementSize(this, newSize);
+                this.fireEvent("moved", this, newSize);
+                this.fireEvent("resize", this, newSize);
+            }
+        }
+    },
+
+    
+    getAdapter : function(){
+        return this.adapter;
+    },
+
+    
+    setAdapter : function(adapter){
+        this.adapter = adapter;
+        this.adapter.init(this);
+    },
+
+    
+    getMinimumSize : function(){
+        return this.minSize;
+    },
+
+    
+    setMinimumSize : function(minSize){
+        this.minSize = minSize;
+    },
+
+    
+    getMaximumSize : function(){
+        return this.maxSize;
+    },
+
+    
+    setMaximumSize : function(maxSize){
+        this.maxSize = maxSize;
+    },
+
+    
+    setCurrentSize : function(size){
+        var oldAnimate = this.animate;
+        this.animate = false;
+        this.adapter.setElementSize(this, size);
+        this.animate = oldAnimate;
+    },
+
+    
+    destroy : function(removeEl){
+        Ext.destroy(this.shim, Ext.get(this.proxy));
+        this.dd.unreg();
+        if(removeEl){
+            this.el.remove();
+        }
+        this.purgeListeners();
+    }
+});
+
+
+Ext.SplitBar.createProxy = function(dir){
+    var proxy = new Ext.Element(document.createElement("div"));
+    document.body.appendChild(proxy.dom);
+    proxy.unselectable();
+    var cls = 'x-splitbar-proxy';
+    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
+    return proxy.dom;
+};
+
+
+Ext.SplitBar.BasicLayoutAdapter = function(){
+};
+
+Ext.SplitBar.BasicLayoutAdapter.prototype = {
+    
+    init : function(s){
+
+    },
+    
+     getElementSize : function(s){
+        if(s.orientation == Ext.SplitBar.HORIZONTAL){
+            return s.resizingEl.getWidth();
+        }else{
+            return s.resizingEl.getHeight();
+        }
+    },
+
+    
+    setElementSize : function(s, newSize, onComplete){
+        if(s.orientation == Ext.SplitBar.HORIZONTAL){
+            if(!s.animate){
+                s.resizingEl.setWidth(newSize);
+                if(onComplete){
+                    onComplete(s, newSize);
+                }
+            }else{
+                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
+            }
+        }else{
+
+            if(!s.animate){
+                s.resizingEl.setHeight(newSize);
+                if(onComplete){
+                    onComplete(s, newSize);
+                }
+            }else{
+                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
+            }
+        }
+    }
+};
+
+
+Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
+    this.basic = new Ext.SplitBar.BasicLayoutAdapter();
+    this.container = Ext.get(container);
+};
+
+Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
+    init : function(s){
+        this.basic.init(s);
+    },
+
+    getElementSize : function(s){
+        return this.basic.getElementSize(s);
+    },
+
+    setElementSize : function(s, newSize, onComplete){
+        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
+    },
+
+    moveSplitter : function(s){
+        var yes = Ext.SplitBar;
+        switch(s.placement){
+            case yes.LEFT:
+                s.el.setX(s.resizingEl.getRight());
+                break;
+            case yes.RIGHT:
+                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
+                break;
+            case yes.TOP:
+                s.el.setY(s.resizingEl.getBottom());
+                break;
+            case yes.BOTTOM:
+                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
+                break;
+        }
+    }
+};
+
+
+Ext.SplitBar.VERTICAL = 1;
+
+
+Ext.SplitBar.HORIZONTAL = 2;
+
+
+Ext.SplitBar.LEFT = 1;
+
+
+Ext.SplitBar.RIGHT = 2;
+
+
+Ext.SplitBar.TOP = 3;
+
+
+Ext.SplitBar.BOTTOM = 4;
+
+Ext.Container = Ext.extend(Ext.BoxComponent, {
+    
+    
+    
+    
+    bufferResize: 50,
+
+    
+    
+    
+
+
+    
+    autoDestroy : true,
+
+    
+    forceLayout: false,
+
+    
+    
+    defaultType : 'panel',
+
+    
+    resizeEvent: 'resize',
+
+    
+    bubbleEvents: ['add', 'remove'],
+
+    
+    initComponent : function(){
+        Ext.Container.superclass.initComponent.call(this);
+
+        this.addEvents(
+            
+            'afterlayout',
+            
+            'beforeadd',
+            
+            'beforeremove',
+            
+            'add',
+            
+            'remove'
+        );
+
+        
+        var items = this.items;
+        if(items){
+            delete this.items;
+            this.add(items);
+        }
+    },
+
+    
+    initItems : function(){
+        if(!this.items){
+            this.items = new Ext.util.MixedCollection(false, this.getComponentId);
+            this.getLayout(); 
+        }
+    },
+
+    
+    setLayout : function(layout){
+        if(this.layout && this.layout != layout){
+            this.layout.setContainer(null);
+        }
+        this.layout = layout;
+        this.initItems();
+        layout.setContainer(this);
+    },
+
+    afterRender: function(){
+        
+        
+        Ext.Container.superclass.afterRender.call(this);
+        if(!this.layout){
+            this.layout = 'auto';
+        }
+        if(Ext.isObject(this.layout) && !this.layout.layout){
+            this.layoutConfig = this.layout;
+            this.layout = this.layoutConfig.type;
+        }
+        if(Ext.isString(this.layout)){
+            this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
+        }
+        this.setLayout(this.layout);
+
+        
+        if(this.activeItem !== undefined && this.layout.setActiveItem){
+            var item = this.activeItem;
+            delete this.activeItem;
+            this.layout.setActiveItem(item);
+        }
+
+        
+        if(!this.ownerCt){
+            this.doLayout(false, true);
+        }
+
+        
+        
+        if(this.monitorResize === true){
+            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
+        }
+    },
+
+    
+    getLayoutTarget : function(){
+        return this.el;
+    },
+
+    
+    getComponentId : function(comp){
+        return comp.getItemId();
+    },
+
+    
+    add : function(comp){
+        this.initItems();
+        var args = arguments.length > 1;
+        if(args || Ext.isArray(comp)){
+            var result = [];
+            Ext.each(args ? arguments : comp, function(c){
+                result.push(this.add(c));
+            }, this);
+            return result;
+        }
+        var c = this.lookupComponent(this.applyDefaults(comp));
+        var index = this.items.length;
+        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
+            this.items.add(c);
+            
+            c.onAdded(this, index);
+            this.onAdd(c);
+            this.fireEvent('add', this, c, index);
+        }
+        return c;
+    },
+
+    onAdd : function(c){
+        
+    },
+
+    
+    onAdded : function(container, pos) {
+        
+        this.ownerCt = container;
+        this.initRef();
+        
+        this.cascade(function(c){
+            c.initRef();
+        });
+        this.fireEvent('added', this, container, pos);
+    },
+
+    
+    insert : function(index, comp) {
+        var args   = arguments,
+            length = args.length,
+            result = [],
+            i, c;
+        
+        this.initItems();
+        
+        if (length > 2) {
+            for (i = length - 1; i >= 1; --i) {
+                result.push(this.insert(index, args[i]));
+            }
+            return result;
+        }
+        
+        c = this.lookupComponent(this.applyDefaults(comp));
+        index = Math.min(index, this.items.length);
+        
+        if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
+            if (c.ownerCt == this) {
+                this.items.remove(c);
+            }
+            this.items.insert(index, c);
+            c.onAdded(this, index);
+            this.onAdd(c);
+            this.fireEvent('add', this, c, index);
+        }
+        
+        return c;
+    },
+
+    
+    applyDefaults : function(c){
+        var d = this.defaults;
+        if(d){
+            if(Ext.isFunction(d)){
+                d = d.call(this, c);
+            }
+            if(Ext.isString(c)){
+                c = Ext.ComponentMgr.get(c);
+                Ext.apply(c, d);
+            }else if(!c.events){
+                Ext.applyIf(c.isAction ? c.initialConfig : c, d);
+            }else{
+                Ext.apply(c, d);
+            }
+        }
+        return c;
+    },
+
+    
+    onBeforeAdd : function(item){
+        if(item.ownerCt){
+            item.ownerCt.remove(item, false);
+        }
+        if(this.hideBorders === true){
+            item.border = (item.border === true);
+        }
+    },
+
+    
+    remove : function(comp, autoDestroy){
+        this.initItems();
+        var c = this.getComponent(comp);
+        if(c && this.fireEvent('beforeremove', this, c) !== false){
+            this.doRemove(c, autoDestroy);
+            this.fireEvent('remove', this, c);
+        }
+        return c;
+    },
+
+    onRemove: function(c){
+        
+    },
+
+    
+    doRemove: function(c, autoDestroy){
+        var l = this.layout,
+            hasLayout = l && this.rendered;
+
+        if(hasLayout){
+            l.onRemove(c);
+        }
+        this.items.remove(c);
+        c.onRemoved();
+        this.onRemove(c);
+        if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
+            c.destroy();
+        }
+        if(hasLayout){
+            l.afterRemove(c);
+        }
+    },
+
+    
+    removeAll: function(autoDestroy){
+        this.initItems();
+        var item, rem = [], items = [];
+        this.items.each(function(i){
+            rem.push(i);
+        });
+        for (var i = 0, len = rem.length; i < len; ++i){
+            item = rem[i];
+            this.remove(item, autoDestroy);
+            if(item.ownerCt !== this){
+                items.push(item);
+            }
+        }
+        return items;
+    },
+
+    
+    getComponent : function(comp){
+        if(Ext.isObject(comp)){
+            comp = comp.getItemId();
+        }
+        return this.items.get(comp);
+    },
+
+    
+    lookupComponent : function(comp){
+        if(Ext.isString(comp)){
+            return Ext.ComponentMgr.get(comp);
+        }else if(!comp.events){
+            return this.createComponent(comp);
+        }
+        return comp;
+    },
+
+    
+    createComponent : function(config, defaultType){
+        if (config.render) {
+            return config;
+        }
+        
+        
+        var c = Ext.create(Ext.apply({
+            ownerCt: this
+        }, config), defaultType || this.defaultType);
+        delete c.initialConfig.ownerCt;
+        delete c.ownerCt;
+        return c;
+    },
+
+    
+    canLayout : function() {
+        var el = this.getVisibilityEl();
+        return el && el.dom && !el.isStyle("display", "none");
+    },
+
+    
+
+    doLayout : function(shallow, force){
+        var rendered = this.rendered,
+            forceLayout = force || this.forceLayout;
+
+        if(this.collapsed || !this.canLayout()){
+            this.deferLayout = this.deferLayout || !shallow;
+            if(!forceLayout){
+                return;
+            }
+            shallow = shallow && !this.deferLayout;
+        } else {
+            delete this.deferLayout;
+        }
+        if(rendered && this.layout){
+            this.layout.layout();
+        }
+        if(shallow !== true && this.items){
+            var cs = this.items.items;
+            for(var i = 0, len = cs.length; i < len; i++){
+                var c = cs[i];
+                if(c.doLayout){
+                    c.doLayout(false, forceLayout);
+                }
+            }
+        }
+        if(rendered){
+            this.onLayout(shallow, forceLayout);
+        }
+        
+        this.hasLayout = true;
+        delete this.forceLayout;
+    },
+
+    onLayout : Ext.emptyFn,
+
+    
+    shouldBufferLayout: function(){
+        
+        var hl = this.hasLayout;
+        if(this.ownerCt){
+            
+            return hl ? !this.hasLayoutPending() : false;
+        }
+        
+        return hl;
+    },
+
+    
+    hasLayoutPending: function(){
+        
+        var pending = false;
+        this.ownerCt.bubble(function(c){
+            if(c.layoutPending){
+                pending = true;
+                return false;
+            }
+        });
+        return pending;
+    },
+
+    onShow : function(){
+        
+        Ext.Container.superclass.onShow.call(this);
+        
+        if(Ext.isDefined(this.deferLayout)){
+            delete this.deferLayout;
+            this.doLayout(true);
+        }
+    },
+
+    
+    getLayout : function(){
+        if(!this.layout){
+            var layout = new Ext.layout.AutoLayout(this.layoutConfig);
+            this.setLayout(layout);
+        }
+        return this.layout;
+    },
+
+    
+    beforeDestroy : function(){
+        var c;
+        if(this.items){
+            while(c = this.items.first()){
+                this.doRemove(c, true);
+            }
+        }
+        if(this.monitorResize){
+            Ext.EventManager.removeResizeListener(this.doLayout, this);
+        }
+        Ext.destroy(this.layout);
+        Ext.Container.superclass.beforeDestroy.call(this);
+    },
+
+    
+    cascade : function(fn, scope, args){
+        if(fn.apply(scope || this, args || [this]) !== false){
+            if(this.items){
+                var cs = this.items.items;
+                for(var i = 0, len = cs.length; i < len; i++){
+                    if(cs[i].cascade){
+                        cs[i].cascade(fn, scope, args);
+                    }else{
+                        fn.apply(scope || cs[i], args || [cs[i]]);
+                    }
+                }
+            }
+        }
+        return this;
+    },
+
+    
+    findById : function(id){
+        var m = null, 
+            ct = this;
+        this.cascade(function(c){
+            if(ct != c && c.id === id){
+                m = c;
+                return false;
+            }
+        });
+        return m;
+    },
+
+    
+    findByType : function(xtype, shallow){
+        return this.findBy(function(c){
+            return c.isXType(xtype, shallow);
+        });
+    },
+
+    
+    find : function(prop, value){
+        return this.findBy(function(c){
+            return c[prop] === value;
+        });
+    },
+
+    
+    findBy : function(fn, scope){
+        var m = [], ct = this;
+        this.cascade(function(c){
+            if(ct != c && fn.call(scope || c, c, ct) === true){
+                m.push(c);
+            }
+        });
+        return m;
+    },
+
+    
+    get : function(key){
+        return this.getComponent(key);
+    }
+});
+
+Ext.Container.LAYOUTS = {};
+Ext.reg('container', Ext.Container);
+
+Ext.layout.ContainerLayout = Ext.extend(Object, {
+    
+    
+
+    
+
+    
+    monitorResize:false,
+    
+    activeItem : null,
+
+    constructor : function(config){
+        this.id = Ext.id(null, 'ext-layout-');
+        Ext.apply(this, config);
+    },
+
+    type: 'container',
+
+    
+    IEMeasureHack : function(target, viewFlag) {
+        var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
+        for (i = 0 ; i < tLen ; i++) {
+            c = tChildren[i];
+            e = Ext.get(c);
+            if (e) {
+                d[i] = e.getStyle('display');
+                e.setStyle({display: 'none'});
+            }
+        }
+        ret = target ? target.getViewSize(viewFlag) : {};
+        for (i = 0 ; i < tLen ; i++) {
+            c = tChildren[i];
+            e = Ext.get(c);
+            if (e) {
+                e.setStyle({display: d[i]});
+            }
+        }
+        return ret;
+    },
+
+    
+    getLayoutTargetSize : Ext.EmptyFn,
+
+    
+    layout : function(){
+        var ct = this.container, target = ct.getLayoutTarget();
+        if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
+            target.addClass(this.targetCls);
+        }
+        this.onLayout(ct, target);
+        ct.fireEvent('afterlayout', ct, this);
+    },
+
+    
+    onLayout : function(ct, target){
+        this.renderAll(ct, target);
+    },
+
+    
+    isValidParent : function(c, target){
+        return target && c.getPositionEl().dom.parentNode == (target.dom || target);
+    },
+
+    
+    renderAll : function(ct, target){
+        var items = ct.items.items, i, c, len = items.length;
+        for(i = 0; i < len; i++) {
+            c = items[i];
+            if(c && (!c.rendered || !this.isValidParent(c, target))){
+                this.renderItem(c, i, target);
+            }
+        }
+    },
+
+    
+    renderItem : function(c, position, target){
+        if (c) {
+            if (!c.rendered) {
+                c.render(target, position);
+                this.configureItem(c);
+            } else if (!this.isValidParent(c, target)) {
+                if (Ext.isNumber(position)) {
+                    position = target.dom.childNodes[position];
+                }
+                
+                target.dom.insertBefore(c.getPositionEl().dom, position || null);
+                c.container = target;
+                this.configureItem(c);
+            }
+        }
+    },
+
+    
+    
+    getRenderedItems: function(ct){
+        var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
+        for (i = 0; i < len; i++) {
+            if((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false){
+                items.push(c);
+            }
+        };
+        return items;
+    },
+
+    
+    configureItem: function(c){
+        if (this.extraCls) {
+            var t = c.getPositionEl ? c.getPositionEl() : c;
+            t.addClass(this.extraCls);
+        }
+        
+        
+        if (c.doLayout && this.forceLayout) {
+            c.doLayout();
+        }
+        if (this.renderHidden && c != this.activeItem) {
+            c.hide();
+        }
+    },
+
+    onRemove: function(c){
+        if(this.activeItem == c){
+            delete this.activeItem;
+        }
+        if(c.rendered && this.extraCls){
+            var t = c.getPositionEl ? c.getPositionEl() : c;
+            t.removeClass(this.extraCls);
+        }
+    },
+
+    afterRemove: function(c){
+        if(c.removeRestore){
+            c.removeMode = 'container';
+            delete c.removeRestore;
+        }
+    },
+
+    
+    onResize: function(){
+        var ct = this.container,
+            b;
+        if(ct.collapsed){
+            return;
+        }
+        if(b = ct.bufferResize && ct.shouldBufferLayout()){
+            if(!this.resizeTask){
+                this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
+                this.resizeBuffer = Ext.isNumber(b) ? b : 50;
+            }
+            ct.layoutPending = true;
+            this.resizeTask.delay(this.resizeBuffer);
+        }else{
+            this.runLayout();
+        }
+    },
+
+    runLayout: function(){
+        var ct = this.container;
+        this.layout();
+        ct.onLayout();
+        delete ct.layoutPending;
+    },
+
+    
+    setContainer : function(ct){
+        
+        if(this.monitorResize && ct != this.container){
+            var old = this.container;
+            if(old){
+                old.un(old.resizeEvent, this.onResize, this);
+            }
+            if(ct){
+                ct.on(ct.resizeEvent, this.onResize, this);
+            }
+        }
+        this.container = ct;
+    },
+
+    
+    parseMargins : function(v){
+        if (Ext.isNumber(v)) {
+            v = v.toString();
+        }
+        var ms  = v.split(' '),
+            len = ms.length;
+            
+        if (len == 1) {
+            ms[1] = ms[2] = ms[3] = ms[0];
+        } else if(len == 2) {
+            ms[2] = ms[0];
+            ms[3] = ms[1];
+        } else if(len == 3) {
+            ms[3] = ms[1];
+        }
+        
+        return {
+            top   :parseInt(ms[0], 10) || 0,
+            right :parseInt(ms[1], 10) || 0,
+            bottom:parseInt(ms[2], 10) || 0,
+            left  :parseInt(ms[3], 10) || 0
+        };
+    },
+
+    
+    fieldTpl: (function() {
+        var t = new Ext.Template(
+            '<div class="x-form-item {itemCls}" tabIndex="-1">',
+                '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
+                '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
+                '</div><div class="{clearCls}"></div>',
+            '</div>'
+        );
+        t.disableFormats = true;
+        return t.compile();
+    })(),
+
+    
+    destroy : function(){
+        
+        if(this.resizeTask && this.resizeTask.cancel){
+            this.resizeTask.cancel();
+        }
+        if(this.container) {
+            this.container.un(this.container.resizeEvent, this.onResize, this);
+        }
+        if(!Ext.isEmpty(this.targetCls)){
+            var target = this.container.getLayoutTarget();
+            if(target){
+                target.removeClass(this.targetCls);
+            }
+        }
+    }
+});
+Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    type: 'auto',
+
+    monitorResize: true,
+
+    onLayout : function(ct, target){
+        Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
+        var cs = this.getRenderedItems(ct), len = cs.length, i, c;
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            if (c.doLayout){
+                
+                c.doLayout(true);
+            }
+        }
+    }
+});
+
+Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
+
+Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+    monitorResize:true,
+
+    type: 'fit',
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget();
+        if (!target) {
+            return {};
+        }
+        
+        return target.getStyleSize();
+    },
+
+    
+    onLayout : function(ct, target){
+        Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
+        if(!ct.collapsed){
+            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
+        }
+    },
+
+    
+    setItemSize : function(item, size){
+        if(item && size.height > 0){ 
+            item.setSize(size);
+        }
+    }
+});
+Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
+Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
+    
+    deferredRender : false,
+
+    
+    layoutOnCardChange : false,
+
+    
+    
+    renderHidden : true,
+
+    type: 'card',
+
+    
+    setActiveItem : function(item){
+        var ai = this.activeItem,
+            ct = this.container;
+        item = ct.getComponent(item);
+
+        
+        if(item && ai != item){
+
+            
+            if(ai){
+                ai.hide();
+                if (ai.hidden !== true) {
+                    return false;
+                }
+                ai.fireEvent('deactivate', ai);
+            }
+
+            var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
+
+            
+            this.activeItem = item;
+
+            
+            
+            delete item.deferLayout;
+
+            
+            item.show();
+
+            this.layout();
+
+            if(layout){
+                item.doLayout();
+            }
+            item.fireEvent('activate', item);
+        }
+    },
+
+    
+    renderAll : function(ct, target){
+        if(this.deferredRender){
+            this.renderItem(this.activeItem, undefined, target);
+        }else{
+            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
+        }
+    }
+});
+Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
+
+Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+
+    
+    monitorResize : true,
+
+    type : 'anchor',
+
+    
+    defaultAnchor : '100%',
+
+    parseAnchorRE : /^(r|right|b|bottom)$/i,
+
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget(), ret = {};
+        if (target) {
+            ret = target.getViewSize();
+
+            
+            
+            
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        return ret;
+    },
+
+    
+    onLayout : function(container, target) {
+        Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
+
+        var size = this.getLayoutTargetSize(),
+            containerWidth = size.width,
+            containerHeight = size.height,
+            overflow = target.getStyle('overflow'),
+            components = this.getRenderedItems(container),
+            len = components.length,
+            boxes = [],
+            box,
+            anchorWidth,
+            anchorHeight,
+            component,
+            anchorSpec,
+            calcWidth,
+            calcHeight,
+            anchorsArray,
+            totalHeight = 0,
+            i,
+            el;
+
+        if(containerWidth < 20 && containerHeight < 20){
+            return;
+        }
+
+        
+        if(container.anchorSize) {
+            if(typeof container.anchorSize == 'number') {
+                anchorWidth = container.anchorSize;
+            } else {
+                anchorWidth = container.anchorSize.width;
+                anchorHeight = container.anchorSize.height;
+            }
+        } else {
+            anchorWidth = container.initialConfig.width;
+            anchorHeight = container.initialConfig.height;
+        }
+
+        for(i = 0; i < len; i++) {
+            component = components[i];
+            el = component.getPositionEl();
+
+            
+            if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
+                component.anchor = this.defaultAnchor;
+            }
+
+            if(component.anchor) {
+                anchorSpec = component.anchorSpec;
+                
+                if(!anchorSpec){
+                    anchorsArray = component.anchor.split(' ');
+                    component.anchorSpec = anchorSpec = {
+                        right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
+                        bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
+                    };
+                }
+                calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
+                calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
+
+                if(calcWidth || calcHeight) {
+                    boxes.push({
+                        component: component,
+                        width: calcWidth || undefined,
+                        height: calcHeight || undefined
+                    });
+                }
+            }
+        }
+        for (i = 0, len = boxes.length; i < len; i++) {
+            box = boxes[i];
+            box.component.setSize(box.width, box.height);
+        }
+
+        if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
+            var newTargetSize = this.getLayoutTargetSize();
+            if (newTargetSize.width != size.width || newTargetSize.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(container, target);
+            }
+        }
+
+        delete this.adjustmentPass;
+    },
+
+    
+    parseAnchor : function(a, start, cstart) {
+        if (a && a != 'none') {
+            var last;
+            
+            if (this.parseAnchorRE.test(a)) {
+                var diff = cstart - start;
+                return function(v){
+                    if(v !== last){
+                        last = v;
+                        return v - diff;
+                    }
+                };
+            
+            } else if(a.indexOf('%') != -1) {
+                var ratio = parseFloat(a.replace('%', ''))*.01;
+                return function(v){
+                    if(v !== last){
+                        last = v;
+                        return Math.floor(v*ratio);
+                    }
+                };
+            
+            } else {
+                a = parseInt(a, 10);
+                if (!isNaN(a)) {
+                    return function(v) {
+                        if (v !== last) {
+                            last = v;
+                            return v + a;
+                        }
+                    };
+                }
+            }
+        }
+        return false;
+    },
+
+    
+    adjustWidthAnchor : function(value, comp){
+        return value;
+    },
+
+    
+    adjustHeightAnchor : function(value, comp){
+        return value;
+    }
+
+    
+});
+Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
+
+Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+    monitorResize:true,
+
+    type: 'column',
+
+    extraCls: 'x-column',
+
+    scrollOffset : 0,
+
+    
+
+    targetCls: 'x-column-layout-ct',
+
+    isValidParent : function(c, target){
+        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
+    },
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget(), ret;
+        if (target) {
+            ret = target.getViewSize();
+
+            
+            
+            
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        return ret;
+    },
+
+    renderAll : function(ct, target) {
+        if(!this.innerCt){
+            
+            
+            this.innerCt = target.createChild({cls:'x-column-inner'});
+            this.innerCt.createChild({cls:'x-clear'});
+        }
+        Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
+    },
+
+    
+    onLayout : function(ct, target){
+        var cs = ct.items.items,
+            len = cs.length,
+            c,
+            i,
+            m,
+            margins = [];
+
+        this.renderAll(ct, target);
+
+        var size = this.getLayoutTargetSize();
+
+        if(size.width < 1 && size.height < 1){ 
+            return;
+        }
+
+        var w = size.width - this.scrollOffset,
+            h = size.height,
+            pw = w;
+
+        this.innerCt.setWidth(w);
+
+        
+        
+
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            m = c.getPositionEl().getMargins('lr');
+            margins[i] = m;
+            if(!c.columnWidth){
+                pw -= (c.getWidth() + m);
+            }
+        }
+
+        pw = pw < 0 ? 0 : pw;
+
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            m = margins[i];
+            if(c.columnWidth){
+                c.setSize(Math.floor(c.columnWidth * pw) - m);
+            }
+        }
+
+        
+        
+        if (Ext.isIE) {
+            if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+                var ts = this.getLayoutTargetSize();
+                if (ts.width != size.width){
+                    this.adjustmentPass = true;
+                    this.onLayout(ct, target);
+                }
+            }
+        }
+        delete this.adjustmentPass;
+    }
+
+    
+});
+
+Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
+
+Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+    monitorResize:true,
+    
+    rendered : false,
+
+    type: 'border',
+
+    targetCls: 'x-border-layout-ct',
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget();
+        return target ? target.getViewSize() : {};
+    },
+
+    
+    onLayout : function(ct, target){
+        var collapsed, i, c, pos, items = ct.items.items, len = items.length;
+        if(!this.rendered){
+            collapsed = [];
+            for(i = 0; i < len; i++) {
+                c = items[i];
+                pos = c.region;
+                if(c.collapsed){
+                    collapsed.push(c);
+                }
+                c.collapsed = false;
+                if(!c.rendered){
+                    c.render(target, i);
+                    c.getPositionEl().addClass('x-border-panel');
+                }
+                this[pos] = pos != 'center' && c.split ?
+                    new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
+                    new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
+                this[pos].render(target, c);
+            }
+            this.rendered = true;
+        }
+
+        var size = this.getLayoutTargetSize();
+        if(size.width < 20 || size.height < 20){ 
+            if(collapsed){
+                this.restoreCollapsed = collapsed;
+            }
+            return;
+        }else if(this.restoreCollapsed){
+            collapsed = this.restoreCollapsed;
+            delete this.restoreCollapsed;
+        }
+
+        var w = size.width, h = size.height,
+            centerW = w, centerH = h, centerY = 0, centerX = 0,
+            n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
+            b, m, totalWidth, totalHeight;
+        if(!c && Ext.layout.BorderLayout.WARN !== false){
+            throw 'No center region defined in BorderLayout ' + ct.id;
+        }
+
+        if(n && n.isVisible()){
+            b = n.getSize();
+            m = n.getMargins();
+            b.width = w - (m.left+m.right);
+            b.x = m.left;
+            b.y = m.top;
+            centerY = b.height + b.y + m.bottom;
+            centerH -= centerY;
+            n.applyLayout(b);
+        }
+        if(s && s.isVisible()){
+            b = s.getSize();
+            m = s.getMargins();
+            b.width = w - (m.left+m.right);
+            b.x = m.left;
+            totalHeight = (b.height + m.top + m.bottom);
+            b.y = h - totalHeight + m.top;
+            centerH -= totalHeight;
+            s.applyLayout(b);
+        }
+        if(west && west.isVisible()){
+            b = west.getSize();
+            m = west.getMargins();
+            b.height = centerH - (m.top+m.bottom);
+            b.x = m.left;
+            b.y = centerY + m.top;
+            totalWidth = (b.width + m.left + m.right);
+            centerX += totalWidth;
+            centerW -= totalWidth;
+            west.applyLayout(b);
+        }
+        if(e && e.isVisible()){
+            b = e.getSize();
+            m = e.getMargins();
+            b.height = centerH - (m.top+m.bottom);
+            totalWidth = (b.width + m.left + m.right);
+            b.x = w - totalWidth + m.left;
+            b.y = centerY + m.top;
+            centerW -= totalWidth;
+            e.applyLayout(b);
+        }
+        if(c){
+            m = c.getMargins();
+            var centerBox = {
+                x: centerX + m.left,
+                y: centerY + m.top,
+                width: centerW - (m.left+m.right),
+                height: centerH - (m.top+m.bottom)
+            };
+            c.applyLayout(centerBox);
+        }
+        if(collapsed){
+            for(i = 0, len = collapsed.length; i < len; i++){
+                collapsed[i].collapse(false);
+            }
+        }
+        if(Ext.isIE && Ext.isStrict){ 
+            target.repaint();
+        }
+        
+        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+            var ts = this.getLayoutTargetSize();
+            if (ts.width != size.width || ts.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(ct, target);
+            }
+        }
+        delete this.adjustmentPass;
+    },
+
+    destroy: function() {
+        var r = ['north', 'south', 'east', 'west'], i, region;
+        for (i = 0; i < r.length; i++) {
+            region = this[r[i]];
+            if(region){
+                if(region.destroy){
+                    region.destroy();
+                }else if (region.split){
+                    region.split.destroy(true);
+                }
+            }
+        }
+        Ext.layout.BorderLayout.superclass.destroy.call(this);
+    }
+
+    
+});
+
+
+Ext.layout.BorderLayout.Region = function(layout, config, pos){
+    Ext.apply(this, config);
+    this.layout = layout;
+    this.position = pos;
+    this.state = {};
+    if(typeof this.margins == 'string'){
+        this.margins = this.layout.parseMargins(this.margins);
+    }
+    this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
+    if(this.collapsible){
+        if(typeof this.cmargins == 'string'){
+            this.cmargins = this.layout.parseMargins(this.cmargins);
+        }
+        if(this.collapseMode == 'mini' && !this.cmargins){
+            this.cmargins = {left:0,top:0,right:0,bottom:0};
+        }else{
+            this.cmargins = Ext.applyIf(this.cmargins || {},
+                pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
+        }
+    }
+};
+
+Ext.layout.BorderLayout.Region.prototype = {
+    
+    
+    
+    
+    
+    
+    collapsible : false,
+    
+    split:false,
+    
+    floatable: true,
+    
+    minWidth:50,
+    
+    minHeight:50,
+
+    
+    defaultMargins : {left:0,top:0,right:0,bottom:0},
+    
+    defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
+    
+    defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
+    floatingZIndex: 100,
+
+    
+    isCollapsed : false,
+
+    
+    
+    
+
+    
+    render : function(ct, p){
+        this.panel = p;
+        p.el.enableDisplayMode();
+        this.targetEl = ct;
+        this.el = p.el;
+
+        var gs = p.getState, ps = this.position;
+        p.getState = function(){
+            return Ext.apply(gs.call(p) || {}, this.state);
+        }.createDelegate(this);
+
+        if(ps != 'center'){
+            p.allowQueuedExpand = false;
+            p.on({
+                beforecollapse: this.beforeCollapse,
+                collapse: this.onCollapse,
+                beforeexpand: this.beforeExpand,
+                expand: this.onExpand,
+                hide: this.onHide,
+                show: this.onShow,
+                scope: this
+            });
+            if(this.collapsible || this.floatable){
+                p.collapseEl = 'el';
+                p.slideAnchor = this.getSlideAnchor();
+            }
+            if(p.tools && p.tools.toggle){
+                p.tools.toggle.addClass('x-tool-collapse-'+ps);
+                p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
+            }
+        }
+    },
+
+    
+    getCollapsedEl : function(){
+        if(!this.collapsedEl){
+            if(!this.toolTemplate){
+                var tt = new Ext.Template(
+                     '<div class="x-tool x-tool-{id}">&#160;</div>'
+                );
+                tt.disableFormats = true;
+                tt.compile();
+                Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
+            }
+            this.collapsedEl = this.targetEl.createChild({
+                cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
+                id: this.panel.id + '-xcollapsed'
+            });
+            this.collapsedEl.enableDisplayMode('block');
+
+            if(this.collapseMode == 'mini'){
+                this.collapsedEl.addClass('x-layout-cmini-'+this.position);
+                this.miniCollapsedEl = this.collapsedEl.createChild({
+                    cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
+                });
+                this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
+                this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
+                this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
+            }else {
+                if(this.collapsible !== false && !this.hideCollapseTool) {
+                    var t = this.expandToolEl = this.toolTemplate.append(
+                            this.collapsedEl.dom,
+                            {id:'expand-'+this.position}, true);
+                    t.addClassOnOver('x-tool-expand-'+this.position+'-over');
+                    t.on('click', this.onExpandClick, this, {stopEvent:true});
+                }
+                if(this.floatable !== false || this.titleCollapse){
+                   this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
+                   this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
+                }
+            }
+        }
+        return this.collapsedEl;
+    },
+
+    
+    onExpandClick : function(e){
+        if(this.isSlid){
+            this.panel.expand(false);
+        }else{
+            this.panel.expand();
+        }
+    },
+
+    
+    onCollapseClick : function(e){
+        this.panel.collapse();
+    },
+
+    
+    beforeCollapse : function(p, animate){
+        this.lastAnim = animate;
+        if(this.splitEl){
+            this.splitEl.hide();
+        }
+        this.getCollapsedEl().show();
+        var el = this.panel.getEl();
+        this.originalZIndex = el.getStyle('z-index');
+        el.setStyle('z-index', 100);
+        this.isCollapsed = true;
+        this.layout.layout();
+    },
+
+    
+    onCollapse : function(animate){
+        this.panel.el.setStyle('z-index', 1);
+        if(this.lastAnim === false || this.panel.animCollapse === false){
+            this.getCollapsedEl().dom.style.visibility = 'visible';
+        }else{
+            this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
+        }
+        this.state.collapsed = true;
+        this.panel.saveState();
+    },
+
+    
+    beforeExpand : function(animate){
+        if(this.isSlid){
+            this.afterSlideIn();
+        }
+        var c = this.getCollapsedEl();
+        this.el.show();
+        if(this.position == 'east' || this.position == 'west'){
+            this.panel.setSize(undefined, c.getHeight());
+        }else{
+            this.panel.setSize(c.getWidth(), undefined);
+        }
+        c.hide();
+        c.dom.style.visibility = 'hidden';
+        this.panel.el.setStyle('z-index', this.floatingZIndex);
+    },
+
+    
+    onExpand : function(){
+        this.isCollapsed = false;
+        if(this.splitEl){
+            this.splitEl.show();
+        }
+        this.layout.layout();
+        this.panel.el.setStyle('z-index', this.originalZIndex);
+        this.state.collapsed = false;
+        this.panel.saveState();
+    },
+
+    
+    collapseClick : function(e){
+        if(this.isSlid){
+           e.stopPropagation();
+           this.slideIn();
+        }else{
+           e.stopPropagation();
+           this.slideOut();
+        }
+    },
+
+    
+    onHide : function(){
+        if(this.isCollapsed){
+            this.getCollapsedEl().hide();
+        }else if(this.splitEl){
+            this.splitEl.hide();
+        }
+    },
+
+    
+    onShow : function(){
+        if(this.isCollapsed){
+            this.getCollapsedEl().show();
+        }else if(this.splitEl){
+            this.splitEl.show();
+        }
+    },
+
+    
+    isVisible : function(){
+        return !this.panel.hidden;
+    },
+
+    
+    getMargins : function(){
+        return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
+    },
+
+    
+    getSize : function(){
+        return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
+    },
+
+    
+    setPanel : function(panel){
+        this.panel = panel;
+    },
+
+    
+    getMinWidth: function(){
+        return this.minWidth;
+    },
+
+    
+    getMinHeight: function(){
+        return this.minHeight;
+    },
+
+    
+    applyLayoutCollapsed : function(box){
+        var ce = this.getCollapsedEl();
+        ce.setLeftTop(box.x, box.y);
+        ce.setSize(box.width, box.height);
+    },
+
+    
+    applyLayout : function(box){
+        if(this.isCollapsed){
+            this.applyLayoutCollapsed(box);
+        }else{
+            this.panel.setPosition(box.x, box.y);
+            this.panel.setSize(box.width, box.height);
+        }
+    },
+
+    
+    beforeSlide: function(){
+        this.panel.beforeEffect();
+    },
+
+    
+    afterSlide : function(){
+        this.panel.afterEffect();
+    },
+
+    
+    initAutoHide : function(){
+        if(this.autoHide !== false){
+            if(!this.autoHideHd){
+                this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
+                this.autoHideHd = {
+                    "mouseout": function(e){
+                        if(!e.within(this.el, true)){
+                            this.autoHideSlideTask.delay(500);
+                        }
+                    },
+                    "mouseover" : function(e){
+                        this.autoHideSlideTask.cancel();
+                    },
+                    scope : this
+                };
+            }
+            this.el.on(this.autoHideHd);
+            this.collapsedEl.on(this.autoHideHd);
+        }
+    },
+
+    
+    clearAutoHide : function(){
+        if(this.autoHide !== false){
+            this.el.un("mouseout", this.autoHideHd.mouseout);
+            this.el.un("mouseover", this.autoHideHd.mouseover);
+            this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
+            this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
+        }
+    },
+
+    
+    clearMonitor : function(){
+        Ext.getDoc().un("click", this.slideInIf, this);
+    },
+
+    
+    slideOut : function(){
+        if(this.isSlid || this.el.hasActiveFx()){
+            return;
+        }
+        this.isSlid = true;
+        var ts = this.panel.tools, dh, pc;
+        if(ts && ts.toggle){
+            ts.toggle.hide();
+        }
+        this.el.show();
+
+        
+        pc = this.panel.collapsed;
+        this.panel.collapsed = false;
+
+        if(this.position == 'east' || this.position == 'west'){
+            
+            dh = this.panel.deferHeight;
+            this.panel.deferHeight = false;
+
+            this.panel.setSize(undefined, this.collapsedEl.getHeight());
+
+            
+            this.panel.deferHeight = dh;
+        }else{
+            this.panel.setSize(this.collapsedEl.getWidth(), undefined);
+        }
+
+        
+        this.panel.collapsed = pc;
+
+        this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
+        this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
+        this.el.setStyle("z-index", this.floatingZIndex+2);
+        this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
+        if(this.animFloat !== false){
+            this.beforeSlide();
+            this.el.slideIn(this.getSlideAnchor(), {
+                callback: function(){
+                    this.afterSlide();
+                    this.initAutoHide();
+                    Ext.getDoc().on("click", this.slideInIf, this);
+                },
+                scope: this,
+                block: true
+            });
+        }else{
+            this.initAutoHide();
+             Ext.getDoc().on("click", this.slideInIf, this);
+        }
+    },
+
+    
+    afterSlideIn : function(){
+        this.clearAutoHide();
+        this.isSlid = false;
+        this.clearMonitor();
+        this.el.setStyle("z-index", "");
+        this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
+        this.el.dom.style.left = this.restoreLT[0];
+        this.el.dom.style.top = this.restoreLT[1];
+
+        var ts = this.panel.tools;
+        if(ts && ts.toggle){
+            ts.toggle.show();
+        }
+    },
+
+    
+    slideIn : function(cb){
+        if(!this.isSlid || this.el.hasActiveFx()){
+            Ext.callback(cb);
+            return;
+        }
+        this.isSlid = false;
+        if(this.animFloat !== false){
+            this.beforeSlide();
+            this.el.slideOut(this.getSlideAnchor(), {
+                callback: function(){
+                    this.el.hide();
+                    this.afterSlide();
+                    this.afterSlideIn();
+                    Ext.callback(cb);
+                },
+                scope: this,
+                block: true
+            });
+        }else{
+            this.el.hide();
+            this.afterSlideIn();
+        }
+    },
+
+    
+    slideInIf : function(e){
+        if(!e.within(this.el)){
+            this.slideIn();
+        }
+    },
+
+    
+    anchors : {
+        "west" : "left",
+        "east" : "right",
+        "north" : "top",
+        "south" : "bottom"
+    },
+
+    
+    sanchors : {
+        "west" : "l",
+        "east" : "r",
+        "north" : "t",
+        "south" : "b"
+    },
+
+    
+    canchors : {
+        "west" : "tl-tr",
+        "east" : "tr-tl",
+        "north" : "tl-bl",
+        "south" : "bl-tl"
+    },
+
+    
+    getAnchor : function(){
+        return this.anchors[this.position];
+    },
+
+    
+    getCollapseAnchor : function(){
+        return this.canchors[this.position];
+    },
+
+    
+    getSlideAnchor : function(){
+        return this.sanchors[this.position];
+    },
+
+    
+    getAlignAdj : function(){
+        var cm = this.cmargins;
+        switch(this.position){
+            case "west":
+                return [0, 0];
+            break;
+            case "east":
+                return [0, 0];
+            break;
+            case "north":
+                return [0, 0];
+            break;
+            case "south":
+                return [0, 0];
+            break;
+        }
+    },
+
+    
+    getExpandAdj : function(){
+        var c = this.collapsedEl, cm = this.cmargins;
+        switch(this.position){
+            case "west":
+                return [-(cm.right+c.getWidth()+cm.left), 0];
+            break;
+            case "east":
+                return [cm.right+c.getWidth()+cm.left, 0];
+            break;
+            case "north":
+                return [0, -(cm.top+cm.bottom+c.getHeight())];
+            break;
+            case "south":
+                return [0, cm.top+cm.bottom+c.getHeight()];
+            break;
+        }
+    },
+
+    destroy : function(){
+        if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
+            this.autoHideSlideTask.cancel();
+        }
+        Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
+    }
+};
+
+
+Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
+    Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
+    
+    this.applyLayout = this.applyFns[pos];
+};
+
+Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
+    
+    
+    splitTip : "Drag to resize.",
+    
+    collapsibleSplitTip : "Drag to resize. Double click to hide.",
+    
+    useSplitTips : false,
+
+    
+    splitSettings : {
+        north : {
+            orientation: Ext.SplitBar.VERTICAL,
+            placement: Ext.SplitBar.TOP,
+            maxFn : 'getVMaxSize',
+            minProp: 'minHeight',
+            maxProp: 'maxHeight'
+        },
+        south : {
+            orientation: Ext.SplitBar.VERTICAL,
+            placement: Ext.SplitBar.BOTTOM,
+            maxFn : 'getVMaxSize',
+            minProp: 'minHeight',
+            maxProp: 'maxHeight'
+        },
+        east : {
+            orientation: Ext.SplitBar.HORIZONTAL,
+            placement: Ext.SplitBar.RIGHT,
+            maxFn : 'getHMaxSize',
+            minProp: 'minWidth',
+            maxProp: 'maxWidth'
+        },
+        west : {
+            orientation: Ext.SplitBar.HORIZONTAL,
+            placement: Ext.SplitBar.LEFT,
+            maxFn : 'getHMaxSize',
+            minProp: 'minWidth',
+            maxProp: 'maxWidth'
+        }
+    },
+
+    
+    applyFns : {
+        west : function(box){
+            if(this.isCollapsed){
+                return this.applyLayoutCollapsed(box);
+            }
+            var sd = this.splitEl.dom, s = sd.style;
+            this.panel.setPosition(box.x, box.y);
+            var sw = sd.offsetWidth;
+            s.left = (box.x+box.width-sw)+'px';
+            s.top = (box.y)+'px';
+            s.height = Math.max(0, box.height)+'px';
+            this.panel.setSize(box.width-sw, box.height);
+        },
+        east : function(box){
+            if(this.isCollapsed){
+                return this.applyLayoutCollapsed(box);
+            }
+            var sd = this.splitEl.dom, s = sd.style;
+            var sw = sd.offsetWidth;
+            this.panel.setPosition(box.x+sw, box.y);
+            s.left = (box.x)+'px';
+            s.top = (box.y)+'px';
+            s.height = Math.max(0, box.height)+'px';
+            this.panel.setSize(box.width-sw, box.height);
+        },
+        north : function(box){
+            if(this.isCollapsed){
+                return this.applyLayoutCollapsed(box);
+            }
+            var sd = this.splitEl.dom, s = sd.style;
+            var sh = sd.offsetHeight;
+            this.panel.setPosition(box.x, box.y);
+            s.left = (box.x)+'px';
+            s.top = (box.y+box.height-sh)+'px';
+            s.width = Math.max(0, box.width)+'px';
+            this.panel.setSize(box.width, box.height-sh);
+        },
+        south : function(box){
+            if(this.isCollapsed){
+                return this.applyLayoutCollapsed(box);
+            }
+            var sd = this.splitEl.dom, s = sd.style;
+            var sh = sd.offsetHeight;
+            this.panel.setPosition(box.x, box.y+sh);
+            s.left = (box.x)+'px';
+            s.top = (box.y)+'px';
+            s.width = Math.max(0, box.width)+'px';
+            this.panel.setSize(box.width, box.height-sh);
+        }
+    },
+
+    
+    render : function(ct, p){
+        Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
+
+        var ps = this.position;
+
+        this.splitEl = ct.createChild({
+            cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
+            id: this.panel.id + '-xsplit'
+        });
+
+        if(this.collapseMode == 'mini'){
+            this.miniSplitEl = this.splitEl.createChild({
+                cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
+            });
+            this.miniSplitEl.addClassOnOver('x-layout-mini-over');
+            this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
+        }
+
+        var s = this.splitSettings[ps];
+
+        this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
+        this.split.tickSize = this.tickSize;
+        this.split.placement = s.placement;
+        this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
+        this.split.minSize = this.minSize || this[s.minProp];
+        this.split.on("beforeapply", this.onSplitMove, this);
+        this.split.useShim = this.useShim === true;
+        this.maxSize = this.maxSize || this[s.maxProp];
+
+        if(p.hidden){
+            this.splitEl.hide();
+        }
+
+        if(this.useSplitTips){
+            this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
+        }
+        if(this.collapsible){
+            this.splitEl.on("dblclick", this.onCollapseClick,  this);
+        }
+    },
+
+    
+    getSize : function(){
+        if(this.isCollapsed){
+            return this.collapsedEl.getSize();
+        }
+        var s = this.panel.getSize();
+        if(this.position == 'north' || this.position == 'south'){
+            s.height += this.splitEl.dom.offsetHeight;
+        }else{
+            s.width += this.splitEl.dom.offsetWidth;
+        }
+        return s;
+    },
+
+    
+    getHMaxSize : function(){
+         var cmax = this.maxSize || 10000;
+         var center = this.layout.center;
+         return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
+    },
+
+    
+    getVMaxSize : function(){
+        var cmax = this.maxSize || 10000;
+        var center = this.layout.center;
+        return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
+    },
+
+    
+    onSplitMove : function(split, newSize){
+        var s = this.panel.getSize();
+        this.lastSplitSize = newSize;
+        if(this.position == 'north' || this.position == 'south'){
+            this.panel.setSize(s.width, newSize);
+            this.state.height = newSize;
+        }else{
+            this.panel.setSize(newSize, s.height);
+            this.state.width = newSize;
+        }
+        this.layout.layout();
+        this.panel.saveState();
+        return false;
+    },
+
+    
+    getSplitBar : function(){
+        return this.split;
+    },
+
+    
+    destroy : function() {
+        Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
+        Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
+    }
+});
+
+Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
+
+Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
+
+    
+    labelSeparator : ':',
+
+    
+
+    
+    trackLabels: true,
+
+    type: 'form',
+
+    onRemove: function(c){
+        Ext.layout.FormLayout.superclass.onRemove.call(this, c);
+        if(this.trackLabels){
+            c.un('show', this.onFieldShow, this);
+            c.un('hide', this.onFieldHide, this);
+        }
+        
+        var el = c.getPositionEl(),
+            ct = c.getItemCt && c.getItemCt();
+        if (c.rendered && ct) {
+            if (el && el.dom) {
+                el.insertAfter(ct);
+            }
+            Ext.destroy(ct);
+            Ext.destroyMembers(c, 'label', 'itemCt');
+            if (c.customItemCt) {
+                Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
+            }
+        }
+    },
+
+    
+    setContainer : function(ct){
+        Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
+        if(ct.labelAlign){
+            ct.addClass('x-form-label-'+ct.labelAlign);
+        }
+
+        if(ct.hideLabels){
+            Ext.apply(this, {
+                labelStyle: 'display:none',
+                elementStyle: 'padding-left:0;',
+                labelAdjust: 0
+            });
+        }else{
+            this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
+            ct.labelWidth = ct.labelWidth || 100;
+            if(Ext.isNumber(ct.labelWidth)){
+                var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
+                Ext.apply(this, {
+                    labelAdjust: ct.labelWidth + pad,
+                    labelStyle: 'width:' + ct.labelWidth + 'px;',
+                    elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
+                });
+            }
+            if(ct.labelAlign == 'top'){
+                Ext.apply(this, {
+                    labelStyle: 'width:auto;',
+                    labelAdjust: 0,
+                    elementStyle: 'padding-left:0;'
+                });
+            }
+        }
+    },
+
+    
+    isHide: function(c){
+        return c.hideLabel || this.container.hideLabels;
+    },
+
+    onFieldShow: function(c){
+        c.getItemCt().removeClass('x-hide-' + c.hideMode);
+
+        
+        if (c.isComposite) {
+            c.doLayout();
+        }
+    },
+
+    onFieldHide: function(c){
+        c.getItemCt().addClass('x-hide-' + c.hideMode);
+    },
+
+    
+    getLabelStyle: function(s){
+        var ls = '', items = [this.labelStyle, s];
+        for (var i = 0, len = items.length; i < len; ++i){
+            if (items[i]){
+                ls += items[i];
+                if (ls.substr(-1, 1) != ';'){
+                    ls += ';';
+                }
+            }
+        }
+        return ls;
+    },
+
+    
+
+    
+    renderItem : function(c, position, target){
+        if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
+            var args = this.getTemplateArgs(c);
+            if(Ext.isNumber(position)){
+                position = target.dom.childNodes[position] || null;
+            }
+            if(position){
+                c.itemCt = this.fieldTpl.insertBefore(position, args, true);
+            }else{
+                c.itemCt = this.fieldTpl.append(target, args, true);
+            }
+            if(!c.getItemCt){
+                
+                
+                Ext.apply(c, {
+                    getItemCt: function(){
+                        return c.itemCt;
+                    },
+                    customItemCt: true
+                });
+            }
+            c.label = c.getItemCt().child('label.x-form-item-label');
+            if(!c.rendered){
+                c.render('x-form-el-' + c.id);
+            }else if(!this.isValidParent(c, target)){
+                Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
+            }
+            if(this.trackLabels){
+                if(c.hidden){
+                    this.onFieldHide(c);
+                }
+                c.on({
+                    scope: this,
+                    show: this.onFieldShow,
+                    hide: this.onFieldHide
+                });
+            }
+            this.configureItem(c);
+        }else {
+            Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
+        }
+    },
+
+    
+    getTemplateArgs: function(field) {
+        var noLabelSep = !field.fieldLabel || field.hideLabel,
+            itemCls = (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : '');
+
+        
+        if (Ext.isIE9 && Ext.isIEQuirks && field instanceof Ext.form.TextField) {
+            itemCls += ' x-input-wrapper';
+        }
+
+        return {
+            id            : field.id,
+            label         : field.fieldLabel,
+            itemCls       : itemCls,
+            clearCls      : field.clearCls || 'x-form-clear-left',
+            labelStyle    : this.getLabelStyle(field.labelStyle),
+            elementStyle  : this.elementStyle || '',
+            labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
+        };
+    },
+
+    
+    adjustWidthAnchor: function(value, c){
+        if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
+            var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
+            return value - this.labelAdjust + (adjust ? -3 : 0);
+        }
+        return value;
+    },
+
+    adjustHeightAnchor : function(value, c){
+        if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
+            return value - c.label.getHeight();
+        }
+        return value;
+    },
+
+    
+    isValidParent : function(c, target){
+        return target && this.container.getEl().contains(c.getPositionEl());
+    }
+
+    
+});
+
+Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
+
+Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
+    
+    fill : true,
+    
+    autoWidth : true,
+    
+    titleCollapse : true,
+    
+    hideCollapseTool : false,
+    
+    collapseFirst : false,
+    
+    animate : false,
+    
+    sequence : false,
+    
+    activeOnTop : false,
+
+    type: 'accordion',
+
+    renderItem : function(c){
+        if(this.animate === false){
+            c.animCollapse = false;
+        }
+        c.collapsible = true;
+        if(this.autoWidth){
+            c.autoWidth = true;
+        }
+        if(this.titleCollapse){
+            c.titleCollapse = true;
+        }
+        if(this.hideCollapseTool){
+            c.hideCollapseTool = true;
+        }
+        if(this.collapseFirst !== undefined){
+            c.collapseFirst = this.collapseFirst;
+        }
+        if(!this.activeItem && !c.collapsed){
+            this.setActiveItem(c, true);
+        }else if(this.activeItem && this.activeItem != c){
+            c.collapsed = true;
+        }
+        Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
+        c.header.addClass('x-accordion-hd');
+        c.on('beforeexpand', this.beforeExpand, this);
+    },
+
+    onRemove: function(c){
+        Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
+        if(c.rendered){
+            c.header.removeClass('x-accordion-hd');
+        }
+        c.un('beforeexpand', this.beforeExpand, this);
+    },
+
+    
+    beforeExpand : function(p, anim){
+        var ai = this.activeItem;
+        if(ai){
+            if(this.sequence){
+                delete this.activeItem;
+                if (!ai.collapsed){
+                    ai.collapse({callback:function(){
+                        p.expand(anim || true);
+                    }, scope: this});
+                    return false;
+                }
+            }else{
+                ai.collapse(this.animate);
+            }
+        }
+        this.setActive(p);
+        if(this.activeOnTop){
+            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
+        }
+        
+        this.layout();
+    },
+
+    
+    setItemSize : function(item, size){
+        if(this.fill && item){
+            var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
+            
+            for (i = 0; i < len; i++) {
+                if((p = ct[i]) != item && !p.hidden){
+                    hh += p.header.getHeight();
+                }
+            };
+            
+            size.height -= hh;
+            
+            
+            item.setSize(size);
+        }
+    },
+
+    
+    setActiveItem : function(item){
+        this.setActive(item, true);
+    },
+
+    
+    setActive : function(item, expand){
+        var ai = this.activeItem;
+        item = this.container.getComponent(item);
+        if(ai != item){
+            if(item.rendered && item.collapsed && expand){
+                item.expand();
+            }else{
+                if(ai){
+                   ai.fireEvent('deactivate', ai);
+                }
+                this.activeItem = item;
+                item.fireEvent('activate', item);
+            }
+        }
+    }
+});
+Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
+
+
+Ext.layout.Accordion = Ext.layout.AccordionLayout;
+Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+
+    
+    monitorResize:false,
+
+    type: 'table',
+
+    targetCls: 'x-table-layout-ct',
+
+    
+    tableAttrs:null,
+
+    
+    setContainer : function(ct){
+        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
+
+        this.currentRow = 0;
+        this.currentColumn = 0;
+        this.cells = [];
+    },
+    
+    
+    onLayout : function(ct, target){
+        var cs = ct.items.items, len = cs.length, c, i;
+
+        if(!this.table){
+            target.addClass('x-table-layout-ct');
+
+            this.table = target.createChild(
+                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
+        }
+        this.renderAll(ct, target);
+    },
+
+    
+    getRow : function(index){
+        var row = this.table.tBodies[0].childNodes[index];
+        if(!row){
+            row = document.createElement('tr');
+            this.table.tBodies[0].appendChild(row);
+        }
+        return row;
+    },
+
+    
+    getNextCell : function(c){
+        var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
+        var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
+        for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
+            if(!this.cells[rowIndex]){
+                this.cells[rowIndex] = [];
+            }
+            for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
+                this.cells[rowIndex][colIndex] = true;
+            }
+        }
+        var td = document.createElement('td');
+        if(c.cellId){
+            td.id = c.cellId;
+        }
+        var cls = 'x-table-layout-cell';
+        if(c.cellCls){
+            cls += ' ' + c.cellCls;
+        }
+        td.className = cls;
+        if(c.colspan){
+            td.colSpan = c.colspan;
+        }
+        if(c.rowspan){
+            td.rowSpan = c.rowspan;
+        }
+        this.getRow(curRow).appendChild(td);
+        return td;
+    },
+
+    
+    getNextNonSpan: function(colIndex, rowIndex){
+        var cols = this.columns;
+        while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
+            if(cols && colIndex >= cols){
+                rowIndex++;
+                colIndex = 0;
+            }else{
+                colIndex++;
+            }
+        }
+        return [colIndex, rowIndex];
+    },
+
+    
+    renderItem : function(c, position, target){
+        
+        if(!this.table){
+            this.table = target.createChild(
+                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
+        }
+        if(c && !c.rendered){
+            c.render(this.getNextCell(c));
+            this.configureItem(c);
+        }else if(c && !this.isValidParent(c, target)){
+            var container = this.getNextCell(c);
+            container.insertBefore(c.getPositionEl().dom, null);
+            c.container = Ext.get(container);
+            this.configureItem(c);
+        }
+    },
+
+    
+    isValidParent : function(c, target){
+        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
+    },
+    
+    destroy: function(){
+        delete this.table;
+        Ext.layout.TableLayout.superclass.destroy.call(this);
+    }
+
+    
+});
+
+Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
+Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
+
+    extraCls: 'x-abs-layout-item',
+
+    type: 'absolute',
+
+    onLayout : function(ct, target){
+        target.position();
+        this.paddingLeft = target.getPadding('l');
+        this.paddingTop = target.getPadding('t');
+        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
+    },
+
+    
+    adjustWidthAnchor : function(value, comp){
+        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
+    },
+
+    
+    adjustHeightAnchor : function(value, comp){
+        return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
+    }
+    
+});
+Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
+
+Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    
+    defaultMargins : {left:0,top:0,right:0,bottom:0},
+    
+    padding : '0',
+    
+    pack : 'start',
+
+    
+    monitorResize : true,
+    type: 'box',
+    scrollOffset : 0,
+    extraCls : 'x-box-item',
+    targetCls : 'x-box-layout-ct',
+    innerCls : 'x-box-inner',
+
+    constructor : function(config){
+        Ext.layout.BoxLayout.superclass.constructor.call(this, config);
+
+        if (Ext.isString(this.defaultMargins)) {
+            this.defaultMargins = this.parseMargins(this.defaultMargins);
+        }
+        
+        var handler = this.overflowHandler;
+        
+        if (typeof handler == 'string') {
+            handler = {
+                type: handler
+            };
+        }
+        
+        var handlerType = 'none';
+        if (handler && handler.type != undefined) {
+            handlerType = handler.type;
+        }
+        
+        var constructor = Ext.layout.boxOverflow[handlerType];
+        if (constructor[this.type]) {
+            constructor = constructor[this.type];
+        }
+        
+        this.overflowHandler = new constructor(this, handler);
+    },
+
+    
+    onLayout: function(container, target) {
+        Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
+
+        var tSize = this.getLayoutTargetSize(),
+            items = this.getVisibleItems(container),
+            calcs = this.calculateChildBoxes(items, tSize),
+            boxes = calcs.boxes,
+            meta  = calcs.meta;
+        
+        
+        if (tSize.width > 0) {
+            var handler = this.overflowHandler,
+                method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
+            
+            var results = handler[method](calcs, tSize);
+            
+            if (results) {
+                if (results.targetSize) {
+                    tSize = results.targetSize;
+                }
+                
+                if (results.recalculate) {
+                    items = this.getVisibleItems(container);
+                    calcs = this.calculateChildBoxes(items, tSize);
+                    boxes = calcs.boxes;
+                }
+            }
+        }
+        
+        
+        this.layoutTargetLastSize = tSize;
+        
+        
+        this.childBoxCache = calcs;
+        
+        this.updateInnerCtSize(tSize, calcs);
+        this.updateChildBoxes(boxes);
+
+        
+        this.handleTargetOverflow(tSize, container, target);
+    },
+
+    
+    updateChildBoxes: function(boxes) {
+        for (var i = 0, length = boxes.length; i < length; i++) {
+            var box  = boxes[i],
+                comp = box.component;
+            
+            if (box.dirtySize) {
+                comp.setSize(box.width, box.height);
+            }
+            
+            if (isNaN(box.left) || isNaN(box.top)) {
+                continue;
+            }
+            
+            comp.setPosition(box.left, box.top);
+        }
+    },
+
+    
+    updateInnerCtSize: function(tSize, calcs) {
+        var align   = this.align,
+            padding = this.padding,
+            width   = tSize.width,
+            height  = tSize.height;
+        
+        if (this.type == 'hbox') {
+            var innerCtWidth  = width,
+                innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
+
+            if (align == 'stretch') {
+                innerCtHeight = height;
+            } else if (align == 'middle') {
+                innerCtHeight = Math.max(height, innerCtHeight);
+            }
+        } else {
+            var innerCtHeight = height,
+                innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
+
+            if (align == 'stretch') {
+                innerCtWidth = width;
+            } else if (align == 'center') {
+                innerCtWidth = Math.max(width, innerCtWidth);
+            }
+        }
+
+        this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+    },
+
+    
+    handleTargetOverflow: function(previousTargetSize, container, target) {
+        var overflow = target.getStyle('overflow');
+
+        if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
+            var newTargetSize = this.getLayoutTargetSize();
+            if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
+                this.adjustmentPass = true;
+                this.onLayout(container, target);
+            }
+        }
+
+        delete this.adjustmentPass;
+    },
+
+    
+    isValidParent : function(c, target) {
+        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
+    },
+
+    
+    getVisibleItems: function(ct) {
+        var ct  = ct || this.container,
+            t   = ct.getLayoutTarget(),
+            cti = ct.items.items,
+            len = cti.length,
+
+            i, c, items = [];
+
+        for (i = 0; i < len; i++) {
+            if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
+                items.push(c);
+            }
+        }
+
+        return items;
+    },
+
+    
+    renderAll : function(ct, target) {
+        if (!this.innerCt) {
+            
+            this.innerCt = target.createChild({cls:this.innerCls});
+            this.padding = this.parseMargins(this.padding);
+        }
+        Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
+    },
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget(), ret;
+        
+        if (target) {
+            ret = target.getViewSize();
+
+            
+            
+            
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+
+            ret.width  -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        
+        return ret;
+    },
+
+    
+    renderItem : function(c) {
+        if(Ext.isString(c.margins)){
+            c.margins = this.parseMargins(c.margins);
+        }else if(!c.margins){
+            c.margins = this.defaultMargins;
+        }
+        Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
+    },
+    
+    
+    destroy: function() {
+        Ext.destroy(this.overflowHandler);
+        
+        Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
+    }
+});
+
+
+
+Ext.layout.boxOverflow.None = Ext.extend(Object, {
+    constructor: function(layout, config) {
+        this.layout = layout;
+        
+        Ext.apply(this, config || {});
+    },
+    
+    handleOverflow: Ext.emptyFn,
+    
+    clearOverflow: Ext.emptyFn
+});
+
+
+Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
+
+Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
+    
+    afterCls: 'x-strip-right',
+    
+    
+    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+    
+    constructor: function(layout) {
+        Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
+        
+        
+        this.menuItems = [];
+    },
+    
+    
+    createInnerElements: function() {
+        if (!this.afterCt) {
+            this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
+        }
+    },
+    
+    
+    clearOverflow: function(calculations, targetSize) {
+        var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
+            items    = this.menuItems;
+        
+        this.hideTrigger();
+        
+        for (var index = 0, length = items.length; index < length; index++) {
+            items.pop().component.show();
+        }
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            }
+        };
+    },
+    
+    
+    showTrigger: function() {
+        this.createMenu();
+        this.menuTrigger.show();
+    },
+    
+    
+    hideTrigger: function() {
+        if (this.menuTrigger != undefined) {
+            this.menuTrigger.hide();
+        }
+    },
+    
+    
+    beforeMenuShow: function(menu) {
+        var items = this.menuItems,
+            len   = items.length,
+            item,
+            prev;
+
+        var needsSep = function(group, item){
+            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+        };
+        
+        this.clearMenu();
+        menu.removeAll();
+        
+        for (var i = 0; i < len; i++) {
+            item = items[i].component;
+            
+            if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
+                menu.add('-');
+            }
+            
+            this.addComponentToMenu(menu, item);
+            prev = item;
+        }
+
+        
+        if (menu.items.length < 1) {
+            menu.add(this.noItemsMenuText);
+        }
+    },
+    
+    
+    createMenuConfig : function(component, hideOnClick){
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
+
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
+
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
+        }
+
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+
+        return config;
+    },
+
+    
+    addComponentToMenu : function(menu, component) {
+        if (component instanceof Ext.Toolbar.Separator) {
+            menu.add('-');
+
+        } else if (Ext.isFunction(component.isXType)) {
+            if (component.isXType('splitbutton')) {
+                menu.add(this.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(this.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     this.addComponentToMenu(menu, item);
+                }, this);
+            }
+        }
+    },
+    
+    
+    clearMenu : function(){
+        var menu = this.moreMenu;
+        if (menu && menu.items) {
+            menu.items.each(function(item){
+                delete item.menu;
+            });
+        }
+    },
+    
+    
+    createMenu: function() {
+        if (!this.menuTrigger) {
+            this.createInnerElements();
+            
+            
+            this.menu = new Ext.menu.Menu({
+                ownerCt : this.layout.container,
+                listeners: {
+                    scope: this,
+                    beforeshow: this.beforeMenuShow
+                }
+            });
+
+            
+            this.menuTrigger = new Ext.Button({
+                iconCls : 'x-toolbar-more-icon',
+                cls     : 'x-toolbar-more',
+                menu    : this.menu,
+                renderTo: this.afterCt
+            });
+        }
+    },
+    
+    
+    destroy: function() {
+        Ext.destroy(this.menu, this.menuTrigger);
+    }
+});
+
+Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
+
+
+
+Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
+    
+    constructor: function() {
+        Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
+        
+        var me = this,
+            layout = me.layout,
+            origFunction = layout.calculateChildBoxes;
+        
+        layout.calculateChildBoxes = function(visibleItems, targetSize) {
+            var calcs = origFunction.apply(layout, arguments),
+                meta  = calcs.meta,
+                items = me.menuItems;
+            
+            
+            
+            var hiddenWidth = 0;
+            for (var index = 0, length = items.length; index < length; index++) {
+                hiddenWidth += items[index].width;
+            }
+            
+            meta.minimumWidth += hiddenWidth;
+            meta.tooNarrow = meta.minimumWidth > targetSize.width;
+            
+            return calcs;
+        };        
+    },
+    
+    handleOverflow: function(calculations, targetSize) {
+        this.showTrigger();
+        
+        var newWidth    = targetSize.width - this.afterCt.getWidth(),
+            boxes       = calculations.boxes,
+            usedWidth   = 0,
+            recalculate = false;
+        
+        
+        for (var index = 0, length = boxes.length; index < length; index++) {
+            usedWidth += boxes[index].width;
+        }
+        
+        var spareWidth = newWidth - usedWidth,
+            showCount  = 0;
+        
+        
+        for (var index = 0, length = this.menuItems.length; index < length; index++) {
+            var hidden = this.menuItems[index],
+                comp   = hidden.component,
+                width  = hidden.width;
+            
+            if (width < spareWidth) {
+                comp.show();
+                
+                spareWidth -= width;
+                showCount ++;
+                recalculate = true;
+            } else {
+                break;
+            }
+        }
+                
+        if (recalculate) {
+            this.menuItems = this.menuItems.slice(showCount);
+        } else {
+            for (var i = boxes.length - 1; i >= 0; i--) {
+                var item  = boxes[i].component,
+                    right = boxes[i].left + boxes[i].width;
+
+                if (right >= newWidth) {
+                    this.menuItems.unshift({
+                        component: item,
+                        width    : boxes[i].width
+                    });
+
+                    item.hide();
+                } else {
+                    break;
+                }
+            }
+        }
+        
+        if (this.menuItems.length == 0) {
+            this.hideTrigger();
+        }
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            },
+            recalculate: recalculate
+        };
+    }
+});
+
+Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;
+Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
+    
+    animateScroll: true,
+    
+    
+    scrollIncrement: 100,
+    
+    
+    wheelIncrement: 3,
+    
+    
+    scrollRepeatInterval: 400,
+    
+    
+    scrollDuration: 0.4,
+    
+    
+    beforeCls: 'x-strip-left',
+    
+    
+    afterCls: 'x-strip-right',
+    
+    
+    scrollerCls: 'x-strip-scroller',
+    
+    
+    beforeScrollerCls: 'x-strip-scroller-left',
+    
+    
+    afterScrollerCls: 'x-strip-scroller-right',
+    
+    
+    createWheelListener: function() {
+        this.layout.innerCt.on({
+            scope     : this,
+            mousewheel: function(e) {
+                e.stopEvent();
+
+                this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
+            }
+        });
+    },
+    
+    
+    handleOverflow: function(calculations, targetSize) {
+        this.createInnerElements();
+        this.showScrollers();
+    },
+    
+    
+    clearOverflow: function() {
+        this.hideScrollers();
+    },
+    
+    
+    showScrollers: function() {
+        this.createScrollers();
+        
+        this.beforeScroller.show();
+        this.afterScroller.show();
+        
+        this.updateScrollButtons();
+    },
+    
+    
+    hideScrollers: function() {
+        if (this.beforeScroller != undefined) {
+            this.beforeScroller.hide();
+            this.afterScroller.hide();          
+        }
+    },
+    
+    
+    createScrollers: function() {
+        if (!this.beforeScroller && !this.afterScroller) {
+            var before = this.beforeCt.createChild({
+                cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
+            });
+            
+            var after = this.afterCt.createChild({
+                cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
+            });
+            
+            before.addClassOnOver(this.beforeScrollerCls + '-hover');
+            after.addClassOnOver(this.afterScrollerCls + '-hover');
+            
+            before.setVisibilityMode(Ext.Element.DISPLAY);
+            after.setVisibilityMode(Ext.Element.DISPLAY);
+            
+            this.beforeRepeater = new Ext.util.ClickRepeater(before, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollLeft,
+                scope   : this
+            });
+            
+            this.afterRepeater = new Ext.util.ClickRepeater(after, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollRight,
+                scope   : this
+            });
+            
+            
+            this.beforeScroller = before;
+            
+            
+            this.afterScroller = after;
+        }
+    },
+    
+    
+    destroy: function() {
+        Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
+    },
+    
+    
+    scrollBy: function(delta, animate) {
+        this.scrollTo(this.getScrollPosition() + delta, animate);
+    },
+    
+    
+    getItem: function(item) {
+        if (Ext.isString(item)) {
+            item = Ext.getCmp(item);
+        } else if (Ext.isNumber(item)) {
+            item = this.items[item];
+        }
+        
+        return item;
+    },
+    
+    
+    getScrollAnim: function() {
+        return {
+            duration: this.scrollDuration, 
+            callback: this.updateScrollButtons, 
+            scope   : this
+        };
+    },
+    
+    
+    updateScrollButtons: function() {
+        if (this.beforeScroller == undefined || this.afterScroller == undefined) {
+            return;
+        }
+        
+        var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
+            afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
+            beforeCls  = this.beforeScrollerCls + '-disabled',
+            afterCls   = this.afterScrollerCls  + '-disabled';
+        
+        this.beforeScroller[beforeMeth](beforeCls);
+        this.afterScroller[afterMeth](afterCls);
+        this.scrolling = false;
+    },
+    
+    
+    atExtremeBefore: function() {
+        return this.getScrollPosition() === 0;
+    },
+    
+    
+    scrollLeft: function(animate) {
+        this.scrollBy(-this.scrollIncrement, animate);
+    },
+    
+    
+    scrollRight: function(animate) {
+        this.scrollBy(this.scrollIncrement, animate);
+    },
+    
+    
+    scrollToItem: function(item, animate) {
+        item = this.getItem(item);
+        
+        if (item != undefined) {
+            var visibility = this.getItemVisibility(item);
+            
+            if (!visibility.fullyVisible) {
+                var box  = item.getBox(true, true),
+                    newX = box.x;
+                    
+                if (visibility.hiddenRight) {
+                    newX -= (this.layout.innerCt.getWidth() - box.width);
+                }
+                
+                this.scrollTo(newX, animate);
+            }
+        }
+    },
+    
+    
+    getItemVisibility: function(item) {
+        var box         = this.getItem(item).getBox(true, true),
+            itemLeft    = box.x,
+            itemRight   = box.x + box.width,
+            scrollLeft  = this.getScrollPosition(),
+            scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
+        
+        return {
+            hiddenLeft  : itemLeft < scrollLeft,
+            hiddenRight : itemRight > scrollRight,
+            fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
+        };
+    }
+});
+
+Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
+
+
+
+Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
+    scrollIncrement: 75,
+    wheelIncrement : 2,
+    
+    handleOverflow: function(calculations, targetSize) {
+        Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
+        
+        return {
+            targetSize: {
+                height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
+                width : targetSize.width
+            }
+        };
+    },
+    
+    
+    createInnerElements: function() {
+        var target = this.layout.innerCt;
+        
+        
+        
+        if (!this.beforeCt) {
+            this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
+            this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
+
+            this.createWheelListener();
+        }
+    },
+    
+    
+    scrollTo: function(position, animate) {
+        var oldPosition = this.getScrollPosition(),
+            newPosition = position.constrain(0, this.getMaxScrollBottom());
+        
+        if (newPosition != oldPosition && !this.scrolling) {
+            if (animate == undefined) {
+                animate = this.animateScroll;
+            }
+            
+            this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
+            
+            if (animate) {
+                this.scrolling = true;
+            } else {
+                this.scrolling = false;
+                this.updateScrollButtons();
+            }
+        }
+    },
+    
+    
+    getScrollPosition: function(){
+        return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
+    },
+    
+    
+    getMaxScrollBottom: function() {
+        return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
+    },
+    
+    
+    atExtremeAfter: function() {
+        return this.getScrollPosition() >= this.getMaxScrollBottom();
+    }
+});
+
+Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
+
+
+
+Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
+    handleOverflow: function(calculations, targetSize) {
+        Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
+            }
+        };
+    },
+    
+    
+    createInnerElements: function() {
+        var target = this.layout.innerCt;
+        
+        
+        
+        if (!this.beforeCt) {
+            this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
+            this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
+            
+            this.createWheelListener();
+        }
+    },
+    
+    
+    scrollTo: function(position, animate) {
+        var oldPosition = this.getScrollPosition(),
+            newPosition = position.constrain(0, this.getMaxScrollRight());
+        
+        if (newPosition != oldPosition && !this.scrolling) {
+            if (animate == undefined) {
+                animate = this.animateScroll;
+            }
+            
+            this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
+            
+            if (animate) {
+                this.scrolling = true;
+            } else {
+                this.scrolling = false;
+                this.updateScrollButtons();
+            }
+        }
+    },
+    
+    
+    getScrollPosition: function(){
+        return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
+    },
+    
+    
+    getMaxScrollRight: function() {
+        return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
+    },
+    
+    
+    atExtremeAfter: function() {
+        return this.getScrollPosition() >= this.getMaxScrollRight();
+    }
+});
+
+Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;
+Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    
+    align: 'top', 
+
+    type : 'hbox',
+
+    
+    
+
+    
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var visibleCount = visibleItems.length,
+
+            padding      = this.padding,
+            topOffset    = padding.top,
+            leftOffset   = padding.left,
+            paddingVert  = topOffset  + padding.bottom,
+            paddingHoriz = leftOffset + padding.right,
+
+            width        = targetSize.width - this.scrollOffset,
+            height       = targetSize.height,
+            availHeight  = Math.max(0, height - paddingVert),
+
+            isStart      = this.pack == 'start',
+            isCenter     = this.pack == 'center',
+            isEnd        = this.pack == 'end',
+
+            nonFlexWidth = 0,
+            maxHeight    = 0,
+            totalFlex    = 0,
+            desiredWidth = 0,
+            minimumWidth = 0,
+
+            
+            boxes        = [],
+
+            
+            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
+            horizMargins, vertMargins, stretchHeight;
+
+        
+        for (i = 0; i < visibleCount; i++) {
+            child       = visibleItems[i];
+            childHeight = child.height;
+            childWidth  = child.width;
+            canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
+
+            
+            if (typeof childWidth != 'number') {
+
+                
+                if (child.flex && !childWidth) {
+                    totalFlex += child.flex;
+
+                
+                } else {
+                    
+                    
+                    if (!childWidth && canLayout) {
+                        child.doLayout();
+                    }
+
+                    childSize   = child.getSize();
+                    childWidth  = childSize.width;
+                    childHeight = childSize.height;
+                }
+            }
+
+            childMargins = child.margins;
+            horizMargins = childMargins.left + childMargins.right;
+
+            nonFlexWidth += horizMargins + (childWidth || 0);
+            desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
+            minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
+
+            
+            if (typeof childHeight != 'number') {
+                if (canLayout) {
+                    child.doLayout();
+                }
+                childHeight = child.getHeight();
+            }
+
+            maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
+
+            
+            boxes.push({
+                component: child,
+                height   : childHeight || undefined,
+                width    : childWidth  || undefined
+            });
+        }
+                
+        var shortfall = desiredWidth - width,
+            tooNarrow = minimumWidth > width;
+            
+        
+        var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
+        
+        if (tooNarrow) {
+            for (i = 0; i < visibleCount; i++) {
+                boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
+            }
+        } else {
+            
+            
+            if (shortfall > 0) {
+                var minWidths = [];
+                
+                
+                for (var index = 0, length = visibleCount; index < length; index++) {
+                    var item     = visibleItems[index],
+                        minWidth = item.minWidth || 0;
+
+                    
+                    
+                    if (item.flex) {
+                        boxes[index].width = minWidth;
+                    } else {
+                        minWidths.push({
+                            minWidth : minWidth,
+                            available: boxes[index].width - minWidth,
+                            index    : index
+                        });
+                    }
+                }
+                
+                
+                minWidths.sort(function(a, b) {
+                    return a.available > b.available ? 1 : -1;
+                });
+                
+                
+                for (var i = 0, length = minWidths.length; i < length; i++) {
+                    var itemIndex = minWidths[i].index;
+                    
+                    if (itemIndex == undefined) {
+                        continue;
+                    }
+                        
+                    var item      = visibleItems[itemIndex],
+                        box       = boxes[itemIndex],
+                        oldWidth  = box.width,
+                        minWidth  = item.minWidth,
+                        newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
+                        reduction = oldWidth - newWidth;
+                    
+                    boxes[itemIndex].width = newWidth;
+                    shortfall -= reduction;                    
+                }
+            } else {
+                
+                var remainingWidth = availableWidth,
+                    remainingFlex  = totalFlex;
+
+                
+                for (i = 0; i < visibleCount; i++) {
+                    child = visibleItems[i];
+                    calcs = boxes[i];
+
+                    childMargins = child.margins;
+                    vertMargins  = childMargins.top + childMargins.bottom;
+
+                    if (isStart && child.flex && !child.width) {
+                        flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
+                        remainingWidth -= flexedWidth;
+                        remainingFlex  -= child.flex;
+
+                        calcs.width = flexedWidth;
+                        calcs.dirtySize = true;
+                    }
+                }
+            }
+        }
+        
+        if (isCenter) {
+            leftOffset += availableWidth / 2;
+        } else if (isEnd) {
+            leftOffset += availableWidth;
+        }
+        
+        
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            calcs = boxes[i];
+            
+            childMargins = child.margins;
+            leftOffset  += childMargins.left;
+            vertMargins  = childMargins.top + childMargins.bottom;
+            
+            calcs.left = leftOffset;
+            calcs.top  = topOffset + childMargins.top;
+
+            switch (this.align) {
+                case 'stretch':
+                    stretchHeight = availHeight - vertMargins;
+                    calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'stretchmax':
+                    stretchHeight = maxHeight - vertMargins;
+                    calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'middle':
+                    var diff = availHeight - calcs.height - vertMargins;
+                    if (diff > 0) {
+                        calcs.top = topOffset + vertMargins + (diff / 2);
+                    }
+            }
+            
+            leftOffset += calcs.width + childMargins.right;
+        }
+
+        return {
+            boxes: boxes,
+            meta : {
+                maxHeight   : maxHeight,
+                nonFlexWidth: nonFlexWidth,
+                desiredWidth: desiredWidth,
+                minimumWidth: minimumWidth,
+                shortfall   : desiredWidth - width,
+                tooNarrow   : tooNarrow
+            }
+        };
+    }
+});
+
+Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
+Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    
+    align : 'left', 
+    type: 'vbox',
+
+    
+
+    
+
+    
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var visibleCount = visibleItems.length,
+
+            padding      = this.padding,
+            topOffset    = padding.top,
+            leftOffset   = padding.left,
+            paddingVert  = topOffset  + padding.bottom,
+            paddingHoriz = leftOffset + padding.right,
+
+            width        = targetSize.width - this.scrollOffset,
+            height       = targetSize.height,
+            availWidth   = Math.max(0, width - paddingHoriz),
+
+            isStart      = this.pack == 'start',
+            isCenter     = this.pack == 'center',
+            isEnd        = this.pack == 'end',
+
+            nonFlexHeight= 0,
+            maxWidth     = 0,
+            totalFlex    = 0,
+            desiredHeight= 0,
+            minimumHeight= 0,
+
+            
+            boxes        = [],
+            
+            
+            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, 
+            horizMargins, vertMargins, stretchWidth, length;
+
+        
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            childHeight = child.height;
+            childWidth  = child.width;
+            canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
+
+            
+            if (typeof childHeight != 'number') {
+
+                
+                if (child.flex && !childHeight) {
+                    totalFlex += child.flex;
+
+                
+                } else {
+                    
+                    
+                    if (!childHeight && canLayout) {
+                        child.doLayout();
+                    }
+
+                    childSize = child.getSize();
+                    childWidth = childSize.width;
+                    childHeight = childSize.height;
+                }
+            }
+            
+            childMargins = child.margins;
+            vertMargins  = childMargins.top + childMargins.bottom;
+
+            nonFlexHeight += vertMargins + (childHeight || 0);
+            desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
+            minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
+
+            
+            if (typeof childWidth != 'number') {
+                if (canLayout) {
+                    child.doLayout();
+                }
+                childWidth = child.getWidth();
+            }
+
+            maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
+
+            
+            boxes.push({
+                component: child,
+                height   : childHeight || undefined,
+                width    : childWidth || undefined
+            });
+        }
+                
+        var shortfall = desiredHeight - height,
+            tooNarrow = minimumHeight > height;
+
+        
+        var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
+        
+        if (tooNarrow) {
+            for (i = 0, length = visibleCount; i < length; i++) {
+                boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
+            }
+        } else {
+            
+            
+            if (shortfall > 0) {
+                var minHeights = [];
+
+                
+                for (var index = 0, length = visibleCount; index < length; index++) {
+                    var item      = visibleItems[index],
+                        minHeight = item.minHeight || 0;
+
+                    
+                    
+                    if (item.flex) {
+                        boxes[index].height = minHeight;
+                    } else {
+                        minHeights.push({
+                            minHeight: minHeight, 
+                            available: boxes[index].height - minHeight,
+                            index    : index
+                        });
+                    }
+                }
+
+                
+                minHeights.sort(function(a, b) {
+                    return a.available > b.available ? 1 : -1;
+                });
+
+                
+                for (var i = 0, length = minHeights.length; i < length; i++) {
+                    var itemIndex = minHeights[i].index;
+
+                    if (itemIndex == undefined) {
+                        continue;
+                    }
+
+                    var item      = visibleItems[itemIndex],
+                        box       = boxes[itemIndex],
+                        oldHeight  = box.height,
+                        minHeight  = item.minHeight,
+                        newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
+                        reduction = oldHeight - newHeight;
+
+                    boxes[itemIndex].height = newHeight;
+                    shortfall -= reduction;
+                }
+            } else {
+                
+                var remainingHeight = availableHeight,
+                    remainingFlex   = totalFlex;
+                
+                
+                for (i = 0; i < visibleCount; i++) {
+                    child = visibleItems[i];
+                    calcs = boxes[i];
+
+                    childMargins = child.margins;
+                    horizMargins = childMargins.left + childMargins.right;
+
+                    if (isStart && child.flex && !child.height) {
+                        flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
+                        remainingHeight -= flexedHeight;
+                        remainingFlex   -= child.flex;
+
+                        calcs.height = flexedHeight;
+                        calcs.dirtySize = true;
+                    }
+                }
+            }
+        }
+
+        if (isCenter) {
+            topOffset += availableHeight / 2;
+        } else if (isEnd) {
+            topOffset += availableHeight;
+        }
+
+        
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            calcs = boxes[i];
+
+            childMargins = child.margins;
+            topOffset   += childMargins.top;
+            horizMargins = childMargins.left + childMargins.right;
+            
+
+            calcs.left = leftOffset + childMargins.left;
+            calcs.top  = topOffset;
+            
+            switch (this.align) {
+                case 'stretch':
+                    stretchWidth = availWidth - horizMargins;
+                    calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'stretchmax':
+                    stretchWidth = maxWidth - horizMargins;
+                    calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'center':
+                    var diff = availWidth - calcs.width - horizMargins;
+                    if (diff > 0) {
+                        calcs.left = leftOffset + horizMargins + (diff / 2);
+                    }
+            }
+
+            topOffset += calcs.height + childMargins.bottom;
+        }
+        
+        return {
+            boxes: boxes,
+            meta : {
+                maxWidth     : maxWidth,
+                nonFlexHeight: nonFlexHeight,
+                desiredHeight: desiredHeight,
+                minimumHeight: minimumHeight,
+                shortfall    : desiredHeight - height,
+                tooNarrow    : tooNarrow
+            }
+        };
+    }
+});
+
+Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
+
+Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    monitorResize : true,
+
+    type: 'toolbar',
+
+    
+    triggerWidth: 18,
+
+    
+    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+
+    
+    lastOverflow: false,
+
+    
+    tableHTML: [
+        '<table cellspacing="0" class="x-toolbar-ct">',
+            '<tbody>',
+                '<tr>',
+                    '<td class="x-toolbar-left" align="{0}">',
+                        '<table cellspacing="0">',
+                            '<tbody>',
+                                '<tr class="x-toolbar-left-row"></tr>',
+                            '</tbody>',
+                        '</table>',
+                    '</td>',
+                    '<td class="x-toolbar-right" align="right">',
+                        '<table cellspacing="0" class="x-toolbar-right-ct">',
+                            '<tbody>',
+                                '<tr>',
+                                    '<td>',
+                                        '<table cellspacing="0">',
+                                            '<tbody>',
+                                                '<tr class="x-toolbar-right-row"></tr>',
+                                            '</tbody>',
+                                        '</table>',
+                                    '</td>',
+                                    '<td>',
+                                        '<table cellspacing="0">',
+                                            '<tbody>',
+                                                '<tr class="x-toolbar-extras-row"></tr>',
+                                            '</tbody>',
+                                        '</table>',
+                                    '</td>',
+                                '</tr>',
+                            '</tbody>',
+                        '</table>',
+                    '</td>',
+                '</tr>',
+            '</tbody>',
+        '</table>'
+    ].join(""),
+
+    
+    onLayout : function(ct, target) {
+        
+        if (!this.leftTr) {
+            var align = ct.buttonAlign == 'center' ? 'center' : 'left';
+
+            target.addClass('x-toolbar-layout-ct');
+            target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
+
+            this.leftTr   = target.child('tr.x-toolbar-left-row', true);
+            this.rightTr  = target.child('tr.x-toolbar-right-row', true);
+            this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
+
+            if (this.hiddenItem == undefined) {
+                
+                this.hiddenItems = [];
+            }
+        }
+
+        var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
+            items    = ct.items.items,
+            position = 0;
+
+        
+        for (var i = 0, len = items.length, c; i < len; i++, position++) {
+            c = items[i];
+
+            if (c.isFill) {
+                side   = this.rightTr;
+                position = -1;
+            } else if (!c.rendered) {
+                c.render(this.insertCell(c, side, position));
+                this.configureItem(c);
+            } else {
+                if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
+                    var td = this.insertCell(c, side, position);
+                    td.appendChild(c.getPositionEl().dom);
+                    c.container = Ext.get(td);
+                }
+            }
+        }
+
+        
+        this.cleanup(this.leftTr);
+        this.cleanup(this.rightTr);
+        this.cleanup(this.extrasTr);
+        this.fitToSize(target);
+    },
+
+    
+    cleanup : function(el) {
+        var cn = el.childNodes, i, c;
+
+        for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
+            if (!c.firstChild) {
+                el.removeChild(c);
+            }
+        }
+    },
+
+    
+    insertCell : function(c, target, position) {
+        var td = document.createElement('td');
+        td.className = 'x-toolbar-cell';
+
+        target.insertBefore(td, target.childNodes[position] || null);
+
+        return td;
+    },
+
+    
+    hideItem : function(item) {
+        this.hiddenItems.push(item);
+
+        item.xtbHidden = true;
+        item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
+        item.hide();
+    },
+
+    
+    unhideItem : function(item) {
+        item.show();
+        item.xtbHidden = false;
+        this.hiddenItems.remove(item);
+    },
+
+    
+    getItemWidth : function(c) {
+        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+    },
+
+    
+    fitToSize : function(target) {
+        if (this.container.enableOverflow === false) {
+            return;
+        }
+
+        var width       = target.dom.clientWidth,
+            tableWidth  = target.dom.firstChild.offsetWidth,
+            clipWidth   = width - this.triggerWidth,
+            lastWidth   = this.lastWidth || 0,
+
+            hiddenItems = this.hiddenItems,
+            hasHiddens  = hiddenItems.length != 0,
+            isLarger    = width >= lastWidth;
+
+        this.lastWidth  = width;
+
+        if (tableWidth > width || (hasHiddens && isLarger)) {
+            var items     = this.container.items.items,
+                len       = items.length,
+                loopWidth = 0,
+                item;
+
+            for (var i = 0; i < len; i++) {
+                item = items[i];
+
+                if (!item.isFill) {
+                    loopWidth += this.getItemWidth(item);
+                    if (loopWidth > clipWidth) {
+                        if (!(item.hidden || item.xtbHidden)) {
+                            this.hideItem(item);
+                        }
+                    } else if (item.xtbHidden) {
+                        this.unhideItem(item);
+                    }
+                }
+            }
+        }
+
+        
+        hasHiddens = hiddenItems.length != 0;
+
+        if (hasHiddens) {
+            this.initMore();
+
+            if (!this.lastOverflow) {
+                this.container.fireEvent('overflowchange', this.container, true);
+                this.lastOverflow = true;
+            }
+        } else if (this.more) {
+            this.clearMenu();
+            this.more.destroy();
+            delete this.more;
+
+            if (this.lastOverflow) {
+                this.container.fireEvent('overflowchange', this.container, false);
+                this.lastOverflow = false;
+            }
+        }
+    },
+
+    
+    createMenuConfig : function(component, hideOnClick){
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
+
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
+
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
+        }
+
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+
+        return config;
+    },
+
+    
+    addComponentToMenu : function(menu, component) {
+        if (component instanceof Ext.Toolbar.Separator) {
+            menu.add('-');
+
+        } else if (Ext.isFunction(component.isXType)) {
+            if (component.isXType('splitbutton')) {
+                menu.add(this.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(this.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     this.addComponentToMenu(menu, item);
+                }, this);
+            }
+        }
+    },
+
+    
+    clearMenu : function(){
+        var menu = this.moreMenu;
+        if (menu && menu.items) {
+            menu.items.each(function(item){
+                delete item.menu;
+            });
+        }
+    },
+
+    
+    beforeMoreShow : function(menu) {
+        var items = this.container.items.items,
+            len   = items.length,
+            item,
+            prev;
+
+        var needsSep = function(group, item){
+            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+        };
+
+        this.clearMenu();
+        menu.removeAll();
+        for (var i = 0; i < len; i++) {
+            item = items[i];
+            if (item.xtbHidden) {
+                if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
+                    menu.add('-');
+                }
+                this.addComponentToMenu(menu, item);
+                prev = item;
+            }
+        }
+
+        
+        if (menu.items.length < 1) {
+            menu.add(this.noItemsMenuText);
+        }
+    },
+
+    
+    initMore : function(){
+        if (!this.more) {
+            
+            this.moreMenu = new Ext.menu.Menu({
+                ownerCt : this.container,
+                listeners: {
+                    beforeshow: this.beforeMoreShow,
+                    scope: this
+                }
+            });
+
+            
+            this.more = new Ext.Button({
+                iconCls: 'x-toolbar-more-icon',
+                cls    : 'x-toolbar-more',
+                menu   : this.moreMenu,
+                ownerCt: this.container
+            });
+
+            var td = this.insertCell(this.more, this.extrasTr, 100);
+            this.more.render(td);
+        }
+    },
+
+    destroy : function(){
+        Ext.destroy(this.more, this.moreMenu);
+        delete this.leftTr;
+        delete this.rightTr;
+        delete this.extrasTr;
+        Ext.layout.ToolbarLayout.superclass.destroy.call(this);
+    }
+});
+
+Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
+
+ Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    monitorResize : true,
+
+    type: 'menu',
+
+    setContainer : function(ct){
+        this.monitorResize = !ct.floating;
+        
+        
+        ct.on('autosize', this.doAutoSize, this);
+        Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
+    },
+
+    renderItem : function(c, position, target){
+        if (!this.itemTpl) {
+            this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
+                '<li id="{itemId}" class="{itemCls}">',
+                    '<tpl if="needsIcon">',
+                        '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
+                    '</tpl>',
+                '</li>'
+            );
+        }
+
+        if(c && !c.rendered){
+            if(Ext.isNumber(position)){
+                position = target.dom.childNodes[position];
+            }
+            var a = this.getItemArgs(c);
+
+
+            c.render(c.positionEl = position ?
+                this.itemTpl.insertBefore(position, a, true) :
+                this.itemTpl.append(target, a, true));
+
+
+            c.positionEl.menuItemId = c.getItemId();
+
+
+
+            if (!a.isMenuItem && a.needsIcon) {
+                c.positionEl.addClass('x-menu-list-item-indent');
+            }
+            this.configureItem(c);
+        }else if(c && !this.isValidParent(c, target)){
+            if(Ext.isNumber(position)){
+                position = target.dom.childNodes[position];
+            }
+            target.dom.insertBefore(c.getActionEl().dom, position || null);
+        }
+    },
+
+    getItemArgs : function(c) {
+        var isMenuItem = c instanceof Ext.menu.Item,
+            canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
+
+        return {
+            isMenuItem: isMenuItem,
+            needsIcon: canHaveIcon && (c.icon || c.iconCls),
+            icon: c.icon || Ext.BLANK_IMAGE_URL,
+            iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
+            itemId: 'x-menu-el-' + c.id,
+            itemCls: 'x-menu-list-item ',
+            altText: c.altText || ''
+        };
+    },
+
+    
+    isValidParent : function(c, target) {
+        return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
+    },
+
+    onLayout : function(ct, target){
+        Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
+        this.doAutoSize();
+    },
+
+    doAutoSize : function(){
+        var ct = this.container, w = ct.width;
+        if(ct.floating){
+            if(w){
+                ct.setWidth(w);
+            }else if(Ext.isIE){
+                ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8 || Ext.isIE9) ? 'auto' : ct.minWidth);
+                var el = ct.getEl(), t = el.dom.offsetWidth; 
+                ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
+            }
+        }
+    }
+});
+Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
+
+Ext.Viewport = Ext.extend(Ext.Container, {
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    initComponent : function() {
+        Ext.Viewport.superclass.initComponent.call(this);
+        document.getElementsByTagName('html')[0].className += ' x-viewport';
+        this.el = Ext.getBody();
+        this.el.setHeight = Ext.emptyFn;
+        this.el.setWidth = Ext.emptyFn;
+        this.el.setSize = Ext.emptyFn;
+        this.el.dom.scroll = 'no';
+        this.allowDomMove = false;
+        this.autoWidth = true;
+        this.autoHeight = true;
+        Ext.EventManager.onWindowResize(this.fireResize, this);
+        this.renderTo = this.el;
+    },
+
+    fireResize : function(w, h){
+        this.fireEvent('resize', this, w, h, w, h);
+    }
+});
+Ext.reg('viewport', Ext.Viewport);
+
+Ext.Panel = Ext.extend(Ext.Container, {
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+    
+
+
+    
+    baseCls : 'x-panel',
+    
+    collapsedCls : 'x-panel-collapsed',
+    
+    maskDisabled : true,
+    
+    animCollapse : Ext.enableFx,
+    
+    headerAsText : true,
+    
+    buttonAlign : 'right',
+    
+    collapsed : false,
+    
+    collapseFirst : true,
+    
+    minButtonWidth : 75,
+    
+    
+    elements : 'body',
+    
+    preventBodyReset : false,
+
+    
+    padding: undefined,
+
+    
+    resizeEvent: 'bodyresize',
+
+    
+    
+    
+    toolTarget : 'header',
+    collapseEl : 'bwrap',
+    slideAnchor : 't',
+    disabledClass : '',
+
+    
+    deferHeight : true,
+    
+    expandDefaults: {
+        duration : 0.25
+    },
+    
+    collapseDefaults : {
+        duration : 0.25
+    },
+
+    
+    initComponent : function(){
+        Ext.Panel.superclass.initComponent.call(this);
+
+        this.addEvents(
+            
+            'bodyresize',
+            
+            'titlechange',
+            
+            'iconchange',
+            
+            'collapse',
+            
+            'expand',
+            
+            'beforecollapse',
+            
+            'beforeexpand',
+            
+            'beforeclose',
+            
+            'close',
+            
+            'activate',
+            
+            'deactivate'
+        );
+
+        if(this.unstyled){
+            this.baseCls = 'x-plain';
+        }
+
+
+        this.toolbars = [];
+        
+        if(this.tbar){
+            this.elements += ',tbar';
+            this.topToolbar = this.createToolbar(this.tbar);
+            this.tbar = null;
+
+        }
+        if(this.bbar){
+            this.elements += ',bbar';
+            this.bottomToolbar = this.createToolbar(this.bbar);
+            this.bbar = null;
+        }
+
+        if(this.header === true){
+            this.elements += ',header';
+            this.header = null;
+        }else if(this.headerCfg || (this.title && this.header !== false)){
+            this.elements += ',header';
+        }
+
+        if(this.footerCfg || this.footer === true){
+            this.elements += ',footer';
+            this.footer = null;
+        }
+
+        if(this.buttons){
+            this.fbar = this.buttons;
+            this.buttons = null;
+        }
+        if(this.fbar){
+            this.createFbar(this.fbar);
+        }
+        if(this.autoLoad){
+            this.on('render', this.doAutoLoad, this, {delay:10});
+        }
+    },
+
+    
+    createFbar : function(fbar){
+        var min = this.minButtonWidth;
+        this.elements += ',footer';
+        this.fbar = this.createToolbar(fbar, {
+            buttonAlign: this.buttonAlign,
+            toolbarCls: 'x-panel-fbar',
+            enableOverflow: false,
+            defaults: function(c){
+                return {
+                    minWidth: c.minWidth || min
+                };
+            }
+        });
+        
+        
+        
+        this.fbar.items.each(function(c){
+            c.minWidth = c.minWidth || this.minButtonWidth;
+        }, this);
+        this.buttons = this.fbar.items.items;
+    },
+
+    
+    createToolbar: function(tb, options){
+        var result;
+        
+        if(Ext.isArray(tb)){
+            tb = {
+                items: tb
+            };
+        }
+        result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
+        this.toolbars.push(result);
+        return result;
+    },
+
+    
+    createElement : function(name, pnode){
+        if(this[name]){
+            pnode.appendChild(this[name].dom);
+            return;
+        }
+
+        if(name === 'bwrap' || this.elements.indexOf(name) != -1){
+            if(this[name+'Cfg']){
+                this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
+            }else{
+                var el = document.createElement('div');
+                el.className = this[name+'Cls'];
+                this[name] = Ext.get(pnode.appendChild(el));
+            }
+            if(this[name+'CssClass']){
+                this[name].addClass(this[name+'CssClass']);
+            }
+            if(this[name+'Style']){
+                this[name].applyStyles(this[name+'Style']);
+            }
+        }
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.Panel.superclass.onRender.call(this, ct, position);
+        this.createClasses();
+
+        var el = this.el,
+            d = el.dom,
+            bw,
+            ts;
+
+
+        if(this.collapsible && !this.hideCollapseTool){
+            this.tools = this.tools ? this.tools.slice(0) : [];
+            this.tools[this.collapseFirst?'unshift':'push']({
+                id: 'toggle',
+                handler : this.toggleCollapse,
+                scope: this
+            });
+        }
+
+        if(this.tools){
+            ts = this.tools;
+            this.elements += (this.header !== false) ? ',header' : '';
+        }
+        this.tools = {};
+
+        el.addClass(this.baseCls);
+        if(d.firstChild){ 
+            this.header = el.down('.'+this.headerCls);
+            this.bwrap = el.down('.'+this.bwrapCls);
+            var cp = this.bwrap ? this.bwrap : el;
+            this.tbar = cp.down('.'+this.tbarCls);
+            this.body = cp.down('.'+this.bodyCls);
+            this.bbar = cp.down('.'+this.bbarCls);
+            this.footer = cp.down('.'+this.footerCls);
+            this.fromMarkup = true;
+        }
+        if (this.preventBodyReset === true) {
+            el.addClass('x-panel-reset');
+        }
+        if(this.cls){
+            el.addClass(this.cls);
+        }
+
+        if(this.buttons){
+            this.elements += ',footer';
+        }
+
+        
+
+        
+        if(this.frame){
+            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
+
+            this.createElement('header', d.firstChild.firstChild.firstChild);
+            this.createElement('bwrap', d);
+
+            
+            bw = this.bwrap.dom;
+            var ml = d.childNodes[1], bl = d.childNodes[2];
+            bw.appendChild(ml);
+            bw.appendChild(bl);
+
+            var mc = bw.firstChild.firstChild.firstChild;
+            this.createElement('tbar', mc);
+            this.createElement('body', mc);
+            this.createElement('bbar', mc);
+            this.createElement('footer', bw.lastChild.firstChild.firstChild);
+
+            if(!this.footer){
+                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
+            }
+            
+            this.ft = Ext.get(this.bwrap.dom.lastChild);
+            this.mc = Ext.get(mc);
+        }else{
+            this.createElement('header', d);
+            this.createElement('bwrap', d);
+
+            
+            bw = this.bwrap.dom;
+            this.createElement('tbar', bw);
+            this.createElement('body', bw);
+            this.createElement('bbar', bw);
+            this.createElement('footer', bw);
+
+            if(!this.header){
+                this.body.addClass(this.bodyCls + '-noheader');
+                if(this.tbar){
+                    this.tbar.addClass(this.tbarCls + '-noheader');
+                }
+            }
+        }
+
+        if(Ext.isDefined(this.padding)){
+            this.body.setStyle('padding', this.body.addUnits(this.padding));
+        }
+
+        if(this.border === false){
+            this.el.addClass(this.baseCls + '-noborder');
+            this.body.addClass(this.bodyCls + '-noborder');
+            if(this.header){
+                this.header.addClass(this.headerCls + '-noborder');
+            }
+            if(this.footer){
+                this.footer.addClass(this.footerCls + '-noborder');
+            }
+            if(this.tbar){
+                this.tbar.addClass(this.tbarCls + '-noborder');
+            }
+            if(this.bbar){
+                this.bbar.addClass(this.bbarCls + '-noborder');
+            }
+        }
+
+        if(this.bodyBorder === false){
+           this.body.addClass(this.bodyCls + '-noborder');
+        }
+
+        this.bwrap.enableDisplayMode('block');
+
+        if(this.header){
+            this.header.unselectable();
+
+            
+            if(this.headerAsText){
+                this.header.dom.innerHTML =
+                    '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
+
+                if(this.iconCls){
+                    this.setIconClass(this.iconCls);
+                }
+            }
+        }
+
+        if(this.floating){
+            this.makeFloating(this.floating);
+        }
+
+        if(this.collapsible && this.titleCollapse && this.header){
+            this.mon(this.header, 'click', this.toggleCollapse, this);
+            this.header.setStyle('cursor', 'pointer');
+        }
+        if(ts){
+            this.addTool.apply(this, ts);
+        }
+
+        
+        if(this.fbar){
+            this.footer.addClass('x-panel-btns');
+            this.fbar.ownerCt = this;
+            this.fbar.render(this.footer);
+            this.footer.createChild({cls:'x-clear'});
+        }
+        if(this.tbar && this.topToolbar){
+            this.topToolbar.ownerCt = this;
+            this.topToolbar.render(this.tbar);
+        }
+        if(this.bbar && this.bottomToolbar){
+            this.bottomToolbar.ownerCt = this;
+            this.bottomToolbar.render(this.bbar);
+        }
+    },
+
+    
+    setIconClass : function(cls){
+        var old = this.iconCls;
+        this.iconCls = cls;
+        if(this.rendered && this.header){
+            if(this.frame){
+                this.header.addClass('x-panel-icon');
+                this.header.replaceClass(old, this.iconCls);
+            }else{
+                var hd = this.header,
+                    img = hd.child('img.x-panel-inline-icon');
+                if(img){
+                    Ext.fly(img).replaceClass(old, this.iconCls);
+                }else{
+                    var hdspan = hd.child('span.' + this.headerTextCls);
+                    if (hdspan) {
+                        Ext.DomHelper.insertBefore(hdspan.dom, {
+                            tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
+                        });
+                    }
+                 }
+            }
+        }
+        this.fireEvent('iconchange', this, cls, old);
+    },
+
+    
+    makeFloating : function(cfg){
+        this.floating = true;
+        this.el = new Ext.Layer(Ext.apply({}, cfg, {
+            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
+            shadowOffset: this.shadowOffset,
+            constrain:false,
+            shim: this.shim === false ? false : undefined
+        }), this.el);
+    },
+
+    
+    getTopToolbar : function(){
+        return this.topToolbar;
+    },
+
+    
+    getBottomToolbar : function(){
+        return this.bottomToolbar;
+    },
+
+    
+    getFooterToolbar : function() {
+        return this.fbar;
+    },
+
+    
+    addButton : function(config, handler, scope){
+        if(!this.fbar){
+            this.createFbar([]);
+        }
+        if(handler){
+            if(Ext.isString(config)){
+                config = {text: config};
+            }
+            config = Ext.apply({
+                handler: handler,
+                scope: scope
+            }, config);
+        }
+        return this.fbar.add(config);
+    },
+
+    
+    addTool : function(){
+        if(!this.rendered){
+            if(!this.tools){
+                this.tools = [];
+            }
+            Ext.each(arguments, function(arg){
+                this.tools.push(arg);
+            }, this);
+            return;
+        }
+         
+        if(!this[this.toolTarget]){
+            return;
+        }
+        if(!this.toolTemplate){
+            
+            var tt = new Ext.Template(
+                 '<div class="x-tool x-tool-{id}">&#160;</div>'
+            );
+            tt.disableFormats = true;
+            tt.compile();
+            Ext.Panel.prototype.toolTemplate = tt;
+        }
+        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
+            var tc = a[i];
+            if(!this.tools[tc.id]){
+                var overCls = 'x-tool-'+tc.id+'-over';
+                var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
+                this.tools[tc.id] = t;
+                t.enableDisplayMode('block');
+                this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
+                if(tc.on){
+                    this.mon(t, tc.on);
+                }
+                if(tc.hidden){
+                    t.hide();
+                }
+                if(tc.qtip){
+                    if(Ext.isObject(tc.qtip)){
+                        Ext.QuickTips.register(Ext.apply({
+                              target: t.id
+                        }, tc.qtip));
+                    } else {
+                        t.dom.qtip = tc.qtip;
+                    }
+                }
+                t.addClassOnOver(overCls);
+            }
+        }
+    },
+
+    onLayout : function(shallow, force){
+        Ext.Panel.superclass.onLayout.apply(this, arguments);
+        if(this.hasLayout && this.toolbars.length > 0){
+            Ext.each(this.toolbars, function(tb){
+                tb.doLayout(undefined, force);
+            });
+            this.syncHeight();
+        }
+    },
+
+    syncHeight : function(){
+        var h = this.toolbarHeight,
+                bd = this.body,
+                lsh = this.lastSize.height,
+                sz;
+
+        if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
+            return;
+        }
+
+
+        if(h != this.getToolbarHeight()){
+            h = Math.max(0, lsh - this.getFrameHeight());
+            bd.setHeight(h);
+            sz = bd.getSize();
+            this.toolbarHeight = this.getToolbarHeight();
+            this.onBodyResize(sz.width, sz.height);
+        }
+    },
+
+    
+    onShow : function(){
+        if(this.floating){
+            return this.el.show();
+        }
+        Ext.Panel.superclass.onShow.call(this);
+    },
+
+    
+    onHide : function(){
+        if(this.floating){
+            return this.el.hide();
+        }
+        Ext.Panel.superclass.onHide.call(this);
+    },
+
+    
+    createToolHandler : function(t, tc, overCls, panel){
+        return function(e){
+            t.removeClass(overCls);
+            if(tc.stopEvent !== false){
+                e.stopEvent();
+            }
+            if(tc.handler){
+                tc.handler.call(tc.scope || t, e, t, panel, tc);
+            }
+        };
+    },
+
+    
+    afterRender : function(){
+        if(this.floating && !this.hidden){
+            this.el.show();
+        }
+        if(this.title){
+            this.setTitle(this.title);
+        }
+        Ext.Panel.superclass.afterRender.call(this); 
+        if (this.collapsed) {
+            this.collapsed = false;
+            this.collapse(false);
+        }
+        this.initEvents();
+    },
+
+    
+    getKeyMap : function(){
+        if(!this.keyMap){
+            this.keyMap = new Ext.KeyMap(this.el, this.keys);
+        }
+        return this.keyMap;
+    },
+
+    
+    initEvents : function(){
+        if(this.keys){
+            this.getKeyMap();
+        }
+        if(this.draggable){
+            this.initDraggable();
+        }
+        if(this.toolbars.length > 0){
+            Ext.each(this.toolbars, function(tb){
+                tb.doLayout();
+                tb.on({
+                    scope: this,
+                    afterlayout: this.syncHeight,
+                    remove: this.syncHeight
+                });
+            }, this);
+            this.syncHeight();
+        }
+
+    },
+
+    
+    initDraggable : function(){
+        
+        this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
+    },
+
+    
+    beforeEffect : function(anim){
+        if(this.floating){
+            this.el.beforeAction();
+        }
+        if(anim !== false){
+            this.el.addClass('x-panel-animated');
+        }
+    },
+
+    
+    afterEffect : function(anim){
+        this.syncShadow();
+        this.el.removeClass('x-panel-animated');
+    },
+
+    
+    createEffect : function(a, cb, scope){
+        var o = {
+            scope:scope,
+            block:true
+        };
+        if(a === true){
+            o.callback = cb;
+            return o;
+        }else if(!a.callback){
+            o.callback = cb;
+        }else { 
+            o.callback = function(){
+                cb.call(scope);
+                Ext.callback(a.callback, a.scope);
+            };
+        }
+        return Ext.applyIf(o, a);
+    },
+
+    
+    collapse : function(animate){
+        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
+            return;
+        }
+        var doAnim = animate === true || (animate !== false && this.animCollapse);
+        this.beforeEffect(doAnim);
+        this.onCollapse(doAnim, animate);
+        return this;
+    },
+
+    
+    onCollapse : function(doAnim, animArg){
+        if(doAnim){
+            this[this.collapseEl].slideOut(this.slideAnchor,
+                    Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
+                        this.collapseDefaults));
+        }else{
+            this[this.collapseEl].hide(this.hideMode);
+            this.afterCollapse(false);
+        }
+    },
+
+    
+    afterCollapse : function(anim){
+        this.collapsed = true;
+        this.el.addClass(this.collapsedCls);
+        if(anim !== false){
+            this[this.collapseEl].hide(this.hideMode);
+        }
+        this.afterEffect(anim);
+
+        
+        this.cascade(function(c) {
+            if (c.lastSize) {
+                c.lastSize = { width: undefined, height: undefined };
+            }
+        });
+        this.fireEvent('collapse', this);
+    },
+
+    
+    expand : function(animate){
+        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
+            return;
+        }
+        var doAnim = animate === true || (animate !== false && this.animCollapse);
+        this.el.removeClass(this.collapsedCls);
+        this.beforeEffect(doAnim);
+        this.onExpand(doAnim, animate);
+        return this;
+    },
+
+    
+    onExpand : function(doAnim, animArg){
+        if(doAnim){
+            this[this.collapseEl].slideIn(this.slideAnchor,
+                    Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
+                        this.expandDefaults));
+        }else{
+            this[this.collapseEl].show(this.hideMode);
+            this.afterExpand(false);
+        }
+    },
+
+    
+    afterExpand : function(anim){
+        this.collapsed = false;
+        if(anim !== false){
+            this[this.collapseEl].show(this.hideMode);
+        }
+        this.afterEffect(anim);
+        if (this.deferLayout) {
+            delete this.deferLayout;
+            this.doLayout(true);
+        }
+        this.fireEvent('expand', this);
+    },
+
+    
+    toggleCollapse : function(animate){
+        this[this.collapsed ? 'expand' : 'collapse'](animate);
+        return this;
+    },
+
+    
+    onDisable : function(){
+        if(this.rendered && this.maskDisabled){
+            this.el.mask();
+        }
+        Ext.Panel.superclass.onDisable.call(this);
+    },
+
+    
+    onEnable : function(){
+        if(this.rendered && this.maskDisabled){
+            this.el.unmask();
+        }
+        Ext.Panel.superclass.onEnable.call(this);
+    },
+
+    
+    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
+        var w = adjWidth,
+            h = adjHeight;
+
+        if(Ext.isDefined(w) || Ext.isDefined(h)){
+            if(!this.collapsed){
+                
+                
+                
+
+                if(Ext.isNumber(w)){
+                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
+                } else if (w == 'auto') {
+                    w = this.body.setWidth('auto').dom.offsetWidth;
+                } else {
+                    w = this.body.dom.offsetWidth;
+                }
+
+                if(this.tbar){
+                    this.tbar.setWidth(w);
+                    if(this.topToolbar){
+                        this.topToolbar.setSize(w);
+                    }
+                }
+                if(this.bbar){
+                    this.bbar.setWidth(w);
+                    if(this.bottomToolbar){
+                        this.bottomToolbar.setSize(w);
+                        
+                        if (Ext.isIE) {
+                            this.bbar.setStyle('position', 'static');
+                            this.bbar.setStyle('position', '');
+                        }
+                    }
+                }
+                if(this.footer){
+                    this.footer.setWidth(w);
+                    if(this.fbar){
+                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
+                    }
+                }
+
+                
+                if(Ext.isNumber(h)){
+                    h = Math.max(0, h - this.getFrameHeight());
+                    
+                    this.body.setHeight(h);
+                }else if(h == 'auto'){
+                    this.body.setHeight(h);
+                }
+
+                if(this.disabled && this.el._mask){
+                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
+                }
+            }else{
+                
+                this.queuedBodySize = {width: w, height: h};
+                if(!this.queuedExpand && this.allowQueuedExpand !== false){
+                    this.queuedExpand = true;
+                    this.on('expand', function(){
+                        delete this.queuedExpand;
+                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
+                    }, this, {single:true});
+                }
+            }
+            this.onBodyResize(w, h);
+        }
+        this.syncShadow();
+        Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
+
+    },
+
+    
+    onBodyResize: function(w, h){
+        this.fireEvent('bodyresize', this, w, h);
+    },
+
+    
+    getToolbarHeight: function(){
+        var h = 0;
+        if(this.rendered){
+            Ext.each(this.toolbars, function(tb){
+                h += tb.getHeight();
+            }, this);
+        }
+        return h;
+    },
+
+    
+    adjustBodyHeight : function(h){
+        return h;
+    },
+
+    
+    adjustBodyWidth : function(w){
+        return w;
+    },
+
+    
+    onPosition : function(){
+        this.syncShadow();
+    },
+
+    
+    getFrameWidth : function(){
+        var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
+
+        if(this.frame){
+            var l = this.bwrap.dom.firstChild;
+            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
+            w += this.mc.getFrameWidth('lr');
+        }
+        return w;
+    },
+
+    
+    getFrameHeight : function() {
+        var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
+        h += (this.tbar ? this.tbar.getHeight() : 0) +
+             (this.bbar ? this.bbar.getHeight() : 0);
+
+        if(this.frame){
+            h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
+        }else{
+            h += (this.header ? this.header.getHeight() : 0) +
+                (this.footer ? this.footer.getHeight() : 0);
+        }
+        return h;
+    },
+
+    
+    getInnerWidth : function(){
+        return this.getSize().width - this.getFrameWidth();
+    },
+
+    
+    getInnerHeight : function(){
+        return this.body.getHeight();
+        
+    },
+
+    
+    syncShadow : function(){
+        if(this.floating){
+            this.el.sync(true);
+        }
+    },
+
+    
+    getLayoutTarget : function(){
+        return this.body;
+    },
+
+    
+    getContentTarget : function(){
+        return this.body;
+    },
+
+    
+    setTitle : function(title, iconCls){
+        this.title = title;
+        if(this.header && this.headerAsText){
+            this.header.child('span').update(title);
+        }
+        if(iconCls){
+            this.setIconClass(iconCls);
+        }
+        this.fireEvent('titlechange', this, title);
+        return this;
+    },
+
+    
+    getUpdater : function(){
+        return this.body.getUpdater();
+    },
+
+     
+    load : function(){
+        var um = this.body.getUpdater();
+        um.update.apply(um, arguments);
+        return this;
+    },
+
+    
+    beforeDestroy : function(){
+        Ext.Panel.superclass.beforeDestroy.call(this);
+        if(this.header){
+            this.header.removeAllListeners();
+        }
+        if(this.tools){
+            for(var k in this.tools){
+                Ext.destroy(this.tools[k]);
+            }
+        }
+        if(this.toolbars.length > 0){
+            Ext.each(this.toolbars, function(tb){
+                tb.un('afterlayout', this.syncHeight, this);
+                tb.un('remove', this.syncHeight, this);
+            }, this);
+        }
+        if(Ext.isArray(this.buttons)){
+            while(this.buttons.length) {
+                Ext.destroy(this.buttons[0]);
+            }
+        }
+        if(this.rendered){
+            Ext.destroy(
+                this.ft,
+                this.header,
+                this.footer,
+                this.tbar,
+                this.bbar,
+                this.body,
+                this.mc,
+                this.bwrap,
+                this.dd
+            );
+            if (this.fbar) {
+                Ext.destroy(
+                    this.fbar,
+                    this.fbar.el
+                );
+            }
+        }
+        Ext.destroy(this.toolbars);
+    },
+
+    
+    createClasses : function(){
+        this.headerCls = this.baseCls + '-header';
+        this.headerTextCls = this.baseCls + '-header-text';
+        this.bwrapCls = this.baseCls + '-bwrap';
+        this.tbarCls = this.baseCls + '-tbar';
+        this.bodyCls = this.baseCls + '-body';
+        this.bbarCls = this.baseCls + '-bbar';
+        this.footerCls = this.baseCls + '-footer';
+    },
+
+    
+    createGhost : function(cls, useShim, appendTo){
+        var el = document.createElement('div');
+        el.className = 'x-panel-ghost ' + (cls ? cls : '');
+        if(this.header){
+            el.appendChild(this.el.dom.firstChild.cloneNode(true));
+        }
+        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
+        el.style.width = this.el.dom.offsetWidth + 'px';;
+        if(!appendTo){
+            this.container.dom.appendChild(el);
+        }else{
+            Ext.getDom(appendTo).appendChild(el);
+        }
+        if(useShim !== false && this.el.useShim !== false){
+            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
+            layer.show();
+            return layer;
+        }else{
+            return new Ext.Element(el);
+        }
+    },
+
+    
+    doAutoLoad : function(){
+        var u = this.body.getUpdater();
+        if(this.renderer){
+            u.setRenderer(this.renderer);
+        }
+        u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
+    },
+
+    
+    getTool : function(id) {
+        return this.tools[id];
+    }
+
+
+});
+Ext.reg('panel', Ext.Panel);
+
+Ext.Editor = function(field, config){
+    if(field.field){
+        this.field = Ext.create(field.field, 'textfield');
+        config = Ext.apply({}, field); 
+        delete config.field;
+    }else{
+        this.field = field;
+    }
+    Ext.Editor.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.Editor, Ext.Component, {
+    
+    
+    allowBlur: true,
+    
+    
+    
+    
+    
+    value : "",
+    
+    alignment: "c-c?",
+    
+    offsets: [0, 0],
+    
+    shadow : "frame",
+    
+    constrain : false,
+    
+    swallowKeys : true,
+    
+    completeOnEnter : true,
+    
+    cancelOnEsc : true,
+    
+    updateEl : false,
+
+    initComponent : function(){
+        Ext.Editor.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            "beforestartedit",
+            
+            "startedit",
+            
+            "beforecomplete",
+            
+            "complete",
+            
+            "canceledit",
+            
+            "specialkey"
+        );
+    },
+
+    
+    onRender : function(ct, position){
+        this.el = new Ext.Layer({
+            shadow: this.shadow,
+            cls: "x-editor",
+            parentEl : ct,
+            shim : this.shim,
+            shadowOffset: this.shadowOffset || 4,
+            id: this.id,
+            constrain: this.constrain
+        });
+        if(this.zIndex){
+            this.el.setZIndex(this.zIndex);
+        }
+        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
+        if(this.field.msgTarget != 'title'){
+            this.field.msgTarget = 'qtip';
+        }
+        this.field.inEditor = true;
+        this.mon(this.field, {
+            scope: this,
+            blur: this.onBlur,
+            specialkey: this.onSpecialKey
+        });
+        if(this.field.grow){
+            this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
+        }
+        this.field.render(this.el).show();
+        this.field.getEl().dom.name = '';
+        if(this.swallowKeys){
+            this.field.el.swallowEvent([
+                'keypress', 
+                'keydown'   
+            ]);
+        }
+    },
+
+    
+    onSpecialKey : function(field, e){
+        var key = e.getKey(),
+            complete = this.completeOnEnter && key == e.ENTER,
+            cancel = this.cancelOnEsc && key == e.ESC;
+        if(complete || cancel){
+            e.stopEvent();
+            if(complete){
+                this.completeEdit();
+            }else{
+                this.cancelEdit();
+            }
+            if(field.triggerBlur){
+                field.triggerBlur();
+            }
+        }
+        this.fireEvent('specialkey', field, e);
+    },
+
+    
+    startEdit : function(el, value){
+        if(this.editing){
+            this.completeEdit();
+        }
+        this.boundEl = Ext.get(el);
+        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
+        if(!this.rendered){
+            this.render(this.parentEl || document.body);
+        }
+        if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
+            this.startValue = v;
+            this.field.reset();
+            this.field.setValue(v);
+            this.realign(true);
+            this.editing = true;
+            this.show();
+        }
+    },
+
+    
+    doAutoSize : function(){
+        if(this.autoSize){
+            var sz = this.boundEl.getSize(),
+                fs = this.field.getSize();
+
+            switch(this.autoSize){
+                case "width":
+                    this.setSize(sz.width, fs.height);
+                    break;
+                case "height":
+                    this.setSize(fs.width, sz.height);
+                    break;
+                case "none":
+                    this.setSize(fs.width, fs.height);
+                    break;
+                default:
+                    this.setSize(sz.width, sz.height);
+            }
+        }
+    },
+
+    
+    setSize : function(w, h){
+        delete this.field.lastSize;
+        this.field.setSize(w, h);
+        if(this.el){
+            
+            if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
+                
+                this.el.setSize(w, h);
+            }
+            this.el.sync();
+        }
+    },
+
+    
+    realign : function(autoSize){
+        if(autoSize === true){
+            this.doAutoSize();
+        }
+        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
+    },
+
+    
+    completeEdit : function(remainVisible){
+        if(!this.editing){
+            return;
+        }
+        
+        if (this.field.assertValue) {
+            this.field.assertValue();
+        }
+        var v = this.getValue();
+        if(!this.field.isValid()){
+            if(this.revertInvalid !== false){
+                this.cancelEdit(remainVisible);
+            }
+            return;
+        }
+        if(String(v) === String(this.startValue) && this.ignoreNoChange){
+            this.hideEdit(remainVisible);
+            return;
+        }
+        if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
+            v = this.getValue();
+            if(this.updateEl && this.boundEl){
+                this.boundEl.update(v);
+            }
+            this.hideEdit(remainVisible);
+            this.fireEvent("complete", this, v, this.startValue);
+        }
+    },
+
+    
+    onShow : function(){
+        this.el.show();
+        if(this.hideEl !== false){
+            this.boundEl.hide();
+        }
+        this.field.show().focus(false, true);
+        this.fireEvent("startedit", this.boundEl, this.startValue);
+    },
+
+    
+    cancelEdit : function(remainVisible){
+        if(this.editing){
+            var v = this.getValue();
+            this.setValue(this.startValue);
+            this.hideEdit(remainVisible);
+            this.fireEvent("canceledit", this, v, this.startValue);
+        }
+    },
+
+    
+    hideEdit: function(remainVisible){
+        if(remainVisible !== true){
+            this.editing = false;
+            this.hide();
+        }
+    },
+
+    
+    onBlur : function(){
+        
+        if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
+            this.completeEdit();
+        }
+    },
+
+    
+    onHide : function(){
+        if(this.editing){
+            this.completeEdit();
+            return;
+        }
+        this.field.blur();
+        if(this.field.collapse){
+            this.field.collapse();
+        }
+        this.el.hide();
+        if(this.hideEl !== false){
+            this.boundEl.show();
+        }
+    },
+
+    
+    setValue : function(v){
+        this.field.setValue(v);
+    },
+
+    
+    getValue : function(){
+        return this.field.getValue();
+    },
+
+    beforeDestroy : function(){
+        Ext.destroyMembers(this, 'field');
+
+        delete this.parentEl;
+        delete this.boundEl;
+    }
+});
+Ext.reg('editor', Ext.Editor);
+
+Ext.ColorPalette = Ext.extend(Ext.Component, {
+	
+    
+    itemCls : 'x-color-palette',
+    
+    value : null,
+    
+    clickEvent :'click',
+    
+    ctype : 'Ext.ColorPalette',
+
+    
+    allowReselect : false,
+
+    
+    colors : [
+        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
+        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
+        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
+        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
+        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
+    ],
+
+    
+    
+    
+    
+    initComponent : function(){
+        Ext.ColorPalette.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler, this.scope, true);
+        }    
+    },
+
+    
+    onRender : function(container, position){
+        this.autoEl = {
+            tag: 'div',
+            cls: this.itemCls
+        };
+        Ext.ColorPalette.superclass.onRender.call(this, container, position);
+        var t = this.tpl || new Ext.XTemplate(
+            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
+        );
+        t.overwrite(this.el, this.colors);
+        this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
+        if(this.clickEvent != 'click'){
+        	this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
+        }
+    },
+
+    
+    afterRender : function(){
+        Ext.ColorPalette.superclass.afterRender.call(this);
+        if(this.value){
+            var s = this.value;
+            this.value = null;
+            this.select(s, true);
+        }
+    },
+
+    
+    handleClick : function(e, t){
+        e.preventDefault();
+        if(!this.disabled){
+            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
+            this.select(c.toUpperCase());
+        }
+    },
+
+    
+    select : function(color, suppressEvent){
+        color = color.replace('#', '');
+        if(color != this.value || this.allowReselect){
+            var el = this.el;
+            if(this.value){
+                el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
+            }
+            el.child('a.color-'+color).addClass('x-color-palette-sel');
+            this.value = color;
+            if(suppressEvent !== true){
+                this.fireEvent('select', this, color);
+            }
+        }
+    }
+
+    
+});
+Ext.reg('colorpalette', Ext.ColorPalette);
+Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
+    
+    todayText : 'Today',
+    
+    okText : '&#160;OK&#160;',
+    
+    cancelText : 'Cancel',
+    
+    
+    
+    todayTip : '{0} (Spacebar)',
+    
+    minText : 'This date is before the minimum date',
+    
+    maxText : 'This date is after the maximum date',
+    
+    format : 'm/d/y',
+    
+    disabledDaysText : 'Disabled',
+    
+    disabledDatesText : 'Disabled',
+    
+    monthNames : Date.monthNames,
+    
+    dayNames : Date.dayNames,
+    
+    nextText : 'Next Month (Control+Right)',
+    
+    prevText : 'Previous Month (Control+Left)',
+    
+    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+    
+    startDay : 0,
+    
+    showToday : true,
+    
+    
+    
+    
+    
+
+    
+    
+    focusOnSelect: true,
+
+    
+    
+    initHour: 12, 
+
+    
+    initComponent : function(){
+        Ext.DatePicker.superclass.initComponent.call(this);
+
+        this.value = this.value ?
+                 this.value.clearTime(true) : new Date().clearTime();
+
+        this.addEvents(
+            
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler,  this.scope || this);
+        }
+
+        this.initDisabledDays();
+    },
+
+    
+    initDisabledDays : function(){
+        if(!this.disabledDatesRE && this.disabledDates){
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = '(?:';
+
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
+                if(i != len){
+                    re += '|';
+                }
+            }, this);
+            this.disabledDatesRE = new RegExp(re + ')');
+        }
+    },
+
+    
+    setDisabledDates : function(dd){
+        if(Ext.isArray(dd)){
+            this.disabledDates = dd;
+            this.disabledDatesRE = null;
+        }else{
+            this.disabledDatesRE = dd;
+        }
+        this.initDisabledDays();
+        this.update(this.value, true);
+    },
+
+    
+    setDisabledDays : function(dd){
+        this.disabledDays = dd;
+        this.update(this.value, true);
+    },
+
+    
+    setMinDate : function(dt){
+        this.minDate = dt;
+        this.update(this.value, true);
+    },
+
+    
+    setMaxDate : function(dt){
+        this.maxDate = dt;
+        this.update(this.value, true);
+    },
+
+    
+    setValue : function(value){
+        this.value = value.clearTime(true);
+        this.update(this.value);
+    },
+
+    
+    getValue : function(){
+        return this.value;
+    },
+
+    
+    focus : function(){
+        this.update(this.activeDate);
+    },
+
+    
+    onEnable: function(initial){
+        Ext.DatePicker.superclass.onEnable.call(this);
+        this.doDisabled(false);
+        this.update(initial ? this.value : this.activeDate);
+        if(Ext.isIE){
+            this.el.repaint();
+        }
+
+    },
+
+    
+    onDisable : function(){
+        Ext.DatePicker.superclass.onDisable.call(this);
+        this.doDisabled(true);
+        if(Ext.isIE && !Ext.isIE8){
+            
+             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
+                 Ext.fly(el).repaint();
+             });
+        }
+    },
+
+    
+    doDisabled : function(disabled){
+        this.keyNav.setDisabled(disabled);
+        this.prevRepeater.setDisabled(disabled);
+        this.nextRepeater.setDisabled(disabled);
+        if(this.showToday){
+            this.todayKeyListener.setDisabled(disabled);
+            this.todayBtn.setDisabled(disabled);
+        }
+    },
+
+    
+    onRender : function(container, position){
+        var m = [
+             '<table cellspacing="0">',
+                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
+                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
+                dn = this.dayNames,
+                i;
+        for(i = 0; i < 7; i++){
+            var d = this.startDay+i;
+            if(d > 6){
+                d = d-7;
+            }
+            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
+        }
+        m[m.length] = '</tr></thead><tbody><tr>';
+        for(i = 0; i < 42; i++) {
+            if(i % 7 === 0 && i !== 0){
+                m[m.length] = '</tr><tr>';
+            }
+            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
+        }
+        m.push('</tr></tbody></table></td></tr>',
+                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
+                '</table><div class="x-date-mp"></div>');
+
+        var el = document.createElement('div');
+        el.className = 'x-date-picker';
+        el.innerHTML = m.join('');
+
+        container.dom.insertBefore(el, position);
+
+        this.el = Ext.get(el);
+        this.eventEl = Ext.get(el.firstChild);
+
+        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
+            handler: this.showPrevMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
+            handler: this.showNextMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.monthPicker = this.el.down('div.x-date-mp');
+        this.monthPicker.enableDisplayMode('block');
+
+        this.keyNav = new Ext.KeyNav(this.eventEl, {
+            'left' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevMonth();
+                }else{
+                    this.update(this.activeDate.add('d', -1));
+                }
+            },
+
+            'right' : function(e){
+                if(e.ctrlKey){
+                    this.showNextMonth();
+                }else{
+                    this.update(this.activeDate.add('d', 1));
+                }
+            },
+
+            'up' : function(e){
+                if(e.ctrlKey){
+                    this.showNextYear();
+                }else{
+                    this.update(this.activeDate.add('d', -7));
+                }
+            },
+
+            'down' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevYear();
+                }else{
+                    this.update(this.activeDate.add('d', 7));
+                }
+            },
+
+            'pageUp' : function(e){
+                this.showNextMonth();
+            },
+
+            'pageDown' : function(e){
+                this.showPrevMonth();
+            },
+
+            'enter' : function(e){
+                e.stopPropagation();
+                return true;
+            },
+
+            scope : this
+        });
+
+        this.el.unselectable();
+
+        this.cells = this.el.select('table.x-date-inner tbody td');
+        this.textNodes = this.el.query('table.x-date-inner tbody span');
+
+        this.mbtn = new Ext.Button({
+            text: '&#160;',
+            tooltip: this.monthYearText,
+            renderTo: this.el.child('td.x-date-middle', true)
+        });
+        this.mbtn.el.child('em').addClass('x-btn-arrow');
+
+        if(this.showToday){
+            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
+            var today = (new Date()).dateFormat(this.format);
+            this.todayBtn = new Ext.Button({
+                renderTo: this.el.child('td.x-date-bottom', true),
+                text: String.format(this.todayText, today),
+                tooltip: String.format(this.todayTip, today),
+                handler: this.selectToday,
+                scope: this
+            });
+        }
+        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
+        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
+        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
+        this.onEnable(true);
+    },
+
+    
+    createMonthPicker : function(){
+        if(!this.monthPicker.dom.firstChild){
+            var buf = ['<table border="0" cellspacing="0">'];
+            for(var i = 0; i < 6; i++){
+                buf.push(
+                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
+                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
+                    i === 0 ?
+                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
+                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
+                );
+            }
+            buf.push(
+                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
+                    this.okText,
+                    '</button><button type="button" class="x-date-mp-cancel">',
+                    this.cancelText,
+                    '</button></td></tr>',
+                '</table>'
+            );
+            this.monthPicker.update(buf.join(''));
+
+            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
+            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+
+            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
+            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+
+            this.mpMonths.each(function(m, a, i){
+                i += 1;
+                if((i%2) === 0){
+                    m.dom.xmonth = 5 + Math.round(i * 0.5);
+                }else{
+                    m.dom.xmonth = Math.round((i-1) * 0.5);
+                }
+            });
+        }
+    },
+
+    
+    showMonthPicker : function(){
+        if(!this.disabled){
+            this.createMonthPicker();
+            var size = this.el.getSize();
+            this.monthPicker.setSize(size);
+            this.monthPicker.child('table').setSize(size);
+
+            this.mpSelMonth = (this.activeDate || this.value).getMonth();
+            this.updateMPMonth(this.mpSelMonth);
+            this.mpSelYear = (this.activeDate || this.value).getFullYear();
+            this.updateMPYear(this.mpSelYear);
+
+            this.monthPicker.slideIn('t', {duration:0.2});
+        }
+    },
+
+    
+    updateMPYear : function(y){
+        this.mpyear = y;
+        var ys = this.mpYears.elements;
+        for(var i = 1; i <= 10; i++){
+            var td = ys[i-1], y2;
+            if((i%2) === 0){
+                y2 = y + Math.round(i * 0.5);
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
+            }else{
+                y2 = y - (5-Math.round(i * 0.5));
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
+            }
+            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
+        }
+    },
+
+    
+    updateMPMonth : function(sm){
+        this.mpMonths.each(function(m, a, i){
+            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
+        });
+    },
+
+    
+    selectMPMonth : function(m){
+
+    },
+
+    
+    onMonthClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if(el.is('button.x-date-mp-cancel')){
+            this.hideMonthPicker();
+        }
+        else if(el.is('button.x-date-mp-ok')){
+            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
+            if(d.getMonth() != this.mpSelMonth){
+                
+                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
+            }
+            this.update(d);
+            this.hideMonthPicker();
+        }
+        else if((pn = el.up('td.x-date-mp-month', 2))){
+            this.mpMonths.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelMonth = pn.dom.xmonth;
+        }
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.mpYears.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelYear = pn.dom.xyear;
+        }
+        else if(el.is('a.x-date-mp-prev')){
+            this.updateMPYear(this.mpyear-10);
+        }
+        else if(el.is('a.x-date-mp-next')){
+            this.updateMPYear(this.mpyear+10);
+        }
+    },
+
+    
+    onMonthDblClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if((pn = el.up('td.x-date-mp-month', 2))){
+            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
+        }
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
+        }
+    },
+
+    
+    hideMonthPicker : function(disableAnim){
+        if(this.monthPicker){
+            if(disableAnim === true){
+                this.monthPicker.hide();
+            }else{
+                this.monthPicker.slideOut('t', {duration:0.2});
+            }
+        }
+    },
+
+    
+    showPrevMonth : function(e){
+        this.update(this.activeDate.add('mo', -1));
+    },
+
+    
+    showNextMonth : function(e){
+        this.update(this.activeDate.add('mo', 1));
+    },
+
+    
+    showPrevYear : function(){
+        this.update(this.activeDate.add('y', -1));
+    },
+
+    
+    showNextYear : function(){
+        this.update(this.activeDate.add('y', 1));
+    },
+
+    
+    handleMouseWheel : function(e){
+        e.stopEvent();
+        if(!this.disabled){
+            var delta = e.getWheelDelta();
+            if(delta > 0){
+                this.showPrevMonth();
+            } else if(delta < 0){
+                this.showNextMonth();
+            }
+        }
+    },
+
+    
+    handleDateClick : function(e, t){
+        e.stopEvent();
+        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
+            this.cancelFocus = this.focusOnSelect === false;
+            this.setValue(new Date(t.dateValue));
+            delete this.cancelFocus;
+            this.fireEvent('select', this, this.value);
+        }
+    },
+
+    
+    selectToday : function(){
+        if(this.todayBtn && !this.todayBtn.disabled){
+            this.setValue(new Date().clearTime());
+            this.fireEvent('select', this, this.value);
+        }
+    },
+
+    
+    update : function(date, forceRefresh){
+        if(this.rendered){
+            var vd = this.activeDate, vis = this.isVisible();
+            this.activeDate = date;
+            if(!forceRefresh && vd && this.el){
+                var t = date.getTime();
+                if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
+                    this.cells.removeClass('x-date-selected');
+                    this.cells.each(function(c){
+                       if(c.dom.firstChild.dateValue == t){
+                           c.addClass('x-date-selected');
+                           if(vis && !this.cancelFocus){
+                               Ext.fly(c.dom.firstChild).focus(50);
+                           }
+                           return false;
+                       }
+                    }, this);
+                    return;
+                }
+            }
+            var days = date.getDaysInMonth(),
+                firstOfMonth = date.getFirstDateOfMonth(),
+                startingPos = firstOfMonth.getDay()-this.startDay;
+
+            if(startingPos < 0){
+                startingPos += 7;
+            }
+            days += startingPos;
+
+            var pm = date.add('mo', -1),
+                prevStart = pm.getDaysInMonth()-startingPos,
+                cells = this.cells.elements,
+                textEls = this.textNodes,
+                
+                d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
+                today = new Date().clearTime().getTime(),
+                sel = date.clearTime(true).getTime(),
+                min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
+                max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
+                ddMatch = this.disabledDatesRE,
+                ddText = this.disabledDatesText,
+                ddays = this.disabledDays ? this.disabledDays.join('') : false,
+                ddaysText = this.disabledDaysText,
+                format = this.format;
+
+            if(this.showToday){
+                var td = new Date().clearTime(),
+                    disable = (td < min || td > max ||
+                    (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
+                    (ddays && ddays.indexOf(td.getDay()) != -1));
+
+                if(!this.disabled){
+                    this.todayBtn.setDisabled(disable);
+                    this.todayKeyListener[disable ? 'disable' : 'enable']();
+                }
+            }
+
+            var setCellClass = function(cal, cell){
+                cell.title = '';
+                var t = d.clearTime(true).getTime();
+                cell.firstChild.dateValue = t;
+                if(t == today){
+                    cell.className += ' x-date-today';
+                    cell.title = cal.todayText;
+                }
+                if(t == sel){
+                    cell.className += ' x-date-selected';
+                    if(vis){
+                        Ext.fly(cell.firstChild).focus(50);
+                    }
+                }
+                
+                if(t < min) {
+                    cell.className = ' x-date-disabled';
+                    cell.title = cal.minText;
+                    return;
+                }
+                if(t > max) {
+                    cell.className = ' x-date-disabled';
+                    cell.title = cal.maxText;
+                    return;
+                }
+                if(ddays){
+                    if(ddays.indexOf(d.getDay()) != -1){
+                        cell.title = ddaysText;
+                        cell.className = ' x-date-disabled';
+                    }
+                }
+                if(ddMatch && format){
+                    var fvalue = d.dateFormat(format);
+                    if(ddMatch.test(fvalue)){
+                        cell.title = ddText.replace('%0', fvalue);
+                        cell.className = ' x-date-disabled';
+                    }
+                }
+            };
+
+            var i = 0;
+            for(; i < startingPos; i++) {
+                textEls[i].innerHTML = (++prevStart);
+                d.setDate(d.getDate()+1);
+                cells[i].className = 'x-date-prevday';
+                setCellClass(this, cells[i]);
+            }
+            for(; i < days; i++){
+                var intDay = i - startingPos + 1;
+                textEls[i].innerHTML = (intDay);
+                d.setDate(d.getDate()+1);
+                cells[i].className = 'x-date-active';
+                setCellClass(this, cells[i]);
+            }
+            var extraDays = 0;
+            for(; i < 42; i++) {
+                 textEls[i].innerHTML = (++extraDays);
+                 d.setDate(d.getDate()+1);
+                 cells[i].className = 'x-date-nextday';
+                 setCellClass(this, cells[i]);
+            }
+
+            this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
+
+            if(!this.internalRender){
+                var main = this.el.dom.firstChild,
+                    w = main.offsetWidth;
+                this.el.setWidth(w + this.el.getBorderWidth('lr'));
+                Ext.fly(main).setWidth(w);
+                this.internalRender = true;
+                
+                
+                
+                if(Ext.isOpera && !this.secondPass){
+                    main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
+                    this.secondPass = true;
+                    this.update.defer(10, this, [date]);
+                }
+            }
+        }
+    },
+
+    
+    beforeDestroy : function() {
+        if(this.rendered){
+            Ext.destroy(
+                this.keyNav,
+                this.monthPicker,
+                this.eventEl,
+                this.mbtn,
+                this.nextRepeater,
+                this.prevRepeater,
+                this.cells.el,
+                this.todayBtn
+            );
+            delete this.textNodes;
+            delete this.cells.elements;
+        }
+    }
+
+    
+});
+
+Ext.reg('datepicker', Ext.DatePicker);
+
+Ext.LoadMask = function(el, config){
+    this.el = Ext.get(el);
+    Ext.apply(this, config);
+    if(this.store){
+        this.store.on({
+            scope: this,
+            beforeload: this.onBeforeLoad,
+            load: this.onLoad,
+            exception: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, false);
+    }else{
+        var um = this.el.getUpdater();
+        um.showLoadIndicator = false; 
+        um.on({
+            scope: this,
+            beforeupdate: this.onBeforeLoad,
+            update: this.onLoad,
+            failure: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, true);
+    }
+};
+
+Ext.LoadMask.prototype = {
+    
+    
+    
+    msg : 'Loading...',
+    
+    msgCls : 'x-mask-loading',
+
+    
+    disabled: false,
+
+    
+    disable : function(){
+       this.disabled = true;
+    },
+
+    
+    enable : function(){
+        this.disabled = false;
+    },
+
+    
+    onLoad : function(){
+        this.el.unmask(this.removeMask);
+    },
+
+    
+    onBeforeLoad : function(){
+        if(!this.disabled){
+            this.el.mask(this.msg, this.msgCls);
+        }
+    },
+
+    
+    show: function(){
+        this.onBeforeLoad();
+    },
+
+    
+    hide: function(){
+        this.onLoad();
+    },
+
+    
+    destroy : function(){
+        if(this.store){
+            this.store.un('beforeload', this.onBeforeLoad, this);
+            this.store.un('load', this.onLoad, this);
+            this.store.un('exception', this.onLoad, this);
+        }else{
+            var um = this.el.getUpdater();
+            um.un('beforeupdate', this.onBeforeLoad, this);
+            um.un('update', this.onLoad, this);
+            um.un('failure', this.onLoad, this);
+        }
+    }
+};
+Ext.slider.Thumb = Ext.extend(Object, {
+    
+    
+    dragging: false,
+
+    
+    constructor: function(config) {
+        
+        Ext.apply(this, config || {}, {
+            cls: 'x-slider-thumb',
+
+            
+            constrain: false
+        });
+
+        Ext.slider.Thumb.superclass.constructor.call(this, config);
+
+        if (this.slider.vertical) {
+            Ext.apply(this, Ext.slider.Thumb.Vertical);
+        }
+    },
+
+    
+    render: function() {
+        this.el = this.slider.innerEl.insertFirst({cls: this.cls});
+
+        this.initEvents();
+    },
+
+    
+    enable: function() {
+        this.disabled = false;
+        this.el.removeClass(this.slider.disabledClass);
+    },
+
+    
+    disable: function() {
+        this.disabled = true;
+        this.el.addClass(this.slider.disabledClass);
+    },
+
+    
+    initEvents: function() {
+        var el = this.el;
+
+        el.addClassOnOver('x-slider-thumb-over');
+
+        this.tracker = new Ext.dd.DragTracker({
+            onBeforeStart: this.onBeforeDragStart.createDelegate(this),
+            onStart      : this.onDragStart.createDelegate(this),
+            onDrag       : this.onDrag.createDelegate(this),
+            onEnd        : this.onDragEnd.createDelegate(this),
+            tolerance    : 3,
+            autoStart    : 300
+        });
+
+        this.tracker.initEl(el);
+    },
+
+    
+    onBeforeDragStart : function(e) {
+        if (this.disabled) {
+            return false;
+        } else {
+            this.slider.promoteThumb(this);
+            return true;
+        }
+    },
+
+    
+    onDragStart: function(e){
+        this.el.addClass('x-slider-thumb-drag');
+        this.dragging = true;
+        this.dragStartValue = this.value;
+
+        this.slider.fireEvent('dragstart', this.slider, e, this);
+    },
+
+    
+    onDrag: function(e) {
+        var slider   = this.slider,
+            index    = this.index,
+            newValue = this.getNewValue();
+
+        if (this.constrain) {
+            var above = slider.thumbs[index + 1],
+                below = slider.thumbs[index - 1];
+
+            if (below != undefined && newValue <= below.value) newValue = below.value;
+            if (above != undefined && newValue >= above.value) newValue = above.value;
+        }
+
+        slider.setValue(index, newValue, false);
+        slider.fireEvent('drag', slider, e, this);
+    },
+
+    getNewValue: function() {
+        var slider   = this.slider,
+            pos      = slider.innerEl.translatePoints(this.tracker.getXY());
+
+        return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
+    },
+
+    
+    onDragEnd: function(e) {
+        var slider = this.slider,
+            value  = this.value;
+
+        this.el.removeClass('x-slider-thumb-drag');
+
+        this.dragging = false;
+        slider.fireEvent('dragend', slider, e);
+
+        if (this.dragStartValue != value) {
+            slider.fireEvent('changecomplete', slider, value, this);
+        }
+    },
+    
+    
+    destroy: function(){
+        Ext.destroyMembers(this, 'tracker', 'el');
+    }
+});
+
+
+Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
+    
+    
+    vertical: false,
+    
+    minValue: 0,
+    
+    maxValue: 100,
+    
+    decimalPrecision: 0,
+    
+    keyIncrement: 1,
+    
+    increment: 0,
+
+    
+    clickRange: [5,15],
+
+    
+    clickToChange : true,
+    
+    animate: true,
+    
+    constrainThumbs: true,
+
+    
+    topThumbZIndex: 10000,
+
+    
+    initComponent : function(){
+        if(!Ext.isDefined(this.value)){
+            this.value = this.minValue;
+        }
+
+        
+        this.thumbs = [];
+
+        Ext.slider.MultiSlider.superclass.initComponent.call(this);
+
+        this.keyIncrement = Math.max(this.increment, this.keyIncrement);
+        this.addEvents(
+            
+            'beforechange',
+
+            
+            'change',
+
+            
+            'changecomplete',
+
+            
+            'dragstart',
+
+            
+            'drag',
+
+            
+            'dragend'
+        );
+
+        
+        if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
+
+        var values = this.values;
+
+        for (var i=0; i < values.length; i++) {
+            this.addThumb(values[i]);
+        }
+
+        if(this.vertical){
+            Ext.apply(this, Ext.slider.Vertical);
+        }
+    },
+
+    
+    addThumb: function(value) {
+        var thumb = new Ext.slider.Thumb({
+            value    : value,
+            slider   : this,
+            index    : this.thumbs.length,
+            constrain: this.constrainThumbs
+        });
+        this.thumbs.push(thumb);
+
+        
+        if (this.rendered) thumb.render();
+    },
+
+    
+    promoteThumb: function(topThumb) {
+        var thumbs = this.thumbs,
+            zIndex, thumb;
+
+        for (var i = 0, j = thumbs.length; i < j; i++) {
+            thumb = thumbs[i];
+
+            if (thumb == topThumb) {
+                zIndex = this.topThumbZIndex;
+            } else {
+                zIndex = '';
+            }
+
+            thumb.el.setStyle('zIndex', zIndex);
+        }
+    },
+
+    
+    onRender : function() {
+        this.autoEl = {
+            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
+            cn : {
+                cls: 'x-slider-end',
+                cn : {
+                    cls:'x-slider-inner',
+                    cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
+                }
+            }
+        };
+
+        Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
+
+        this.endEl   = this.el.first();
+        this.innerEl = this.endEl.first();
+        this.focusEl = this.innerEl.child('.x-slider-focus');
+
+        
+        for (var i=0; i < this.thumbs.length; i++) {
+            this.thumbs[i].render();
+        }
+
+        
+        var thumb      = this.innerEl.child('.x-slider-thumb');
+        this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
+
+        this.initEvents();
+    },
+
+    
+    initEvents : function(){
+        this.mon(this.el, {
+            scope    : this,
+            mousedown: this.onMouseDown,
+            keydown  : this.onKeyDown
+        });
+
+        this.focusEl.swallowEvent("click", true);
+    },
+
+    
+    onMouseDown : function(e){
+        if(this.disabled){
+            return;
+        }
+
+        
+        var thumbClicked = false;
+        for (var i=0; i < this.thumbs.length; i++) {
+            thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
+        }
+
+        if (this.clickToChange && !thumbClicked) {
+            var local = this.innerEl.translatePoints(e.getXY());
+            this.onClickChange(local);
+        }
+        this.focus();
+    },
+
+    
+    onClickChange : function(local) {
+        if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
+            
+            var thumb = this.getNearest(local, 'left'),
+                index = thumb.index;
+
+            this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
+        }
+    },
+
+    
+    getNearest: function(local, prop) {
+        var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
+            clickValue = this.reverseValue(localValue),
+            nearestDistance = (this.maxValue - this.minValue) + 5, 
+            index = 0,
+            nearest = null;
+
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                value = thumb.value,
+                dist  = Math.abs(value - clickValue);
+
+            if (Math.abs(dist <= nearestDistance)) {
+                nearest = thumb;
+                index = i;
+                nearestDistance = dist;
+            }
+        }
+        return nearest;
+    },
+
+    
+    onKeyDown : function(e){
+        
+        if(this.disabled || this.thumbs.length !== 1){
+            e.preventDefault();
+            return;
+        }
+        var k = e.getKey(),
+            val;
+        switch(k){
+            case e.UP:
+            case e.RIGHT:
+                e.stopEvent();
+                val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
+                this.setValue(0, val, undefined, true);
+            break;
+            case e.DOWN:
+            case e.LEFT:
+                e.stopEvent();
+                val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
+                this.setValue(0, val, undefined, true);
+            break;
+            default:
+                e.preventDefault();
+        }
+    },
+
+    
+    doSnap : function(value){
+        if (!(this.increment && value)) {
+            return value;
+        }
+        var newValue = value,
+            inc = this.increment,
+            m = value % inc;
+        if (m != 0) {
+            newValue -= m;
+            if (m * 2 >= inc) {
+                newValue += inc;
+            } else if (m * 2 < -inc) {
+                newValue -= inc;
+            }
+        }
+        return newValue.constrain(this.minValue,  this.maxValue);
+    },
+
+    
+    afterRender : function(){
+        Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
+
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i];
+
+            if (thumb.value !== undefined) {
+                var v = this.normalizeValue(thumb.value);
+
+                if (v !== thumb.value) {
+                    
+                    this.setValue(i, v, false);
+                } else {
+                    this.moveThumb(i, this.translateValue(v), false);
+                }
+            }
+        };
+    },
+
+    
+    getRatio : function(){
+        var w = this.innerEl.getWidth(),
+            v = this.maxValue - this.minValue;
+        return v == 0 ? w : (w/v);
+    },
+
+    
+    normalizeValue : function(v){
+        v = this.doSnap(v);
+        v = Ext.util.Format.round(v, this.decimalPrecision);
+        v = v.constrain(this.minValue, this.maxValue);
+        return v;
+    },
+
+    
+    setMinValue : function(val){
+        this.minValue = val;
+        var i = 0,
+            thumbs = this.thumbs,
+            len = thumbs.length,
+            t;
+            
+        for(; i < len; ++i){
+            t = thumbs[i];
+            t.value = t.value < val ? val : t.value;
+        }
+        this.syncThumb();
+    },
+
+    
+    setMaxValue : function(val){
+        this.maxValue = val;
+        var i = 0,
+            thumbs = this.thumbs,
+            len = thumbs.length,
+            t;
+            
+        for(; i < len; ++i){
+            t = thumbs[i];
+            t.value = t.value > val ? val : t.value;
+        }
+        this.syncThumb();
+    },
+
+    
+    setValue : function(index, v, animate, changeComplete) {
+        var thumb = this.thumbs[index],
+            el    = thumb.el;
+
+        v = this.normalizeValue(v);
+
+        if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
+            thumb.value = v;
+            if(this.rendered){
+                this.moveThumb(index, this.translateValue(v), animate !== false);
+                this.fireEvent('change', this, v, thumb);
+                if(changeComplete){
+                    this.fireEvent('changecomplete', this, v, thumb);
+                }
+            }
+        }
+    },
+
+    
+    translateValue : function(v) {
+        var ratio = this.getRatio();
+        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
+    },
+
+    
+    reverseValue : function(pos){
+        var ratio = this.getRatio();
+        return (pos + (this.minValue * ratio)) / ratio;
+    },
+
+    
+    moveThumb: function(index, v, animate){
+        var thumb = this.thumbs[index].el;
+
+        if(!animate || this.animate === false){
+            thumb.setLeft(v);
+        }else{
+            thumb.shift({left: v, stopFx: true, duration:.35});
+        }
+    },
+
+    
+    focus : function(){
+        this.focusEl.focus(10);
+    },
+
+    
+    onResize : function(w, h){
+        var thumbs = this.thumbs,
+            len = thumbs.length,
+            i = 0;
+            
+        
+        for(; i < len; ++i){
+            thumbs[i].el.stopFx();    
+        }
+        
+        if(Ext.isNumber(w)){
+            this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
+        }
+        this.syncThumb();
+        Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
+    },
+
+    
+    onDisable: function(){
+        Ext.slider.MultiSlider.superclass.onDisable.call(this);
+
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                el    = thumb.el;
+
+            thumb.disable();
+
+            if(Ext.isIE){
+                
+                
+                var xy = el.getXY();
+                el.hide();
+
+                this.innerEl.addClass(this.disabledClass).dom.disabled = true;
+
+                if (!this.thumbHolder) {
+                    this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
+                }
+
+                this.thumbHolder.show().setXY(xy);
+            }
+        }
+    },
+
+    
+    onEnable: function(){
+        Ext.slider.MultiSlider.superclass.onEnable.call(this);
+
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                el    = thumb.el;
+
+            thumb.enable();
+
+            if (Ext.isIE) {
+                this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
+
+                if (this.thumbHolder) this.thumbHolder.hide();
+
+                el.show();
+                this.syncThumb();
+            }
+        }
+    },
+
+    
+    syncThumb : function() {
+        if (this.rendered) {
+            for (var i=0; i < this.thumbs.length; i++) {
+                this.moveThumb(i, this.translateValue(this.thumbs[i].value));
+            }
+        }
+    },
+
+    
+    getValue : function(index) {
+        return this.thumbs[index].value;
+    },
+
+    
+    getValues: function() {
+        var values = [];
+
+        for (var i=0; i < this.thumbs.length; i++) {
+            values.push(this.thumbs[i].value);
+        }
+
+        return values;
+    },
+
+    
+    beforeDestroy : function(){
+        var thumbs = this.thumbs;
+        for(var i = 0, len = thumbs.length; i < len; ++i){
+            thumbs[i].destroy();
+            thumbs[i] = null;
+        }
+        Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
+        Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
+    }
+});
+
+Ext.reg('multislider', Ext.slider.MultiSlider);
+
+
+Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
+    constructor: function(config) {
+      config = config || {};
+
+      Ext.applyIf(config, {
+          values: [config.value || 0]
+      });
+
+      Ext.slider.SingleSlider.superclass.constructor.call(this, config);
+    },
+
+    
+    getValue: function() {
+        
+        return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
+    },
+
+    
+    setValue: function(value, animate) {
+        var args = Ext.toArray(arguments),
+            len  = args.length;
+
+        
+        
+        
+        if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
+            args.unshift(0);
+        }
+
+        return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
+    },
+
+    
+    syncThumb : function() {
+        return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
+    },
+    
+    
+    getNearest : function(){
+        
+        return this.thumbs[0];    
+    }
+});
+
+
+Ext.Slider = Ext.slider.SingleSlider;
+
+Ext.reg('slider', Ext.slider.SingleSlider);
+
+
+Ext.slider.Vertical = {
+    onResize : function(w, h){
+        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
+        this.syncThumb();
+    },
+
+    getRatio : function(){
+        var h = this.innerEl.getHeight(),
+            v = this.maxValue - this.minValue;
+        return h/v;
+    },
+
+    moveThumb: function(index, v, animate) {
+        var thumb = this.thumbs[index],
+            el    = thumb.el;
+
+        if (!animate || this.animate === false) {
+            el.setBottom(v);
+        } else {
+            el.shift({bottom: v, stopFx: true, duration:.35});
+        }
+    },
+
+    onClickChange : function(local) {
+        if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
+            var thumb = this.getNearest(local, 'top'),
+                index = thumb.index,
+                value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
+
+            this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
+        }
+    }
+};
+
+
+Ext.slider.Thumb.Vertical = {
+    getNewValue: function() {
+        var slider   = this.slider,
+            innerEl  = slider.innerEl,
+            pos      = innerEl.translatePoints(this.tracker.getXY()),
+            bottom   = innerEl.getHeight() - pos.top;
+
+        return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
+    }
+};
+
+Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
+   
+    baseCls : 'x-progress',
+    
+    
+    animate : false,
+
+    
+    waitTimer : null,
+
+    
+    initComponent : function(){
+        Ext.ProgressBar.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            "update"
+        );
+    },
+
+    
+    onRender : function(ct, position){
+        var tpl = new Ext.Template(
+            '<div class="{cls}-wrap">',
+                '<div class="{cls}-inner">',
+                    '<div class="{cls}-bar">',
+                        '<div class="{cls}-text">',
+                            '<div>&#160;</div>',
+                        '</div>',
+                    '</div>',
+                    '<div class="{cls}-text {cls}-text-back">',
+                        '<div>&#160;</div>',
+                    '</div>',
+                '</div>',
+            '</div>'
+        );
+
+        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
+            : tpl.append(ct, {cls: this.baseCls}, true);
+                
+        if(this.id){
+            this.el.dom.id = this.id;
+        }
+        var inner = this.el.dom.firstChild;
+        this.progressBar = Ext.get(inner.firstChild);
+
+        if(this.textEl){
+            
+            this.textEl = Ext.get(this.textEl);
+            delete this.textTopEl;
+        }else{
+            
+            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
+            var textBackEl = Ext.get(inner.childNodes[1]);
+            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
+            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
+            this.textEl.setWidth(inner.offsetWidth);
+        }
+        this.progressBar.setHeight(inner.offsetHeight);
+    },
+    
+    
+    afterRender : function(){
+        Ext.ProgressBar.superclass.afterRender.call(this);
+        if(this.value){
+            this.updateProgress(this.value, this.text);
+        }else{
+            this.updateText(this.text);
+        }
+    },
+
+    
+    updateProgress : function(value, text, animate){
+        this.value = value || 0;
+        if(text){
+            this.updateText(text);
+        }
+        if(this.rendered && !this.isDestroyed){
+            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
+            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
+            if(this.textTopEl){
+                
+                this.textTopEl.removeClass('x-hidden').setWidth(w);
+            }
+        }
+        this.fireEvent('update', this, value, text);
+        return this;
+    },
+
+    
+    wait : function(o){
+        if(!this.waitTimer){
+            var scope = this;
+            o = o || {};
+            this.updateText(o.text);
+            this.waitTimer = Ext.TaskMgr.start({
+                run: function(i){
+                    var inc = o.increment || 10;
+                    i -= 1;
+                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
+                },
+                interval: o.interval || 1000,
+                duration: o.duration,
+                onStop: function(){
+                    if(o.fn){
+                        o.fn.apply(o.scope || this);
+                    }
+                    this.reset();
+                },
+                scope: scope
+            });
+        }
+        return this;
+    },
+
+    
+    isWaiting : function(){
+        return this.waitTimer !== null;
+    },
+
+    
+    updateText : function(text){
+        this.text = text || '&#160;';
+        if(this.rendered){
+            this.textEl.update(this.text);
+        }
+        return this;
+    },
+    
+    
+    syncProgressBar : function(){
+        if(this.value){
+            this.updateProgress(this.value, this.text);
+        }
+        return this;
+    },
+
+    
+    setSize : function(w, h){
+        Ext.ProgressBar.superclass.setSize.call(this, w, h);
+        if(this.textTopEl){
+            var inner = this.el.dom.firstChild;
+            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
+        }
+        this.syncProgressBar();
+        return this;
+    },
+
+    
+    reset : function(hide){
+        this.updateProgress(0);
+        if(this.textTopEl){
+            this.textTopEl.addClass('x-hidden');
+        }
+        this.clearTimer();
+        if(hide === true){
+            this.hide();
+        }
+        return this;
+    },
+    
+    
+    clearTimer : function(){
+        if(this.waitTimer){
+            this.waitTimer.onStop = null; 
+            Ext.TaskMgr.stop(this.waitTimer);
+            this.waitTimer = null;
+        }
+    },
+    
+    onDestroy: function(){
+        this.clearTimer();
+        if(this.rendered){
+            if(this.textEl.isComposite){
+                this.textEl.clear();
+            }
+            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
+        }
+        Ext.ProgressBar.superclass.onDestroy.call(this);
+    }
+});
+Ext.reg('progress', Ext.ProgressBar);
+
+(function() {
+
+var Event=Ext.EventManager;
+var Dom=Ext.lib.Dom;
+
+
+Ext.dd.DragDrop = function(id, sGroup, config) {
+    if(id) {
+        this.init(id, sGroup, config);
+    }
+};
+
+Ext.dd.DragDrop.prototype = {
+
+    
+
+    
+    id: null,
+
+    
+    config: null,
+
+    
+    dragElId: null,
+
+    
+    handleElId: null,
+
+    
+    invalidHandleTypes: null,
+
+    
+    invalidHandleIds: null,
+
+    
+    invalidHandleClasses: null,
+
+    
+    startPageX: 0,
+
+    
+    startPageY: 0,
+
+    
+    groups: null,
+
+    
+    locked: false,
+
+    
+    lock: function() {
+        this.locked = true;
+    },
+
+    
+    moveOnly: false,
+
+    
+    unlock: function() {
+        this.locked = false;
+    },
+
+    
+    isTarget: true,
+
+    
+    padding: null,
+
+    
+    _domRef: null,
+
+    
+    __ygDragDrop: true,
+
+    
+    constrainX: false,
+
+    
+    constrainY: false,
+
+    
+    minX: 0,
+
+    
+    maxX: 0,
+
+    
+    minY: 0,
+
+    
+    maxY: 0,
+
+    
+    maintainOffset: false,
+
+    
+    xTicks: null,
+
+    
+    yTicks: null,
+
+    
+    primaryButtonOnly: true,
+
+    
+    available: false,
+
+    
+    hasOuterHandles: false,
+
+    
+    b4StartDrag: function(x, y) { },
+
+    
+    startDrag: function(x, y) {  },
+
+    
+    b4Drag: function(e) { },
+
+    
+    onDrag: function(e) {  },
+
+    
+    onDragEnter: function(e, id) {  },
+
+    
+    b4DragOver: function(e) { },
+
+    
+    onDragOver: function(e, id) {  },
+
+    
+    b4DragOut: function(e) { },
+
+    
+    onDragOut: function(e, id) {  },
+
+    
+    b4DragDrop: function(e) { },
+
+    
+    onDragDrop: function(e, id) {  },
+
+    
+    onInvalidDrop: function(e) {  },
+
+    
+    b4EndDrag: function(e) { },
+
+    
+    endDrag: function(e) {  },
+
+    
+    b4MouseDown: function(e) {  },
+
+    
+    onMouseDown: function(e) {  },
+
+    
+    onMouseUp: function(e) {  },
+
+    
+    onAvailable: function () {
+    },
+
+    
+    defaultPadding : {left:0, right:0, top:0, bottom:0},
+
+    
+    constrainTo : function(constrainTo, pad, inContent){
+        if(Ext.isNumber(pad)){
+            pad = {left: pad, right:pad, top:pad, bottom:pad};
+        }
+        pad = pad || this.defaultPadding;
+        var b = Ext.get(this.getEl()).getBox(),
+            ce = Ext.get(constrainTo),
+            s = ce.getScroll(),
+            c, 
+            cd = ce.dom;
+        if(cd == document.body){
+            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
+        }else{
+            var xy = ce.getXY();
+            c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
+        }
+
+
+        var topSpace = b.y - c.y,
+            leftSpace = b.x - c.x;
+
+        this.resetConstraints();
+        this.setXConstraint(leftSpace - (pad.left||0), 
+                c.width - leftSpace - b.width - (pad.right||0), 
+				this.xTickSize
+        );
+        this.setYConstraint(topSpace - (pad.top||0), 
+                c.height - topSpace - b.height - (pad.bottom||0), 
+				this.yTickSize
+        );
+    },
+
+    
+    getEl: function() {
+        if (!this._domRef) {
+            this._domRef = Ext.getDom(this.id);
+        }
+
+        return this._domRef;
+    },
+
+    
+    getDragEl: function() {
+        return Ext.getDom(this.dragElId);
+    },
+
+    
+    init: function(id, sGroup, config) {
+        this.initTarget(id, sGroup, config);
+        Event.on(this.id, "mousedown", this.handleMouseDown, this);
+        
+    },
+
+    
+    initTarget: function(id, sGroup, config) {
+
+        
+        this.config = config || {};
+
+        
+        this.DDM = Ext.dd.DDM;
+        
+        this.groups = {};
+
+        
+        
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+
+        
+        this.id = id;
+
+        
+        this.addToGroup((sGroup) ? sGroup : "default");
+
+        
+        
+        this.handleElId = id;
+
+        
+        this.setDragElId(id);
+
+        
+        this.invalidHandleTypes = { A: "A" };
+        this.invalidHandleIds = {};
+        this.invalidHandleClasses = [];
+
+        this.applyConfig();
+
+        this.handleOnAvailable();
+    },
+
+    
+    applyConfig: function() {
+
+        
+        
+        this.padding           = this.config.padding || [0, 0, 0, 0];
+        this.isTarget          = (this.config.isTarget !== false);
+        this.maintainOffset    = (this.config.maintainOffset);
+        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
+
+    },
+
+    
+    handleOnAvailable: function() {
+        this.available = true;
+        this.resetConstraints();
+        this.onAvailable();
+    },
+
+     
+    setPadding: function(iTop, iRight, iBot, iLeft) {
+        
+        if (!iRight && 0 !== iRight) {
+            this.padding = [iTop, iTop, iTop, iTop];
+        } else if (!iBot && 0 !== iBot) {
+            this.padding = [iTop, iRight, iTop, iRight];
+        } else {
+            this.padding = [iTop, iRight, iBot, iLeft];
+        }
+    },
+
+    
+    setInitPosition: function(diffX, diffY) {
+        var el = this.getEl();
+
+        if (!this.DDM.verifyEl(el)) {
+            return;
+        }
+
+        var dx = diffX || 0;
+        var dy = diffY || 0;
+
+        var p = Dom.getXY( el );
+
+        this.initPageX = p[0] - dx;
+        this.initPageY = p[1] - dy;
+
+        this.lastPageX = p[0];
+        this.lastPageY = p[1];
+
+        this.setStartPosition(p);
+    },
+
+    
+    setStartPosition: function(pos) {
+        var p = pos || Dom.getXY( this.getEl() );
+        this.deltaSetXY = null;
+
+        this.startPageX = p[0];
+        this.startPageY = p[1];
+    },
+
+    
+    addToGroup: function(sGroup) {
+        this.groups[sGroup] = true;
+        this.DDM.regDragDrop(this, sGroup);
+    },
+
+    
+    removeFromGroup: function(sGroup) {
+        if (this.groups[sGroup]) {
+            delete this.groups[sGroup];
+        }
+
+        this.DDM.removeDDFromGroup(this, sGroup);
+    },
+
+    
+    setDragElId: function(id) {
+        this.dragElId = id;
+    },
+
+    
+    setHandleElId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        this.handleElId = id;
+        this.DDM.regHandle(this.id, id);
+    },
+
+    
+    setOuterHandleElId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        Event.on(id, "mousedown",
+                this.handleMouseDown, this);
+        this.setHandleElId(id);
+
+        this.hasOuterHandles = true;
+    },
+
+    
+    unreg: function() {
+        Event.un(this.id, "mousedown",
+                this.handleMouseDown);
+        this._domRef = null;
+        this.DDM._remove(this);
+    },
+
+    destroy : function(){
+        this.unreg();
+    },
+
+    
+    isLocked: function() {
+        return (this.DDM.isLocked() || this.locked);
+    },
+
+    
+    handleMouseDown: function(e, oDD){
+        if (this.primaryButtonOnly && e.button != 0) {
+            return;
+        }
+
+        if (this.isLocked()) {
+            return;
+        }
+
+        this.DDM.refreshCache(this.groups);
+
+        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
+        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
+        } else {
+            if (this.clickValidator(e)) {
+
+                
+                this.setStartPosition();
+
+                this.b4MouseDown(e);
+                this.onMouseDown(e);
+
+                this.DDM.handleMouseDown(e, this);
+
+                this.DDM.stopEvent(e);
+            } else {
+
+
+            }
+        }
+    },
+
+    clickValidator: function(e) {
+        var target = e.getTarget();
+        return ( this.isValidHandleChild(target) &&
+                    (this.id == this.handleElId ||
+                        this.DDM.handleWasClicked(target, this.id)) );
+    },
+
+    
+    addInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = type;
+    },
+
+    
+    addInvalidHandleId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        this.invalidHandleIds[id] = id;
+    },
+
+    
+    addInvalidHandleClass: function(cssClass) {
+        this.invalidHandleClasses.push(cssClass);
+    },
+
+    
+    removeInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        
+        delete this.invalidHandleTypes[type];
+    },
+
+    
+    removeInvalidHandleId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        delete this.invalidHandleIds[id];
+    },
+
+    
+    removeInvalidHandleClass: function(cssClass) {
+        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
+            if (this.invalidHandleClasses[i] == cssClass) {
+                delete this.invalidHandleClasses[i];
+            }
+        }
+    },
+
+    
+    isValidHandleChild: function(node) {
+
+        var valid = true;
+        
+        var nodeName;
+        try {
+            nodeName = node.nodeName.toUpperCase();
+        } catch(e) {
+            nodeName = node.nodeName;
+        }
+        valid = valid && !this.invalidHandleTypes[nodeName];
+        valid = valid && !this.invalidHandleIds[node.id];
+
+        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
+            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
+        }
+
+
+        return valid;
+
+    },
+
+    
+    setXTicks: function(iStartX, iTickSize) {
+        this.xTicks = [];
+        this.xTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.xTicks.sort(this.DDM.numericSort) ;
+    },
+
+    
+    setYTicks: function(iStartY, iTickSize) {
+        this.yTicks = [];
+        this.yTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.yTicks.sort(this.DDM.numericSort) ;
+    },
+
+    
+    setXConstraint: function(iLeft, iRight, iTickSize) {
+        this.leftConstraint = iLeft;
+        this.rightConstraint = iRight;
+
+        this.minX = this.initPageX - iLeft;
+        this.maxX = this.initPageX + iRight;
+        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+        this.constrainX = true;
+    },
+
+    
+    clearConstraints: function() {
+        this.constrainX = false;
+        this.constrainY = false;
+        this.clearTicks();
+    },
+
+    
+    clearTicks: function() {
+        this.xTicks = null;
+        this.yTicks = null;
+        this.xTickSize = 0;
+        this.yTickSize = 0;
+    },
+
+    
+    setYConstraint: function(iUp, iDown, iTickSize) {
+        this.topConstraint = iUp;
+        this.bottomConstraint = iDown;
+
+        this.minY = this.initPageY - iUp;
+        this.maxY = this.initPageY + iDown;
+        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+        this.constrainY = true;
+
+    },
+
+    
+    resetConstraints: function() {
+        
+        if (this.initPageX || this.initPageX === 0) {
+            
+            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+            this.setInitPosition(dx, dy);
+
+        
+        } else {
+            this.setInitPosition();
+        }
+
+        if (this.constrainX) {
+            this.setXConstraint( this.leftConstraint,
+                                 this.rightConstraint,
+                                 this.xTickSize        );
+        }
+
+        if (this.constrainY) {
+            this.setYConstraint( this.topConstraint,
+                                 this.bottomConstraint,
+                                 this.yTickSize         );
+        }
+    },
+
+    
+    getTick: function(val, tickArray) {
+        if (!tickArray) {
+            
+            
+            return val;
+        } else if (tickArray[0] >= val) {
+            
+            
+            return tickArray[0];
+        } else {
+            for (var i=0, len=tickArray.length; i<len; ++i) {
+                var next = i + 1;
+                if (tickArray[next] && tickArray[next] >= val) {
+                    var diff1 = val - tickArray[i];
+                    var diff2 = tickArray[next] - val;
+                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
+                }
+            }
+
+            
+            
+            return tickArray[tickArray.length - 1];
+        }
+    },
+
+    
+    toString: function() {
+        return ("DragDrop " + this.id);
+    }
+
+};
+
+})();
+
+
+
+
+if (!Ext.dd.DragDropMgr) {
+
+
+Ext.dd.DragDropMgr = function() {
+
+    var Event = Ext.EventManager;
+
+    return {
+
+        
+        ids: {},
+
+        
+        handleIds: {},
+
+        
+        dragCurrent: null,
+
+        
+        dragOvers: {},
+
+        
+        deltaX: 0,
+
+        
+        deltaY: 0,
+
+        
+        preventDefault: true,
+
+        
+        stopPropagation: true,
+
+        
+        initialized: false,
+
+        
+        locked: false,
+
+        
+        init: function() {
+            this.initialized = true;
+        },
+
+        
+        POINT: 0,
+
+        
+        INTERSECT: 1,
+
+        
+        mode: 0,
+
+        
+        _execOnAll: function(sMethod, args) {
+            for (var i in this.ids) {
+                for (var j in this.ids[i]) {
+                    var oDD = this.ids[i][j];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+                    oDD[sMethod].apply(oDD, args);
+                }
+            }
+        },
+
+        
+        _onLoad: function() {
+
+            this.init();
+
+
+            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
+            Event.on(document, "mousemove", this.handleMouseMove, this, true);
+            Event.on(window,   "unload",    this._onUnload, this, true);
+            Event.on(window,   "resize",    this._onResize, this, true);
+            
+
+        },
+
+        
+        _onResize: function(e) {
+            this._execOnAll("resetConstraints", []);
+        },
+
+        
+        lock: function() { this.locked = true; },
+
+        
+        unlock: function() { this.locked = false; },
+
+        
+        isLocked: function() { return this.locked; },
+
+        
+        locationCache: {},
+
+        
+        useCache: true,
+
+        
+        clickPixelThresh: 3,
+
+        
+        clickTimeThresh: 350,
+
+        
+        dragThreshMet: false,
+
+        
+        clickTimeout: null,
+
+        
+        startX: 0,
+
+        
+        startY: 0,
+
+        
+        regDragDrop: function(oDD, sGroup) {
+            if (!this.initialized) { this.init(); }
+
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+            this.ids[sGroup][oDD.id] = oDD;
+        },
+
+        
+        removeDDFromGroup: function(oDD, sGroup) {
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+
+            var obj = this.ids[sGroup];
+            if (obj && obj[oDD.id]) {
+                delete obj[oDD.id];
+            }
+        },
+
+        
+        _remove: function(oDD) {
+            for (var g in oDD.groups) {
+                if (g && this.ids[g] && this.ids[g][oDD.id]) {
+                    delete this.ids[g][oDD.id];
+                }
+            }
+            delete this.handleIds[oDD.id];
+        },
+
+        
+        regHandle: function(sDDId, sHandleId) {
+            if (!this.handleIds[sDDId]) {
+                this.handleIds[sDDId] = {};
+            }
+            this.handleIds[sDDId][sHandleId] = sHandleId;
+        },
+
+        
+        isDragDrop: function(id) {
+            return ( this.getDDById(id) ) ? true : false;
+        },
+
+        
+        getRelated: function(p_oDD, bTargetsOnly) {
+            var oDDs = [];
+            for (var i in p_oDD.groups) {
+                for (var j in this.ids[i]) {
+                    var dd = this.ids[i][j];
+                    if (! this.isTypeOfDD(dd)) {
+                        continue;
+                    }
+                    if (!bTargetsOnly || dd.isTarget) {
+                        oDDs[oDDs.length] = dd;
+                    }
+                }
+            }
+
+            return oDDs;
+        },
+
+        
+        isLegalTarget: function (oDD, oTargetDD) {
+            var targets = this.getRelated(oDD, true);
+            for (var i=0, len=targets.length;i<len;++i) {
+                if (targets[i].id == oTargetDD.id) {
+                    return true;
+                }
+            }
+
+            return false;
+        },
+
+        
+        isTypeOfDD: function (oDD) {
+            return (oDD && oDD.__ygDragDrop);
+        },
+
+        
+        isHandle: function(sDDId, sHandleId) {
+            return ( this.handleIds[sDDId] &&
+                            this.handleIds[sDDId][sHandleId] );
+        },
+
+        
+        getDDById: function(id) {
+            for (var i in this.ids) {
+                if (this.ids[i][id]) {
+                    return this.ids[i][id];
+                }
+            }
+            return null;
+        },
+
+        
+        handleMouseDown: function(e, oDD) {
+            if(Ext.QuickTips){
+                Ext.QuickTips.ddDisable();
+            }
+            if(this.dragCurrent){
+                
+                
+                this.handleMouseUp(e);
+            }
+            
+            this.currentTarget = e.getTarget();
+            this.dragCurrent = oDD;
+
+            var el = oDD.getEl();
+
+            
+            this.startX = e.getPageX();
+            this.startY = e.getPageY();
+
+            this.deltaX = this.startX - el.offsetLeft;
+            this.deltaY = this.startY - el.offsetTop;
+
+            this.dragThreshMet = false;
+
+            this.clickTimeout = setTimeout(
+                    function() {
+                        var DDM = Ext.dd.DDM;
+                        DDM.startDrag(DDM.startX, DDM.startY);
+                    },
+                    this.clickTimeThresh );
+        },
+
+        
+        startDrag: function(x, y) {
+            clearTimeout(this.clickTimeout);
+            if (this.dragCurrent) {
+                this.dragCurrent.b4StartDrag(x, y);
+                this.dragCurrent.startDrag(x, y);
+            }
+            this.dragThreshMet = true;
+        },
+
+        
+        handleMouseUp: function(e) {
+
+            if(Ext.QuickTips){
+                Ext.QuickTips.ddEnable();
+            }
+            if (! this.dragCurrent) {
+                return;
+            }
+
+            clearTimeout(this.clickTimeout);
+
+            if (this.dragThreshMet) {
+                this.fireEvents(e, true);
+            } else {
+            }
+
+            this.stopDrag(e);
+
+            this.stopEvent(e);
+        },
+
+        
+        stopEvent: function(e){
+            if(this.stopPropagation) {
+                e.stopPropagation();
+            }
+
+            if (this.preventDefault) {
+                e.preventDefault();
+            }
+        },
+
+        
+        stopDrag: function(e) {
+            
+            if (this.dragCurrent) {
+                if (this.dragThreshMet) {
+                    this.dragCurrent.b4EndDrag(e);
+                    this.dragCurrent.endDrag(e);
+                }
+
+                this.dragCurrent.onMouseUp(e);
+            }
+
+            this.dragCurrent = null;
+            this.dragOvers = {};
+        },
+
+        
+        handleMouseMove: function(e) {
+            if (! this.dragCurrent) {
+                return true;
+            }
+            
+
+            
+            if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
+                this.stopEvent(e);
+                return this.handleMouseUp(e);
+            }
+
+            if (!this.dragThreshMet) {
+                var diffX = Math.abs(this.startX - e.getPageX());
+                var diffY = Math.abs(this.startY - e.getPageY());
+                if (diffX > this.clickPixelThresh ||
+                            diffY > this.clickPixelThresh) {
+                    this.startDrag(this.startX, this.startY);
+                }
+            }
+
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4Drag(e);
+                this.dragCurrent.onDrag(e);
+                if(!this.dragCurrent.moveOnly){
+                    this.fireEvents(e, false);
+                }
+            }
+
+            this.stopEvent(e);
+
+            return true;
+        },
+
+        
+        fireEvents: function(e, isDrop) {
+            var dc = this.dragCurrent;
+
+            
+            
+            if (!dc || dc.isLocked()) {
+                return;
+            }
+
+            var pt = e.getPoint();
+
+            
+            var oldOvers = [];
+
+            var outEvts   = [];
+            var overEvts  = [];
+            var dropEvts  = [];
+            var enterEvts = [];
+
+            
+            
+            for (var i in this.dragOvers) {
+
+                var ddo = this.dragOvers[i];
+
+                if (! this.isTypeOfDD(ddo)) {
+                    continue;
+                }
+
+                if (! this.isOverTarget(pt, ddo, this.mode)) {
+                    outEvts.push( ddo );
+                }
+
+                oldOvers[i] = true;
+                delete this.dragOvers[i];
+            }
+
+            for (var sGroup in dc.groups) {
+
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+
+                    if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
+                        if (this.isOverTarget(pt, oDD, this.mode)) {
+                            
+                            if (isDrop) {
+                                dropEvts.push( oDD );
+                            
+                            } else {
+
+                                
+                                if (!oldOvers[oDD.id]) {
+                                    enterEvts.push( oDD );
+                                
+                                } else {
+                                    overEvts.push( oDD );
+                                }
+
+                                this.dragOvers[oDD.id] = oDD;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (this.mode) {
+                if (outEvts.length) {
+                    dc.b4DragOut(e, outEvts);
+                    dc.onDragOut(e, outEvts);
+                }
+
+                if (enterEvts.length) {
+                    dc.onDragEnter(e, enterEvts);
+                }
+
+                if (overEvts.length) {
+                    dc.b4DragOver(e, overEvts);
+                    dc.onDragOver(e, overEvts);
+                }
+
+                if (dropEvts.length) {
+                    dc.b4DragDrop(e, dropEvts);
+                    dc.onDragDrop(e, dropEvts);
+                }
+
+            } else {
+                
+                var len = 0;
+                for (i=0, len=outEvts.length; i<len; ++i) {
+                    dc.b4DragOut(e, outEvts[i].id);
+                    dc.onDragOut(e, outEvts[i].id);
+                }
+
+                
+                for (i=0,len=enterEvts.length; i<len; ++i) {
+                    
+                    dc.onDragEnter(e, enterEvts[i].id);
+                }
+
+                
+                for (i=0,len=overEvts.length; i<len; ++i) {
+                    dc.b4DragOver(e, overEvts[i].id);
+                    dc.onDragOver(e, overEvts[i].id);
+                }
+
+                
+                for (i=0, len=dropEvts.length; i<len; ++i) {
+                    dc.b4DragDrop(e, dropEvts[i].id);
+                    dc.onDragDrop(e, dropEvts[i].id);
+                }
+
+            }
+
+            
+            if (isDrop && !dropEvts.length) {
+                dc.onInvalidDrop(e);
+            }
+
+        },
+
+        
+        getBestMatch: function(dds) {
+            var winner = null;
+            
+            
+               
+            
+            
+
+            var len = dds.length;
+
+            if (len == 1) {
+                winner = dds[0];
+            } else {
+                
+                for (var i=0; i<len; ++i) {
+                    var dd = dds[i];
+                    
+                    
+                    
+                    if (dd.cursorIsOver) {
+                        winner = dd;
+                        break;
+                    
+                    } else {
+                        if (!winner ||
+                            winner.overlap.getArea() < dd.overlap.getArea()) {
+                            winner = dd;
+                        }
+                    }
+                }
+            }
+
+            return winner;
+        },
+
+        
+        refreshCache: function(groups) {
+            for (var sGroup in groups) {
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+                for (var i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+
+                    if (this.isTypeOfDD(oDD)) {
+                    
+                        var loc = this.getLocation(oDD);
+                        if (loc) {
+                            this.locationCache[oDD.id] = loc;
+                        } else {
+                            delete this.locationCache[oDD.id];
+                            
+                            
+                            
+                        }
+                    }
+                }
+            }
+        },
+
+        
+        verifyEl: function(el) {
+            if (el) {
+                var parent;
+                if(Ext.isIE){
+                    try{
+                        parent = el.offsetParent;
+                    }catch(e){}
+                }else{
+                    parent = el.offsetParent;
+                }
+                if (parent) {
+                    return true;
+                }
+            }
+
+            return false;
+        },
+
+        
+        getLocation: function(oDD) {
+            if (! this.isTypeOfDD(oDD)) {
+                return null;
+            }
+
+            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l, region;
+
+            try {
+                pos= Ext.lib.Dom.getXY(el);
+            } catch (e) { }
+
+            if (!pos) {
+                return null;
+            }
+
+            x1 = pos[0];
+            x2 = x1 + el.offsetWidth;
+            y1 = pos[1];
+            y2 = y1 + el.offsetHeight;
+
+            t = y1 - oDD.padding[0];
+            r = x2 + oDD.padding[1];
+            b = y2 + oDD.padding[2];
+            l = x1 - oDD.padding[3];
+
+            region = new Ext.lib.Region( t, r, b, l );
+            
+            el = Ext.get(el.parentNode);
+            while (el && region) {
+	            if (el.isScrollable()) {
+	                
+	                region = region.intersect(el.getRegion());
+	            }
+	            el = el.parent();
+            }
+            return region;
+        },
+
+        
+        isOverTarget: function(pt, oTarget, intersect) {
+            
+            var loc = this.locationCache[oTarget.id];
+            if (!loc || !this.useCache) {
+                loc = this.getLocation(oTarget);
+                this.locationCache[oTarget.id] = loc;
+
+            }
+
+            if (!loc) {
+                return false;
+            }
+
+            oTarget.cursorIsOver = loc.contains( pt );
+
+            
+            
+            
+            
+            
+            var dc = this.dragCurrent;
+            if (!dc || !dc.getTargetCoord ||
+                    (!intersect && !dc.constrainX && !dc.constrainY)) {
+                return oTarget.cursorIsOver;
+            }
+
+            oTarget.overlap = null;
+
+            
+            
+            
+            
+            var pos = dc.getTargetCoord(pt.x, pt.y);
+
+            var el = dc.getDragEl();
+            var curRegion = new Ext.lib.Region( pos.y,
+                                                   pos.x + el.offsetWidth,
+                                                   pos.y + el.offsetHeight,
+                                                   pos.x );
+
+            var overlap = curRegion.intersect(loc);
+
+            if (overlap) {
+                oTarget.overlap = overlap;
+                return (intersect) ? true : oTarget.cursorIsOver;
+            } else {
+                return false;
+            }
+        },
+
+        
+        _onUnload: function(e, me) {
+            Event.removeListener(document, "mouseup",   this.handleMouseUp, this);
+            Event.removeListener(document, "mousemove", this.handleMouseMove, this);
+            Event.removeListener(window,   "resize",    this._onResize, this);
+            Ext.dd.DragDropMgr.unregAll();
+        },
+
+        
+        unregAll: function() {
+
+            if (this.dragCurrent) {
+                this.stopDrag();
+                this.dragCurrent = null;
+            }
+
+            this._execOnAll("unreg", []);
+
+            for (var i in this.elementCache) {
+                delete this.elementCache[i];
+            }
+
+            this.elementCache = {};
+            this.ids = {};
+        },
+
+        
+        elementCache: {},
+
+        
+        getElWrapper: function(id) {
+            var oWrapper = this.elementCache[id];
+            if (!oWrapper || !oWrapper.el) {
+                oWrapper = this.elementCache[id] =
+                    new this.ElementWrapper(Ext.getDom(id));
+            }
+            return oWrapper;
+        },
+
+        
+        getElement: function(id) {
+            return Ext.getDom(id);
+        },
+
+        
+        getCss: function(id) {
+            var el = Ext.getDom(id);
+            return (el) ? el.style : null;
+        },
+
+        
+        ElementWrapper: function(el) {
+                
+                this.el = el || null;
+                
+                this.id = this.el && el.id;
+                
+                this.css = this.el && el.style;
+            },
+
+        
+        getPosX: function(el) {
+            return Ext.lib.Dom.getX(el);
+        },
+
+        
+        getPosY: function(el) {
+            return Ext.lib.Dom.getY(el);
+        },
+
+        
+        swapNode: function(n1, n2) {
+            if (n1.swapNode) {
+                n1.swapNode(n2);
+            } else {
+                var p = n2.parentNode;
+                var s = n2.nextSibling;
+
+                if (s == n1) {
+                    p.insertBefore(n1, n2);
+                } else if (n2 == n1.nextSibling) {
+                    p.insertBefore(n2, n1);
+                } else {
+                    n1.parentNode.replaceChild(n2, n1);
+                    p.insertBefore(n1, s);
+                }
+            }
+        },
+
+        
+        getScroll: function () {
+            var t, l, dde=document.documentElement, db=document.body;
+            if (dde && (dde.scrollTop || dde.scrollLeft)) {
+                t = dde.scrollTop;
+                l = dde.scrollLeft;
+            } else if (db) {
+                t = db.scrollTop;
+                l = db.scrollLeft;
+            } else {
+
+            }
+            return { top: t, left: l };
+        },
+
+        
+        getStyle: function(el, styleProp) {
+            return Ext.fly(el).getStyle(styleProp);
+        },
+
+        
+        getScrollTop: function () {
+            return this.getScroll().top;
+        },
+
+        
+        getScrollLeft: function () {
+            return this.getScroll().left;
+        },
+
+        
+        moveToEl: function (moveEl, targetEl) {
+            var aCoord = Ext.lib.Dom.getXY(targetEl);
+            Ext.lib.Dom.setXY(moveEl, aCoord);
+        },
+
+        
+        numericSort: function(a, b) {
+            return (a - b);
+        },
+
+        
+        _timeoutCount: 0,
+
+        
+        _addListeners: function() {
+            var DDM = Ext.dd.DDM;
+            if ( Ext.lib.Event && document ) {
+                DDM._onLoad();
+            } else {
+                if (DDM._timeoutCount > 2000) {
+                } else {
+                    setTimeout(DDM._addListeners, 10);
+                    if (document && document.body) {
+                        DDM._timeoutCount += 1;
+                    }
+                }
+            }
+        },
+
+        
+        handleWasClicked: function(node, id) {
+            if (this.isHandle(id, node.id)) {
+                return true;
+            } else {
+                
+                var p = node.parentNode;
+
+                while (p) {
+                    if (this.isHandle(id, p.id)) {
+                        return true;
+                    } else {
+                        p = p.parentNode;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+    };
+
+}();
+
+
+Ext.dd.DDM = Ext.dd.DragDropMgr;
+Ext.dd.DDM._addListeners();
+
+}
+
+
+Ext.dd.DD = function(id, sGroup, config) {
+    if (id) {
+        this.init(id, sGroup, config);
+    }
+};
+
+Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
+
+    
+    scroll: true,
+
+    
+    autoOffset: function(iPageX, iPageY) {
+        var x = iPageX - this.startPageX;
+        var y = iPageY - this.startPageY;
+        this.setDelta(x, y);
+    },
+
+    
+    setDelta: function(iDeltaX, iDeltaY) {
+        this.deltaX = iDeltaX;
+        this.deltaY = iDeltaY;
+    },
+
+    
+    setDragElPos: function(iPageX, iPageY) {
+        
+        
+
+        var el = this.getDragEl();
+        this.alignElWithMouse(el, iPageX, iPageY);
+    },
+
+    
+    alignElWithMouse: function(el, iPageX, iPageY) {
+        var oCoord = this.getTargetCoord(iPageX, iPageY);
+        var fly = el.dom ? el : Ext.fly(el, '_dd');
+        if (!this.deltaSetXY) {
+            var aCoord = [oCoord.x, oCoord.y];
+            fly.setXY(aCoord);
+            var newLeft = fly.getLeft(true);
+            var newTop  = fly.getTop(true);
+            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
+        } else {
+            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
+        }
+
+        this.cachePosition(oCoord.x, oCoord.y);
+        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+        return oCoord;
+    },
+
+    
+    cachePosition: function(iPageX, iPageY) {
+        if (iPageX) {
+            this.lastPageX = iPageX;
+            this.lastPageY = iPageY;
+        } else {
+            var aCoord = Ext.lib.Dom.getXY(this.getEl());
+            this.lastPageX = aCoord[0];
+            this.lastPageY = aCoord[1];
+        }
+    },
+
+    
+    autoScroll: function(x, y, h, w) {
+
+        if (this.scroll) {
+            
+            var clientH = Ext.lib.Dom.getViewHeight();
+
+            
+            var clientW = Ext.lib.Dom.getViewWidth();
+
+            
+            var st = this.DDM.getScrollTop();
+
+            
+            var sl = this.DDM.getScrollLeft();
+
+            
+            var bot = h + y;
+
+            
+            var right = w + x;
+
+            
+            
+            
+            var toBot = (clientH + st - y - this.deltaY);
+
+            
+            var toRight = (clientW + sl - x - this.deltaX);
+
+
+            
+            
+            var thresh = 40;
+
+            
+            
+            
+            var scrAmt = (document.all) ? 80 : 30;
+
+            
+            
+            if ( bot > clientH && toBot < thresh ) {
+                window.scrollTo(sl, st + scrAmt);
+            }
+
+            
+            
+            if ( y < st && st > 0 && y - st < thresh ) {
+                window.scrollTo(sl, st - scrAmt);
+            }
+
+            
+            
+            if ( right > clientW && toRight < thresh ) {
+                window.scrollTo(sl + scrAmt, st);
+            }
+
+            
+            
+            if ( x < sl && sl > 0 && x - sl < thresh ) {
+                window.scrollTo(sl - scrAmt, st);
+            }
+        }
+    },
+
+    
+    getTargetCoord: function(iPageX, iPageY) {
+        var x = iPageX - this.deltaX;
+        var y = iPageY - this.deltaY;
+
+        if (this.constrainX) {
+            if (x < this.minX) { x = this.minX; }
+            if (x > this.maxX) { x = this.maxX; }
+        }
+
+        if (this.constrainY) {
+            if (y < this.minY) { y = this.minY; }
+            if (y > this.maxY) { y = this.maxY; }
+        }
+
+        x = this.getTick(x, this.xTicks);
+        y = this.getTick(y, this.yTicks);
+
+
+        return {x:x, y:y};
+    },
+
+    
+    applyConfig: function() {
+        Ext.dd.DD.superclass.applyConfig.call(this);
+        this.scroll = (this.config.scroll !== false);
+    },
+
+    
+    b4MouseDown: function(e) {
+        
+        this.autoOffset(e.getPageX(),
+                            e.getPageY());
+    },
+
+    
+    b4Drag: function(e) {
+        this.setDragElPos(e.getPageX(),
+                            e.getPageY());
+    },
+
+    toString: function() {
+        return ("DD " + this.id);
+    }
+
+    
+    
+    
+    
+
+});
+
+Ext.dd.DDProxy = function(id, sGroup, config) {
+    if (id) {
+        this.init(id, sGroup, config);
+        this.initFrame();
+    }
+};
+
+
+Ext.dd.DDProxy.dragElId = "ygddfdiv";
+
+Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
+
+    
+    resizeFrame: true,
+
+    
+    centerFrame: false,
+
+    
+    createFrame: function() {
+        var self = this;
+        var body = document.body;
+
+        if (!body || !body.firstChild) {
+            setTimeout( function() { self.createFrame(); }, 50 );
+            return;
+        }
+
+        var div = this.getDragEl();
+
+        if (!div) {
+            div    = document.createElement("div");
+            div.id = this.dragElId;
+            var s  = div.style;
+
+            s.position   = "absolute";
+            s.visibility = "hidden";
+            s.cursor     = "move";
+            s.border     = "2px solid #aaa";
+            s.zIndex     = 999;
+
+            
+            
+            
+            body.insertBefore(div, body.firstChild);
+        }
+    },
+
+    
+    initFrame: function() {
+        this.createFrame();
+    },
+
+    applyConfig: function() {
+        Ext.dd.DDProxy.superclass.applyConfig.call(this);
+
+        this.resizeFrame = (this.config.resizeFrame !== false);
+        this.centerFrame = (this.config.centerFrame);
+        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+    },
+
+    
+    showFrame: function(iPageX, iPageY) {
+        var el = this.getEl();
+        var dragEl = this.getDragEl();
+        var s = dragEl.style;
+
+        this._resizeProxy();
+
+        if (this.centerFrame) {
+            this.setDelta( Math.round(parseInt(s.width,  10)/2),
+                           Math.round(parseInt(s.height, 10)/2) );
+        }
+
+        this.setDragElPos(iPageX, iPageY);
+
+        Ext.fly(dragEl).show();
+    },
+
+    
+    _resizeProxy: function() {
+        if (this.resizeFrame) {
+            var el = this.getEl();
+            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
+        }
+    },
+
+    
+    b4MouseDown: function(e) {
+        var x = e.getPageX();
+        var y = e.getPageY();
+        this.autoOffset(x, y);
+        this.setDragElPos(x, y);
+    },
+
+    
+    b4StartDrag: function(x, y) {
+        
+        this.showFrame(x, y);
+    },
+
+    
+    b4EndDrag: function(e) {
+        Ext.fly(this.getDragEl()).hide();
+    },
+
+    
+    
+    
+    endDrag: function(e) {
+
+        var lel = this.getEl();
+        var del = this.getDragEl();
+
+        
+        del.style.visibility = "";
+
+        this.beforeMove();
+        
+        
+        lel.style.visibility = "hidden";
+        Ext.dd.DDM.moveToEl(lel, del);
+        del.style.visibility = "hidden";
+        lel.style.visibility = "";
+
+        this.afterDrag();
+    },
+
+    beforeMove : function(){
+
+    },
+
+    afterDrag : function(){
+
+    },
+
+    toString: function() {
+        return ("DDProxy " + this.id);
+    }
+
+});
+
+Ext.dd.DDTarget = function(id, sGroup, config) {
+    if (id) {
+        this.initTarget(id, sGroup, config);
+    }
+};
+
+
+Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
+    
+    getDragEl: Ext.emptyFn,
+    
+    isValidHandleChild: Ext.emptyFn,
+    
+    startDrag: Ext.emptyFn,
+    
+    endDrag: Ext.emptyFn,
+    
+    onDrag: Ext.emptyFn,
+    
+    onDragDrop: Ext.emptyFn,
+    
+    onDragEnter: Ext.emptyFn,
+    
+    onDragOut: Ext.emptyFn,
+    
+    onDragOver: Ext.emptyFn,
+    
+    onInvalidDrop: Ext.emptyFn,
+    
+    onMouseDown: Ext.emptyFn,
+    
+    onMouseUp: Ext.emptyFn,
+    
+    setXConstraint: Ext.emptyFn,
+    
+    setYConstraint: Ext.emptyFn,
+    
+    resetConstraints: Ext.emptyFn,
+    
+    clearConstraints: Ext.emptyFn,
+    
+    clearTicks: Ext.emptyFn,
+    
+    setInitPosition: Ext.emptyFn,
+    
+    setDragElId: Ext.emptyFn,
+    
+    setHandleElId: Ext.emptyFn,
+    
+    setOuterHandleElId: Ext.emptyFn,
+    
+    addInvalidHandleClass: Ext.emptyFn,
+    
+    addInvalidHandleId: Ext.emptyFn,
+    
+    addInvalidHandleType: Ext.emptyFn,
+    
+    removeInvalidHandleClass: Ext.emptyFn,
+    
+    removeInvalidHandleId: Ext.emptyFn,
+    
+    removeInvalidHandleType: Ext.emptyFn,
+
+    toString: function() {
+        return ("DDTarget " + this.id);
+    }
+});
+Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
+    	
+    active: false,
+    	
+    tolerance: 5,
+    	
+    autoStart: false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+	    this.addEvents(
+	        
+	        'mousedown',
+	        
+	        'mouseup',
+	        
+	        'mousemove',
+	        
+	        'dragstart',
+	        
+	        'dragend',
+	        
+	        'drag'
+	    );
+	
+	    this.dragRegion = new Ext.lib.Region(0,0,0,0);
+	
+	    if(this.el){
+	        this.initEl(this.el);
+	    }
+        Ext.dd.DragTracker.superclass.constructor.call(this, config);
+    },
+
+    initEl: function(el){
+        this.el = Ext.get(el);
+        el.on('mousedown', this.onMouseDown, this,
+                this.delegate ? {delegate: this.delegate} : undefined);
+    },
+
+    destroy : function(){
+        this.el.un('mousedown', this.onMouseDown, this);
+        delete this.el;
+    },
+
+    onMouseDown: function(e, target){
+        if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
+            this.startXY = this.lastXY = e.getXY();
+            this.dragTarget = this.delegate ? target : this.el.dom;
+            if(this.preventDefault !== false){
+                e.preventDefault();
+            }
+            Ext.getDoc().on({
+                scope: this,
+                mouseup: this.onMouseUp,
+                mousemove: this.onMouseMove,
+                selectstart: this.stopSelect
+            });
+            if(this.autoStart){
+                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [e]);
+            }
+        }
+    },
+
+    onMouseMove: function(e, target){
+        
+        if(this.active && Ext.isIE && !e.browserEvent.button){
+            e.preventDefault();
+            this.onMouseUp(e);
+            return;
+        }
+
+        e.preventDefault();
+        var xy = e.getXY(), s = this.startXY;
+        this.lastXY = xy;
+        if(!this.active){
+            if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
+                this.triggerStart(e);
+            }else{
+                return;
+            }
+        }
+        this.fireEvent('mousemove', this, e);
+        this.onDrag(e);
+        this.fireEvent('drag', this, e);
+    },
+
+    onMouseUp: function(e) {
+        var doc = Ext.getDoc(),
+            wasActive = this.active;
+            
+        doc.un('mousemove', this.onMouseMove, this);
+        doc.un('mouseup', this.onMouseUp, this);
+        doc.un('selectstart', this.stopSelect, this);
+        e.preventDefault();
+        this.clearStart();
+        this.active = false;
+        delete this.elRegion;
+        this.fireEvent('mouseup', this, e);
+        if(wasActive){
+            this.onEnd(e);
+            this.fireEvent('dragend', this, e);
+        }
+    },
+
+    triggerStart: function(e) {
+        this.clearStart();
+        this.active = true;
+        this.onStart(e);
+        this.fireEvent('dragstart', this, e);
+    },
+
+    clearStart : function() {
+        if(this.timer){
+            clearTimeout(this.timer);
+            delete this.timer;
+        }
+    },
+
+    stopSelect : function(e) {
+        e.stopEvent();
+        return false;
+    },
+    
+    
+    onBeforeStart : function(e) {
+
+    },
+
+    
+    onStart : function(xy) {
+
+    },
+
+    
+    onDrag : function(e) {
+
+    },
+
+    
+    onEnd : function(e) {
+
+    },
+
+    
+    getDragTarget : function(){
+        return this.dragTarget;
+    },
+
+    getDragCt : function(){
+        return this.el;
+    },
+
+    getXY : function(constrain){
+        return constrain ?
+               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
+    },
+
+    getOffset : function(constrain){
+        var xy = this.getXY(constrain),
+            s = this.startXY;
+        return [s[0]-xy[0], s[1]-xy[1]];
+    },
+
+    constrainModes: {
+        'point' : function(xy){
+
+            if(!this.elRegion){
+                this.elRegion = this.getDragCt().getRegion();
+            }
+
+            var dr = this.dragRegion;
+
+            dr.left = xy[0];
+            dr.top = xy[1];
+            dr.right = xy[0];
+            dr.bottom = xy[1];
+
+            dr.constrainTo(this.elRegion);
+
+            return [dr.left, dr.top];
+        }
+    }
+});
+Ext.dd.ScrollManager = function(){
+    var ddm = Ext.dd.DragDropMgr;
+    var els = {};
+    var dragEl = null;
+    var proc = {};
+    
+    var onStop = function(e){
+        dragEl = null;
+        clearProc();
+    };
+    
+    var triggerRefresh = function(){
+        if(ddm.dragCurrent){
+             ddm.refreshCache(ddm.dragCurrent.groups);
+        }
+    };
+    
+    var doScroll = function(){
+        if(ddm.dragCurrent){
+            var dds = Ext.dd.ScrollManager;
+            var inc = proc.el.ddScrollConfig ?
+                      proc.el.ddScrollConfig.increment : dds.increment;
+            if(!dds.animate){
+                if(proc.el.scroll(proc.dir, inc)){
+                    triggerRefresh();
+                }
+            }else{
+                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
+            }
+        }
+    };
+    
+    var clearProc = function(){
+        if(proc.id){
+            clearInterval(proc.id);
+        }
+        proc.id = 0;
+        proc.el = null;
+        proc.dir = "";
+    };
+
+    var startProc = function(el, dir){
+        clearProc();
+        proc.el = el;
+        proc.dir = dir;
+        var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
+            freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
+                  ? el.ddScrollConfig.frequency
+                  : Ext.dd.ScrollManager.frequency;
+
+        if (group === undefined || ddm.dragCurrent.ddGroup == group) {
+            proc.id = setInterval(doScroll, freq);
+        }
+    };
+    
+    var onFire = function(e, isDrop){
+        if(isDrop || !ddm.dragCurrent){ return; }
+        var dds = Ext.dd.ScrollManager;
+        if(!dragEl || dragEl != ddm.dragCurrent){
+            dragEl = ddm.dragCurrent;
+            
+            dds.refreshCache();
+        }
+        
+        var xy = Ext.lib.Event.getXY(e);
+        var pt = new Ext.lib.Point(xy[0], xy[1]);
+        for(var id in els){
+            var el = els[id], r = el._region;
+            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
+            if(r && r.contains(pt) && el.isScrollable()){
+                if(r.bottom - pt.y <= c.vthresh){
+                    if(proc.el != el){
+                        startProc(el, "down");
+                    }
+                    return;
+                }else if(r.right - pt.x <= c.hthresh){
+                    if(proc.el != el){
+                        startProc(el, "left");
+                    }
+                    return;
+                }else if(pt.y - r.top <= c.vthresh){
+                    if(proc.el != el){
+                        startProc(el, "up");
+                    }
+                    return;
+                }else if(pt.x - r.left <= c.hthresh){
+                    if(proc.el != el){
+                        startProc(el, "right");
+                    }
+                    return;
+                }
+            }
+        }
+        clearProc();
+    };
+    
+    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
+    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
+    
+    return {
+        
+        register : function(el){
+            if(Ext.isArray(el)){
+                for(var i = 0, len = el.length; i < len; i++) {
+                	this.register(el[i]);
+                }
+            }else{
+                el = Ext.get(el);
+                els[el.id] = el;
+            }
+        },
+        
+        
+        unregister : function(el){
+            if(Ext.isArray(el)){
+                for(var i = 0, len = el.length; i < len; i++) {
+                	this.unregister(el[i]);
+                }
+            }else{
+                el = Ext.get(el);
+                delete els[el.id];
+            }
+        },
+        
+        
+        vthresh : 25,
+        
+        hthresh : 25,
+
+        
+        increment : 100,
+        
+        
+        frequency : 500,
+        
+        
+        animate: true,
+        
+        
+        animDuration: .4,
+        
+        
+        ddGroup: undefined,
+        
+        
+        refreshCache : function(){
+            for(var id in els){
+                if(typeof els[id] == 'object'){ 
+                    els[id]._region = els[id].getRegion();
+                }
+            }
+        }
+    };
+}();
+Ext.dd.Registry = function(){
+    var elements = {}; 
+    var handles = {}; 
+    var autoIdSeed = 0;
+
+    var getId = function(el, autogen){
+        if(typeof el == "string"){
+            return el;
+        }
+        var id = el.id;
+        if(!id && autogen !== false){
+            id = "extdd-" + (++autoIdSeed);
+            el.id = id;
+        }
+        return id;
+    };
+    
+    return {
+    
+        register : function(el, data){
+            data = data || {};
+            if(typeof el == "string"){
+                el = document.getElementById(el);
+            }
+            data.ddel = el;
+            elements[getId(el)] = data;
+            if(data.isHandle !== false){
+                handles[data.ddel.id] = data;
+            }
+            if(data.handles){
+                var hs = data.handles;
+                for(var i = 0, len = hs.length; i < len; i++){
+                	handles[getId(hs[i])] = data;
+                }
+            }
+        },
+
+    
+        unregister : function(el){
+            var id = getId(el, false);
+            var data = elements[id];
+            if(data){
+                delete elements[id];
+                if(data.handles){
+                    var hs = data.handles;
+                    for(var i = 0, len = hs.length; i < len; i++){
+                    	delete handles[getId(hs[i], false)];
+                    }
+                }
+            }
+        },
+
+    
+        getHandle : function(id){
+            if(typeof id != "string"){ 
+                id = id.id;
+            }
+            return handles[id];
+        },
+
+    
+        getHandleFromEvent : function(e){
+            var t = Ext.lib.Event.getTarget(e);
+            return t ? handles[t.id] : null;
+        },
+
+    
+        getTarget : function(id){
+            if(typeof id != "string"){ 
+                id = id.id;
+            }
+            return elements[id];
+        },
+
+    
+        getTargetFromEvent : function(e){
+            var t = Ext.lib.Event.getTarget(e);
+            return t ? elements[t.id] || handles[t.id] : null;
+        }
+    };
+}();
+Ext.dd.StatusProxy = function(config){
+    Ext.apply(this, config);
+    this.id = this.id || Ext.id();
+    this.el = new Ext.Layer({
+        dh: {
+            id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
+                {tag: "div", cls: "x-dd-drop-icon"},
+                {tag: "div", cls: "x-dd-drag-ghost"}
+            ]
+        }, 
+        shadow: !config || config.shadow !== false
+    });
+    this.ghost = Ext.get(this.el.dom.childNodes[1]);
+    this.dropStatus = this.dropNotAllowed;
+};
+
+Ext.dd.StatusProxy.prototype = {
+    
+    dropAllowed : "x-dd-drop-ok",
+    
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    
+    setStatus : function(cssClass){
+        cssClass = cssClass || this.dropNotAllowed;
+        if(this.dropStatus != cssClass){
+            this.el.replaceClass(this.dropStatus, cssClass);
+            this.dropStatus = cssClass;
+        }
+    },
+
+    
+    reset : function(clearGhost){
+        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
+        this.dropStatus = this.dropNotAllowed;
+        if(clearGhost){
+            this.ghost.update("");
+        }
+    },
+
+    
+    update : function(html){
+        if(typeof html == "string"){
+            this.ghost.update(html);
+        }else{
+            this.ghost.update("");
+            html.style.margin = "0";
+            this.ghost.dom.appendChild(html);
+        }
+        var el = this.ghost.dom.firstChild; 
+        if(el){
+            Ext.fly(el).setStyle('float', 'none');
+        }
+    },
+
+    
+    getEl : function(){
+        return this.el;
+    },
+
+    
+    getGhost : function(){
+        return this.ghost;
+    },
+
+    
+    hide : function(clear){
+        this.el.hide();
+        if(clear){
+            this.reset(true);
+        }
+    },
+
+    
+    stop : function(){
+        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
+            this.anim.stop();
+        }
+    },
+
+    
+    show : function(){
+        this.el.show();
+    },
+
+    
+    sync : function(){
+        this.el.sync();
+    },
+
+    
+    repair : function(xy, callback, scope){
+        this.callback = callback;
+        this.scope = scope;
+        if(xy && this.animRepair !== false){
+            this.el.addClass("x-dd-drag-repair");
+            this.el.hideUnders(true);
+            this.anim = this.el.shift({
+                duration: this.repairDuration || .5,
+                easing: 'easeOut',
+                xy: xy,
+                stopFx: true,
+                callback: this.afterRepair,
+                scope: this
+            });
+        }else{
+            this.afterRepair();
+        }
+    },
+
+    
+    afterRepair : function(){
+        this.hide(true);
+        if(typeof this.callback == "function"){
+            this.callback.call(this.scope || this);
+        }
+        this.callback = null;
+        this.scope = null;
+    },
+    
+    destroy: function(){
+        Ext.destroy(this.ghost, this.el);    
+    }
+};
+Ext.dd.DragSource = function(el, config){
+    this.el = Ext.get(el);
+    if(!this.dragData){
+        this.dragData = {};
+    }
+    
+    Ext.apply(this, config);
+    
+    if(!this.proxy){
+        this.proxy = new Ext.dd.StatusProxy();
+    }
+    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
+          {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
+    
+    this.dragging = false;
+};
+
+Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
+    
+    
+    dropAllowed : "x-dd-drop-ok",
+    
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    
+    getDragData : function(e){
+        return this.dragData;
+    },
+
+    
+    onDragEnter : function(e, id){
+        var target = Ext.dd.DragDropMgr.getDDById(id);
+        this.cachedTarget = target;
+        if(this.beforeDragEnter(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                var status = target.notifyEnter(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }else{
+                this.proxy.setStatus(this.dropAllowed);
+            }
+            
+            if(this.afterDragEnter){
+                
+                this.afterDragEnter(target, e, id);
+            }
+        }
+    },
+
+    
+    beforeDragEnter : function(target, e, id){
+        return true;
+    },
+
+    
+    alignElWithMouse: function() {
+        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
+        this.proxy.sync();
+    },
+
+    
+    onDragOver : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragOver(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                var status = target.notifyOver(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }
+
+            if(this.afterDragOver){
+                
+                this.afterDragOver(target, e, id);
+            }
+        }
+    },
+
+    
+    beforeDragOver : function(target, e, id){
+        return true;
+    },
+
+    
+    onDragOut : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragOut(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                target.notifyOut(this, e, this.dragData);
+            }
+            this.proxy.reset();
+            if(this.afterDragOut){
+                
+                this.afterDragOut(target, e, id);
+            }
+        }
+        this.cachedTarget = null;
+    },
+
+    
+    beforeDragOut : function(target, e, id){
+        return true;
+    },
+    
+    
+    onDragDrop : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragDrop(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                if(target.notifyDrop(this, e, this.dragData)){ 
+                    this.onValidDrop(target, e, id);
+                }else{
+                    this.onInvalidDrop(target, e, id);
+                }
+            }else{
+                this.onValidDrop(target, e, id);
+            }
+            
+            if(this.afterDragDrop){
+                
+                this.afterDragDrop(target, e, id);
+            }
+        }
+        delete this.cachedTarget;
+    },
+
+    
+    beforeDragDrop : function(target, e, id){
+        return true;
+    },
+
+    
+    onValidDrop : function(target, e, id){
+        this.hideProxy();
+        if(this.afterValidDrop){
+            
+            this.afterValidDrop(target, e, id);
+        }
+    },
+
+    
+    getRepairXY : function(e, data){
+        return this.el.getXY();  
+    },
+
+    
+    onInvalidDrop : function(target, e, id){
+        this.beforeInvalidDrop(target, e, id);
+        if(this.cachedTarget){
+            if(this.cachedTarget.isNotifyTarget){
+                this.cachedTarget.notifyOut(this, e, this.dragData);
+            }
+            this.cacheTarget = null;
+        }
+        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
+
+        if(this.afterInvalidDrop){
+            
+            this.afterInvalidDrop(e, id);
+        }
+    },
+
+    
+    afterRepair : function(){
+        if(Ext.enableFx){
+            this.el.highlight(this.hlColor || "c3daf9");
+        }
+        this.dragging = false;
+    },
+
+    
+    beforeInvalidDrop : function(target, e, id){
+        return true;
+    },
+
+    
+    handleMouseDown : function(e){
+        if(this.dragging) {
+            return;
+        }
+        var data = this.getDragData(e);
+        if(data && this.onBeforeDrag(data, e) !== false){
+            this.dragData = data;
+            this.proxy.stop();
+            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
+        } 
+    },
+
+    
+    onBeforeDrag : function(data, e){
+        return true;
+    },
+
+    
+    onStartDrag : Ext.emptyFn,
+
+    
+    startDrag : function(x, y){
+        this.proxy.reset();
+        this.dragging = true;
+        this.proxy.update("");
+        this.onInitDrag(x, y);
+        this.proxy.show();
+    },
+
+    
+    onInitDrag : function(x, y){
+        var clone = this.el.dom.cloneNode(true);
+        clone.id = Ext.id(); 
+        this.proxy.update(clone);
+        this.onStartDrag(x, y);
+        return true;
+    },
+
+    
+    getProxy : function(){
+        return this.proxy;  
+    },
+
+    
+    hideProxy : function(){
+        this.proxy.hide();  
+        this.proxy.reset(true);
+        this.dragging = false;
+    },
+
+    
+    triggerCacheRefresh : function(){
+        Ext.dd.DDM.refreshCache(this.groups);
+    },
+
+    
+    b4EndDrag: function(e) {
+    },
+
+    
+    endDrag : function(e){
+        this.onEndDrag(this.dragData, e);
+    },
+
+    
+    onEndDrag : function(data, e){
+    },
+    
+    
+    autoOffset : function(x, y) {
+        this.setDelta(-12, -20);
+    },
+    
+    destroy: function(){
+        Ext.dd.DragSource.superclass.destroy.call(this);
+        Ext.destroy(this.proxy);
+    }
+});
+Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
+    
+    constructor : function(el, config){
+        this.el = Ext.get(el);
+    
+        Ext.apply(this, config);
+    
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.register(this.el);
+        }
+    
+        Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
+              {isTarget: true});        
+    },
+    
+    
+    
+    
+    dropAllowed : "x-dd-drop-ok",
+    
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    
+    isTarget : true,
+
+    
+    isNotifyTarget : true,
+
+    
+    notifyEnter : function(dd, e, data){
+        if(this.overClass){
+            this.el.addClass(this.overClass);
+        }
+        return this.dropAllowed;
+    },
+
+    
+    notifyOver : function(dd, e, data){
+        return this.dropAllowed;
+    },
+
+    
+    notifyOut : function(dd, e, data){
+        if(this.overClass){
+            this.el.removeClass(this.overClass);
+        }
+    },
+
+    
+    notifyDrop : function(dd, e, data){
+        return false;
+    },
+    
+    destroy : function(){
+        Ext.dd.DropTarget.superclass.destroy.call(this);
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.unregister(this.el);
+        }
+    }
+});
+Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
+    
+    constructor : function(el, config){
+        Ext.dd.DragZone.superclass.constructor.call(this, el, config);
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.register(this.el);
+        }
+    },
+    
+    
+    
+    
+
+    
+    getDragData : function(e){
+        return Ext.dd.Registry.getHandleFromEvent(e);
+    },
+    
+    
+    onInitDrag : function(x, y){
+        this.proxy.update(this.dragData.ddel.cloneNode(true));
+        this.onStartDrag(x, y);
+        return true;
+    },
+    
+    
+    afterRepair : function(){
+        if(Ext.enableFx){
+            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
+        }
+        this.dragging = false;
+    },
+
+    
+    getRepairXY : function(e){
+        return Ext.Element.fly(this.dragData.ddel).getXY();  
+    },
+    
+    destroy : function(){
+        Ext.dd.DragZone.superclass.destroy.call(this);
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.unregister(this.el);
+        }
+    }
+});
+Ext.dd.DropZone = function(el, config){
+    Ext.dd.DropZone.superclass.constructor.call(this, el, config);
+};
+
+Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
+    
+    getTargetFromEvent : function(e){
+        return Ext.dd.Registry.getTargetFromEvent(e);
+    },
+
+    
+    onNodeEnter : function(n, dd, e, data){
+        
+    },
+
+    
+    onNodeOver : function(n, dd, e, data){
+        return this.dropAllowed;
+    },
+
+    
+    onNodeOut : function(n, dd, e, data){
+        
+    },
+
+    
+    onNodeDrop : function(n, dd, e, data){
+        return false;
+    },
+
+    
+    onContainerOver : function(dd, e, data){
+        return this.dropNotAllowed;
+    },
+
+    
+    onContainerDrop : function(dd, e, data){
+        return false;
+    },
+
+    
+    notifyEnter : function(dd, e, data){
+        return this.dropNotAllowed;
+    },
+
+    
+    notifyOver : function(dd, e, data){
+        var n = this.getTargetFromEvent(e);
+        if(!n){ 
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+                this.lastOverNode = null;
+            }
+            return this.onContainerOver(dd, e, data);
+        }
+        if(this.lastOverNode != n){
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+            }
+            this.onNodeEnter(n, dd, e, data);
+            this.lastOverNode = n;
+        }
+        return this.onNodeOver(n, dd, e, data);
+    },
+
+    
+    notifyOut : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
+        }
+    },
+
+    
+    notifyDrop : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
+        }
+        var n = this.getTargetFromEvent(e);
+        return n ?
+            this.onNodeDrop(n, dd, e, data) :
+            this.onContainerDrop(dd, e, data);
+    },
+
+    
+    triggerCacheRefresh : function(){
+        Ext.dd.DDM.refreshCache(this.groups);
+    }  
+});
+Ext.Element.addMethods({
+    
+    initDD : function(group, config, overrides){
+        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    },
+
+    
+    initDDProxy : function(group, config, overrides){
+        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    },
+
+    
+    initDDTarget : function(group, config, overrides){
+        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    }
+});
+
+Ext.data.Api = (function() {
+
+    
+    
+    
+    
+    var validActions = {};
+
+    return {
+        
+        actions : {
+            create  : 'create',
+            read    : 'read',
+            update  : 'update',
+            destroy : 'destroy'
+        },
+
+        
+        restActions : {
+            create  : 'POST',
+            read    : 'GET',
+            update  : 'PUT',
+            destroy : 'DELETE'
+        },
+
+        
+        isAction : function(action) {
+            return (Ext.data.Api.actions[action]) ? true : false;
+        },
+
+        
+        getVerb : function(name) {
+            if (validActions[name]) {
+                return validActions[name];  
+            }
+            for (var verb in this.actions) {
+                if (this.actions[verb] === name) {
+                    validActions[name] = verb;
+                    break;
+                }
+            }
+            return (validActions[name] !== undefined) ? validActions[name] : null;
+        },
+
+        
+        isValid : function(api){
+            var invalid = [];
+            var crud = this.actions; 
+            for (var action in api) {
+                if (!(action in crud)) {
+                    invalid.push(action);
+                }
+            }
+            return (!invalid.length) ? true : invalid;
+        },
+
+        
+        hasUniqueUrl : function(proxy, verb) {
+            var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
+            var unique = true;
+            for (var action in proxy.api) {
+                if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
+                    break;
+                }
+            }
+            return unique;
+        },
+
+        
+        prepare : function(proxy) {
+            if (!proxy.api) {
+                proxy.api = {}; 
+            }
+            for (var verb in this.actions) {
+                var action = this.actions[verb];
+                proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
+                if (typeof(proxy.api[action]) == 'string') {
+                    proxy.api[action] = {
+                        url: proxy.api[action],
+                        method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
+                    };
+                }
+            }
+        },
+
+        
+        restify : function(proxy) {
+            proxy.restful = true;
+            for (var verb in this.restActions) {
+                proxy.api[this.actions[verb]].method ||
+                    (proxy.api[this.actions[verb]].method = this.restActions[verb]);
+            }
+            
+            
+            proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
+                var reader = o.reader;
+                var res = new Ext.data.Response({
+                    action: action,
+                    raw: response
+                });
+
+                switch (response.status) {
+                    case 200:   
+                        return true;
+                        break;
+                    case 201:   
+                        if (Ext.isEmpty(res.raw.responseText)) {
+                          res.success = true;
+                        } else {
+                          
+                          return true;
+                        }
+                        break;
+                    case 204:  
+                        res.success = true;
+                        res.data = null;
+                        break;
+                    default:
+                        return true;
+                        break;
+                }
+                if (res.success === true) {
+                    this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
+                } else {
+                    this.fireEvent('exception', this, 'remote', action, o, res, rs);
+                }
+                o.request.callback.call(o.request.scope, res.data, res, res.success);
+
+                return false;   
+            }, proxy);
+        }
+    };
+})();
+
+
+Ext.data.Response = function(params, response) {
+    Ext.apply(this, params, {
+        raw: response
+    });
+};
+Ext.data.Response.prototype = {
+    message : null,
+    success : false,
+    status : null,
+    root : null,
+    raw : null,
+
+    getMessage : function() {
+        return this.message;
+    },
+    getSuccess : function() {
+        return this.success;
+    },
+    getStatus : function() {
+        return this.status;
+    },
+    getRoot : function() {
+        return this.root;
+    },
+    getRawResponse : function() {
+        return this.raw;
+    }
+};
+
+
+Ext.data.Api.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name: 'Ext.data.Api'
+});
+Ext.apply(Ext.data.Api.Error.prototype, {
+    lang: {
+        'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
+        'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
+        'invalid-url': 'Invalid url.  Please review your proxy configuration.',
+        'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
+    }
+});
+
+
+
+
+Ext.data.SortTypes = {
+    
+    none : function(s){
+        return s;
+    },
+    
+    
+    stripTagsRE : /<\/?[^>]+>/gi,
+    
+    
+    asText : function(s){
+        return String(s).replace(this.stripTagsRE, "");
+    },
+    
+    
+    asUCText : function(s){
+        return String(s).toUpperCase().replace(this.stripTagsRE, "");
+    },
+    
+    
+    asUCString : function(s) {
+    	return String(s).toUpperCase();
+    },
+    
+    
+    asDate : function(s) {
+        if(!s){
+            return 0;
+        }
+        if(Ext.isDate(s)){
+            return s.getTime();
+        }
+    	return Date.parse(String(s));
+    },
+    
+    
+    asFloat : function(s) {
+    	var val = parseFloat(String(s).replace(/,/g, ""));
+    	return isNaN(val) ? 0 : val;
+    },
+    
+    
+    asInt : function(s) {
+        var val = parseInt(String(s).replace(/,/g, ""), 10);
+        return isNaN(val) ? 0 : val;
+    }
+};
+Ext.data.Record = function(data, id){
+    
+    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
+    this.data = data || {};
+};
+
+
+Ext.data.Record.create = function(o){
+    var f = Ext.extend(Ext.data.Record, {});
+    var p = f.prototype;
+    p.fields = new Ext.util.MixedCollection(false, function(field){
+        return field.name;
+    });
+    for(var i = 0, len = o.length; i < len; i++){
+        p.fields.add(new Ext.data.Field(o[i]));
+    }
+    f.getField = function(name){
+        return p.fields.get(name);
+    };
+    return f;
+};
+
+Ext.data.Record.PREFIX = 'ext-record';
+Ext.data.Record.AUTO_ID = 1;
+Ext.data.Record.EDIT = 'edit';
+Ext.data.Record.REJECT = 'reject';
+Ext.data.Record.COMMIT = 'commit';
+
+
+
+Ext.data.Record.id = function(rec) {
+    rec.phantom = true;
+    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
+};
+
+Ext.data.Record.prototype = {
+    
+    
+    
+    
+    
+    
+    dirty : false,
+    editing : false,
+    error : null,
+    
+    modified : null,
+    
+    phantom : false,
+
+    
+    join : function(store){
+        
+        this.store = store;
+    },
+
+    
+    set : function(name, value){
+        var encode = Ext.isPrimitive(value) ? String : Ext.encode;
+        if(encode(this.data[name]) == encode(value)) {
+            return;
+        }        
+        this.dirty = true;
+        if(!this.modified){
+            this.modified = {};
+        }
+        if(this.modified[name] === undefined){
+            this.modified[name] = this.data[name];
+        }
+        this.data[name] = value;
+        if(!this.editing){
+            this.afterEdit();
+        }
+    },
+
+    
+    afterEdit : function(){
+        if (this.store != undefined && typeof this.store.afterEdit == "function") {
+            this.store.afterEdit(this);
+        }
+    },
+
+    
+    afterReject : function(){
+        if(this.store){
+            this.store.afterReject(this);
+        }
+    },
+
+    
+    afterCommit : function(){
+        if(this.store){
+            this.store.afterCommit(this);
+        }
+    },
+
+    
+    get : function(name){
+        return this.data[name];
+    },
+
+    
+    beginEdit : function(){
+        this.editing = true;
+        this.modified = this.modified || {};
+    },
+
+    
+    cancelEdit : function(){
+        this.editing = false;
+        delete this.modified;
+    },
+
+    
+    endEdit : function(){
+        this.editing = false;
+        if(this.dirty){
+            this.afterEdit();
+        }
+    },
+
+    
+    reject : function(silent){
+        var m = this.modified;
+        for(var n in m){
+            if(typeof m[n] != "function"){
+                this.data[n] = m[n];
+            }
+        }
+        this.dirty = false;
+        delete this.modified;
+        this.editing = false;
+        if(silent !== true){
+            this.afterReject();
+        }
+    },
+
+    
+    commit : function(silent){
+        this.dirty = false;
+        delete this.modified;
+        this.editing = false;
+        if(silent !== true){
+            this.afterCommit();
+        }
+    },
+
+    
+    getChanges : function(){
+        var m = this.modified, cs = {};
+        for(var n in m){
+            if(m.hasOwnProperty(n)){
+                cs[n] = this.data[n];
+            }
+        }
+        return cs;
+    },
+
+    
+    hasError : function(){
+        return this.error !== null;
+    },
+
+    
+    clearError : function(){
+        this.error = null;
+    },
+
+    
+    copy : function(newId) {
+        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
+    },
+
+    
+    isModified : function(fieldName){
+        return !!(this.modified && this.modified.hasOwnProperty(fieldName));
+    },
+
+    
+    isValid : function() {
+        return this.fields.find(function(f) {
+            return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
+        },this) ? false : true;
+    },
+
+    
+    markDirty : function(){
+        this.dirty = true;
+        if(!this.modified){
+            this.modified = {};
+        }
+        this.fields.each(function(f) {
+            this.modified[f.name] = this.data[f.name];
+        },this);
+    }
+};
+
+Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
+    
+
+    
+    register : function(){
+        for(var i = 0, s; (s = arguments[i]); i++){
+            this.add(s);
+        }
+    },
+
+    
+    unregister : function(){
+        for(var i = 0, s; (s = arguments[i]); i++){
+            this.remove(this.lookup(s));
+        }
+    },
+
+    
+    lookup : function(id){
+        if(Ext.isArray(id)){
+            var fields = ['field1'], expand = !Ext.isArray(id[0]);
+            if(!expand){
+                for(var i = 2, len = id[0].length; i <= len; ++i){
+                    fields.push('field' + i);
+                }
+            }
+            return new Ext.data.ArrayStore({
+                fields: fields,
+                data: id,
+                expandData: expand,
+                autoDestroy: true,
+                autoCreated: true
+
+            });
+        }
+        return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
+    },
+
+    
+    getKey : function(o){
+         return o.storeId;
+    }
+});
+Ext.data.Store = Ext.extend(Ext.util.Observable, {
+    
+    
+    
+    
+    
+    
+    
+    writer : undefined,
+    
+    
+    
+    remoteSort : false,
+
+    
+    autoDestroy : false,
+
+    
+    pruneModifiedRecords : false,
+
+    
+    lastOptions : null,
+
+    
+    autoSave : true,
+
+    
+    batch : true,
+
+    
+    restful: false,
+
+    
+    paramNames : undefined,
+
+    
+    defaultParamNames : {
+        start : 'start',
+        limit : 'limit',
+        sort : 'sort',
+        dir : 'dir'
+    },
+
+    isDestroyed: false,    
+    hasMultiSort: false,
+
+    
+    batchKey : '_ext_batch_',
+
+    constructor : function(config){
+        
+        
+        
+        
+        this.data = new Ext.util.MixedCollection(false);
+        this.data.getKey = function(o){
+            return o.id;
+        };
+        
+
+        
+        this.removed = [];
+
+        if(config && config.data){
+            this.inlineData = config.data;
+            delete config.data;
+        }
+
+        Ext.apply(this, config);
+
+        
+        this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
+
+        this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
+
+        if((this.url || this.api) && !this.proxy){
+            this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
+        }
+        
+        if (this.restful === true && this.proxy) {
+            
+            
+            this.batch = false;
+            Ext.data.Api.restify(this.proxy);
+        }
+
+        if(this.reader){ 
+            if(!this.recordType){
+                this.recordType = this.reader.recordType;
+            }
+            if(this.reader.onMetaChange){
+                this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
+            }
+            if (this.writer) { 
+                if (this.writer instanceof(Ext.data.DataWriter) === false) {    
+                    this.writer = this.buildWriter(this.writer);
+                }
+                this.writer.meta = this.reader.meta;
+                this.pruneModifiedRecords = true;
+            }
+        }
+
+        
+
+        if(this.recordType){
+            
+            this.fields = this.recordType.prototype.fields;
+        }
+        this.modified = [];
+
+        this.addEvents(
+            
+            'datachanged',
+            
+            'metachange',
+            
+            'add',
+            
+            'remove',
+            
+            'update',
+            
+            'clear',
+            
+            'exception',
+            
+            'beforeload',
+            
+            'load',
+            
+            'loadexception',
+            
+            'beforewrite',
+            
+            'write',
+            
+            'beforesave',
+            
+            'save'
+
+        );
+
+        if(this.proxy){
+            
+            this.relayEvents(this.proxy,  ['loadexception', 'exception']);
+        }
+        
+        if (this.writer) {
+            this.on({
+                scope: this,
+                add: this.createRecords,
+                remove: this.destroyRecord,
+                update: this.updateRecord,
+                clear: this.onClear
+            });
+        }
+
+        this.sortToggle = {};
+        if(this.sortField){
+            this.setDefaultSort(this.sortField, this.sortDir);
+        }else if(this.sortInfo){
+            this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
+        }
+
+        Ext.data.Store.superclass.constructor.call(this);
+
+        if(this.id){
+            this.storeId = this.id;
+            delete this.id;
+        }
+        if(this.storeId){
+            Ext.StoreMgr.register(this);
+        }
+        if(this.inlineData){
+            this.loadData(this.inlineData);
+            delete this.inlineData;
+        }else if(this.autoLoad){
+            this.load.defer(10, this, [
+                typeof this.autoLoad == 'object' ?
+                    this.autoLoad : undefined]);
+        }
+        
+        this.batchCounter = 0;
+        this.batches = {};
+    },
+
+    
+    buildWriter : function(config) {
+        var klass = undefined,
+            type = (config.format || 'json').toLowerCase();
+        switch (type) {
+            case 'json':
+                klass = Ext.data.JsonWriter;
+                break;
+            case 'xml':
+                klass = Ext.data.XmlWriter;
+                break;
+            default:
+                klass = Ext.data.JsonWriter;
+        }
+        return new klass(config);
+    },
+
+    
+    destroy : function(){
+        if(!this.isDestroyed){
+            if(this.storeId){
+                Ext.StoreMgr.unregister(this);
+            }
+            this.clearData();
+            this.data = null;
+            Ext.destroy(this.proxy);
+            this.reader = this.writer = null;
+            this.purgeListeners();
+            this.isDestroyed = true;
+        }
+    },
+
+    
+    add : function(records) {
+        var i, len, record, index;
+        
+        records = [].concat(records);
+        if (records.length < 1) {
+            return;
+        }
+        
+        for (i = 0, len = records.length; i < len; i++) {
+            record = records[i];
+            
+            record.join(this);
+            
+            if (record.dirty || record.phantom) {
+                this.modified.push(record);
+            }
+        }
+        
+        index = this.data.length;
+        this.data.addAll(records);
+        
+        if (this.snapshot) {
+            this.snapshot.addAll(records);
+        }
+        
+        this.fireEvent('add', this, records, index);
+    },
+
+    
+    addSorted : function(record){
+        var index = this.findInsertIndex(record);
+        this.insert(index, record);
+    },
+    
+    
+    doUpdate: function(rec){
+        var id = rec.id;
+        
+        this.getById(id).join(null);
+        
+        this.data.replace(id, rec);
+        if (this.snapshot) {
+            this.snapshot.replace(id, rec);
+        }
+        rec.join(this);
+        this.fireEvent('update', this, rec, Ext.data.Record.COMMIT);
+    },
+
+    
+    remove : function(record){
+        if(Ext.isArray(record)){
+            Ext.each(record, function(r){
+                this.remove(r);
+            }, this);
+            return;
+        }
+        var index = this.data.indexOf(record);
+        if(index > -1){
+            record.join(null);
+            this.data.removeAt(index);
+        }
+        if(this.pruneModifiedRecords){
+            this.modified.remove(record);
+        }
+        if(this.snapshot){
+            this.snapshot.remove(record);
+        }
+        if(index > -1){
+            this.fireEvent('remove', this, record, index);
+        }
+    },
+
+    
+    removeAt : function(index){
+        this.remove(this.getAt(index));
+    },
+
+    
+    removeAll : function(silent){
+        var items = [];
+        this.each(function(rec){
+            items.push(rec);
+        });
+        this.clearData();
+        if(this.snapshot){
+            this.snapshot.clear();
+        }
+        if(this.pruneModifiedRecords){
+            this.modified = [];
+        }
+        if (silent !== true) {  
+            this.fireEvent('clear', this, items);
+        }
+    },
+
+    
+    onClear: function(store, records){
+        Ext.each(records, function(rec, index){
+            this.destroyRecord(this, rec, index);
+        }, this);
+    },
+
+    
+    insert : function(index, records) {
+        var i, len, record;
+        
+        records = [].concat(records);
+        for (i = 0, len = records.length; i < len; i++) {
+            record = records[i];
+            
+            this.data.insert(index + i, record);
+            record.join(this);
+            
+            if (record.dirty || record.phantom) {
+                this.modified.push(record);
+            }
+        }
+        
+        if (this.snapshot) {
+            this.snapshot.addAll(records);
+        }
+        
+        this.fireEvent('add', this, records, index);
+    },
+
+    
+    indexOf : function(record){
+        return this.data.indexOf(record);
+    },
+
+    
+    indexOfId : function(id){
+        return this.data.indexOfKey(id);
+    },
+
+    
+    getById : function(id){
+        return (this.snapshot || this.data).key(id);
+    },
+
+    
+    getAt : function(index){
+        return this.data.itemAt(index);
+    },
+
+    
+    getRange : function(start, end){
+        return this.data.getRange(start, end);
+    },
+
+    
+    storeOptions : function(o){
+        o = Ext.apply({}, o);
+        delete o.callback;
+        delete o.scope;
+        this.lastOptions = o;
+    },
+
+    
+    clearData: function(){
+        this.data.each(function(rec) {
+            rec.join(null);
+        });
+        this.data.clear();
+    },
+
+    
+    load : function(options) {
+        options = Ext.apply({}, options);
+        this.storeOptions(options);
+        if(this.sortInfo && this.remoteSort){
+            var pn = this.paramNames;
+            options.params = Ext.apply({}, options.params);
+            options.params[pn.sort] = this.sortInfo.field;
+            options.params[pn.dir] = this.sortInfo.direction;
+        }
+        try {
+            return this.execute('read', null, options); 
+        } catch(e) {
+            this.handleException(e);
+            return false;
+        }
+    },
+
+    
+    updateRecord : function(store, record, action) {
+        if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
+            this.save();
+        }
+    },
+
+    
+    createRecords : function(store, records, index) {
+        var modified = this.modified,
+            length   = records.length,
+            record, i;
+        
+        for (i = 0; i < length; i++) {
+            record = records[i];
+            
+            if (record.phantom && record.isValid()) {
+                record.markDirty();  
+                
+                if (modified.indexOf(record) == -1) {
+                    modified.push(record);
+                }
+            }
+        }
+        if (this.autoSave === true) {
+            this.save();
+        }
+    },
+
+    
+    destroyRecord : function(store, record, index) {
+        if (this.modified.indexOf(record) != -1) {  
+            this.modified.remove(record);
+        }
+        if (!record.phantom) {
+            this.removed.push(record);
+
+            
+            
+            
+            record.lastIndex = index;
+
+            if (this.autoSave === true) {
+                this.save();
+            }
+        }
+    },
+
+    
+    execute : function(action, rs, options,  batch) {
+        
+        if (!Ext.data.Api.isAction(action)) {
+            throw new Ext.data.Api.Error('execute', action);
+        }
+        
+        options = Ext.applyIf(options||{}, {
+            params: {}
+        });
+        if(batch !== undefined){
+            this.addToBatch(batch);
+        }
+        
+        
+        var doRequest = true;
+
+        if (action === 'read') {
+            doRequest = this.fireEvent('beforeload', this, options);
+            Ext.applyIf(options.params, this.baseParams);
+        }
+        else {
+            
+            
+            if (this.writer.listful === true && this.restful !== true) {
+                rs = (Ext.isArray(rs)) ? rs : [rs];
+            }
+            
+            else if (Ext.isArray(rs) && rs.length == 1) {
+                rs = rs.shift();
+            }
+            
+            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
+                this.writer.apply(options.params, this.baseParams, action, rs);
+            }
+        }
+        if (doRequest !== false) {
+            
+            if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
+                options.params.xaction = action;    
+            }
+            
+            
+            
+            
+            
+            this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
+        }
+        return doRequest;
+    },
+
+    
+    save : function() {
+        if (!this.writer) {
+            throw new Ext.data.Store.Error('writer-undefined');
+        }
+
+        var queue = [],
+            len,
+            trans,
+            batch,
+            data = {},
+            i;
+        
+        if(this.removed.length){
+            queue.push(['destroy', this.removed]);
+        }
+
+        
+        var rs = [].concat(this.getModifiedRecords());
+        if(rs.length){
+            
+            var phantoms = [];
+            for(i = rs.length-1; i >= 0; i--){
+                if(rs[i].phantom === true){
+                    var rec = rs.splice(i, 1).shift();
+                    if(rec.isValid()){
+                        phantoms.push(rec);
+                    }
+                }else if(!rs[i].isValid()){ 
+                    rs.splice(i,1);
+                }
+            }
+            
+            if(phantoms.length){
+                queue.push(['create', phantoms]);
+            }
+
+            
+            if(rs.length){
+                queue.push(['update', rs]);
+            }
+        }
+        len = queue.length;
+        if(len){
+            batch = ++this.batchCounter;
+            for(i = 0; i < len; ++i){
+                trans = queue[i];
+                data[trans[0]] = trans[1];
+            }
+            if(this.fireEvent('beforesave', this, data) !== false){
+                for(i = 0; i < len; ++i){
+                    trans = queue[i];
+                    this.doTransaction(trans[0], trans[1], batch);
+                }
+                return batch;
+            }
+        }
+        return -1;
+    },
+
+    
+    doTransaction : function(action, rs, batch) {
+        function transaction(records) {
+            try{
+                this.execute(action, records, undefined, batch);
+            }catch (e){
+                this.handleException(e);
+            }
+        }
+        if(this.batch === false){
+            for(var i = 0, len = rs.length; i < len; i++){
+                transaction.call(this, rs[i]);
+            }
+        }else{
+            transaction.call(this, rs);
+        }
+    },
+
+    
+    addToBatch : function(batch){
+        var b = this.batches,
+            key = this.batchKey + batch,
+            o = b[key];
+
+        if(!o){
+            b[key] = o = {
+                id: batch,
+                count: 0,
+                data: {}
+            };
+        }
+        ++o.count;
+    },
+
+    removeFromBatch : function(batch, action, data){
+        var b = this.batches,
+            key = this.batchKey + batch,
+            o = b[key],
+            arr;
+
+
+        if(o){
+            arr = o.data[action] || [];
+            o.data[action] = arr.concat(data);
+            if(o.count === 1){
+                data = o.data;
+                delete b[key];
+                this.fireEvent('save', this, batch, data);
+            }else{
+                --o.count;
+            }
+        }
+    },
+
+    
+    
+    createCallback : function(action, rs, batch) {
+        var actions = Ext.data.Api.actions;
+        return (action == 'read') ? this.loadRecords : function(data, response, success) {
+            
+            this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
+            
+            if (success === true) {
+                this.fireEvent('write', this, action, data, response, rs);
+            }
+            this.removeFromBatch(batch, action, data);
+        };
+    },
+
+    
+    
+    
+    clearModified : function(rs) {
+        if (Ext.isArray(rs)) {
+            for (var n=rs.length-1;n>=0;n--) {
+                this.modified.splice(this.modified.indexOf(rs[n]), 1);
+            }
+        } else {
+            this.modified.splice(this.modified.indexOf(rs), 1);
+        }
+    },
+
+    
+    reMap : function(record) {
+        if (Ext.isArray(record)) {
+            for (var i = 0, len = record.length; i < len; i++) {
+                this.reMap(record[i]);
+            }
+        } else {
+            delete this.data.map[record._phid];
+            this.data.map[record.id] = record;
+            var index = this.data.keys.indexOf(record._phid);
+            this.data.keys.splice(index, 1, record.id);
+            delete record._phid;
+        }
+    },
+
+    
+    onCreateRecords : function(success, rs, data) {
+        if (success === true) {
+            try {
+                this.reader.realize(rs, data);
+            }
+            catch (e) {
+                this.handleException(e);
+                if (Ext.isArray(rs)) {
+                    
+                    this.onCreateRecords(success, rs, data);
+                }
+            }
+        }
+    },
+
+    
+    onUpdateRecords : function(success, rs, data) {
+        if (success === true) {
+            try {
+                this.reader.update(rs, data);
+            } catch (e) {
+                this.handleException(e);
+                if (Ext.isArray(rs)) {
+                    
+                    this.onUpdateRecords(success, rs, data);
+                }
+            }
+        }
+    },
+
+    
+    onDestroyRecords : function(success, rs, data) {
+        
+        rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
+        for (var i=0,len=rs.length;i<len;i++) {
+            this.removed.splice(this.removed.indexOf(rs[i]), 1);
+        }
+        if (success === false) {
+            
+            
+            for (i=rs.length-1;i>=0;i--) {
+                this.insert(rs[i].lastIndex, rs[i]);    
+            }
+        }
+    },
+
+    
+    handleException : function(e) {
+        
+        Ext.handleError(e);
+    },
+
+    
+    reload : function(options){
+        this.load(Ext.applyIf(options||{}, this.lastOptions));
+    },
+
+    
+    
+    loadRecords : function(o, options, success){
+        var i, len;
+        
+        if (this.isDestroyed === true) {
+            return;
+        }
+        if(!o || success === false){
+            if(success !== false){
+                this.fireEvent('load', this, [], options);
+            }
+            if(options.callback){
+                options.callback.call(options.scope || this, [], options, false, o);
+            }
+            return;
+        }
+        var r = o.records, t = o.totalRecords || r.length;
+        if(!options || options.add !== true){
+            if(this.pruneModifiedRecords){
+                this.modified = [];
+            }
+            for(i = 0, len = r.length; i < len; i++){
+                r[i].join(this);
+            }
+            if(this.snapshot){
+                this.data = this.snapshot;
+                delete this.snapshot;
+            }
+            this.clearData();
+            this.data.addAll(r);
+            this.totalLength = t;
+            this.applySort();
+            this.fireEvent('datachanged', this);
+        }else{
+            var toAdd = [],
+                rec,
+                cnt = 0;
+            for(i = 0, len = r.length; i < len; ++i){
+                rec = r[i];
+                if(this.indexOfId(rec.id) > -1){
+                    this.doUpdate(rec);
+                }else{
+                    toAdd.push(rec);
+                    ++cnt;
+                }
+            }
+            this.totalLength = Math.max(t, this.data.length + cnt);
+            this.add(toAdd);
+        }
+        this.fireEvent('load', this, r, options);
+        if(options.callback){
+            options.callback.call(options.scope || this, r, options, true);
+        }
+    },
+
+    
+    loadData : function(o, append){
+        var r = this.reader.readRecords(o);
+        this.loadRecords(r, {add: append}, true);
+    },
+
+    
+    getCount : function(){
+        return this.data.length || 0;
+    },
+
+    
+    getTotalCount : function(){
+        return this.totalLength || 0;
+    },
+
+    
+    getSortState : function(){
+        return this.sortInfo;
+    },
+
+    
+    applySort : function(){
+        if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
+            this.sortData();
+        }
+    },
+
+    
+    sortData : function() {
+        var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
+            direction = sortInfo.direction || "ASC",
+            sorters   = sortInfo.sorters,
+            sortFns   = [];
+
+        
+        if (!this.hasMultiSort) {
+            sorters = [{direction: direction, field: sortInfo.field}];
+        }
+
+        
+        for (var i=0, j = sorters.length; i < j; i++) {
+            sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
+        }
+        
+        if (sortFns.length == 0) {
+            return;
+        }
+
+        
+        
+        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
+
+        
+        var fn = function(r1, r2) {
+          var result = sortFns[0].call(this, r1, r2);
+
+          
+          if (sortFns.length > 1) {
+              for (var i=1, j = sortFns.length; i < j; i++) {
+                  result = result || sortFns[i].call(this, r1, r2);
+              }
+          }
+
+          return directionModifier * result;
+        };
+
+        
+        this.data.sort(direction, fn);
+        if (this.snapshot && this.snapshot != this.data) {
+            this.snapshot.sort(direction, fn);
+        }
+    },
+
+    
+    createSortFunction: function(field, direction) {
+        direction = direction || "ASC";
+        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
+
+        var sortType = this.fields.get(field).sortType;
+
+        
+        
+        return function(r1, r2) {
+            var v1 = sortType(r1.data[field]),
+                v2 = sortType(r2.data[field]);
+
+            return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
+        };
+    },
+
+    
+    setDefaultSort : function(field, dir) {
+        dir = dir ? dir.toUpperCase() : 'ASC';
+        this.sortInfo = {field: field, direction: dir};
+        this.sortToggle[field] = dir;
+    },
+
+    
+    sort : function(fieldName, dir) {
+        if (Ext.isArray(arguments[0])) {
+            return this.multiSort.call(this, fieldName, dir);
+        } else {
+            return this.singleSort(fieldName, dir);
+        }
+    },
+
+    
+    singleSort: function(fieldName, dir) {
+        var field = this.fields.get(fieldName);
+        if (!field) {
+            return false;
+        }
+
+        var name       = field.name,
+            sortInfo   = this.sortInfo || null,
+            sortToggle = this.sortToggle ? this.sortToggle[name] : null;
+
+        if (!dir) {
+            if (sortInfo && sortInfo.field == name) { 
+                dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
+            } else {
+                dir = field.sortDir;
+            }
+        }
+
+        this.sortToggle[name] = dir;
+        this.sortInfo = {field: name, direction: dir};
+        this.hasMultiSort = false;
+
+        if (this.remoteSort) {
+            if (!this.load(this.lastOptions)) {
+                if (sortToggle) {
+                    this.sortToggle[name] = sortToggle;
+                }
+                if (sortInfo) {
+                    this.sortInfo = sortInfo;
+                }
+            }
+        } else {
+            this.applySort();
+            this.fireEvent('datachanged', this);
+        }
+        return true;
+    },
+
+    
+    multiSort: function(sorters, direction) {
+        this.hasMultiSort = true;
+        direction = direction || "ASC";
+
+        
+        if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
+            direction = direction.toggle("ASC", "DESC");
+        }
+
+        
+        this.multiSortInfo = {
+            sorters  : sorters,
+            direction: direction
+        };
+        
+        if (this.remoteSort) {
+            this.singleSort(sorters[0].field, sorters[0].direction);
+
+        } else {
+            this.applySort();
+            this.fireEvent('datachanged', this);
+        }
+    },
+
+    
+    each : function(fn, scope){
+        this.data.each(fn, scope);
+    },
+
+    
+    getModifiedRecords : function(){
+        return this.modified;
+    },
+
+    
+    sum : function(property, start, end){
+        var rs = this.data.items, v = 0;
+        start = start || 0;
+        end = (end || end === 0) ? end : rs.length-1;
+
+        for(var i = start; i <= end; i++){
+            v += (rs[i].data[property] || 0);
+        }
+        return v;
+    },
+
+    
+    createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
+        if(Ext.isEmpty(value, false)){
+            return false;
+        }
+        value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
+        return function(r) {
+            return value.test(r.data[property]);
+        };
+    },
+
+    
+    createMultipleFilterFn: function(filters) {
+        return function(record) {
+            var isMatch = true;
+
+            for (var i=0, j = filters.length; i < j; i++) {
+                var filter = filters[i],
+                    fn     = filter.fn,
+                    scope  = filter.scope;
+
+                isMatch = isMatch && fn.call(scope, record);
+            }
+
+            return isMatch;
+        };
+    },
+
+    
+    filter : function(property, value, anyMatch, caseSensitive, exactMatch){
+        var fn;
+        
+        if (Ext.isObject(property)) {
+            property = [property];
+        }
+
+        if (Ext.isArray(property)) {
+            var filters = [];
+
+            
+            for (var i=0, j = property.length; i < j; i++) {
+                var filter = property[i],
+                    func   = filter.fn,
+                    scope  = filter.scope || this;
+
+                
+                if (!Ext.isFunction(func)) {
+                    func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
+                }
+
+                filters.push({fn: func, scope: scope});
+            }
+
+            fn = this.createMultipleFilterFn(filters);
+        } else {
+            
+            fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
+        }
+
+        return fn ? this.filterBy(fn) : this.clearFilter();
+    },
+
+    
+    filterBy : function(fn, scope){
+        this.snapshot = this.snapshot || this.data;
+        this.data = this.queryBy(fn, scope || this);
+        this.fireEvent('datachanged', this);
+    },
+
+    
+    clearFilter : function(suppressEvent){
+        if(this.isFiltered()){
+            this.data = this.snapshot;
+            delete this.snapshot;
+            if(suppressEvent !== true){
+                this.fireEvent('datachanged', this);
+            }
+        }
+    },
+
+    
+    isFiltered : function(){
+        return !!this.snapshot && this.snapshot != this.data;
+    },
+
+    
+    query : function(property, value, anyMatch, caseSensitive){
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
+        return fn ? this.queryBy(fn) : this.data.clone();
+    },
+
+    
+    queryBy : function(fn, scope){
+        var data = this.snapshot || this.data;
+        return data.filterBy(fn, scope||this);
+    },
+
+    
+    find : function(property, value, start, anyMatch, caseSensitive){
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
+        return fn ? this.data.findIndexBy(fn, null, start) : -1;
+    },
+
+    
+    findExact: function(property, value, start){
+        return this.data.findIndexBy(function(rec){
+            return rec.get(property) === value;
+        }, this, start);
+    },
+
+    
+    findBy : function(fn, scope, start){
+        return this.data.findIndexBy(fn, scope, start);
+    },
+
+    
+    collect : function(dataIndex, allowNull, bypassFilter){
+        var d = (bypassFilter === true && this.snapshot) ?
+                this.snapshot.items : this.data.items;
+        var v, sv, r = [], l = {};
+        for(var i = 0, len = d.length; i < len; i++){
+            v = d[i].data[dataIndex];
+            sv = String(v);
+            if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
+                l[sv] = true;
+                r[r.length] = v;
+            }
+        }
+        return r;
+    },
+
+    
+    afterEdit : function(record){
+        if(this.modified.indexOf(record) == -1){
+            this.modified.push(record);
+        }
+        this.fireEvent('update', this, record, Ext.data.Record.EDIT);
+    },
+
+    
+    afterReject : function(record){
+        this.modified.remove(record);
+        this.fireEvent('update', this, record, Ext.data.Record.REJECT);
+    },
+
+    
+    afterCommit : function(record){
+        this.modified.remove(record);
+        this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
+    },
+
+    
+    commitChanges : function(){
+        var modified = this.modified.slice(0),
+            length   = modified.length,
+            i;
+            
+        for (i = 0; i < length; i++){
+            modified[i].commit();
+        }
+        
+        this.modified = [];
+        this.removed  = [];
+    },
+
+    
+    rejectChanges : function() {
+        var modified = this.modified.slice(0),
+            removed  = this.removed.slice(0).reverse(),
+            mLength  = modified.length,
+            rLength  = removed.length,
+            i;
+        
+        for (i = 0; i < mLength; i++) {
+            modified[i].reject();
+        }
+        
+        for (i = 0; i < rLength; i++) {
+            this.insert(removed[i].lastIndex || 0, removed[i]);
+            removed[i].reject();
+        }
+        
+        this.modified = [];
+        this.removed  = [];
+    },
+
+    
+    onMetaChange : function(meta){
+        this.recordType = this.reader.recordType;
+        this.fields = this.recordType.prototype.fields;
+        delete this.snapshot;
+        if(this.reader.meta.sortInfo){
+            this.sortInfo = this.reader.meta.sortInfo;
+        }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
+            delete this.sortInfo;
+        }
+        if(this.writer){
+            this.writer.meta = this.reader.meta;
+        }
+        this.modified = [];
+        this.fireEvent('metachange', this, this.reader.meta);
+    },
+
+    
+    findInsertIndex : function(record){
+        this.suspendEvents();
+        var data = this.data.clone();
+        this.data.add(record);
+        this.applySort();
+        var index = this.data.indexOf(record);
+        this.data = data;
+        this.resumeEvents();
+        return index;
+    },
+
+    
+    setBaseParam : function (name, value){
+        this.baseParams = this.baseParams || {};
+        this.baseParams[name] = value;
+    }
+});
+
+Ext.reg('store', Ext.data.Store);
+
+
+Ext.data.Store.Error = Ext.extend(Ext.Error, {
+    name: 'Ext.data.Store'
+});
+Ext.apply(Ext.data.Store.Error.prototype, {
+    lang: {
+        'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
+    }
+});
+
+Ext.data.Field = Ext.extend(Object, {
+    
+    constructor : function(config){
+        if(Ext.isString(config)){
+            config = {name: config};
+        }
+        Ext.apply(this, config);
+        
+        var types = Ext.data.Types,
+            st = this.sortType,
+            t;
+
+        if(this.type){
+            if(Ext.isString(this.type)){
+                this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
+            }
+        }else{
+            this.type = types.AUTO;
+        }
+
+        
+        if(Ext.isString(st)){
+            this.sortType = Ext.data.SortTypes[st];
+        }else if(Ext.isEmpty(st)){
+            this.sortType = this.type.sortType;
+        }
+
+        if(!this.convert){
+            this.convert = this.type.convert;
+        }
+    },
+    
+    
+    
+    
+    
+    dateFormat: null,
+    
+    
+    useNull: false,
+    
+    
+    defaultValue: "",
+    
+    mapping: null,
+    
+    sortType : null,
+    
+    sortDir : "ASC",
+    
+    allowBlank : true
+});
+
+Ext.data.DataReader = function(meta, recordType){
+    
+    this.meta = meta;
+    
+    this.recordType = Ext.isArray(recordType) ?
+        Ext.data.Record.create(recordType) : recordType;
+
+    
+    if (this.recordType){
+        this.buildExtractors();
+    }
+};
+
+Ext.data.DataReader.prototype = {
+    
+    
+    getTotal: Ext.emptyFn,
+    
+    getRoot: Ext.emptyFn,
+    
+    getMessage: Ext.emptyFn,
+    
+    getSuccess: Ext.emptyFn,
+    
+    getId: Ext.emptyFn,
+    
+    buildExtractors : Ext.emptyFn,
+    
+    extractValues : Ext.emptyFn,
+
+    
+    realize: function(rs, data){
+        if (Ext.isArray(rs)) {
+            for (var i = rs.length - 1; i >= 0; i--) {
+                
+                if (Ext.isArray(data)) {
+                    this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
+                }
+                else {
+                    
+                    
+                    this.realize(rs.splice(i,1).shift(), data);
+                }
+            }
+        }
+        else {
+            
+            if (Ext.isArray(data) && data.length == 1) {
+                data = data.shift();
+            }
+            if (!this.isData(data)) {
+                
+                
+                throw new Ext.data.DataReader.Error('realize', rs);
+            }
+            rs.phantom = false; 
+            rs._phid = rs.id;  
+            rs.id = this.getId(data);
+            rs.data = data;
+
+            rs.commit();
+            rs.store.reMap(rs);
+        }
+    },
+
+    
+    update : function(rs, data) {
+        if (Ext.isArray(rs)) {
+            for (var i=rs.length-1; i >= 0; i--) {
+                if (Ext.isArray(data)) {
+                    this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
+                }
+                else {
+                    
+                    
+                    this.update(rs.splice(i,1).shift(), data);
+                }
+            }
+        }
+        else {
+            
+            if (Ext.isArray(data) && data.length == 1) {
+                data = data.shift();
+            }
+            if (this.isData(data)) {
+                rs.data = Ext.apply(rs.data, data);
+            }
+            rs.commit();
+        }
+    },
+
+    
+    extractData : function(root, returnRecords) {
+        
+        var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
+
+        var rs = [];
+
+        
+        
+        if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
+            root = [root];
+        }
+        var f       = this.recordType.prototype.fields,
+            fi      = f.items,
+            fl      = f.length,
+            rs      = [];
+        if (returnRecords === true) {
+            var Record = this.recordType;
+            for (var i = 0; i < root.length; i++) {
+                var n = root[i];
+                var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
+                record[rawName] = n;    
+                rs.push(record);
+            }
+        }
+        else {
+            for (var i = 0; i < root.length; i++) {
+                var data = this.extractValues(root[i], fi, fl);
+                data[this.meta.idProperty] = this.getId(root[i]);
+                rs.push(data);
+            }
+        }
+        return rs;
+    },
+
+    
+    isData : function(data) {
+        return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
+    },
+
+    
+    onMetaChange : function(meta){
+        delete this.ef;
+        this.meta = meta;
+        this.recordType = Ext.data.Record.create(meta.fields);
+        this.buildExtractors();
+    }
+};
+
+
+Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name: 'Ext.data.DataReader'
+});
+Ext.apply(Ext.data.DataReader.Error.prototype, {
+    lang : {
+        'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
+        'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
+        'invalid-response': "#readResponse received an invalid response from the server."
+    }
+});
+
+Ext.data.DataWriter = function(config){
+    Ext.apply(this, config);
+};
+Ext.data.DataWriter.prototype = {
+
+    
+    writeAllFields : false,
+    
+    listful : false,    
+
+    
+    apply : function(params, baseParams, action, rs) {
+        var data    = [],
+        renderer    = action + 'Record';
+        
+        if (Ext.isArray(rs)) {
+            Ext.each(rs, function(rec){
+                data.push(this[renderer](rec));
+            }, this);
+        }
+        else if (rs instanceof Ext.data.Record) {
+            data = this[renderer](rs);
+        }
+        this.render(params, baseParams, data);
+    },
+
+    
+    render : Ext.emptyFn,
+
+    
+    updateRecord : Ext.emptyFn,
+
+    
+    createRecord : Ext.emptyFn,
+
+    
+    destroyRecord : Ext.emptyFn,
+
+    
+    toHash : function(rec, config) {
+        var map = rec.fields.map,
+            data = {},
+            raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
+            m;
+        Ext.iterate(raw, function(prop, value){
+            if((m = map[prop])){
+                data[m.mapping ? m.mapping : m.name] = value;
+            }
+        });
+        
+        
+        
+        if (rec.phantom) {
+            if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
+                delete data[this.meta.idProperty];
+            }
+        } else {
+            data[this.meta.idProperty] = rec.id;
+        }
+        return data;
+    },
+
+    
+    toArray : function(data) {
+        var fields = [];
+        Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
+        return fields;
+    }
+};
+Ext.data.DataProxy = function(conn){
+    
+    
+    conn = conn || {};
+
+    
+    
+    
+
+    this.api     = conn.api;
+    this.url     = conn.url;
+    this.restful = conn.restful;
+    this.listeners = conn.listeners;
+
+    
+    this.prettyUrls = conn.prettyUrls;
+
+    
+
+    this.addEvents(
+        
+        'exception',
+        
+        'beforeload',
+        
+        'load',
+        
+        'loadexception',
+        
+        'beforewrite',
+        
+        'write'
+    );
+    Ext.data.DataProxy.superclass.constructor.call(this);
+
+    
+    try {
+        Ext.data.Api.prepare(this);
+    } catch (e) {
+        if (e instanceof Ext.data.Api.Error) {
+            e.toConsole();
+        }
+    }
+    
+    Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
+};
+
+Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
+    
+    restful: false,
+
+    
+    setApi : function() {
+        if (arguments.length == 1) {
+            var valid = Ext.data.Api.isValid(arguments[0]);
+            if (valid === true) {
+                this.api = arguments[0];
+            }
+            else {
+                throw new Ext.data.Api.Error('invalid', valid);
+            }
+        }
+        else if (arguments.length == 2) {
+            if (!Ext.data.Api.isAction(arguments[0])) {
+                throw new Ext.data.Api.Error('invalid', arguments[0]);
+            }
+            this.api[arguments[0]] = arguments[1];
+        }
+        Ext.data.Api.prepare(this);
+    },
+
+    
+    isApiAction : function(action) {
+        return (this.api[action]) ? true : false;
+    },
+
+    
+    request : function(action, rs, params, reader, callback, scope, options) {
+        if (!this.api[action] && !this.load) {
+            throw new Ext.data.DataProxy.Error('action-undefined', action);
+        }
+        params = params || {};
+        if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
+            this.doRequest.apply(this, arguments);
+        }
+        else {
+            callback.call(scope || this, null, options, false);
+        }
+    },
+
+
+    
+    load : null,
+
+    
+    doRequest : function(action, rs, params, reader, callback, scope, options) {
+        
+        
+        
+        this.load(params, reader, callback, scope, options);
+    },
+
+    
+    onRead : Ext.emptyFn,
+    
+    onWrite : Ext.emptyFn,
+    
+    buildUrl : function(action, record) {
+        record = record || null;
+
+        
+        
+        
+        var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
+        if (!url) {
+            throw new Ext.data.Api.Error('invalid-url', action);
+        }
+
+        
+        
+        
+        
+        
+        
+        var provides = null;
+        var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
+        if (m) {
+            provides = m[2];    
+            url      = m[1];    
+        }
+        
+        if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
+            url += '/' + record.id;
+        }
+        return (provides === null) ? url : url + provides;
+    },
+
+    
+    destroy: function(){
+        this.purgeListeners();
+    }
+});
+
+
+
+Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
+Ext.util.Observable.call(Ext.data.DataProxy);
+
+
+Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name: 'Ext.data.DataProxy'
+});
+Ext.apply(Ext.data.DataProxy.Error.prototype, {
+    lang: {
+        'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
+        'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
+    }
+});
+
+
+
+Ext.data.Request = function(params) {
+    Ext.apply(this, params);
+};
+Ext.data.Request.prototype = {
+    
+    action : undefined,
+    
+    rs : undefined,
+    
+    params: undefined,
+    
+    callback : Ext.emptyFn,
+    
+    scope : undefined,
+    
+    reader : undefined
+};
+
+Ext.data.Response = function(params) {
+    Ext.apply(this, params);
+};
+Ext.data.Response.prototype = {
+    
+    action: undefined,
+    
+    success : undefined,
+    
+    message : undefined,
+    
+    data: undefined,
+    
+    raw: undefined,
+    
+    records: undefined
+};
+
+Ext.data.ScriptTagProxy = function(config){
+    Ext.apply(this, config);
+
+    Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
+
+    this.head = document.getElementsByTagName("head")[0];
+
+    
+};
+
+Ext.data.ScriptTagProxy.TRANS_ID = 1000;
+
+Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
+    
+    
+    timeout : 30000,
+    
+    callbackParam : "callback",
+    
+    nocache : true,
+
+    
+    doRequest : function(action, rs, params, reader, callback, scope, arg) {
+        var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
+
+        var url = this.buildUrl(action, rs);
+        if (!url) {
+            throw new Ext.data.Api.Error('invalid-url', url);
+        }
+        url = Ext.urlAppend(url, p);
+
+        if(this.nocache){
+            url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
+        }
+        var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
+        var trans = {
+            id : transId,
+            action: action,
+            cb : "stcCallback"+transId,
+            scriptId : "stcScript"+transId,
+            params : params,
+            arg : arg,
+            url : url,
+            callback : callback,
+            scope : scope,
+            reader : reader
+        };
+        window[trans.cb] = this.createCallback(action, rs, trans);
+        url += String.format("&{0}={1}", this.callbackParam, trans.cb);
+        if(this.autoAbort !== false){
+            this.abort();
+        }
+
+        trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
+
+        var script = document.createElement("script");
+        script.setAttribute("src", url);
+        script.setAttribute("type", "text/javascript");
+        script.setAttribute("id", trans.scriptId);
+        this.head.appendChild(script);
+
+        this.trans = trans;
+    },
+
+    
+    createCallback : function(action, rs, trans) {
+        var self = this;
+        return function(res) {
+            self.trans = false;
+            self.destroyTrans(trans, true);
+            if (action === Ext.data.Api.actions.read) {
+                self.onRead.call(self, action, trans, res);
+            } else {
+                self.onWrite.call(self, action, trans, res, rs);
+            }
+        };
+    },
+    
+    onRead : function(action, trans, res) {
+        var result;
+        try {
+            result = trans.reader.readRecords(res);
+        }catch(e){
+            
+            this.fireEvent("loadexception", this, trans, res, e);
+
+            this.fireEvent('exception', this, 'response', action, trans, res, e);
+            trans.callback.call(trans.scope||window, null, trans.arg, false);
+            return;
+        }
+        if (result.success === false) {
+            
+            this.fireEvent('loadexception', this, trans, res);
+
+            this.fireEvent('exception', this, 'remote', action, trans, res, null);
+        } else {
+            this.fireEvent("load", this, res, trans.arg);
+        }
+        trans.callback.call(trans.scope||window, result, trans.arg, result.success);
+    },
+    
+    onWrite : function(action, trans, response, rs) {
+        var reader = trans.reader;
+        try {
+            
+            var res = reader.readResponse(action, response);
+        } catch (e) {
+            this.fireEvent('exception', this, 'response', action, trans, res, e);
+            trans.callback.call(trans.scope||window, null, res, false);
+            return;
+        }
+        if(!res.success === true){
+            this.fireEvent('exception', this, 'remote', action, trans, res, rs);
+            trans.callback.call(trans.scope||window, null, res, false);
+            return;
+        }
+        this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
+        trans.callback.call(trans.scope||window, res.data, res, true);
+    },
+
+    
+    isLoading : function(){
+        return this.trans ? true : false;
+    },
+
+    
+    abort : function(){
+        if(this.isLoading()){
+            this.destroyTrans(this.trans);
+        }
+    },
+
+    
+    destroyTrans : function(trans, isLoaded){
+        this.head.removeChild(document.getElementById(trans.scriptId));
+        clearTimeout(trans.timeoutId);
+        if(isLoaded){
+            window[trans.cb] = undefined;
+            try{
+                delete window[trans.cb];
+            }catch(e){}
+        }else{
+            
+            window[trans.cb] = function(){
+                window[trans.cb] = undefined;
+                try{
+                    delete window[trans.cb];
+                }catch(e){}
+            };
+        }
+    },
+
+    
+    handleFailure : function(trans){
+        this.trans = false;
+        this.destroyTrans(trans, false);
+        if (trans.action === Ext.data.Api.actions.read) {
+            
+            this.fireEvent("loadexception", this, null, trans.arg);
+        }
+
+        this.fireEvent('exception', this, 'response', trans.action, {
+            response: null,
+            options: trans.arg
+        });
+        trans.callback.call(trans.scope||window, null, trans.arg, false);
+    },
+
+    
+    destroy: function(){
+        this.abort();
+        Ext.data.ScriptTagProxy.superclass.destroy.call(this);
+    }
+});
+Ext.data.HttpProxy = function(conn){
+    Ext.data.HttpProxy.superclass.constructor.call(this, conn);
+
+    
+    this.conn = conn;
+
+    
+    
+    
+    
+    this.conn.url = null;
+
+    this.useAjax = !conn || !conn.events;
+
+    
+    var actions = Ext.data.Api.actions;
+    this.activeRequest = {};
+    for (var verb in actions) {
+        this.activeRequest[actions[verb]] = undefined;
+    }
+};
+
+Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
+    
+    getConnection : function() {
+        return this.useAjax ? Ext.Ajax : this.conn;
+    },
+
+    
+    setUrl : function(url, makePermanent) {
+        this.conn.url = url;
+        if (makePermanent === true) {
+            this.url = url;
+            this.api = null;
+            Ext.data.Api.prepare(this);
+        }
+    },
+
+    
+    doRequest : function(action, rs, params, reader, cb, scope, arg) {
+        var  o = {
+            method: (this.api[action]) ? this.api[action]['method'] : undefined,
+            request: {
+                callback : cb,
+                scope : scope,
+                arg : arg
+            },
+            reader: reader,
+            callback : this.createCallback(action, rs),
+            scope: this
+        };
+
+        
+        
+        if (params.jsonData) {
+            o.jsonData = params.jsonData;
+        } else if (params.xmlData) {
+            o.xmlData = params.xmlData;
+        } else {
+            o.params = params || {};
+        }
+        
+        
+        
+        this.conn.url = this.buildUrl(action, rs);
+
+        if(this.useAjax){
+
+            Ext.applyIf(o, this.conn);
+
+            
+            if (this.activeRequest[action]) {
+                
+                
+                
+                
+                
+            }
+            this.activeRequest[action] = Ext.Ajax.request(o);
+        }else{
+            this.conn.request(o);
+        }
+        
+        this.conn.url = null;
+    },
+
+    
+    createCallback : function(action, rs) {
+        return function(o, success, response) {
+            this.activeRequest[action] = undefined;
+            if (!success) {
+                if (action === Ext.data.Api.actions.read) {
+                    
+                    
+                    this.fireEvent('loadexception', this, o, response);
+                }
+                this.fireEvent('exception', this, 'response', action, o, response);
+                o.request.callback.call(o.request.scope, null, o.request.arg, false);
+                return;
+            }
+            if (action === Ext.data.Api.actions.read) {
+                this.onRead(action, o, response);
+            } else {
+                this.onWrite(action, o, response, rs);
+            }
+        };
+    },
+
+    
+    onRead : function(action, o, response) {
+        var result;
+        try {
+            result = o.reader.read(response);
+        }catch(e){
+            
+            
+            this.fireEvent('loadexception', this, o, response, e);
+
+            this.fireEvent('exception', this, 'response', action, o, response, e);
+            o.request.callback.call(o.request.scope, null, o.request.arg, false);
+            return;
+        }
+        if (result.success === false) {
+            
+            
+            this.fireEvent('loadexception', this, o, response);
+
+            
+            var res = o.reader.readResponse(action, response);
+            this.fireEvent('exception', this, 'remote', action, o, res, null);
+        }
+        else {
+            this.fireEvent('load', this, o, o.request.arg);
+        }
+        
+        
+        
+        o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
+    },
+    
+    onWrite : function(action, o, response, rs) {
+        var reader = o.reader;
+        var res;
+        try {
+            res = reader.readResponse(action, response);
+        } catch (e) {
+            this.fireEvent('exception', this, 'response', action, o, response, e);
+            o.request.callback.call(o.request.scope, null, o.request.arg, false);
+            return;
+        }
+        if (res.success === true) {
+            this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
+        } else {
+            this.fireEvent('exception', this, 'remote', action, o, res, rs);
+        }
+        
+        
+        
+        o.request.callback.call(o.request.scope, res.data, res, res.success);
+    },
+
+    
+    destroy: function(){
+        if(!this.useAjax){
+            this.conn.abort();
+        }else if(this.activeRequest){
+            var actions = Ext.data.Api.actions;
+            for (var verb in actions) {
+                if(this.activeRequest[actions[verb]]){
+                    Ext.Ajax.abort(this.activeRequest[actions[verb]]);
+                }
+            }
+        }
+        Ext.data.HttpProxy.superclass.destroy.call(this);
+    }
+});
+Ext.data.MemoryProxy = function(data){
+    
+    var api = {};
+    api[Ext.data.Api.actions.read] = true;
+    Ext.data.MemoryProxy.superclass.constructor.call(this, {
+        api: api
+    });
+    this.data = data;
+};
+
+Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
+    
+
+       
+    doRequest : function(action, rs, params, reader, callback, scope, arg) {
+        
+        params = params || {};
+        var result;
+        try {
+            result = reader.readRecords(this.data);
+        }catch(e){
+            
+            this.fireEvent("loadexception", this, null, arg, e);
+
+            this.fireEvent('exception', this, 'response', action, arg, null, e);
+            callback.call(scope, null, arg, false);
+            return;
+        }
+        callback.call(scope, result, arg, true);
+    }
+});
+Ext.data.Types = new function(){
+    var st = Ext.data.SortTypes;
+    Ext.apply(this, {
+        
+        stripRe: /[\$,%]/g,
+        
+        
+        AUTO: {
+            convert: function(v){ return v; },
+            sortType: st.none,
+            type: 'auto'
+        },
+
+        
+        STRING: {
+            convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
+            sortType: st.asUCString,
+            type: 'string'
+        },
+
+        
+        INT: {
+            convert: function(v){
+                return v !== undefined && v !== null && v !== '' ?
+                    parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
+            },
+            sortType: st.none,
+            type: 'int'
+        },
+        
+        
+        FLOAT: {
+            convert: function(v){
+                return v !== undefined && v !== null && v !== '' ?
+                    parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
+            },
+            sortType: st.none,
+            type: 'float'
+        },
+        
+        
+        BOOL: {
+            convert: function(v){ return v === true || v === 'true' || v == 1; },
+            sortType: st.none,
+            type: 'bool'
+        },
+        
+        
+        DATE: {
+            convert: function(v){
+                var df = this.dateFormat;
+                if(!v){
+                    return null;
+                }
+                if(Ext.isDate(v)){
+                    return v;
+                }
+                if(df){
+                    if(df == 'timestamp'){
+                        return new Date(v*1000);
+                    }
+                    if(df == 'time'){
+                        return new Date(parseInt(v, 10));
+                    }
+                    return Date.parseDate(v, df);
+                }
+                var parsed = Date.parse(v);
+                return parsed ? new Date(parsed) : null;
+            },
+            sortType: st.asDate,
+            type: 'date'
+        }
+    });
+    
+    Ext.apply(this, {
+        
+        BOOLEAN: this.BOOL,
+        
+        INTEGER: this.INT,
+        
+        NUMBER: this.FLOAT    
+    });
+};
+Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
+    
+    encode : true,
+    
+    encodeDelete: false,
+    
+    constructor : function(config){
+        Ext.data.JsonWriter.superclass.constructor.call(this, config);    
+    },
+
+    
+    render : function(params, baseParams, data) {
+        if (this.encode === true) {
+            
+            Ext.apply(params, baseParams);
+            params[this.meta.root] = Ext.encode(data);
+        } else {
+            
+            var jdata = Ext.apply({}, baseParams);
+            jdata[this.meta.root] = data;
+            params.jsonData = jdata;
+        }
+    },
+    
+    createRecord : function(rec) {
+       return this.toHash(rec);
+    },
+    
+    updateRecord : function(rec) {
+        return this.toHash(rec);
+
+    },
+    
+    destroyRecord : function(rec){
+        if(this.encodeDelete){
+            var data = {};
+            data[this.meta.idProperty] = rec.id;
+            return data;
+        }else{
+            return rec.id;
+        }
+    }
+});
+Ext.data.JsonReader = function(meta, recordType){
+    meta = meta || {};
+    
+    
+    
+    
+    Ext.applyIf(meta, {
+        idProperty: 'id',
+        successProperty: 'success',
+        totalProperty: 'total'
+    });
+
+    Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
+};
+Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
+    
+    
+    read : function(response){
+        var json = response.responseText;
+        var o = Ext.decode(json);
+        if(!o) {
+            throw {message: 'JsonReader.read: Json object not found'};
+        }
+        return this.readRecords(o);
+    },
+
+    
+    
+    readResponse : function(action, response) {
+        var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
+        if(!o) {
+            throw new Ext.data.JsonReader.Error('response');
+        }
+
+        var root = this.getRoot(o),
+            success = this.getSuccess(o);
+        if (success && action === Ext.data.Api.actions.create) {
+            var def = Ext.isDefined(root);
+            if (def && Ext.isEmpty(root)) {
+                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
+            }
+            else if (!def) {
+                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
+            }
+        }
+
+        
+        var res = new Ext.data.Response({
+            action: action,
+            success: success,
+            data: (root) ? this.extractData(root, false) : [],
+            message: this.getMessage(o),
+            raw: o
+        });
+
+        
+        if (Ext.isEmpty(res.success)) {
+            throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
+        }
+        return res;
+    },
+
+    
+    readRecords : function(o){
+        
+        this.jsonData = o;
+        if(o.metaData){
+            this.onMetaChange(o.metaData);
+        }
+        var s = this.meta, Record = this.recordType,
+            f = Record.prototype.fields, fi = f.items, fl = f.length, v;
+
+        var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
+        if(s.totalProperty){
+            v = parseInt(this.getTotal(o), 10);
+            if(!isNaN(v)){
+                totalRecords = v;
+            }
+        }
+        if(s.successProperty){
+            v = this.getSuccess(o);
+            if(v === false || v === 'false'){
+                success = false;
+            }
+        }
+
+        
+        return {
+            success : success,
+            records : this.extractData(root, true), 
+            totalRecords : totalRecords
+        };
+    },
+
+    
+    buildExtractors : function() {
+        if(this.ef){
+            return;
+        }
+        var s = this.meta, Record = this.recordType,
+            f = Record.prototype.fields, fi = f.items, fl = f.length;
+
+        if(s.totalProperty) {
+            this.getTotal = this.createAccessor(s.totalProperty);
+        }
+        if(s.successProperty) {
+            this.getSuccess = this.createAccessor(s.successProperty);
+        }
+        if (s.messageProperty) {
+            this.getMessage = this.createAccessor(s.messageProperty);
+        }
+        this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
+        if (s.id || s.idProperty) {
+            var g = this.createAccessor(s.id || s.idProperty);
+            this.getId = function(rec) {
+                var r = g(rec);
+                return (r === undefined || r === '') ? null : r;
+            };
+        } else {
+            this.getId = function(){return null;};
+        }
+        var ef = [];
+        for(var i = 0; i < fl; i++){
+            f = fi[i];
+            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
+            ef.push(this.createAccessor(map));
+        }
+        this.ef = ef;
+    },
+
+    
+    simpleAccess : function(obj, subsc) {
+        return obj[subsc];
+    },
+
+    
+    createAccessor : function(){
+        var re = /[\[\.]/;
+        return function(expr) {
+            if(Ext.isEmpty(expr)){
+                return Ext.emptyFn;
+            }
+            if(Ext.isFunction(expr)){
+                return expr;
+            }
+            var i = String(expr).search(re);
+            if(i >= 0){
+                return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
+            }
+            return function(obj){
+                return obj[expr];
+            };
+
+        };
+    }(),
+
+    
+    extractValues : function(data, items, len) {
+        var f, values = {};
+        for(var j = 0; j < len; j++){
+            f = items[j];
+            var v = this.ef[j](data);
+            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
+        }
+        return values;
+    }
+});
+
+
+Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name : 'Ext.data.JsonReader'
+});
+Ext.apply(Ext.data.JsonReader.Error.prototype, {
+    lang: {
+        'response': 'An error occurred while json-decoding your server response',
+        'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
+        'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
+        'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
+        'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
+    }
+});
+
+Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
+    
+    
+    
+    
+    readRecords : function(o){
+        this.arrayData = o;
+        var s = this.meta,
+            sid = s ? Ext.num(s.idIndex, s.id) : null,
+            recordType = this.recordType,
+            fields = recordType.prototype.fields,
+            records = [],
+            success = true,
+            v;
+
+        var root = this.getRoot(o);
+
+        for(var i = 0, len = root.length; i < len; i++) {
+            var n = root[i],
+                values = {},
+                id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
+            for(var j = 0, jlen = fields.length; j < jlen; j++) {
+                var f = fields.items[j],
+                    k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
+                v = n[k] !== undefined ? n[k] : f.defaultValue;
+                v = f.convert(v, n);
+                values[f.name] = v;
+            }
+            var record = new recordType(values, id);
+            record.json = n;
+            records[records.length] = record;
+        }
+
+        var totalRecords = records.length;
+
+        if(s.totalProperty) {
+            v = parseInt(this.getTotal(o), 10);
+            if(!isNaN(v)) {
+                totalRecords = v;
+            }
+        }
+        if(s.successProperty){
+            v = this.getSuccess(o);
+            if(v === false || v === 'false'){
+                success = false;
+            }
+        }
+
+        return {
+            success : success,
+            records : records,
+            totalRecords : totalRecords
+        };
+    }
+});
+Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
+    
+    constructor: function(config){
+        Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
+            reader: new Ext.data.ArrayReader(config)
+        }));
+    },
+
+    loadData : function(data, append){
+        if(this.expandData === true){
+            var r = [];
+            for(var i = 0, len = data.length; i < len; i++){
+                r[r.length] = [data[i]];
+            }
+            data = r;
+        }
+        Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
+    }
+});
+Ext.reg('arraystore', Ext.data.ArrayStore);
+
+
+Ext.data.SimpleStore = Ext.data.ArrayStore;
+Ext.reg('simplestore', Ext.data.SimpleStore);
+Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
+    
+    constructor: function(config){
+        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
+            reader: new Ext.data.JsonReader(config)
+        }));
+    }
+});
+Ext.reg('jsonstore', Ext.data.JsonStore);
+Ext.data.XmlWriter = function(params) {
+    Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
+    
+    this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
+};
+Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
+    
+    documentRoot: 'xrequest',
+    
+    forceDocumentRoot: false,
+    
+    root: 'records',
+    
+    xmlVersion : '1.0',
+    
+    xmlEncoding: 'ISO-8859-15',
+    
+    
+    tpl: '<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}></tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
+
+
+    
+    render : function(params, baseParams, data) {
+        baseParams = this.toArray(baseParams);
+        params.xmlData = this.tpl.applyTemplate({
+            version: this.xmlVersion,
+            encoding: this.xmlEncoding,
+            documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
+            record: this.meta.record,
+            root: this.root,
+            baseParams: baseParams,
+            records: (Ext.isArray(data[0])) ? data : [data]
+        });
+    },
+
+    
+    createRecord : function(rec) {
+        return this.toArray(this.toHash(rec));
+    },
+
+    
+    updateRecord : function(rec) {
+        return this.toArray(this.toHash(rec));
+
+    },
+    
+    destroyRecord : function(rec) {
+        var data = {};
+        data[this.meta.idProperty] = rec.id;
+        return this.toArray(data);
+    }
+});
+
+Ext.data.XmlReader = function(meta, recordType){
+    meta = meta || {};
+
+    
+    Ext.applyIf(meta, {
+        idProperty: meta.idProperty || meta.idPath || meta.id,
+        successProperty: meta.successProperty || meta.success
+    });
+
+    Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
+};
+Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
+    
+    read : function(response){
+        var doc = response.responseXML;
+        if(!doc) {
+            throw {message: "XmlReader.read: XML Document not available"};
+        }
+        return this.readRecords(doc);
+    },
+
+    
+    readRecords : function(doc){
+        
+        this.xmlData = doc;
+
+        var root    = doc.documentElement || doc,
+            q       = Ext.DomQuery,
+            totalRecords = 0,
+            success = true;
+
+        if(this.meta.totalProperty){
+            totalRecords = this.getTotal(root, 0);
+        }
+        if(this.meta.successProperty){
+            success = this.getSuccess(root);
+        }
+
+        var records = this.extractData(q.select(this.meta.record, root), true); 
+
+        
+        return {
+            success : success,
+            records : records,
+            totalRecords : totalRecords || records.length
+        };
+    },
+
+    
+    readResponse : function(action, response) {
+        var q = Ext.DomQuery,
+            doc = response.responseXML,
+            root = doc.documentElement || doc;
+
+        
+        var res = new Ext.data.Response({
+            action: action,
+            success : this.getSuccess(root),
+            message: this.getMessage(root),
+            data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
+            raw: doc
+        });
+
+        if (Ext.isEmpty(res.success)) {
+            throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
+        }
+
+        
+        if (action === Ext.data.Api.actions.create) {
+            var def = Ext.isDefined(res.data);
+            if (def && Ext.isEmpty(res.data)) {
+                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
+            }
+            else if (!def) {
+                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
+            }
+        }
+        return res;
+    },
+
+    getSuccess : function() {
+        return true;
+    },
+
+    
+    buildExtractors : function() {
+        if(this.ef){
+            return;
+        }
+        var s       = this.meta,
+            Record  = this.recordType,
+            f       = Record.prototype.fields,
+            fi      = f.items,
+            fl      = f.length;
+
+        if(s.totalProperty) {
+            this.getTotal = this.createAccessor(s.totalProperty);
+        }
+        if(s.successProperty) {
+            this.getSuccess = this.createAccessor(s.successProperty);
+        }
+        if (s.messageProperty) {
+            this.getMessage = this.createAccessor(s.messageProperty);
+        }
+        this.getRoot = function(res) {
+            return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
+        };
+        if (s.idPath || s.idProperty) {
+            var g = this.createAccessor(s.idPath || s.idProperty);
+            this.getId = function(rec) {
+                var id = g(rec) || rec.id;
+                return (id === undefined || id === '') ? null : id;
+            };
+        } else {
+            this.getId = function(){return null;};
+        }
+        var ef = [];
+        for(var i = 0; i < fl; i++){
+            f = fi[i];
+            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
+            ef.push(this.createAccessor(map));
+        }
+        this.ef = ef;
+    },
+
+    
+    createAccessor : function(){
+        var q = Ext.DomQuery;
+        return function(key) {
+            if (Ext.isFunction(key)) {
+                return key;
+            }
+            switch(key) {
+                case this.meta.totalProperty:
+                    return function(root, def){
+                        return q.selectNumber(key, root, def);
+                    };
+                    break;
+                case this.meta.successProperty:
+                    return function(root, def) {
+                        var sv = q.selectValue(key, root, true);
+                        var success = sv !== false && sv !== 'false';
+                        return success;
+                    };
+                    break;
+                default:
+                    return function(root, def) {
+                        return q.selectValue(key, root, def);
+                    };
+                    break;
+            }
+        };
+    }(),
+
+    
+    extractValues : function(data, items, len) {
+        var f, values = {};
+        for(var j = 0; j < len; j++){
+            f = items[j];
+            var v = this.ef[j](data);
+            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
+        }
+        return values;
+    }
+});
+Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
+    
+    constructor: function(config){
+        Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
+            reader: new Ext.data.XmlReader(config)
+        }));
+    }
+});
+Ext.reg('xmlstore', Ext.data.XmlStore);
+Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
+
+    
+    constructor: function(config) {
+        config = config || {};
+
+        
+        
+        
+        
+        this.hasMultiSort  = true;
+        this.multiSortInfo = this.multiSortInfo || {sorters: []};
+
+        var sorters    = this.multiSortInfo.sorters,
+            groupField = config.groupField || this.groupField,
+            sortInfo   = config.sortInfo || this.sortInfo,
+            groupDir   = config.groupDir || this.groupDir;
+
+        
+        if(groupField){
+            sorters.push({
+                field    : groupField,
+                direction: groupDir
+            });
+        }
+
+        
+        if (sortInfo) {
+            sorters.push(sortInfo);
+        }
+
+        Ext.data.GroupingStore.superclass.constructor.call(this, config);
+
+        this.addEvents(
+          
+          'groupchange'
+        );
+
+        this.applyGroupField();
+    },
+
+    
+    
+    remoteGroup : false,
+    
+    groupOnSort:false,
+
+    
+    groupDir : 'ASC',
+
+    
+    clearGrouping : function(){
+        this.groupField = false;
+
+        if(this.remoteGroup){
+            if(this.baseParams){
+                delete this.baseParams.groupBy;
+                delete this.baseParams.groupDir;
+            }
+            var lo = this.lastOptions;
+            if(lo && lo.params){
+                delete lo.params.groupBy;
+                delete lo.params.groupDir;
+            }
+
+            this.reload();
+        }else{
+            this.sort();
+            this.fireEvent('datachanged', this);
+        }
+    },
+
+    
+    groupBy : function(field, forceRegroup, direction) {
+        direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
+
+        if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
+            return; 
+        }
+
+        
+        
+        var sorters = this.multiSortInfo.sorters;
+        if (sorters.length > 0 && sorters[0].field == this.groupField) {
+            sorters.shift();
+        }
+
+        this.groupField = field;
+        this.groupDir = direction;
+        this.applyGroupField();
+
+        var fireGroupEvent = function() {
+            this.fireEvent('groupchange', this, this.getGroupState());
+        };
+
+        if (this.groupOnSort) {
+            this.sort(field, direction);
+            fireGroupEvent.call(this);
+            return;
+        }
+
+        if (this.remoteGroup) {
+            this.on('load', fireGroupEvent, this, {single: true});
+            this.reload();
+        } else {
+            this.sort(sorters);
+            fireGroupEvent.call(this);
+        }
+    },
+
+    
+    
+    sort : function(fieldName, dir) {
+        if (this.remoteSort) {
+            return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
+        }
+
+        var sorters = [];
+
+        
+        if (Ext.isArray(arguments[0])) {
+            sorters = arguments[0];
+        } else if (fieldName == undefined) {
+            
+            
+            sorters = this.sortInfo ? [this.sortInfo] : [];
+        } else {
+            
+            
+            var field = this.fields.get(fieldName);
+            if (!field) return false;
+
+            var name       = field.name,
+                sortInfo   = this.sortInfo || null,
+                sortToggle = this.sortToggle ? this.sortToggle[name] : null;
+
+            if (!dir) {
+                if (sortInfo && sortInfo.field == name) { 
+                    dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
+                } else {
+                    dir = field.sortDir;
+                }
+            }
+
+            this.sortToggle[name] = dir;
+            this.sortInfo = {field: name, direction: dir};
+
+            sorters = [this.sortInfo];
+        }
+
+        
+        if (this.groupField) {
+            sorters.unshift({direction: this.groupDir, field: this.groupField});
+        }
+
+        return this.multiSort.call(this, sorters, dir);
+    },
+
+    
+    applyGroupField: function(){
+        if (this.remoteGroup) {
+            if(!this.baseParams){
+                this.baseParams = {};
+            }
+
+            Ext.apply(this.baseParams, {
+                groupBy : this.groupField,
+                groupDir: this.groupDir
+            });
+
+            var lo = this.lastOptions;
+            if (lo && lo.params) {
+                lo.params.groupDir = this.groupDir;
+
+                
+                delete lo.params.groupBy;
+            }
+        }
+    },
+
+    
+    applyGrouping : function(alwaysFireChange){
+        if(this.groupField !== false){
+            this.groupBy(this.groupField, true, this.groupDir);
+            return true;
+        }else{
+            if(alwaysFireChange === true){
+                this.fireEvent('datachanged', this);
+            }
+            return false;
+        }
+    },
+
+    
+    getGroupState : function(){
+        return this.groupOnSort && this.groupField !== false ?
+               (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
+    }
+});
+Ext.reg('groupingstore', Ext.data.GroupingStore);
+
+Ext.data.DirectProxy = function(config){
+    Ext.apply(this, config);
+    if(typeof this.paramOrder == 'string'){
+        this.paramOrder = this.paramOrder.split(/[\s,|]/);
+    }
+    Ext.data.DirectProxy.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
+    
+    paramOrder: undefined,
+
+    
+    paramsAsHash: true,
+
+    
+    directFn : undefined,
+
+    
+    doRequest : function(action, rs, params, reader, callback, scope, options) {
+        var args = [],
+            directFn = this.api[action] || this.directFn;
+
+        switch (action) {
+            case Ext.data.Api.actions.create:
+                args.push(params.jsonData);		
+                break;
+            case Ext.data.Api.actions.read:
+                
+                if(directFn.directCfg.method.len > 0){
+                    if(this.paramOrder){
+                        for(var i = 0, len = this.paramOrder.length; i < len; i++){
+                            args.push(params[this.paramOrder[i]]);
+                        }
+                    }else if(this.paramsAsHash){
+                        args.push(params);
+                    }
+                }
+                break;
+            case Ext.data.Api.actions.update:
+                args.push(params.jsonData);        
+                break;
+            case Ext.data.Api.actions.destroy:
+                args.push(params.jsonData);        
+                break;
+        }
+
+        var trans = {
+            params : params || {},
+            request: {
+                callback : callback,
+                scope : scope,
+                arg : options
+            },
+            reader: reader
+        };
+
+        args.push(this.createCallback(action, rs, trans), this);
+        directFn.apply(window, args);
+    },
+
+    
+    createCallback : function(action, rs, trans) {
+        var me = this;
+        return function(result, res) {
+            if (!res.status) {
+                
+                if (action === Ext.data.Api.actions.read) {
+                    me.fireEvent("loadexception", me, trans, res, null);
+                }
+                me.fireEvent('exception', me, 'remote', action, trans, res, null);
+                trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
+                return;
+            }
+            if (action === Ext.data.Api.actions.read) {
+                me.onRead(action, trans, result, res);
+            } else {
+                me.onWrite(action, trans, result, res, rs);
+            }
+        };
+    },
+
+    
+    onRead : function(action, trans, result, res) {
+        var records;
+        try {
+            records = trans.reader.readRecords(result);
+        }
+        catch (ex) {
+            
+            this.fireEvent("loadexception", this, trans, res, ex);
+
+            this.fireEvent('exception', this, 'response', action, trans, res, ex);
+            trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
+            return;
+        }
+        this.fireEvent("load", this, res, trans.request.arg);
+        trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
+    },
+    
+    onWrite : function(action, trans, result, res, rs) {
+        var data = trans.reader.extractData(trans.reader.getRoot(result), false);
+        var success = trans.reader.getSuccess(result);
+        success = (success !== false);
+        if (success){
+            this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
+        }else{
+            this.fireEvent('exception', this, 'remote', action, trans, result, rs);
+        }
+        trans.request.callback.call(trans.request.scope, data, res, success);
+    }
+});
+
+Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
+    constructor : function(config){
+        
+        var c = Ext.apply({}, {
+            batchTransactions: false
+        }, config);
+        Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
+            proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
+            reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
+        }));
+    }
+});
+Ext.reg('directstore', Ext.data.DirectStore);
+
+Ext.Direct = Ext.extend(Ext.util.Observable, {
+    
+
+    
+    exceptions: {
+        TRANSPORT: 'xhr',
+        PARSE: 'parse',
+        LOGIN: 'login',
+        SERVER: 'exception'
+    },
+
+    
+    constructor: function(){
+        this.addEvents(
+            
+            'event',
+            
+            'exception'
+        );
+        this.transactions = {};
+        this.providers = {};
+    },
+
+    
+    addProvider : function(provider){
+        var a = arguments;
+        if(a.length > 1){
+            for(var i = 0, len = a.length; i < len; i++){
+                this.addProvider(a[i]);
+            }
+            return;
+        }
+
+        
+        if(!provider.events){
+            provider = new Ext.Direct.PROVIDERS[provider.type](provider);
+        }
+        provider.id = provider.id || Ext.id();
+        this.providers[provider.id] = provider;
+
+        provider.on('data', this.onProviderData, this);
+        provider.on('exception', this.onProviderException, this);
+
+
+        if(!provider.isConnected()){
+            provider.connect();
+        }
+
+        return provider;
+    },
+
+    
+    getProvider : function(id){
+        return this.providers[id];
+    },
+
+    removeProvider : function(id){
+        var provider = id.id ? id : this.providers[id];
+        provider.un('data', this.onProviderData, this);
+        provider.un('exception', this.onProviderException, this);
+        delete this.providers[provider.id];
+        return provider;
+    },
+
+    addTransaction: function(t){
+        this.transactions[t.tid] = t;
+        return t;
+    },
+
+    removeTransaction: function(t){
+        delete this.transactions[t.tid || t];
+        return t;
+    },
+
+    getTransaction: function(tid){
+        return this.transactions[tid.tid || tid];
+    },
+
+    onProviderData : function(provider, e){
+        if(Ext.isArray(e)){
+            for(var i = 0, len = e.length; i < len; i++){
+                this.onProviderData(provider, e[i]);
+            }
+            return;
+        }
+        if(e.name && e.name != 'event' && e.name != 'exception'){
+            this.fireEvent(e.name, e);
+        }else if(e.type == 'exception'){
+            this.fireEvent('exception', e);
+        }
+        this.fireEvent('event', e, provider);
+    },
+
+    createEvent : function(response, extraProps){
+        return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
+    }
+});
+
+Ext.Direct = new Ext.Direct();
+
+Ext.Direct.TID = 1;
+Ext.Direct.PROVIDERS = {};
+Ext.Direct.Transaction = function(config){
+    Ext.apply(this, config);
+    this.tid = ++Ext.Direct.TID;
+    this.retryCount = 0;
+};
+Ext.Direct.Transaction.prototype = {
+    send: function(){
+        this.provider.queueTransaction(this);
+    },
+
+    retry: function(){
+        this.retryCount++;
+        this.send();
+    },
+
+    getProvider: function(){
+        return this.provider;
+    }
+};Ext.Direct.Event = function(config){
+    Ext.apply(this, config);
+};
+
+Ext.Direct.Event.prototype = {
+    status: true,
+    getData: function(){
+        return this.data;
+    }
+};
+
+Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
+    type: 'rpc',
+    getTransaction: function(){
+        return this.transaction || Ext.Direct.getTransaction(this.tid);
+    }
+});
+
+Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
+    status: false,
+    type: 'exception'
+});
+
+Ext.Direct.eventTypes = {
+    'rpc':  Ext.Direct.RemotingEvent,
+    'event':  Ext.Direct.Event,
+    'exception':  Ext.Direct.ExceptionEvent
+};
+
+Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
+    
+        
+        
+    priority: 1,
+
+        
+ 
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+        this.addEvents(
+                        
+            'connect',
+                        
+            'disconnect',
+                        
+            'data',
+                                    
+            'exception'
+        );
+        Ext.direct.Provider.superclass.constructor.call(this, config);
+    },
+
+    
+    isConnected: function(){
+        return false;
+    },
+
+    
+    connect: Ext.emptyFn,
+    
+    
+    disconnect: Ext.emptyFn
+});
+
+Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
+    parseResponse: function(xhr){
+        if(!Ext.isEmpty(xhr.responseText)){
+            if(typeof xhr.responseText == 'object'){
+                return xhr.responseText;
+            }
+            return Ext.decode(xhr.responseText);
+        }
+        return null;
+    },
+
+    getEvents: function(xhr){
+        var data = null;
+        try{
+            data = this.parseResponse(xhr);
+        }catch(e){
+            var event = new Ext.Direct.ExceptionEvent({
+                data: e,
+                xhr: xhr,
+                code: Ext.Direct.exceptions.PARSE,
+                message: 'Error parsing json response: \n\n ' + data
+            });
+            return [event];
+        }
+        var events = [];
+        if(Ext.isArray(data)){
+            for(var i = 0, len = data.length; i < len; i++){
+                events.push(Ext.Direct.createEvent(data[i]));
+            }
+        }else{
+            events.push(Ext.Direct.createEvent(data));
+        }
+        return events;
+    }
+});
+Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
+    
+    
+    priority: 3,
+    
+    
+    interval: 3000,
+
+    
+    
+    
+
+    
+    constructor : function(config){
+        Ext.direct.PollingProvider.superclass.constructor.call(this, config);
+        this.addEvents(
+            
+            'beforepoll',            
+            
+            'poll'
+        );
+    },
+
+    
+    isConnected: function(){
+        return !!this.pollTask;
+    },
+
+    
+    connect: function(){
+        if(this.url && !this.pollTask){
+            this.pollTask = Ext.TaskMgr.start({
+                run: function(){
+                    if(this.fireEvent('beforepoll', this) !== false){
+                        if(typeof this.url == 'function'){
+                            this.url(this.baseParams);
+                        }else{
+                            Ext.Ajax.request({
+                                url: this.url,
+                                callback: this.onData,
+                                scope: this,
+                                params: this.baseParams
+                            });
+                        }
+                    }
+                },
+                interval: this.interval,
+                scope: this
+            });
+            this.fireEvent('connect', this);
+        }else if(!this.url){
+            throw 'Error initializing PollingProvider, no url configured.';
+        }
+    },
+
+    
+    disconnect: function(){
+        if(this.pollTask){
+            Ext.TaskMgr.stop(this.pollTask);
+            delete this.pollTask;
+            this.fireEvent('disconnect', this);
+        }
+    },
+
+    
+    onData: function(opt, success, xhr){
+        if(success){
+            var events = this.getEvents(xhr);
+            for(var i = 0, len = events.length; i < len; i++){
+                var e = events[i];
+                this.fireEvent('data', this, e);
+            }
+        }else{
+            var e = new Ext.Direct.ExceptionEvent({
+                data: e,
+                code: Ext.Direct.exceptions.TRANSPORT,
+                message: 'Unable to connect to the server.',
+                xhr: xhr
+            });
+            this.fireEvent('data', this, e);
+        }
+    }
+});
+
+Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
+Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    enableBuffer: 10,
+    
+    
+    maxRetries: 1,
+    
+    
+    timeout: undefined,
+
+    constructor : function(config){
+        Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
+        this.addEvents(
+                        
+            'beforecall',            
+                        
+            'call'
+        );
+        this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
+        this.transactions = {};
+        this.callBuffer = [];
+    },
+
+    
+    initAPI : function(){
+        var o = this.actions;
+        for(var c in o){
+            var cls = this.namespace[c] || (this.namespace[c] = {}),
+                ms = o[c];
+            for(var i = 0, len = ms.length; i < len; i++){
+                var m = ms[i];
+                cls[m.name] = this.createMethod(c, m);
+            }
+        }
+    },
+
+    
+    isConnected: function(){
+        return !!this.connected;
+    },
+
+    connect: function(){
+        if(this.url){
+            this.initAPI();
+            this.connected = true;
+            this.fireEvent('connect', this);
+        }else if(!this.url){
+            throw 'Error initializing RemotingProvider, no url configured.';
+        }
+    },
+
+    disconnect: function(){
+        if(this.connected){
+            this.connected = false;
+            this.fireEvent('disconnect', this);
+        }
+    },
+
+    onData: function(opt, success, xhr){
+        if(success){
+            var events = this.getEvents(xhr);
+            for(var i = 0, len = events.length; i < len; i++){
+                var e = events[i],
+                    t = this.getTransaction(e);
+                this.fireEvent('data', this, e);
+                if(t){
+                    this.doCallback(t, e, true);
+                    Ext.Direct.removeTransaction(t);
+                }
+            }
+        }else{
+            var ts = [].concat(opt.ts);
+            for(var i = 0, len = ts.length; i < len; i++){
+                var t = this.getTransaction(ts[i]);
+                if(t && t.retryCount < this.maxRetries){
+                    t.retry();
+                }else{
+                    var e = new Ext.Direct.ExceptionEvent({
+                        data: e,
+                        transaction: t,
+                        code: Ext.Direct.exceptions.TRANSPORT,
+                        message: 'Unable to connect to the server.',
+                        xhr: xhr
+                    });
+                    this.fireEvent('data', this, e);
+                    if(t){
+                        this.doCallback(t, e, false);
+                        Ext.Direct.removeTransaction(t);
+                    }
+                }
+            }
+        }
+    },
+
+    getCallData: function(t){
+        return {
+            action: t.action,
+            method: t.method,
+            data: t.data,
+            type: 'rpc',
+            tid: t.tid
+        };
+    },
+
+    doSend : function(data){
+        var o = {
+            url: this.url,
+            callback: this.onData,
+            scope: this,
+            ts: data,
+            timeout: this.timeout
+        }, callData;
+
+        if(Ext.isArray(data)){
+            callData = [];
+            for(var i = 0, len = data.length; i < len; i++){
+                callData.push(this.getCallData(data[i]));
+            }
+        }else{
+            callData = this.getCallData(data);
+        }
+
+        if(this.enableUrlEncode){
+            var params = {};
+            params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
+            o.params = params;
+        }else{
+            o.jsonData = callData;
+        }
+        Ext.Ajax.request(o);
+    },
+
+    combineAndSend : function(){
+        var len = this.callBuffer.length;
+        if(len > 0){
+            this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
+            this.callBuffer = [];
+        }
+    },
+
+    queueTransaction: function(t){
+        if(t.form){
+            this.processForm(t);
+            return;
+        }
+        this.callBuffer.push(t);
+        if(this.enableBuffer){
+            if(!this.callTask){
+                this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
+            }
+            this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
+        }else{
+            this.combineAndSend();
+        }
+    },
+
+    doCall : function(c, m, args){
+        var data = null, hs = args[m.len], scope = args[m.len+1];
+
+        if(m.len !== 0){
+            data = args.slice(0, m.len);
+        }
+
+        var t = new Ext.Direct.Transaction({
+            provider: this,
+            args: args,
+            action: c,
+            method: m.name,
+            data: data,
+            cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
+        });
+
+        if(this.fireEvent('beforecall', this, t, m) !== false){
+            Ext.Direct.addTransaction(t);
+            this.queueTransaction(t);
+            this.fireEvent('call', this, t, m);
+        }
+    },
+
+    doForm : function(c, m, form, callback, scope){
+        var t = new Ext.Direct.Transaction({
+            provider: this,
+            action: c,
+            method: m.name,
+            args:[form, callback, scope],
+            cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
+            isForm: true
+        });
+
+        if(this.fireEvent('beforecall', this, t, m) !== false){
+            Ext.Direct.addTransaction(t);
+            var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
+                params = {
+                    extTID: t.tid,
+                    extAction: c,
+                    extMethod: m.name,
+                    extType: 'rpc',
+                    extUpload: String(isUpload)
+                };
+            
+            
+            
+            Ext.apply(t, {
+                form: Ext.getDom(form),
+                isUpload: isUpload,
+                params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
+            });
+            this.fireEvent('call', this, t, m);
+            this.processForm(t);
+        }
+    },
+    
+    processForm: function(t){
+        Ext.Ajax.request({
+            url: this.url,
+            params: t.params,
+            callback: this.onData,
+            scope: this,
+            form: t.form,
+            isUpload: t.isUpload,
+            ts: t
+        });
+    },
+
+    createMethod : function(c, m){
+        var f;
+        if(!m.formHandler){
+            f = function(){
+                this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
+            }.createDelegate(this);
+        }else{
+            f = function(form, callback, scope){
+                this.doForm(c, m, form, callback, scope);
+            }.createDelegate(this);
+        }
+        f.directCfg = {
+            action: c,
+            method: m
+        };
+        return f;
+    },
+
+    getTransaction: function(opt){
+        return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
+    },
+
+    doCallback: function(t, e){
+        var fn = e.status ? 'success' : 'failure';
+        if(t && t.cb){
+            var hs = t.cb,
+                result = Ext.isDefined(e.result) ? e.result : e.data;
+            if(Ext.isFunction(hs)){
+                hs(result, e);
+            } else{
+                Ext.callback(hs[fn], hs.scope, [result, e]);
+                Ext.callback(hs.callback, hs.scope, [result, e]);
+            }
+        }
+    }
+});
+Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
+Ext.Resizable = Ext.extend(Ext.util.Observable, {
+
+    constructor: function(el, config){
+        this.el = Ext.get(el);
+        if(config && config.wrap){
+            config.resizeChild = this.el;
+            this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
+            this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
+            this.el.setStyle('overflow', 'hidden');
+            this.el.setPositioning(config.resizeChild.getPositioning());
+            config.resizeChild.clearPositioning();
+            if(!config.width || !config.height){
+                var csize = config.resizeChild.getSize();
+                this.el.setSize(csize.width, csize.height);
+            }
+            if(config.pinned && !config.adjustments){
+                config.adjustments = 'auto';
+            }
+        }
+
+        
+        this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
+        this.proxy.unselectable();
+        this.proxy.enableDisplayMode('block');
+
+        Ext.apply(this, config);
+
+        if(this.pinned){
+            this.disableTrackOver = true;
+            this.el.addClass('x-resizable-pinned');
+        }
+        
+        var position = this.el.getStyle('position');
+        if(position != 'absolute' && position != 'fixed'){
+            this.el.setStyle('position', 'relative');
+        }
+        if(!this.handles){ 
+            this.handles = 's,e,se';
+            if(this.multiDirectional){
+                this.handles += ',n,w';
+            }
+        }
+        if(this.handles == 'all'){
+            this.handles = 'n s e w ne nw se sw';
+        }
+        var hs = this.handles.split(/\s*?[,;]\s*?| /);
+        var ps = Ext.Resizable.positions;
+        for(var i = 0, len = hs.length; i < len; i++){
+            if(hs[i] && ps[hs[i]]){
+                var pos = ps[hs[i]];
+                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
+            }
+        }
+        
+        this.corner = this.southeast;
+
+        if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
+            this.updateBox = true;
+        }
+
+        this.activeHandle = null;
+
+        if(this.resizeChild){
+            if(typeof this.resizeChild == 'boolean'){
+                this.resizeChild = Ext.get(this.el.dom.firstChild, true);
+            }else{
+                this.resizeChild = Ext.get(this.resizeChild, true);
+            }
+        }
+
+        if(this.adjustments == 'auto'){
+            var rc = this.resizeChild;
+            var hw = this.west, he = this.east, hn = this.north, hs = this.south;
+            if(rc && (hw || hn)){
+                rc.position('relative');
+                rc.setLeft(hw ? hw.el.getWidth() : 0);
+                rc.setTop(hn ? hn.el.getHeight() : 0);
+            }
+            this.adjustments = [
+                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
+                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
+            ];
+        }
+
+        if(this.draggable){
+            this.dd = this.dynamic ?
+                this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
+            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
+            if(this.constrainTo){
+                this.dd.constrainTo(this.constrainTo);
+            }
+        }
+
+        this.addEvents(
+            
+            'beforeresize',
+            
+            'resize'
+        );
+
+        if(this.width !== null && this.height !== null){
+            this.resizeTo(this.width, this.height);
+        }else{
+            this.updateChildSize();
+        }
+        if(Ext.isIE){
+            this.el.dom.style.zoom = 1;
+        }
+        Ext.Resizable.superclass.constructor.call(this);
+    },
+
+    
+    adjustments : [0, 0],
+    
+    animate : false,
+    
+    
+    disableTrackOver : false,
+    
+    draggable: false,
+    
+    duration : 0.35,
+    
+    dynamic : false,
+    
+    easing : 'easeOutStrong',
+    
+    enabled : true,
+    
+    
+    handles : false,
+    
+    multiDirectional : false,
+    
+    height : null,
+    
+    width : null,
+    
+    heightIncrement : 0,
+    
+    widthIncrement : 0,
+    
+    minHeight : 5,
+    
+    minWidth : 5,
+    
+    maxHeight : 10000,
+    
+    maxWidth : 10000,
+    
+    minX: 0,
+    
+    minY: 0,
+    
+    pinned : false,
+    
+    preserveRatio : false,
+    
+    resizeChild : false,
+    
+    transparent: false,
+    
+    
+    
+
+
+    
+    resizeTo : function(width, height){
+        this.el.setSize(width, height);
+        this.updateChildSize();
+        this.fireEvent('resize', this, width, height, null);
+    },
+
+    
+    startSizing : function(e, handle){
+        this.fireEvent('beforeresize', this, e);
+        if(this.enabled){ 
+
+            if(!this.overlay){
+                this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
+                this.overlay.unselectable();
+                this.overlay.enableDisplayMode('block');
+                this.overlay.on({
+                    scope: this,
+                    mousemove: this.onMouseMove,
+                    mouseup: this.onMouseUp
+                });
+            }
+            this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
+
+            this.resizing = true;
+            this.startBox = this.el.getBox();
+            this.startPoint = e.getXY();
+            this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
+                            (this.startBox.y + this.startBox.height) - this.startPoint[1]];
+
+            this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
+            this.overlay.show();
+
+            if(this.constrainTo) {
+                var ct = Ext.get(this.constrainTo);
+                this.resizeRegion = ct.getRegion().adjust(
+                    ct.getFrameWidth('t'),
+                    ct.getFrameWidth('l'),
+                    -ct.getFrameWidth('b'),
+                    -ct.getFrameWidth('r')
+                );
+            }
+
+            this.proxy.setStyle('visibility', 'hidden'); 
+            this.proxy.show();
+            this.proxy.setBox(this.startBox);
+            if(!this.dynamic){
+                this.proxy.setStyle('visibility', 'visible');
+            }
+        }
+    },
+
+    
+    onMouseDown : function(handle, e){
+        if(this.enabled){
+            e.stopEvent();
+            this.activeHandle = handle;
+            this.startSizing(e, handle);
+        }
+    },
+
+    
+    onMouseUp : function(e){
+        this.activeHandle = null;
+        var size = this.resizeElement();
+        this.resizing = false;
+        this.handleOut();
+        this.overlay.hide();
+        this.proxy.hide();
+        this.fireEvent('resize', this, size.width, size.height, e);
+    },
+
+    
+    updateChildSize : function(){
+        if(this.resizeChild){
+            var el = this.el;
+            var child = this.resizeChild;
+            var adj = this.adjustments;
+            if(el.dom.offsetWidth){
+                var b = el.getSize(true);
+                child.setSize(b.width+adj[0], b.height+adj[1]);
+            }
+            
+            
+            
+            
+            if(Ext.isIE){
+                setTimeout(function(){
+                    if(el.dom.offsetWidth){
+                        var b = el.getSize(true);
+                        child.setSize(b.width+adj[0], b.height+adj[1]);
+                    }
+                }, 10);
+            }
+        }
+    },
+
+    
+    snap : function(value, inc, min){
+        if(!inc || !value){
+            return value;
+        }
+        var newValue = value;
+        var m = value % inc;
+        if(m > 0){
+            if(m > (inc/2)){
+                newValue = value + (inc-m);
+            }else{
+                newValue = value - m;
+            }
+        }
+        return Math.max(min, newValue);
+    },
+
+    
+    resizeElement : function(){
+        var box = this.proxy.getBox();
+        if(this.updateBox){
+            this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
+        }else{
+            this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
+        }
+        this.updateChildSize();
+        if(!this.dynamic){
+            this.proxy.hide();
+        }
+        if(this.draggable && this.constrainTo){
+            this.dd.resetConstraints();
+            this.dd.constrainTo(this.constrainTo);
+        }
+        return box;
+    },
+
+    
+    constrain : function(v, diff, m, mx){
+        if(v - diff < m){
+            diff = v - m;
+        }else if(v - diff > mx){
+            diff = v - mx;
+        }
+        return diff;
+    },
+
+    
+    onMouseMove : function(e){
+        if(this.enabled && this.activeHandle){
+            try{
+
+            if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
+                return;
+            }
+
+            
+            var curSize = this.curSize || this.startBox,
+                x = this.startBox.x, y = this.startBox.y,
+                ox = x,
+                oy = y,
+                w = curSize.width,
+                h = curSize.height,
+                ow = w,
+                oh = h,
+                mw = this.minWidth,
+                mh = this.minHeight,
+                mxw = this.maxWidth,
+                mxh = this.maxHeight,
+                wi = this.widthIncrement,
+                hi = this.heightIncrement,
+                eventXY = e.getXY(),
+                diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
+                diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
+                pos = this.activeHandle.position,
+                tw,
+                th;
+
+            switch(pos){
+                case 'east':
+                    w += diffX;
+                    w = Math.min(Math.max(mw, w), mxw);
+                    break;
+                case 'south':
+                    h += diffY;
+                    h = Math.min(Math.max(mh, h), mxh);
+                    break;
+                case 'southeast':
+                    w += diffX;
+                    h += diffY;
+                    w = Math.min(Math.max(mw, w), mxw);
+                    h = Math.min(Math.max(mh, h), mxh);
+                    break;
+                case 'north':
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    break;
+                case 'west':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    x += diffX;
+                    w -= diffX;
+                    break;
+                case 'northeast':
+                    w += diffX;
+                    w = Math.min(Math.max(mw, w), mxw);
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    break;
+                case 'northwest':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    x += diffX;
+                    w -= diffX;
+                    break;
+               case 'southwest':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    h += diffY;
+                    h = Math.min(Math.max(mh, h), mxh);
+                    x += diffX;
+                    w -= diffX;
+                    break;
+            }
+
+            var sw = this.snap(w, wi, mw);
+            var sh = this.snap(h, hi, mh);
+            if(sw != w || sh != h){
+                switch(pos){
+                    case 'northeast':
+                        y -= sh - h;
+                    break;
+                    case 'north':
+                        y -= sh - h;
+                        break;
+                    case 'southwest':
+                        x -= sw - w;
+                    break;
+                    case 'west':
+                        x -= sw - w;
+                        break;
+                    case 'northwest':
+                        x -= sw - w;
+                        y -= sh - h;
+                    break;
+                }
+                w = sw;
+                h = sh;
+            }
+
+            if(this.preserveRatio){
+                switch(pos){
+                    case 'southeast':
+                    case 'east':
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        w = ow * (h/oh);
+                       break;
+                    case 'south':
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                        break;
+                    case 'northeast':
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                    break;
+                    case 'north':
+                        tw = w;
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                        x += (tw - w) / 2;
+                        break;
+                    case 'southwest':
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        tw = w;
+                        w = ow * (h/oh);
+                        x += tw - w;
+                        break;
+                    case 'west':
+                        th = h;
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        y += (th - h) / 2;
+                        tw = w;
+                        w = ow * (h/oh);
+                        x += tw - w;
+                       break;
+                    case 'northwest':
+                        tw = w;
+                        th = h;
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        w = ow * (h/oh);
+                        y += th - h;
+                        x += tw - w;
+                        break;
+
+                }
+            }
+            this.proxy.setBounds(x, y, w, h);
+            if(this.dynamic){
+                this.resizeElement();
+            }
+            }catch(ex){}
+        }
+    },
+
+    
+    handleOver : function(){
+        if(this.enabled){
+            this.el.addClass('x-resizable-over');
+        }
+    },
+
+    
+    handleOut : function(){
+        if(!this.resizing){
+            this.el.removeClass('x-resizable-over');
+        }
+    },
+
+    
+    getEl : function(){
+        return this.el;
+    },
+
+    
+    getResizeChild : function(){
+        return this.resizeChild;
+    },
+
+    
+    destroy : function(removeEl){
+        Ext.destroy(this.dd, this.overlay, this.proxy);
+        this.overlay = null;
+        this.proxy = null;
+
+        var ps = Ext.Resizable.positions;
+        for(var k in ps){
+            if(typeof ps[k] != 'function' && this[ps[k]]){
+                this[ps[k]].destroy();
+            }
+        }
+        if(removeEl){
+            this.el.update('');
+            Ext.destroy(this.el);
+            this.el = null;
+        }
+        this.purgeListeners();
+    },
+
+    syncHandleHeight : function(){
+        var h = this.el.getHeight(true);
+        if(this.west){
+            this.west.el.setHeight(h);
+        }
+        if(this.east){
+            this.east.el.setHeight(h);
+        }
+    }
+});
+
+
+
+Ext.Resizable.positions = {
+    n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
+};
+
+Ext.Resizable.Handle = Ext.extend(Object, {
+    constructor : function(rz, pos, disableTrackOver, transparent, cls){
+       if(!this.tpl){
+            
+            var tpl = Ext.DomHelper.createTemplate(
+                {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
+            );
+            tpl.compile();
+            Ext.Resizable.Handle.prototype.tpl = tpl;
+        }
+        this.position = pos;
+        this.rz = rz;
+        this.el = this.tpl.append(rz.el.dom, [this.position], true);
+        this.el.unselectable();
+        if(transparent){
+            this.el.setOpacity(0);
+        }
+        if(!Ext.isEmpty(cls)){
+            this.el.addClass(cls);
+        }
+        this.el.on('mousedown', this.onMouseDown, this);
+        if(!disableTrackOver){
+            this.el.on({
+                scope: this,
+                mouseover: this.onMouseOver,
+                mouseout: this.onMouseOut
+            });
+        }
+    },
+
+    
+    afterResize : function(rz){
+        
+    },
+    
+    onMouseDown : function(e){
+        this.rz.onMouseDown(this, e);
+    },
+    
+    onMouseOver : function(e){
+        this.rz.handleOver(this, e);
+    },
+    
+    onMouseOut : function(e){
+        this.rz.handleOut(this, e);
+    },
+    
+    destroy : function(){
+        Ext.destroy(this.el);
+        this.el = null;
+    }
+});
+
+Ext.Window = Ext.extend(Ext.Panel, {
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    baseCls : 'x-window',
+    
+    resizable : true,
+    
+    draggable : true,
+    
+    closable : true,
+    
+    closeAction : 'close',
+    
+    constrain : false,
+    
+    constrainHeader : false,
+    
+    plain : false,
+    
+    minimizable : false,
+    
+    maximizable : false,
+    
+    minHeight : 100,
+    
+    minWidth : 200,
+    
+    expandOnShow : true,
+    
+    
+    showAnimDuration: 0.25,
+    
+    
+    hideAnimDuration: 0.25,
+
+    
+    collapsible : false,
+
+    
+    initHidden : undefined,
+
+    
+    hidden : true,
+
+    
+    
+    
+    
+    
+    elements : 'header,body',
+    
+    frame : true,
+    
+    floating : true,
+
+    
+    initComponent : function(){
+        this.initTools();
+        Ext.Window.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            
+            
+            'resize',
+            
+            'maximize',
+            
+            'minimize',
+            
+            'restore'
+        );
+        
+        if(Ext.isDefined(this.initHidden)){
+            this.hidden = this.initHidden;
+        }
+        if(this.hidden === false){
+            this.hidden = true;
+            this.show();
+        }
+    },
+
+    
+    getState : function(){
+        return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.Window.superclass.onRender.call(this, ct, position);
+
+        if(this.plain){
+            this.el.addClass('x-window-plain');
+        }
+
+        
+        this.focusEl = this.el.createChild({
+                    tag: 'a', href:'#', cls:'x-dlg-focus',
+                    tabIndex:'-1', html: '&#160;'});
+        this.focusEl.swallowEvent('click', true);
+
+        this.proxy = this.el.createProxy('x-window-proxy');
+        this.proxy.enableDisplayMode('block');
+
+        if(this.modal){
+            this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
+            this.mask.enableDisplayMode('block');
+            this.mask.hide();
+            this.mon(this.mask, 'click', this.focus, this);
+        }
+        if(this.maximizable){
+            this.mon(this.header, 'dblclick', this.toggleMaximize, this);
+        }
+    },
+
+    
+    initEvents : function(){
+        Ext.Window.superclass.initEvents.call(this);
+        if(this.animateTarget){
+            this.setAnimateTarget(this.animateTarget);
+        }
+
+        if(this.resizable){
+            this.resizer = new Ext.Resizable(this.el, {
+                minWidth: this.minWidth,
+                minHeight:this.minHeight,
+                handles: this.resizeHandles || 'all',
+                pinned: true,
+                resizeElement : this.resizerAction,
+                handleCls: 'x-window-handle'
+            });
+            this.resizer.window = this;
+            this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
+        }
+
+        if(this.draggable){
+            this.header.addClass('x-window-draggable');
+        }
+        this.mon(this.el, 'mousedown', this.toFront, this);
+        this.manager = this.manager || Ext.WindowMgr;
+        this.manager.register(this);
+        if(this.maximized){
+            this.maximized = false;
+            this.maximize();
+        }
+        if(this.closable){
+            var km = this.getKeyMap();
+            km.on(27, this.onEsc, this);
+            km.disable();
+        }
+    },
+
+    initDraggable : function(){
+        
+        this.dd = new Ext.Window.DD(this);
+    },
+
+   
+    onEsc : function(k, e){
+        if (this.activeGhost) {
+            this.unghost();
+        }
+        e.stopEvent();
+        this[this.closeAction]();
+    },
+
+    
+    beforeDestroy : function(){
+        if(this.rendered){
+            this.hide();
+            this.clearAnchor();
+            Ext.destroy(
+                this.focusEl,
+                this.resizer,
+                this.dd,
+                this.proxy,
+                this.mask
+            );
+        }
+        Ext.Window.superclass.beforeDestroy.call(this);
+    },
+
+    
+    onDestroy : function(){
+        if(this.manager){
+            this.manager.unregister(this);
+        }
+        Ext.Window.superclass.onDestroy.call(this);
+    },
+
+    
+    initTools : function(){
+        if(this.minimizable){
+            this.addTool({
+                id: 'minimize',
+                handler: this.minimize.createDelegate(this, [])
+            });
+        }
+        if(this.maximizable){
+            this.addTool({
+                id: 'maximize',
+                handler: this.maximize.createDelegate(this, [])
+            });
+            this.addTool({
+                id: 'restore',
+                handler: this.restore.createDelegate(this, []),
+                hidden:true
+            });
+        }
+        if(this.closable){
+            this.addTool({
+                id: 'close',
+                handler: this[this.closeAction].createDelegate(this, [])
+            });
+        }
+    },
+
+    
+    resizerAction : function(){
+        var box = this.proxy.getBox();
+        this.proxy.hide();
+        this.window.handleResize(box);
+        return box;
+    },
+
+    
+    beforeResize : function(){
+        this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
+        this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
+        this.resizeBox = this.el.getBox();
+    },
+
+    
+    updateHandles : function(){
+        if(Ext.isIE && this.resizer){
+            this.resizer.syncHandleHeight();
+            this.el.repaint();
+        }
+    },
+
+    
+    handleResize : function(box){
+        var rz = this.resizeBox;
+        if(rz.x != box.x || rz.y != box.y){
+            this.updateBox(box);
+        }else{
+            this.setSize(box);
+            if (Ext.isIE6 && Ext.isStrict) {
+                this.doLayout();
+            }
+        }
+        this.focus();
+        this.updateHandles();
+        this.saveState();
+    },
+
+    
+    focus : function(){
+        var f = this.focusEl,
+            db = this.defaultButton,
+            t = typeof db,
+            el,
+            ct;
+        if(Ext.isDefined(db)){
+            if(Ext.isNumber(db) && this.fbar){
+                f = this.fbar.items.get(db);
+            }else if(Ext.isString(db)){
+                f = Ext.getCmp(db);
+            }else{
+                f = db;
+            }
+            el = f.getEl();
+            ct = Ext.getDom(this.container);
+            if (el && ct) {
+                if (ct != document.body && !Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
+                    return;
+                }
+            }
+        }
+        f = f || this.focusEl;
+        f.focus.defer(10, f);
+    },
+
+    
+    setAnimateTarget : function(el){
+        el = Ext.get(el);
+        this.animateTarget = el;
+    },
+
+    
+    beforeShow : function(){
+        delete this.el.lastXY;
+        delete this.el.lastLT;
+        if(this.x === undefined || this.y === undefined){
+            var xy = this.el.getAlignToXY(this.container, 'c-c');
+            var pos = this.el.translatePoints(xy[0], xy[1]);
+            this.x = this.x === undefined? pos.left : this.x;
+            this.y = this.y === undefined? pos.top : this.y;
+        }
+        this.el.setLeftTop(this.x, this.y);
+
+        if(this.expandOnShow){
+            this.expand(false);
+        }
+
+        if(this.modal){
+            Ext.getBody().addClass('x-body-masked');
+            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
+            this.mask.show();
+        }
+    },
+
+    
+    show : function(animateTarget, cb, scope){
+        if(!this.rendered){
+            this.render(Ext.getBody());
+        }
+        if(this.hidden === false){
+            this.toFront();
+            return this;
+        }
+        if(this.fireEvent('beforeshow', this) === false){
+            return this;
+        }
+        if(cb){
+            this.on('show', cb, scope, {single:true});
+        }
+        this.hidden = false;
+        if(Ext.isDefined(animateTarget)){
+            this.setAnimateTarget(animateTarget);
+        }
+        this.beforeShow();
+        if(this.animateTarget){
+            this.animShow();
+        }else{
+            this.afterShow();
+        }
+        return this;
+    },
+
+    
+    afterShow : function(isAnim){
+        if (this.isDestroyed){
+            return false;
+        }
+        this.proxy.hide();
+        this.el.setStyle('display', 'block');
+        this.el.show();
+        if(this.maximized){
+            this.fitContainer();
+        }
+        if(Ext.isMac && Ext.isGecko2){ 
+            this.cascade(this.setAutoScroll);
+        }
+
+        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
+            Ext.EventManager.onWindowResize(this.onWindowResize, this);
+        }
+        this.doConstrain();
+        this.doLayout();
+        if(this.keyMap){
+            this.keyMap.enable();
+        }
+        this.toFront();
+        this.updateHandles();
+        if(isAnim && (Ext.isIE || Ext.isWebKit)){
+            var sz = this.getSize();
+            this.onResize(sz.width, sz.height);
+        }
+        this.onShow();
+        this.fireEvent('show', this);
+    },
+
+    
+    animShow : function(){
+        this.proxy.show();
+        this.proxy.setBox(this.animateTarget.getBox());
+        this.proxy.setOpacity(0);
+        var b = this.getBox();
+        this.el.setStyle('display', 'none');
+        this.proxy.shift(Ext.apply(b, {
+            callback: this.afterShow.createDelegate(this, [true], false),
+            scope: this,
+            easing: 'easeNone',
+            duration: this.showAnimDuration,
+            opacity: 0.5
+        }));
+    },
+
+    
+    hide : function(animateTarget, cb, scope){
+        if(this.hidden || this.fireEvent('beforehide', this) === false){
+            return this;
+        }
+        if(cb){
+            this.on('hide', cb, scope, {single:true});
+        }
+        this.hidden = true;
+        if(animateTarget !== undefined){
+            this.setAnimateTarget(animateTarget);
+        }
+        if(this.modal){
+            this.mask.hide();
+            Ext.getBody().removeClass('x-body-masked');
+        }
+        if(this.animateTarget){
+            this.animHide();
+        }else{
+            this.el.hide();
+            this.afterHide();
+        }
+        return this;
+    },
+
+    
+    afterHide : function(){
+        this.proxy.hide();
+        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
+            Ext.EventManager.removeResizeListener(this.onWindowResize, this);
+        }
+        if(this.keyMap){
+            this.keyMap.disable();
+        }
+        this.onHide();
+        this.fireEvent('hide', this);
+    },
+
+    
+    animHide : function(){
+        this.proxy.setOpacity(0.5);
+        this.proxy.show();
+        var tb = this.getBox(false);
+        this.proxy.setBox(tb);
+        this.el.hide();
+        this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
+            callback: this.afterHide,
+            scope: this,
+            duration: this.hideAnimDuration,
+            easing: 'easeNone',
+            opacity: 0
+        }));
+    },
+
+    
+    onShow : Ext.emptyFn,
+
+    
+    onHide : Ext.emptyFn,
+
+    
+    onWindowResize : function(){
+        if(this.maximized){
+            this.fitContainer();
+        }
+        if(this.modal){
+            this.mask.setSize('100%', '100%');
+            var force = this.mask.dom.offsetHeight;
+            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
+        }
+        this.doConstrain();
+    },
+
+    
+    doConstrain : function(){
+        if(this.constrain || this.constrainHeader){
+            var offsets;
+            if(this.constrain){
+                offsets = {
+                    right:this.el.shadowOffset,
+                    left:this.el.shadowOffset,
+                    bottom:this.el.shadowOffset
+                };
+            }else {
+                var s = this.getSize();
+                offsets = {
+                    right:-(s.width - 100),
+                    bottom:-(s.height - 25 + this.el.getConstrainOffset())
+                };
+            }
+
+            var xy = this.el.getConstrainToXY(this.container, true, offsets);
+            if(xy){
+                this.setPosition(xy[0], xy[1]);
+            }
+        }
+    },
+
+    
+    ghost : function(cls){
+        var ghost = this.createGhost(cls);
+        var box = this.getBox(true);
+        ghost.setLeftTop(box.x, box.y);
+        ghost.setWidth(box.width);
+        this.el.hide();
+        this.activeGhost = ghost;
+        return ghost;
+    },
+
+    
+    unghost : function(show, matchPosition){
+        if(!this.activeGhost) {
+            return;
+        }
+        if(show !== false){
+            this.el.show();
+            this.focus.defer(10, this);
+            if(Ext.isMac && Ext.isGecko2){ 
+                this.cascade(this.setAutoScroll);
+            }
+        }
+        if(matchPosition !== false){
+            this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
+        }
+        this.activeGhost.hide();
+        this.activeGhost.remove();
+        delete this.activeGhost;
+    },
+
+    
+    minimize : function(){
+        this.fireEvent('minimize', this);
+        return this;
+    },
+
+    
+    close : function(){
+        if(this.fireEvent('beforeclose', this) !== false){
+            if(this.hidden){
+                this.doClose();
+            }else{
+                this.hide(null, this.doClose, this);
+            }
+        }
+    },
+
+    
+    doClose : function(){
+        this.fireEvent('close', this);
+        this.destroy();
+    },
+
+    
+    maximize : function(){
+        if(!this.maximized){
+            this.expand(false);
+            this.restoreSize = this.getSize();
+            this.restorePos = this.getPosition(true);
+            if (this.maximizable){
+                this.tools.maximize.hide();
+                this.tools.restore.show();
+            }
+            this.maximized = true;
+            this.el.disableShadow();
+
+            if(this.dd){
+                this.dd.lock();
+            }
+            if(this.collapsible){
+                this.tools.toggle.hide();
+            }
+            this.el.addClass('x-window-maximized');
+            this.container.addClass('x-window-maximized-ct');
+
+            this.setPosition(0, 0);
+            this.fitContainer();
+            this.fireEvent('maximize', this);
+        }
+        return this;
+    },
+
+    
+    restore : function(){
+        if(this.maximized){
+            var t = this.tools;
+            this.el.removeClass('x-window-maximized');
+            if(t.restore){
+                t.restore.hide();
+            }
+            if(t.maximize){
+                t.maximize.show();
+            }
+            this.setPosition(this.restorePos[0], this.restorePos[1]);
+            this.setSize(this.restoreSize.width, this.restoreSize.height);
+            delete this.restorePos;
+            delete this.restoreSize;
+            this.maximized = false;
+            this.el.enableShadow(true);
+
+            if(this.dd){
+                this.dd.unlock();
+            }
+            if(this.collapsible && t.toggle){
+                t.toggle.show();
+            }
+            this.container.removeClass('x-window-maximized-ct');
+
+            this.doConstrain();
+            this.fireEvent('restore', this);
+        }
+        return this;
+    },
+
+    
+    toggleMaximize : function(){
+        return this[this.maximized ? 'restore' : 'maximize']();
+    },
+
+    
+    fitContainer : function(){
+        var vs = this.container.getViewSize(false);
+        this.setSize(vs.width, vs.height);
+    },
+
+    
+    
+    setZIndex : function(index){
+        if(this.modal){
+            this.mask.setStyle('z-index', index);
+        }
+        this.el.setZIndex(++index);
+        index += 5;
+
+        if(this.resizer){
+            this.resizer.proxy.setStyle('z-index', ++index);
+        }
+
+        this.lastZIndex = index;
+    },
+
+    
+    alignTo : function(element, position, offsets){
+        var xy = this.el.getAlignToXY(element, position, offsets);
+        this.setPagePosition(xy[0], xy[1]);
+        return this;
+    },
+
+    
+    anchorTo : function(el, alignment, offsets, monitorScroll){
+        this.clearAnchor();
+        this.anchorTarget = {
+            el: el,
+            alignment: alignment,
+            offsets: offsets
+        };
+
+        Ext.EventManager.onWindowResize(this.doAnchor, this);
+        var tm = typeof monitorScroll;
+        if(tm != 'undefined'){
+            Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
+                {buffer: tm == 'number' ? monitorScroll : 50});
+        }
+        return this.doAnchor();
+    },
+
+    
+    doAnchor : function(){
+        var o = this.anchorTarget;
+        this.alignTo(o.el, o.alignment, o.offsets);
+        return this;
+    },
+
+    
+    clearAnchor : function(){
+        if(this.anchorTarget){
+            Ext.EventManager.removeResizeListener(this.doAnchor, this);
+            Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
+            delete this.anchorTarget;
+        }
+        return this;
+    },
+
+    
+    toFront : function(e){
+        if(this.manager.bringToFront(this)){
+            if(!e || !e.getTarget().focus){
+                this.focus();
+            }
+        }
+        return this;
+    },
+
+    
+    setActive : function(active){
+        if(active){
+            if(!this.maximized){
+                this.el.enableShadow(true);
+            }
+            this.fireEvent('activate', this);
+        }else{
+            this.el.disableShadow();
+            this.fireEvent('deactivate', this);
+        }
+    },
+
+    
+    toBack : function(){
+        this.manager.sendToBack(this);
+        return this;
+    },
+
+    
+    center : function(){
+        var xy = this.el.getAlignToXY(this.container, 'c-c');
+        this.setPagePosition(xy[0], xy[1]);
+        return this;
+    }
+
+    
+});
+Ext.reg('window', Ext.Window);
+
+
+Ext.Window.DD = Ext.extend(Ext.dd.DD, {
+    
+    constructor : function(win){
+        this.win = win;
+        Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
+        this.setHandleElId(win.header.id);
+        this.scroll = false;        
+    },
+    
+    moveOnly:true,
+    headerOffsets:[100, 25],
+    startDrag : function(){
+        var w = this.win;
+        this.proxy = w.ghost(w.initialConfig.cls);
+        if(w.constrain !== false){
+            var so = w.el.shadowOffset;
+            this.constrainTo(w.container, {right: so, left: so, bottom: so});
+        }else if(w.constrainHeader !== false){
+            var s = this.proxy.getSize();
+            this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
+        }
+    },
+    b4Drag : Ext.emptyFn,
+
+    onDrag : function(e){
+        this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
+    },
+
+    endDrag : function(e){
+        this.win.unghost();
+        this.win.saveState();
+    }
+});
+
+Ext.WindowGroup = function(){
+    var list = {};
+    var accessList = [];
+    var front = null;
+
+    
+    var sortWindows = function(d1, d2){
+        return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
+    };
+
+    
+    var orderWindows = function(){
+        var a = accessList, len = a.length;
+        if(len > 0){
+            a.sort(sortWindows);
+            var seed = a[0].manager.zseed;
+            for(var i = 0; i < len; i++){
+                var win = a[i];
+                if(win && !win.hidden){
+                    win.setZIndex(seed + (i*10));
+                }
+            }
+        }
+        activateLast();
+    };
+
+    
+    var setActiveWin = function(win){
+        if(win != front){
+            if(front){
+                front.setActive(false);
+            }
+            front = win;
+            if(win){
+                win.setActive(true);
+            }
+        }
+    };
+
+    
+    var activateLast = function(){
+        for(var i = accessList.length-1; i >=0; --i) {
+            if(!accessList[i].hidden){
+                setActiveWin(accessList[i]);
+                return;
+            }
+        }
+        
+        setActiveWin(null);
+    };
+
+    return {
+        
+        zseed : 9000,
+
+        
+        register : function(win){
+            if(win.manager){
+                win.manager.unregister(win);
+            }
+            win.manager = this;
+
+            list[win.id] = win;
+            accessList.push(win);
+            win.on('hide', activateLast);
+        },
+
+        
+        unregister : function(win){
+            delete win.manager;
+            delete list[win.id];
+            win.un('hide', activateLast);
+            accessList.remove(win);
+        },
+
+        
+        get : function(id){
+            return typeof id == "object" ? id : list[id];
+        },
+
+        
+        bringToFront : function(win){
+            win = this.get(win);
+            if(win != front){
+                win._lastAccess = new Date().getTime();
+                orderWindows();
+                return true;
+            }
+            return false;
+        },
+
+        
+        sendToBack : function(win){
+            win = this.get(win);
+            win._lastAccess = -(new Date().getTime());
+            orderWindows();
+            return win;
+        },
+
+        
+        hideAll : function(){
+            for(var id in list){
+                if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
+                    list[id].hide();
+                }
+            }
+        },
+
+        
+        getActive : function(){
+            return front;
+        },
+
+        
+        getBy : function(fn, scope){
+            var r = [];
+            for(var i = accessList.length-1; i >=0; --i) {
+                var win = accessList[i];
+                if(fn.call(scope||win, win) !== false){
+                    r.push(win);
+                }
+            }
+            return r;
+        },
+
+        
+        each : function(fn, scope){
+            for(var id in list){
+                if(list[id] && typeof list[id] != "function"){
+                    if(fn.call(scope || list[id], list[id]) === false){
+                        return;
+                    }
+                }
+            }
+        }
+    };
+};
+
+
+
+Ext.WindowMgr = new Ext.WindowGroup();
+Ext.MessageBox = function(){
+    var dlg, opt, mask, waitTimer,
+        bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
+        buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
+        buttonNames = ['ok', 'yes', 'no', 'cancel'];
+
+    
+    var handleButton = function(button){
+        buttons[button].blur();
+        if(dlg.isVisible()){
+            dlg.hide();
+            handleHide();
+            Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
+        }
+    };
+
+    
+    var handleHide = function(){
+        if(opt && opt.cls){
+            dlg.el.removeClass(opt.cls);
+        }
+        progressBar.reset();        
+    };
+
+    
+    var handleEsc = function(d, k, e){
+        if(opt && opt.closable !== false){
+            dlg.hide();
+            handleHide();
+        }
+        if(e){
+            e.stopEvent();
+        }
+    };
+
+    
+    var updateButtons = function(b){
+        var width = 0,
+            cfg;
+        if(!b){
+            Ext.each(buttonNames, function(name){
+                buttons[name].hide();
+            });
+            return width;
+        }
+        dlg.footer.dom.style.display = '';
+        Ext.iterate(buttons, function(name, btn){
+            cfg = b[name];
+            if(cfg){
+                btn.show();
+                btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
+                width += btn.getEl().getWidth() + 15;
+            }else{
+                btn.hide();
+            }
+        });
+        return width;
+    };
+
+    return {
+        
+        getDialog : function(titleText){
+           if(!dlg){
+                var btns = [];
+                
+                buttons = {};
+                Ext.each(buttonNames, function(name){
+                    btns.push(buttons[name] = new Ext.Button({
+                        text: this.buttonText[name],
+                        handler: handleButton.createCallback(name),
+                        hideMode: 'offsets'
+                    }));
+                }, this);
+                dlg = new Ext.Window({
+                    autoCreate : true,
+                    title:titleText,
+                    resizable:false,
+                    constrain:true,
+                    constrainHeader:true,
+                    minimizable : false,
+                    maximizable : false,
+                    stateful: false,
+                    modal: true,
+                    shim:true,
+                    buttonAlign:"center",
+                    width:400,
+                    height:100,
+                    minHeight: 80,
+                    plain:true,
+                    footer:true,
+                    closable:true,
+                    close : function(){
+                        if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
+                            handleButton("no");
+                        }else{
+                            handleButton("cancel");
+                        }
+                    },
+                    fbar: new Ext.Toolbar({
+                        items: btns,
+                        enableOverflow: false
+                    })
+                });
+                dlg.render(document.body);
+                dlg.getEl().addClass('x-window-dlg');
+                mask = dlg.mask;
+                bodyEl = dlg.body.createChild({
+                    html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
+                });
+                iconEl = Ext.get(bodyEl.dom.firstChild);
+                var contentEl = bodyEl.dom.childNodes[1];
+                msgEl = Ext.get(contentEl.firstChild);
+                textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
+                textboxEl.enableDisplayMode();
+                textboxEl.addKeyListener([10,13], function(){
+                    if(dlg.isVisible() && opt && opt.buttons){
+                        if(opt.buttons.ok){
+                            handleButton("ok");
+                        }else if(opt.buttons.yes){
+                            handleButton("yes");
+                        }
+                    }
+                });
+                textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
+                textareaEl.enableDisplayMode();
+                progressBar = new Ext.ProgressBar({
+                    renderTo:bodyEl
+                });
+               bodyEl.createChild({cls:'x-clear'});
+            }
+            return dlg;
+        },
+
+        
+        updateText : function(text){
+            if(!dlg.isVisible() && !opt.width){
+                dlg.setSize(this.maxWidth, 100); 
+            }
+            
+            msgEl.update(text ? text + ' ' : '&#160;');
+
+            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
+                mw = msgEl.getWidth() + msgEl.getMargins('lr'),
+                fw = dlg.getFrameWidth('lr'),
+                bw = dlg.body.getFrameWidth('lr'),
+                w;
+                
+            w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
+                    Math.max(opt.minWidth || this.minWidth, bwidth || 0));
+
+            if(opt.prompt === true){
+                activeTextEl.setWidth(w-iw-fw-bw);
+            }
+            if(opt.progress === true || opt.wait === true){
+                progressBar.setSize(w-iw-fw-bw);
+            }
+            if(Ext.isIE && w == bwidth){
+                w += 4; 
+            }
+            msgEl.update(text || '&#160;');
+            dlg.setSize(w, 'auto').center();
+            return this;
+        },
+
+        
+        updateProgress : function(value, progressText, msg){
+            progressBar.updateProgress(value, progressText);
+            if(msg){
+                this.updateText(msg);
+            }
+            return this;
+        },
+
+        
+        isVisible : function(){
+            return dlg && dlg.isVisible();
+        },
+
+        
+        hide : function(){
+            var proxy = dlg ? dlg.activeGhost : null;
+            if(this.isVisible() || proxy){
+                dlg.hide();
+                handleHide();
+                if (proxy){
+                    
+                    
+                    dlg.unghost(false, false);
+                } 
+            }
+            return this;
+        },
+
+        
+        show : function(options){
+            if(this.isVisible()){
+                this.hide();
+            }
+            opt = options;
+            var d = this.getDialog(opt.title || "&#160;");
+
+            d.setTitle(opt.title || "&#160;");
+            var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
+            d.tools.close.setDisplayed(allowClose);
+            activeTextEl = textboxEl;
+            opt.prompt = opt.prompt || (opt.multiline ? true : false);
+            if(opt.prompt){
+                if(opt.multiline){
+                    textboxEl.hide();
+                    textareaEl.show();
+                    textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
+                    activeTextEl = textareaEl;
+                }else{
+                    textboxEl.show();
+                    textareaEl.hide();
+                }
+            }else{
+                textboxEl.hide();
+                textareaEl.hide();
+            }
+            activeTextEl.dom.value = opt.value || "";
+            if(opt.prompt){
+                d.focusEl = activeTextEl;
+            }else{
+                var bs = opt.buttons;
+                var db = null;
+                if(bs && bs.ok){
+                    db = buttons["ok"];
+                }else if(bs && bs.yes){
+                    db = buttons["yes"];
+                }
+                if (db){
+                    d.focusEl = db;
+                }
+            }
+            if(Ext.isDefined(opt.iconCls)){
+              d.setIconClass(opt.iconCls);
+            }
+            this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
+            bwidth = updateButtons(opt.buttons);
+            progressBar.setVisible(opt.progress === true || opt.wait === true);
+            this.updateProgress(0, opt.progressText);
+            this.updateText(opt.msg);
+            if(opt.cls){
+                d.el.addClass(opt.cls);
+            }
+            d.proxyDrag = opt.proxyDrag === true;
+            d.modal = opt.modal !== false;
+            d.mask = opt.modal !== false ? mask : false;
+            if(!d.isVisible()){
+                
+                document.body.appendChild(dlg.el.dom);
+                d.setAnimateTarget(opt.animEl);
+                
+                d.on('show', function(){
+                    if(allowClose === true){
+                        d.keyMap.enable();
+                    }else{
+                        d.keyMap.disable();
+                    }
+                }, this, {single:true});
+                d.show(opt.animEl);
+            }
+            if(opt.wait === true){
+                progressBar.wait(opt.waitConfig);
+            }
+            return this;
+        },
+
+        
+        setIcon : function(icon){
+            if(!dlg){
+                bufferIcon = icon;
+                return;
+            }
+            bufferIcon = undefined;
+            if(icon && icon != ''){
+                iconEl.removeClass('x-hidden');
+                iconEl.replaceClass(iconCls, icon);
+                bodyEl.addClass('x-dlg-icon');
+                iconCls = icon;
+            }else{
+                iconEl.replaceClass(iconCls, 'x-hidden');
+                bodyEl.removeClass('x-dlg-icon');
+                iconCls = '';
+            }
+            return this;
+        },
+
+        
+        progress : function(title, msg, progressText){
+            this.show({
+                title : title,
+                msg : msg,
+                buttons: false,
+                progress:true,
+                closable:false,
+                minWidth: this.minProgressWidth,
+                progressText: progressText
+            });
+            return this;
+        },
+
+        
+        wait : function(msg, title, config){
+            this.show({
+                title : title,
+                msg : msg,
+                buttons: false,
+                closable:false,
+                wait:true,
+                modal:true,
+                minWidth: this.minProgressWidth,
+                waitConfig: config
+            });
+            return this;
+        },
+
+        
+        alert : function(title, msg, fn, scope){
+            this.show({
+                title : title,
+                msg : msg,
+                buttons: this.OK,
+                fn: fn,
+                scope : scope,
+                minWidth: this.minWidth
+            });
+            return this;
+        },
+
+        
+        confirm : function(title, msg, fn, scope){
+            this.show({
+                title : title,
+                msg : msg,
+                buttons: this.YESNO,
+                fn: fn,
+                scope : scope,
+                icon: this.QUESTION,
+                minWidth: this.minWidth
+            });
+            return this;
+        },
+
+        
+        prompt : function(title, msg, fn, scope, multiline, value){
+            this.show({
+                title : title,
+                msg : msg,
+                buttons: this.OKCANCEL,
+                fn: fn,
+                minWidth: this.minPromptWidth,
+                scope : scope,
+                prompt:true,
+                multiline: multiline,
+                value: value
+            });
+            return this;
+        },
+
+        
+        OK : {ok:true},
+        
+        CANCEL : {cancel:true},
+        
+        OKCANCEL : {ok:true, cancel:true},
+        
+        YESNO : {yes:true, no:true},
+        
+        YESNOCANCEL : {yes:true, no:true, cancel:true},
+        
+        INFO : 'ext-mb-info',
+        
+        WARNING : 'ext-mb-warning',
+        
+        QUESTION : 'ext-mb-question',
+        
+        ERROR : 'ext-mb-error',
+
+        
+        defaultTextHeight : 75,
+        
+        maxWidth : 600,
+        
+        minWidth : 100,
+        
+        minProgressWidth : 250,
+        
+        minPromptWidth: 250,
+        
+        buttonText : {
+            ok : "OK",
+            cancel : "Cancel",
+            yes : "Yes",
+            no : "No"
+        }
+    };
+}();
+
+
+Ext.Msg = Ext.MessageBox;
+Ext.dd.PanelProxy  = Ext.extend(Object, {
+    
+    constructor : function(panel, config){
+        this.panel = panel;
+        this.id = this.panel.id +'-ddproxy';
+        Ext.apply(this, config);        
+    },
+    
+    
+    insertProxy : true,
+
+    
+    setStatus : Ext.emptyFn,
+    reset : Ext.emptyFn,
+    update : Ext.emptyFn,
+    stop : Ext.emptyFn,
+    sync: Ext.emptyFn,
+
+    
+    getEl : function(){
+        return this.ghost;
+    },
+
+    
+    getGhost : function(){
+        return this.ghost;
+    },
+
+    
+    getProxy : function(){
+        return this.proxy;
+    },
+
+    
+    hide : function(){
+        if(this.ghost){
+            if(this.proxy){
+                this.proxy.remove();
+                delete this.proxy;
+            }
+            this.panel.el.dom.style.display = '';
+            this.ghost.remove();
+            delete this.ghost;
+        }
+    },
+
+    
+    show : function(){
+        if(!this.ghost){
+            this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, undefined, Ext.getBody());
+            this.ghost.setXY(this.panel.el.getXY());
+            if(this.insertProxy){
+                this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
+                this.proxy.setSize(this.panel.getSize());
+            }
+            this.panel.el.dom.style.display = 'none';
+        }
+    },
+
+    
+    repair : function(xy, callback, scope){
+        this.hide();
+        if(typeof callback == "function"){
+            callback.call(scope || this);
+        }
+    },
+
+    
+    moveProxy : function(parentNode, before){
+        if(this.proxy){
+            parentNode.insertBefore(this.proxy.dom, before);
+        }
+    }
+});
+
+
+Ext.Panel.DD = Ext.extend(Ext.dd.DragSource, {
+    
+    constructor : function(panel, cfg){
+        this.panel = panel;
+        this.dragData = {panel: panel};
+        this.proxy = new Ext.dd.PanelProxy(panel, cfg);
+        Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
+        var h = panel.header,
+            el = panel.body;
+        if(h){
+            this.setHandleElId(h.id);
+            el = panel.header;
+        }
+        el.setStyle('cursor', 'move');
+        this.scroll = false;        
+    },
+    
+    showFrame: Ext.emptyFn,
+    startDrag: Ext.emptyFn,
+    b4StartDrag: function(x, y) {
+        this.proxy.show();
+    },
+    b4MouseDown: function(e) {
+        var x = e.getPageX(),
+            y = e.getPageY();
+        this.autoOffset(x, y);
+    },
+    onInitDrag : function(x, y){
+        this.onStartDrag(x, y);
+        return true;
+    },
+    createFrame : Ext.emptyFn,
+    getDragEl : function(e){
+        return this.proxy.ghost.dom;
+    },
+    endDrag : function(e){
+        this.proxy.hide();
+        this.panel.saveState();
+    },
+
+    autoOffset : function(x, y) {
+        x -= this.startPageX;
+        y -= this.startPageY;
+        this.setDelta(x, y);
+    }
+});
+Ext.state.Provider = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(){
+        
+        this.addEvents("statechange");
+        this.state = {};
+        Ext.state.Provider.superclass.constructor.call(this);
+    },
+    
+    
+    get : function(name, defaultValue){
+        return typeof this.state[name] == "undefined" ?
+            defaultValue : this.state[name];
+    },
+
+    
+    clear : function(name){
+        delete this.state[name];
+        this.fireEvent("statechange", this, name, null);
+    },
+
+    
+    set : function(name, value){
+        this.state[name] = value;
+        this.fireEvent("statechange", this, name, value);
+    },
+
+    
+    decodeValue : function(cookie){
+        
+        var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
+            matches = re.exec(unescape(cookie)),
+            all,
+            type,
+            v,
+            kv;
+        if(!matches || !matches[1]){
+            return; 
+        }
+        type = matches[1];
+        v = matches[2];
+        switch(type){
+            case 'e':
+                return null;
+            case 'n':
+                return parseFloat(v);
+            case 'd':
+                return new Date(Date.parse(v));
+            case 'b':
+                return (v == '1');
+            case 'a':
+                all = [];
+                if(v != ''){
+                    Ext.each(v.split('^'), function(val){
+                        all.push(this.decodeValue(val));
+                    }, this);
+                }
+                return all;
+           case 'o':
+                all = {};
+                if(v != ''){
+                    Ext.each(v.split('^'), function(val){
+                        kv = val.split('=');
+                        all[kv[0]] = this.decodeValue(kv[1]);
+                    }, this);
+                }
+                return all;
+           default:
+                return v;
+        }
+    },
+
+    
+    encodeValue : function(v){
+        var enc,
+            flat = '',
+            i = 0,
+            len,
+            key;
+        if(v == null){
+            return 'e:1';    
+        }else if(typeof v == 'number'){
+            enc = 'n:' + v;
+        }else if(typeof v == 'boolean'){
+            enc = 'b:' + (v ? '1' : '0');
+        }else if(Ext.isDate(v)){
+            enc = 'd:' + v.toGMTString();
+        }else if(Ext.isArray(v)){
+            for(len = v.length; i < len; i++){
+                flat += this.encodeValue(v[i]);
+                if(i != len - 1){
+                    flat += '^';
+                }
+            }
+            enc = 'a:' + flat;
+        }else if(typeof v == 'object'){
+            for(key in v){
+                if(typeof v[key] != 'function' && v[key] !== undefined){
+                    flat += key + '=' + this.encodeValue(v[key]) + '^';
+                }
+            }
+            enc = 'o:' + flat.substring(0, flat.length-1);
+        }else{
+            enc = 's:' + v;
+        }
+        return escape(enc);
+    }
+});
+
+Ext.state.Manager = function(){
+    var provider = new Ext.state.Provider();
+
+    return {
+        
+        setProvider : function(stateProvider){
+            provider = stateProvider;
+        },
+
+        
+        get : function(key, defaultValue){
+            return provider.get(key, defaultValue);
+        },
+
+        
+         set : function(key, value){
+            provider.set(key, value);
+        },
+
+        
+        clear : function(key){
+            provider.clear(key);
+        },
+
+        
+        getProvider : function(){
+            return provider;
+        }
+    };
+}();
+
+Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {
+    
+    constructor : function(config){
+        Ext.state.CookieProvider.superclass.constructor.call(this);
+        this.path = "/";
+        this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
+        this.domain = null;
+        this.secure = false;
+        Ext.apply(this, config);
+        this.state = this.readCookies();
+    },
+    
+    
+    set : function(name, value){
+        if(typeof value == "undefined" || value === null){
+            this.clear(name);
+            return;
+        }
+        this.setCookie(name, value);
+        Ext.state.CookieProvider.superclass.set.call(this, name, value);
+    },
+
+    
+    clear : function(name){
+        this.clearCookie(name);
+        Ext.state.CookieProvider.superclass.clear.call(this, name);
+    },
+
+    
+    readCookies : function(){
+        var cookies = {},
+            c = document.cookie + ";",
+            re = /\s?(.*?)=(.*?);/g,
+    	    matches,
+            name,
+            value;
+    	while((matches = re.exec(c)) != null){
+            name = matches[1];
+            value = matches[2];
+            if(name && name.substring(0,3) == "ys-"){
+                cookies[name.substr(3)] = this.decodeValue(value);
+            }
+        }
+        return cookies;
+    },
+
+    
+    setCookie : function(name, value){
+        document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
+           ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
+           ((this.path == null) ? "" : ("; path=" + this.path)) +
+           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
+           ((this.secure == true) ? "; secure" : "");
+    },
+
+    
+    clearCookie : function(name){
+        document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
+           ((this.path == null) ? "" : ("; path=" + this.path)) +
+           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
+           ((this.secure == true) ? "; secure" : "");
+    }
+});
+Ext.DataView = Ext.extend(Ext.BoxComponent, {
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    selectedClass : "x-view-selected",
+    
+    emptyText : "",
+
+    
+    deferEmptyText: true,
+    
+    trackOver: false,
+    
+    
+    blockRefresh: false,
+
+    
+    last: false,
+
+    
+    initComponent : function(){
+        Ext.DataView.superclass.initComponent.call(this);
+        if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
+            this.tpl = new Ext.XTemplate(this.tpl);
+        }
+
+        this.addEvents(
+            
+            "beforeclick",
+            
+            "click",
+            
+            "mouseenter",
+            
+            "mouseleave",
+            
+            "containerclick",
+            
+            "dblclick",
+            
+            "contextmenu",
+            
+            "containercontextmenu",
+            
+            "selectionchange",
+
+            
+            "beforeselect"
+        );
+
+        this.store = Ext.StoreMgr.lookup(this.store);
+        this.all = new Ext.CompositeElementLite();
+        this.selected = new Ext.CompositeElementLite();
+    },
+
+    
+    afterRender : function(){
+        Ext.DataView.superclass.afterRender.call(this);
+
+		this.mon(this.getTemplateTarget(), {
+            "click": this.onClick,
+            "dblclick": this.onDblClick,
+            "contextmenu": this.onContextMenu,
+            scope:this
+        });
+
+        if(this.overClass || this.trackOver){
+            this.mon(this.getTemplateTarget(), {
+                "mouseover": this.onMouseOver,
+                "mouseout": this.onMouseOut,
+                scope:this
+            });
+        }
+
+        if(this.store){
+            this.bindStore(this.store, true);
+        }
+    },
+
+    
+    refresh : function() {
+        this.clearSelections(false, true);
+        var el = this.getTemplateTarget(),
+            records = this.store.getRange();
+            
+        el.update('');
+        if(records.length < 1){
+            if(!this.deferEmptyText || this.hasSkippedEmptyText){
+                el.update(this.emptyText);
+            }
+            this.all.clear();
+        }else{
+            this.tpl.overwrite(el, this.collectData(records, 0));
+            this.all.fill(Ext.query(this.itemSelector, el.dom));
+            this.updateIndexes(0);
+        }
+        this.hasSkippedEmptyText = true;
+    },
+
+    getTemplateTarget: function(){
+        return this.el;
+    },
+
+    
+    prepareData : function(data){
+        return data;
+    },
+
+    
+    collectData : function(records, startIndex){
+        var r = [],
+            i = 0,
+            len = records.length;
+        for(; i < len; i++){
+            r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
+        }
+        return r;
+    },
+
+    
+    bufferRender : function(records, index){
+        var div = document.createElement('div');
+        this.tpl.overwrite(div, this.collectData(records, index));
+        return Ext.query(this.itemSelector, div);
+    },
+
+    
+    onUpdate : function(ds, record){
+        var index = this.store.indexOf(record);
+        if(index > -1){
+            var sel = this.isSelected(index),
+                original = this.all.elements[index],
+                node = this.bufferRender([record], index)[0];
+
+            this.all.replaceElement(index, node, true);
+            if(sel){
+                this.selected.replaceElement(original, node);
+                this.all.item(index).addClass(this.selectedClass);
+            }
+            this.updateIndexes(index, index);
+        }
+    },
+
+    
+    onAdd : function(ds, records, index){
+        if(this.all.getCount() === 0){
+            this.refresh();
+            return;
+        }
+        var nodes = this.bufferRender(records, index), n, a = this.all.elements;
+        if(index < this.all.getCount()){
+            n = this.all.item(index).insertSibling(nodes, 'before', true);
+            a.splice.apply(a, [index, 0].concat(nodes));
+        }else{
+            n = this.all.last().insertSibling(nodes, 'after', true);
+            a.push.apply(a, nodes);
+        }
+        this.updateIndexes(index);
+    },
+
+    
+    onRemove : function(ds, record, index){
+        this.deselect(index);
+        this.all.removeElement(index, true);
+        this.updateIndexes(index);
+        if (this.store.getCount() === 0){
+            this.refresh();
+        }
+    },
+
+    
+    refreshNode : function(index){
+        this.onUpdate(this.store, this.store.getAt(index));
+    },
+
+    
+    updateIndexes : function(startIndex, endIndex){
+        var ns = this.all.elements;
+        startIndex = startIndex || 0;
+        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
+        for(var i = startIndex; i <= endIndex; i++){
+            ns[i].viewIndex = i;
+        }
+    },
+    
+    
+    getStore : function(){
+        return this.store;
+    },
+
+    
+    bindStore : function(store, initial){
+        if(!initial && this.store){
+            if(store !== this.store && this.store.autoDestroy){
+                this.store.destroy();
+            }else{
+                this.store.un("beforeload", this.onBeforeLoad, this);
+                this.store.un("datachanged", this.onDataChanged, this);
+                this.store.un("add", this.onAdd, this);
+                this.store.un("remove", this.onRemove, this);
+                this.store.un("update", this.onUpdate, this);
+                this.store.un("clear", this.refresh, this);
+            }
+            if(!store){
+                this.store = null;
+            }
+        }
+        if(store){
+            store = Ext.StoreMgr.lookup(store);
+            store.on({
+                scope: this,
+                beforeload: this.onBeforeLoad,
+                datachanged: this.onDataChanged,
+                add: this.onAdd,
+                remove: this.onRemove,
+                update: this.onUpdate,
+                clear: this.refresh
+            });
+        }
+        this.store = store;
+        if(store){
+            this.refresh();
+        }
+    },
+    
+    
+    onDataChanged: function() {
+        if (this.blockRefresh !== true) {
+            this.refresh.apply(this, arguments);
+        }
+    },
+
+    
+    findItemFromChild : function(node){
+        return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
+    },
+
+    
+    onClick : function(e){
+        var item = e.getTarget(this.itemSelector, this.getTemplateTarget()),
+            index;
+        if(item){
+            index = this.indexOf(item);
+            if(this.onItemClick(item, index, e) !== false){
+                this.fireEvent("click", this, index, item, e);
+            }
+        }else{
+            if(this.fireEvent("containerclick", this, e) !== false){
+                this.onContainerClick(e);
+            }
+        }
+    },
+
+    onContainerClick : function(e){
+        this.clearSelections();
+    },
+
+    
+    onContextMenu : function(e){
+        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
+        if(item){
+            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
+        }else{
+            this.fireEvent("containercontextmenu", this, e);
+        }
+    },
+
+    
+    onDblClick : function(e){
+        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
+        if(item){
+            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
+        }
+    },
+
+    
+    onMouseOver : function(e){
+        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
+        if(item && item !== this.lastItem){
+            this.lastItem = item;
+            Ext.fly(item).addClass(this.overClass);
+            this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
+        }
+    },
+
+    
+    onMouseOut : function(e){
+        if(this.lastItem){
+            if(!e.within(this.lastItem, true, true)){
+                Ext.fly(this.lastItem).removeClass(this.overClass);
+                this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
+                delete this.lastItem;
+            }
+        }
+    },
+
+    
+    onItemClick : function(item, index, e){
+        if(this.fireEvent("beforeclick", this, index, item, e) === false){
+            return false;
+        }
+        if(this.multiSelect){
+            this.doMultiSelection(item, index, e);
+            e.preventDefault();
+        }else if(this.singleSelect){
+            this.doSingleSelection(item, index, e);
+            e.preventDefault();
+        }
+        return true;
+    },
+
+    
+    doSingleSelection : function(item, index, e){
+        if(e.ctrlKey && this.isSelected(index)){
+            this.deselect(index);
+        }else{
+            this.select(index, false);
+        }
+    },
+
+    
+    doMultiSelection : function(item, index, e){
+        if(e.shiftKey && this.last !== false){
+            var last = this.last;
+            this.selectRange(last, index, e.ctrlKey);
+            this.last = last; 
+        }else{
+            if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
+                this.deselect(index);
+            }else{
+                this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
+            }
+        }
+    },
+
+    
+    getSelectionCount : function(){
+        return this.selected.getCount();
+    },
+
+    
+    getSelectedNodes : function(){
+        return this.selected.elements;
+    },
+
+    
+    getSelectedIndexes : function(){
+        var indexes = [], 
+            selected = this.selected.elements,
+            i = 0,
+            len = selected.length;
+            
+        for(; i < len; i++){
+            indexes.push(selected[i].viewIndex);
+        }
+        return indexes;
+    },
+
+    
+    getSelectedRecords : function(){
+        return this.getRecords(this.selected.elements);
+    },
+
+    
+    getRecords : function(nodes){
+        var records = [], 
+            i = 0,
+            len = nodes.length;
+            
+        for(; i < len; i++){
+            records[records.length] = this.store.getAt(nodes[i].viewIndex);
+        }
+        return records;
+    },
+
+    
+    getRecord : function(node){
+        return this.store.getAt(node.viewIndex);
+    },
+
+    
+    clearSelections : function(suppressEvent, skipUpdate){
+        if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
+            if(!skipUpdate){
+                this.selected.removeClass(this.selectedClass);
+            }
+            this.selected.clear();
+            this.last = false;
+            if(!suppressEvent){
+                this.fireEvent("selectionchange", this, this.selected.elements);
+            }
+        }
+    },
+
+    
+    isSelected : function(node){
+        return this.selected.contains(this.getNode(node));
+    },
+
+    
+    deselect : function(node){
+        if(this.isSelected(node)){
+            node = this.getNode(node);
+            this.selected.removeElement(node);
+            if(this.last == node.viewIndex){
+                this.last = false;
+            }
+            Ext.fly(node).removeClass(this.selectedClass);
+            this.fireEvent("selectionchange", this, this.selected.elements);
+        }
+    },
+
+    
+    select : function(nodeInfo, keepExisting, suppressEvent){
+        if(Ext.isArray(nodeInfo)){
+            if(!keepExisting){
+                this.clearSelections(true);
+            }
+            for(var i = 0, len = nodeInfo.length; i < len; i++){
+                this.select(nodeInfo[i], true, true);
+            }
+            if(!suppressEvent){
+                this.fireEvent("selectionchange", this, this.selected.elements);
+            }
+        } else{
+            var node = this.getNode(nodeInfo);
+            if(!keepExisting){
+                this.clearSelections(true);
+            }
+            if(node && !this.isSelected(node)){
+                if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
+                    Ext.fly(node).addClass(this.selectedClass);
+                    this.selected.add(node);
+                    this.last = node.viewIndex;
+                    if(!suppressEvent){
+                        this.fireEvent("selectionchange", this, this.selected.elements);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    selectRange : function(start, end, keepExisting){
+        if(!keepExisting){
+            this.clearSelections(true);
+        }
+        this.select(this.getNodes(start, end), true);
+    },
+
+    
+    getNode : function(nodeInfo){
+        if(Ext.isString(nodeInfo)){
+            return document.getElementById(nodeInfo);
+        }else if(Ext.isNumber(nodeInfo)){
+            return this.all.elements[nodeInfo];
+        }else if(nodeInfo instanceof Ext.data.Record){
+            var idx = this.store.indexOf(nodeInfo);
+            return this.all.elements[idx];
+        }
+        return nodeInfo;
+    },
+
+    
+    getNodes : function(start, end){
+        var ns = this.all.elements,
+            nodes = [],
+            i;
+            
+        start = start || 0;
+        end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
+        if(start <= end){
+            for(i = start; i <= end && ns[i]; i++){
+                nodes.push(ns[i]);
+            }
+        } else{
+            for(i = start; i >= end && ns[i]; i--){
+                nodes.push(ns[i]);
+            }
+        }
+        return nodes;
+    },
+
+    
+    indexOf : function(node){
+        node = this.getNode(node);
+        if(Ext.isNumber(node.viewIndex)){
+            return node.viewIndex;
+        }
+        return this.all.indexOf(node);
+    },
+
+    
+    onBeforeLoad : function(){
+        if(this.loadingText){
+            this.clearSelections(false, true);
+            this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
+            this.all.clear();
+        }
+    },
+
+    onDestroy : function(){
+        this.all.clear();
+        this.selected.clear();
+        Ext.DataView.superclass.onDestroy.call(this);
+        this.bindStore(null);
+    }
+});
+
+
+Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
+
+Ext.reg('dataview', Ext.DataView);
+
+Ext.list.ListView = Ext.extend(Ext.DataView, {
+    
+    
+    
+    itemSelector: 'dl',
+    
+    selectedClass:'x-list-selected',
+    
+    overClass:'x-list-over',
+    
+    
+    scrollOffset : undefined,
+    
+    columnResize: true,
+    
+    
+    columnSort: true,
+    
+
+    
+    maxColumnWidth: Ext.isIE ? 99 : 100,
+
+    initComponent : function(){
+        if(this.columnResize){
+            this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
+            this.colResizer.init(this);
+        }
+        if(this.columnSort){
+            this.colSorter = new Ext.list.Sorter(this.columnSort);
+            this.colSorter.init(this);
+        }
+        if(!this.internalTpl){
+            this.internalTpl = new Ext.XTemplate(
+                '<div class="x-list-header"><div class="x-list-header-inner">',
+                    '<tpl for="columns">',
+                    '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
+                        '{header}',
+                    '</em></div>',
+                    '</tpl>',
+                    '<div class="x-clear"></div>',
+                '</div></div>',
+                '<div class="x-list-body"><div class="x-list-body-inner">',
+                '</div></div>'
+            );
+        }
+        if(!this.tpl){
+            this.tpl = new Ext.XTemplate(
+                '<tpl for="rows">',
+                    '<dl>',
+                        '<tpl for="parent.columns">',
+                        '<dt style="width:{[values.width*100]}%;text-align:{align};">',
+                        '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
+                            '{[values.tpl.apply(parent)]}',
+                        '</em></dt>',
+                        '</tpl>',
+                        '<div class="x-clear"></div>',
+                    '</dl>',
+                '</tpl>'
+            );
+        };
+
+        var cs = this.columns,
+            allocatedWidth = 0,
+            colsWithWidth = 0,
+            len = cs.length,
+            columns = [];
+
+        for(var i = 0; i < len; i++){
+            var c = cs[i];
+            if(!c.isColumn) {
+                c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
+                c = Ext.create(c);
+            }
+            if(c.width) {
+                allocatedWidth += c.width*100;
+                if(allocatedWidth > this.maxColumnWidth){
+                    c.width -= (allocatedWidth - this.maxColumnWidth) / 100;
+                }
+                colsWithWidth++;
+            }
+            columns.push(c);
+        }
+
+        cs = this.columns = columns;
+
+        
+        if(colsWithWidth < len){
+            var remaining = len - colsWithWidth;
+            if(allocatedWidth < this.maxColumnWidth){
+                var perCol = ((this.maxColumnWidth-allocatedWidth) / remaining)/100;
+                for(var j = 0; j < len; j++){
+                    var c = cs[j];
+                    if(!c.width){
+                        c.width = perCol;
+                    }
+                }
+            }
+        }
+        Ext.list.ListView.superclass.initComponent.call(this);
+    },
+
+    onRender : function(){
+        this.autoEl = {
+            cls: 'x-list-wrap'
+        };
+        Ext.list.ListView.superclass.onRender.apply(this, arguments);
+
+        this.internalTpl.overwrite(this.el, {columns: this.columns});
+
+        this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
+        this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
+
+        if(this.hideHeaders){
+            this.el.dom.firstChild.style.display = 'none';
+        }
+    },
+
+    getTemplateTarget : function(){
+        return this.innerBody;
+    },
+
+    
+    collectData : function(){
+        var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
+        return {
+            columns: this.columns,
+            rows: rs
+        };
+    },
+
+    verifyInternalSize : function(){
+        if(this.lastSize){
+            this.onResize(this.lastSize.width, this.lastSize.height);
+        }
+    },
+
+    
+    onResize : function(w, h){
+        var body = this.innerBody.dom,
+            header = this.innerHd.dom,
+            scrollWidth = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + 'px',
+            parentNode;
+            
+        if(!body){
+            return;
+        }
+        parentNode = body.parentNode;
+        if(Ext.isNumber(w)){
+            if(this.reserveScrollOffset || ((parentNode.offsetWidth - parentNode.clientWidth) > 10)){
+                body.style.width = scrollWidth;
+                header.style.width = scrollWidth;
+            }else{
+                body.style.width = w + 'px';
+                header.style.width = w + 'px';
+                setTimeout(function(){
+                    if((parentNode.offsetWidth - parentNode.clientWidth) > 10){
+                        body.style.width = scrollWidth;
+                        header.style.width = scrollWidth;
+                    }
+                }, 10);
+            }
+        }
+        if(Ext.isNumber(h)){
+            parentNode.style.height = Math.max(0, h - header.parentNode.offsetHeight) + 'px';
+        }
+    },
+
+    updateIndexes : function(){
+        Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
+        this.verifyInternalSize();
+    },
+
+    findHeaderIndex : function(header){
+        header = header.dom || header;
+        var parentNode = header.parentNode, 
+            children = parentNode.parentNode.childNodes,
+            i = 0,
+            c;
+        for(; c = children[i]; i++){
+            if(c == parentNode){
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    setHdWidths : function(){
+        var els = this.innerHd.dom.getElementsByTagName('div'),
+            i = 0,
+            columns = this.columns,
+            len = columns.length;
+            
+        for(; i < len; i++){
+            els[i].style.width = (columns[i].width*100) + '%';
+        }
+    }
+});
+
+Ext.reg('listview', Ext.list.ListView);
+
+
+Ext.ListView = Ext.list.ListView;
+Ext.list.Column = Ext.extend(Object, {
+    
+    isColumn: true,
+    
+            
+    align: 'left',
+        
+    header: '',
+    
+        
+    width: null,
+
+    
+    cls: '',
+    
+    
+
+    
+    
+    constructor : function(c){
+        if(!c.tpl){
+            c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
+        }
+        else if(Ext.isString(c.tpl)){
+            c.tpl = new Ext.XTemplate(c.tpl);
+        }
+        
+        Ext.apply(this, c);
+    }
+});
+
+Ext.reg('lvcolumn', Ext.list.Column);
+
+
+Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
+        
+    format: '0,000.00',
+    
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
+        Ext.list.NumberColumn.superclass.constructor.call(this, c);
+    }
+});
+
+Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
+
+
+Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
+    format: 'm/d/Y',
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
+        Ext.list.DateColumn.superclass.constructor.call(this, c);
+    }
+});
+Ext.reg('lvdatecolumn', Ext.list.DateColumn);
+
+
+Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
+    
+    trueText: 'true',
+    
+    falseText: 'false',
+    
+    undefinedText: '&#160;',
+    
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
+        
+        var t = this.trueText, f = this.falseText, u = this.undefinedText;
+        c.tpl.format = function(v){
+            if(v === undefined){
+                return u;
+            }
+            if(!v || v === 'false'){
+                return f;
+            }
+            return t;
+        };
+        
+        Ext.list.DateColumn.superclass.constructor.call(this, c);
+    }
+});
+
+Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
+Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
+    
+    minPct: .05,
+
+    constructor: function(config){
+        Ext.apply(this, config);
+        Ext.list.ColumnResizer.superclass.constructor.call(this);
+    },
+    init : function(listView){
+        this.view = listView;
+        listView.on('render', this.initEvents, this);
+    },
+
+    initEvents : function(view){
+        view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
+        this.tracker = new Ext.dd.DragTracker({
+            onBeforeStart: this.onBeforeStart.createDelegate(this),
+            onStart: this.onStart.createDelegate(this),
+            onDrag: this.onDrag.createDelegate(this),
+            onEnd: this.onEnd.createDelegate(this),
+            tolerance: 3,
+            autoStart: 300
+        });
+        this.tracker.initEl(view.innerHd);
+        view.on('beforedestroy', this.tracker.destroy, this.tracker);
+    },
+
+    handleHdMove : function(e, t){
+        var handleWidth = 5,
+            x = e.getPageX(),
+            header = e.getTarget('em', 3, true);
+        if(header){
+            var region = header.getRegion(),
+                style = header.dom.style,
+                parentNode = header.dom.parentNode;
+
+            if(x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild){
+                this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
+                style.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
+            } else if(region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling){
+                this.activeHd = header;
+                style.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
+            } else{
+                delete this.activeHd;
+                style.cursor = '';
+            }
+        }
+    },
+
+    onBeforeStart : function(e){
+        this.dragHd = this.activeHd;
+        return !!this.dragHd;
+    },
+
+    onStart: function(e){
+        
+        var me = this,
+            view = me.view,
+            dragHeader = me.dragHd,
+            x = me.tracker.getXY()[0];            
+        
+        me.proxy = view.el.createChild({cls:'x-list-resizer'});
+        me.dragX = dragHeader.getX();
+        me.headerIndex = view.findHeaderIndex(dragHeader);
+        
+        me.headersDisabled = view.disableHeaders;
+        view.disableHeaders = true;
+        
+        me.proxy.setHeight(view.el.getHeight());
+        me.proxy.setX(me.dragX);
+        me.proxy.setWidth(x - me.dragX);
+        
+        this.setBoundaries();
+        
+    },
+    
+    
+    setBoundaries: function(relativeX){
+        var view = this.view,
+            headerIndex = this.headerIndex,
+            width = view.innerHd.getWidth(),
+            relativeX = view.innerHd.getX(),
+            minWidth = Math.ceil(width * this.minPct),
+            maxWidth = width - minWidth,
+            numColumns = view.columns.length,
+            headers = view.innerHd.select('em', true),
+            minX = minWidth + relativeX,
+            maxX = maxWidth + relativeX,
+            header;
+          
+        if (numColumns == 2) {
+            this.minX = minX;
+            this.maxX = maxX;
+        }else{
+            header = headers.item(headerIndex + 2);
+            this.minX = headers.item(headerIndex).getX() + minWidth;
+            this.maxX = header ? header.getX() - minWidth : maxX;
+            if (headerIndex == 0) {
+                
+                this.minX = minX;
+            } else if (headerIndex == numColumns - 2) {
+                
+                this.maxX = maxX;
+            }
+        }
+    },
+
+    onDrag: function(e){
+        var me = this,
+            cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);
+            
+        me.proxy.setWidth(cursorX - this.dragX);
+    },
+
+    onEnd: function(e){
+        
+        var newWidth = this.proxy.getWidth(),
+            index = this.headerIndex,
+            view = this.view,
+            columns = view.columns,
+            width = view.innerHd.getWidth(),
+            newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100,
+            disabled = this.headersDisabled,
+            headerCol = columns[index],
+            otherCol = columns[index + 1],
+            totalPercent = headerCol.width + otherCol.width;
+
+        this.proxy.remove();
+
+        headerCol.width = newPercent;
+        otherCol.width = totalPercent - newPercent;
+      
+        delete this.dragHd;
+        view.setHdWidths();
+        view.refresh();
+        
+        setTimeout(function(){
+            view.disableHeaders = disabled;
+        }, 100);
+    }
+});
+
+
+Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
+Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
+    
+    sortClasses : ["sort-asc", "sort-desc"],
+
+    constructor: function(config){
+        Ext.apply(this, config);
+        Ext.list.Sorter.superclass.constructor.call(this);
+    },
+
+    init : function(listView){
+        this.view = listView;
+        listView.on('render', this.initEvents, this);
+    },
+
+    initEvents : function(view){
+        view.mon(view.innerHd, 'click', this.onHdClick, this);
+        view.innerHd.setStyle('cursor', 'pointer');
+        view.mon(view.store, 'datachanged', this.updateSortState, this);
+        this.updateSortState.defer(10, this, [view.store]);
+    },
+
+    updateSortState : function(store){
+        var state = store.getSortState();
+        if(!state){
+            return;
+        }
+        this.sortState = state;
+        var cs = this.view.columns, sortColumn = -1;
+        for(var i = 0, len = cs.length; i < len; i++){
+            if(cs[i].dataIndex == state.field){
+                sortColumn = i;
+                break;
+            }
+        }
+        if(sortColumn != -1){
+            var sortDir = state.direction;
+            this.updateSortIcon(sortColumn, sortDir);
+        }
+    },
+
+    updateSortIcon : function(col, dir){
+        var sc = this.sortClasses;
+        var hds = this.view.innerHd.select('em').removeClass(sc);
+        hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
+    },
+
+    onHdClick : function(e){
+        var hd = e.getTarget('em', 3);
+        if(hd && !this.view.disableHeaders){
+            var index = this.view.findHeaderIndex(hd);
+            this.view.store.sort(this.view.columns[index].dataIndex);
+        }
+    }
+});
+
+
+Ext.ListView.Sorter = Ext.list.Sorter;
+Ext.TabPanel = Ext.extend(Ext.Panel,  {
+    
+    
+    
+    deferredRender : true,
+    
+    tabWidth : 120,
+    
+    minTabWidth : 30,
+    
+    resizeTabs : false,
+    
+    enableTabScroll : false,
+    
+    scrollIncrement : 0,
+    
+    scrollRepeatInterval : 400,
+    
+    scrollDuration : 0.35,
+    
+    animScroll : true,
+    
+    tabPosition : 'top',
+    
+    baseCls : 'x-tab-panel',
+    
+    autoTabs : false,
+    
+    autoTabSelector : 'div.x-tab',
+    
+    activeTab : undefined,
+    
+    tabMargin : 2,
+    
+    plain : false,
+    
+    wheelIncrement : 20,
+
+    
+    idDelimiter : '__',
+
+    
+    itemCls : 'x-tab-item',
+
+    
+    elements : 'body',
+    headerAsText : false,
+    frame : false,
+    hideBorders :true,
+
+    
+    initComponent : function(){
+        this.frame = false;
+        Ext.TabPanel.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'beforetabchange',
+            
+            'tabchange',
+            
+            'contextmenu'
+        );
+        
+        this.setLayout(new Ext.layout.CardLayout(Ext.apply({
+            layoutOnCardChange: this.layoutOnTabChange,
+            deferredRender: this.deferredRender
+        }, this.layoutConfig)));
+
+        if(this.tabPosition == 'top'){
+            this.elements += ',header';
+            this.stripTarget = 'header';
+        }else {
+            this.elements += ',footer';
+            this.stripTarget = 'footer';
+        }
+        if(!this.stack){
+            this.stack = Ext.TabPanel.AccessStack();
+        }
+        this.initItems();
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.TabPanel.superclass.onRender.call(this, ct, position);
+
+        if(this.plain){
+            var pos = this.tabPosition == 'top' ? 'header' : 'footer';
+            this[pos].addClass('x-tab-panel-'+pos+'-plain');
+        }
+
+        var st = this[this.stripTarget];
+
+        this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
+            tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
+
+        var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
+        st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
+        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
+
+        
+        this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
+        this.strip.createChild({cls:'x-clear'});
+
+        this.body.addClass('x-tab-panel-body-'+this.tabPosition);
+
+        
+        if(!this.itemTpl){
+            var tt = new Ext.Template(
+                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
+                 '<a class="x-tab-right" href="#"><em class="x-tab-left">',
+                 '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
+                 '</em></a></li>'
+            );
+            tt.disableFormats = true;
+            tt.compile();
+            Ext.TabPanel.prototype.itemTpl = tt;
+        }
+
+        this.items.each(this.initTab, this);
+    },
+
+    
+    afterRender : function(){
+        Ext.TabPanel.superclass.afterRender.call(this);
+        if(this.autoTabs){
+            this.readTabs(false);
+        }
+        if(this.activeTab !== undefined){
+            var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
+            delete this.activeTab;
+            this.setActiveTab(item);
+        }
+    },
+
+    
+    initEvents : function(){
+        Ext.TabPanel.superclass.initEvents.call(this);
+        this.mon(this.strip, {
+            scope: this,
+            mousedown: this.onStripMouseDown,
+            contextmenu: this.onStripContextMenu
+        });
+        if(this.enableTabScroll){
+            this.mon(this.strip, 'mousewheel', this.onWheel, this);
+        }
+    },
+
+    
+    findTargets : function(e){
+        var item = null,
+            itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
+
+        if(itemEl){
+            item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
+            if(item.disabled){
+                return {
+                    close : null,
+                    item : null,
+                    el : null
+                };
+            }
+        }
+        return {
+            close : e.getTarget('.x-tab-strip-close', this.strip),
+            item : item,
+            el : itemEl
+        };
+    },
+
+    
+    onStripMouseDown : function(e){
+        if(e.button !== 0){
+            return;
+        }
+        e.preventDefault();
+        var t = this.findTargets(e);
+        if(t.close){
+            if (t.item.fireEvent('beforeclose', t.item) !== false) {
+                t.item.fireEvent('close', t.item);
+                this.remove(t.item);
+            }
+            return;
+        }
+        if(t.item && t.item != this.activeTab){
+            this.setActiveTab(t.item);
+        }
+    },
+
+    
+    onStripContextMenu : function(e){
+        e.preventDefault();
+        var t = this.findTargets(e);
+        if(t.item){
+            this.fireEvent('contextmenu', this, t.item, e);
+        }
+    },
+
+    
+    readTabs : function(removeExisting){
+        if(removeExisting === true){
+            this.items.each(function(item){
+                this.remove(item);
+            }, this);
+        }
+        var tabs = this.el.query(this.autoTabSelector);
+        for(var i = 0, len = tabs.length; i < len; i++){
+            var tab = tabs[i],
+                title = tab.getAttribute('title');
+            tab.removeAttribute('title');
+            this.add({
+                title: title,
+                contentEl: tab
+            });
+        }
+    },
+
+    
+    initTab : function(item, index){
+        var before = this.strip.dom.childNodes[index],
+            p = this.getTemplateArgs(item),
+            el = before ?
+                 this.itemTpl.insertBefore(before, p) :
+                 this.itemTpl.append(this.strip, p),
+            cls = 'x-tab-strip-over',
+            tabEl = Ext.get(el);
+
+        tabEl.hover(function(){
+            if(!item.disabled){
+                tabEl.addClass(cls);
+            }
+        }, function(){
+            tabEl.removeClass(cls);
+        });
+
+        if(item.tabTip){
+            tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
+        }
+        item.tabEl = el;
+
+        
+        tabEl.select('a').on('click', function(e){
+            if(!e.getPageX()){
+                this.onStripMouseDown(e);
+            }
+        }, this, {preventDefault: true});
+
+        item.on({
+            scope: this,
+            disable: this.onItemDisabled,
+            enable: this.onItemEnabled,
+            titlechange: this.onItemTitleChanged,
+            iconchange: this.onItemIconChanged,
+            beforeshow: this.onBeforeShowItem
+        });
+    },
+
+
+
+    
+    getTemplateArgs : function(item) {
+        var cls = item.closable ? 'x-tab-strip-closable' : '';
+        if(item.disabled){
+            cls += ' x-item-disabled';
+        }
+        if(item.iconCls){
+            cls += ' x-tab-with-icon';
+        }
+        if(item.tabCls){
+            cls += ' ' + item.tabCls;
+        }
+
+        return {
+            id: this.id + this.idDelimiter + item.getItemId(),
+            text: item.title,
+            cls: cls,
+            iconCls: item.iconCls || ''
+        };
+    },
+
+    
+    onAdd : function(c){
+        Ext.TabPanel.superclass.onAdd.call(this, c);
+        if(this.rendered){
+            var items = this.items;
+            this.initTab(c, items.indexOf(c));
+            this.delegateUpdates();
+        }
+    },
+
+    
+    onBeforeAdd : function(item){
+        var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
+        if(existing){
+            this.setActiveTab(item);
+            return false;
+        }
+        Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
+        var es = item.elements;
+        item.elements = es ? es.replace(',header', '') : es;
+        item.border = (item.border === true);
+    },
+
+    
+    onRemove : function(c){
+        var te = Ext.get(c.tabEl);
+        
+        if(te){
+            te.select('a').removeAllListeners();
+            Ext.destroy(te);
+        }
+        Ext.TabPanel.superclass.onRemove.call(this, c);
+        this.stack.remove(c);
+        delete c.tabEl;
+        c.un('disable', this.onItemDisabled, this);
+        c.un('enable', this.onItemEnabled, this);
+        c.un('titlechange', this.onItemTitleChanged, this);
+        c.un('iconchange', this.onItemIconChanged, this);
+        c.un('beforeshow', this.onBeforeShowItem, this);
+        if(c == this.activeTab){
+            var next = this.stack.next();
+            if(next){
+                this.setActiveTab(next);
+            }else if(this.items.getCount() > 0){
+                this.setActiveTab(0);
+            }else{
+                this.setActiveTab(null);
+            }
+        }
+        if(!this.destroying){
+            this.delegateUpdates();
+        }
+    },
+
+    
+    onBeforeShowItem : function(item){
+        if(item != this.activeTab){
+            this.setActiveTab(item);
+            return false;
+        }
+    },
+
+    
+    onItemDisabled : function(item){
+        var el = this.getTabEl(item);
+        if(el){
+            Ext.fly(el).addClass('x-item-disabled');
+        }
+        this.stack.remove(item);
+    },
+
+    
+    onItemEnabled : function(item){
+        var el = this.getTabEl(item);
+        if(el){
+            Ext.fly(el).removeClass('x-item-disabled');
+        }
+    },
+
+    
+    onItemTitleChanged : function(item){
+        var el = this.getTabEl(item);
+        if(el){
+            Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
+        }
+    },
+
+    
+    onItemIconChanged : function(item, iconCls, oldCls){
+        var el = this.getTabEl(item);
+        if(el){
+            el = Ext.get(el);
+            el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
+            el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
+        }
+    },
+
+    
+    getTabEl : function(item){
+        var c = this.getComponent(item);
+        return c ? c.tabEl : null;
+    },
+
+    
+    onResize : function(){
+        Ext.TabPanel.superclass.onResize.apply(this, arguments);
+        this.delegateUpdates();
+    },
+
+    
+    beginUpdate : function(){
+        this.suspendUpdates = true;
+    },
+
+    
+    endUpdate : function(){
+        this.suspendUpdates = false;
+        this.delegateUpdates();
+    },
+
+    
+    hideTabStripItem : function(item){
+        item = this.getComponent(item);
+        var el = this.getTabEl(item);
+        if(el){
+            el.style.display = 'none';
+            this.delegateUpdates();
+        }
+        this.stack.remove(item);
+    },
+
+    
+    unhideTabStripItem : function(item){
+        item = this.getComponent(item);
+        var el = this.getTabEl(item);
+        if(el){
+            el.style.display = '';
+            this.delegateUpdates();
+        }
+    },
+
+    
+    delegateUpdates : function(){
+        var rendered = this.rendered;
+        if(this.suspendUpdates){
+            return;
+        }
+        if(this.resizeTabs && rendered){
+            this.autoSizeTabs();
+        }
+        if(this.enableTabScroll && rendered){
+            this.autoScrollTabs();
+        }
+    },
+
+    
+    autoSizeTabs : function(){
+        var count = this.items.length,
+            ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
+            ow = this[ce].dom.offsetWidth,
+            aw = this[ce].dom.clientWidth;
+
+        if(!this.resizeTabs || count < 1 || !aw){ 
+            return;
+        }
+
+        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
+        this.lastTabWidth = each;
+        var lis = this.strip.query('li:not(.x-tab-edge)');
+        for(var i = 0, len = lis.length; i < len; i++) {
+            var li = lis[i],
+                inner = Ext.fly(li).child('.x-tab-strip-inner', true),
+                tw = li.offsetWidth,
+                iw = inner.offsetWidth;
+            inner.style.width = (each - (tw-iw)) + 'px';
+        }
+    },
+
+    
+    adjustBodyWidth : function(w){
+        if(this.header){
+            this.header.setWidth(w);
+        }
+        if(this.footer){
+            this.footer.setWidth(w);
+        }
+        return w;
+    },
+
+    
+    setActiveTab : function(item){
+        item = this.getComponent(item);
+        if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
+            return;
+        }
+        if(!this.rendered){
+            this.activeTab = item;
+            return;
+        }
+        if(this.activeTab != item){
+            if(this.activeTab){
+                var oldEl = this.getTabEl(this.activeTab);
+                if(oldEl){
+                    Ext.fly(oldEl).removeClass('x-tab-strip-active');
+                }
+            }
+            this.activeTab = item;
+            if(item){
+                var el = this.getTabEl(item);
+                Ext.fly(el).addClass('x-tab-strip-active');
+                this.stack.add(item);
+
+                this.layout.setActiveItem(item);
+                
+                this.delegateUpdates();
+                if(this.scrolling){
+                    this.scrollToTab(item, this.animScroll);
+                }
+            }
+            this.fireEvent('tabchange', this, item);
+        }
+    },
+
+    
+    getActiveTab : function(){
+        return this.activeTab || null;
+    },
+
+    
+    getItem : function(item){
+        return this.getComponent(item);
+    },
+
+    
+    autoScrollTabs : function(){
+        this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
+        var count = this.items.length,
+            ow = this.pos.dom.offsetWidth,
+            tw = this.pos.dom.clientWidth,
+            wrap = this.stripWrap,
+            wd = wrap.dom,
+            cw = wd.offsetWidth,
+            pos = this.getScrollPos(),
+            l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
+
+        if(!this.enableTabScroll || cw < 20){ 
+            return;
+        }
+        if(count == 0 || l <= tw){
+            
+            wd.scrollLeft = 0;
+            wrap.setWidth(tw);
+            if(this.scrolling){
+                this.scrolling = false;
+                this.pos.removeClass('x-tab-scrolling');
+                this.scrollLeft.hide();
+                this.scrollRight.hide();
+                
+                if(Ext.isAir || Ext.isWebKit){
+                    wd.style.marginLeft = '';
+                    wd.style.marginRight = '';
+                }
+            }
+        }else{
+            if(!this.scrolling){
+                this.pos.addClass('x-tab-scrolling');
+                
+                if(Ext.isAir || Ext.isWebKit){
+                    wd.style.marginLeft = '18px';
+                    wd.style.marginRight = '18px';
+                }
+            }
+            tw -= wrap.getMargins('lr');
+            wrap.setWidth(tw > 20 ? tw : 20);
+            if(!this.scrolling){
+                if(!this.scrollLeft){
+                    this.createScrollers();
+                }else{
+                    this.scrollLeft.show();
+                    this.scrollRight.show();
+                }
+            }
+            this.scrolling = true;
+            if(pos > (l-tw)){ 
+                wd.scrollLeft = l-tw;
+            }else{ 
+                this.scrollToTab(this.activeTab, false);
+            }
+            this.updateScrollButtons();
+        }
+    },
+
+    
+    createScrollers : function(){
+        this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
+        var h = this.stripWrap.dom.offsetHeight;
+
+        
+        var sl = this.pos.insertFirst({
+            cls:'x-tab-scroller-left'
+        });
+        sl.setHeight(h);
+        sl.addClassOnOver('x-tab-scroller-left-over');
+        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
+            interval : this.scrollRepeatInterval,
+            handler: this.onScrollLeft,
+            scope: this
+        });
+        this.scrollLeft = sl;
+
+        
+        var sr = this.pos.insertFirst({
+            cls:'x-tab-scroller-right'
+        });
+        sr.setHeight(h);
+        sr.addClassOnOver('x-tab-scroller-right-over');
+        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
+            interval : this.scrollRepeatInterval,
+            handler: this.onScrollRight,
+            scope: this
+        });
+        this.scrollRight = sr;
+    },
+
+    
+    getScrollWidth : function(){
+        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
+    },
+
+    
+    getScrollPos : function(){
+        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
+    },
+
+    
+    getScrollArea : function(){
+        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
+    },
+
+    
+    getScrollAnim : function(){
+        return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
+    },
+
+    
+    getScrollIncrement : function(){
+        return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
+    },
+
+    
+
+    scrollToTab : function(item, animate){
+        if(!item){
+            return;
+        }
+        var el = this.getTabEl(item),
+            pos = this.getScrollPos(),
+            area = this.getScrollArea(),
+            left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
+            right = left + el.offsetWidth;
+        if(left < pos){
+            this.scrollTo(left, animate);
+        }else if(right > (pos + area)){
+            this.scrollTo(right - area, animate);
+        }
+    },
+
+    
+    scrollTo : function(pos, animate){
+        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
+        if(!animate){
+            this.updateScrollButtons();
+        }
+    },
+
+    onWheel : function(e){
+        var d = e.getWheelDelta()*this.wheelIncrement*-1;
+        e.stopEvent();
+
+        var pos = this.getScrollPos(),
+            newpos = pos + d,
+            sw = this.getScrollWidth()-this.getScrollArea();
+
+        var s = Math.max(0, Math.min(sw, newpos));
+        if(s != pos){
+            this.scrollTo(s, false);
+        }
+    },
+
+    
+    onScrollRight : function(){
+        var sw = this.getScrollWidth()-this.getScrollArea(),
+            pos = this.getScrollPos(),
+            s = Math.min(sw, pos + this.getScrollIncrement());
+        if(s != pos){
+            this.scrollTo(s, this.animScroll);
+        }
+    },
+
+    
+    onScrollLeft : function(){
+        var pos = this.getScrollPos(),
+            s = Math.max(0, pos - this.getScrollIncrement());
+        if(s != pos){
+            this.scrollTo(s, this.animScroll);
+        }
+    },
+
+    
+    updateScrollButtons : function(){
+        var pos = this.getScrollPos();
+        this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
+        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
+    },
+
+    
+    beforeDestroy : function() {
+        Ext.destroy(this.leftRepeater, this.rightRepeater);
+        this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
+        this.activeTab = null;
+        Ext.TabPanel.superclass.beforeDestroy.apply(this);
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+});
+Ext.reg('tabpanel', Ext.TabPanel);
+
+
+Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
+
+
+Ext.TabPanel.AccessStack = function(){
+    var items = [];
+    return {
+        add : function(item){
+            items.push(item);
+            if(items.length > 10){
+                items.shift();
+            }
+        },
+
+        remove : function(item){
+            var s = [];
+            for(var i = 0, len = items.length; i < len; i++) {
+                if(items[i] != item){
+                    s.push(items[i]);
+                }
+            }
+            items = s;
+        },
+
+        next : function(){
+            return items.pop();
+        }
+    };
+};
+
+Ext.Button = Ext.extend(Ext.BoxComponent, {
+    
+    hidden : false,
+    
+    disabled : false,
+    
+    pressed : false,
+
+    
+
+    
+
+    
+    enableToggle : false,
+    
+    
+    
+    menuAlign : 'tl-bl?',
+
+    
+    
+    
+    type : 'button',
+
+    
+    menuClassTarget : 'tr:nth(2)',
+
+    
+    clickEvent : 'click',
+
+    
+    handleMouseEvents : true,
+
+    
+    tooltipType : 'qtip',
+
+    
+    buttonSelector : 'button:first-child',
+
+    
+    scale : 'small',
+
+    
+
+    
+    iconAlign : 'left',
+
+    
+    arrowAlign : 'right',
+
+    
+    
+    
+    
+
+    initComponent : function(){
+        if(this.menu){
+            
+            
+            if (Ext.isArray(this.menu)){
+                this.menu = { items: this.menu };
+            }
+            
+            
+            
+            if (Ext.isObject(this.menu)){
+                this.menu.ownerCt = this;
+            }
+            
+            this.menu = Ext.menu.MenuMgr.get(this.menu);
+            this.menu.ownerCt = undefined;
+        }
+        
+        Ext.Button.superclass.initComponent.call(this);
+
+        this.addEvents(
+            
+            'click',
+            
+            'toggle',
+            
+            'mouseover',
+            
+            'mouseout',
+            
+            'menushow',
+            
+            'menuhide',
+            
+            'menutriggerover',
+            
+            'menutriggerout'
+        );
+        
+        if(Ext.isString(this.toggleGroup)){
+            this.enableToggle = true;
+        }
+    },
+
+
+    getTemplateArgs : function(){
+        return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
+    },
+
+    
+    setButtonClass : function(){
+        if(this.useSetClass){
+            if(!Ext.isEmpty(this.oldCls)){
+                this.el.removeClass([this.oldCls, 'x-btn-pressed']);
+            }
+            this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
+            this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
+        }
+    },
+
+    
+    getMenuClass : function(){
+        return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
+    },
+
+    
+    onRender : function(ct, position){
+        if(!this.template){
+            if(!Ext.Button.buttonTemplate){
+                
+                Ext.Button.buttonTemplate = new Ext.Template(
+                    '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
+                    '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
+                    '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
+                    '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
+                    '</tbody></table>');
+                Ext.Button.buttonTemplate.compile();
+            }
+            this.template = Ext.Button.buttonTemplate;
+        }
+
+        var btn, targs = this.getTemplateArgs();
+
+        if(position){
+            btn = this.template.insertBefore(position, targs, true);
+        }else{
+            btn = this.template.append(ct, targs, true);
+        }
+        
+        this.btnEl = btn.child(this.buttonSelector);
+        this.mon(this.btnEl, {
+            scope: this,
+            focus: this.onFocus,
+            blur: this.onBlur
+        });
+
+        this.initButtonEl(btn, this.btnEl);
+
+        Ext.ButtonToggleMgr.register(this);
+    },
+
+    
+    initButtonEl : function(btn, btnEl){
+        this.el = btn;
+        this.setIcon(this.icon);
+        this.setText(this.text);
+        this.setIconClass(this.iconCls);
+        if(Ext.isDefined(this.tabIndex)){
+            btnEl.dom.tabIndex = this.tabIndex;
+        }
+        if(this.tooltip){
+            this.setTooltip(this.tooltip, true);
+        }
+
+        if(this.handleMouseEvents){
+            this.mon(btn, {
+                scope: this,
+                mouseover: this.onMouseOver,
+                mousedown: this.onMouseDown
+            });
+
+            
+            
+        }
+
+        if(this.menu){
+            this.mon(this.menu, {
+                scope: this,
+                show: this.onMenuShow,
+                hide: this.onMenuHide
+            });
+        }
+
+        if(this.repeat){
+            var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
+            this.mon(repeater, 'click', this.onRepeatClick, this);
+        }else{
+            this.mon(btn, this.clickEvent, this.onClick, this);
+        }
+    },
+
+    
+    afterRender : function(){
+        Ext.Button.superclass.afterRender.call(this);
+        this.useSetClass = true;
+        this.setButtonClass();
+        this.doc = Ext.getDoc();
+        this.doAutoWidth();
+    },
+
+    
+    setIconClass : function(cls){
+        this.iconCls = cls;
+        if(this.el){
+            this.btnEl.dom.className = '';
+            this.btnEl.addClass(['x-btn-text', cls || '']);
+            this.setButtonClass();
+        }
+        return this;
+    },
+
+    
+    setTooltip : function(tooltip,  initial){
+        if(this.rendered){
+            if(!initial){
+                this.clearTip();
+            }
+            if(Ext.isObject(tooltip)){
+                Ext.QuickTips.register(Ext.apply({
+                      target: this.btnEl.id
+                }, tooltip));
+                this.tooltip = tooltip;
+            }else{
+                this.btnEl.dom[this.tooltipType] = tooltip;
+            }
+        }else{
+            this.tooltip = tooltip;
+        }
+        return this;
+    },
+
+    
+    clearTip : function(){
+        if(Ext.isObject(this.tooltip)){
+            Ext.QuickTips.unregister(this.btnEl);
+        }
+    },
+
+    
+    beforeDestroy : function(){
+        if(this.rendered){
+            this.clearTip();
+        }
+        if(this.menu && this.destroyMenu !== false) {
+            Ext.destroy(this.btnEl, this.menu);
+        }
+        Ext.destroy(this.repeater);
+    },
+
+    
+    onDestroy : function(){
+        if(this.rendered){
+            this.doc.un('mouseover', this.monitorMouseOver, this);
+            this.doc.un('mouseup', this.onMouseUp, this);
+            delete this.doc;
+            delete this.btnEl;
+            Ext.ButtonToggleMgr.unregister(this);
+        }
+        Ext.Button.superclass.onDestroy.call(this);
+    },
+
+    
+    doAutoWidth : function(){
+        if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
+            this.el.setWidth('auto');
+            if(Ext.isIE7 && Ext.isStrict){
+                var ib = this.btnEl;
+                if(ib && ib.getWidth() > 20){
+                    ib.clip();
+                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
+                }
+            }
+            if(this.minWidth){
+                if(this.el.getWidth() < this.minWidth){
+                    this.el.setWidth(this.minWidth);
+                }
+            }
+        }
+    },
+
+    
+    setHandler : function(handler, scope){
+        this.handler = handler;
+        this.scope = scope;
+        return this;
+    },
+
+    
+    setText : function(text){
+        this.text = text;
+        if(this.el){
+            this.btnEl.update(text || '&#160;');
+            this.setButtonClass();
+        }
+        this.doAutoWidth();
+        return this;
+    },
+
+    
+    setIcon : function(icon){
+        this.icon = icon;
+        if(this.el){
+            this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
+            this.setButtonClass();
+        }
+        return this;
+    },
+
+    
+    getText : function(){
+        return this.text;
+    },
+
+    
+    toggle : function(state, suppressEvent){
+        state = state === undefined ? !this.pressed : !!state;
+        if(state != this.pressed){
+            if(this.rendered){
+                this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
+            }
+            this.pressed = state;
+            if(!suppressEvent){
+                this.fireEvent('toggle', this, state);
+                if(this.toggleHandler){
+                    this.toggleHandler.call(this.scope || this, this, state);
+                }
+            }
+        }
+        return this;
+    },
+
+    
+    onDisable : function(){
+        this.onDisableChange(true);
+    },
+
+    
+    onEnable : function(){
+        this.onDisableChange(false);
+    },
+
+    onDisableChange : function(disabled){
+        if(this.el){
+            if(!Ext.isIE6 || !this.text){
+                this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
+            }
+            this.el.dom.disabled = disabled;
+        }
+        this.disabled = disabled;
+    },
+
+    
+    showMenu : function(){
+        if(this.rendered && this.menu){
+            if(this.tooltip){
+                Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
+            }
+            if(this.menu.isVisible()){
+                this.menu.hide();
+            }
+            this.menu.ownerCt = this;
+            this.menu.show(this.el, this.menuAlign);
+        }
+        return this;
+    },
+
+    
+    hideMenu : function(){
+        if(this.hasVisibleMenu()){
+            this.menu.hide();
+        }
+        return this;
+    },
+
+    
+    hasVisibleMenu : function(){
+        return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
+    },
+    
+    
+    onRepeatClick : function(repeat, e){
+        this.onClick(e);
+    },
+
+    
+    onClick : function(e){
+        if(e){
+            e.preventDefault();
+        }
+        if(e.button !== 0){
+            return;
+        }
+        if(!this.disabled){
+            this.doToggle();
+            if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
+                this.showMenu();
+            }
+            this.fireEvent('click', this, e);
+            if(this.handler){
+                
+                this.handler.call(this.scope || this, this, e);
+            }
+        }
+    },
+    
+    
+    doToggle: function(){
+        if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {
+            this.toggle();
+        }
+    },
+
+    
+    isMenuTriggerOver : function(e, internal){
+        return this.menu && !internal;
+    },
+
+    
+    isMenuTriggerOut : function(e, internal){
+        return this.menu && !internal;
+    },
+
+    
+    onMouseOver : function(e){
+        if(!this.disabled){
+            var internal = e.within(this.el,  true);
+            if(!internal){
+                this.el.addClass('x-btn-over');
+                if(!this.monitoringMouseOver){
+                    this.doc.on('mouseover', this.monitorMouseOver, this);
+                    this.monitoringMouseOver = true;
+                }
+                this.fireEvent('mouseover', this, e);
+            }
+            if(this.isMenuTriggerOver(e, internal)){
+                this.fireEvent('menutriggerover', this, this.menu, e);
+            }
+        }
+    },
+
+    
+    monitorMouseOver : function(e){
+        if(e.target != this.el.dom && !e.within(this.el)){
+            if(this.monitoringMouseOver){
+                this.doc.un('mouseover', this.monitorMouseOver, this);
+                this.monitoringMouseOver = false;
+            }
+            this.onMouseOut(e);
+        }
+    },
+
+    
+    onMouseOut : function(e){
+        var internal = e.within(this.el) && e.target != this.el.dom;
+        this.el.removeClass('x-btn-over');
+        this.fireEvent('mouseout', this, e);
+        if(this.isMenuTriggerOut(e, internal)){
+            this.fireEvent('menutriggerout', this, this.menu, e);
+        }
+    },
+
+    focus : function() {
+        this.btnEl.focus();
+    },
+
+    blur : function() {
+        this.btnEl.blur();
+    },
+
+    
+    onFocus : function(e){
+        if(!this.disabled){
+            this.el.addClass('x-btn-focus');
+        }
+    },
+    
+    onBlur : function(e){
+        this.el.removeClass('x-btn-focus');
+    },
+
+    
+    getClickEl : function(e, isUp){
+       return this.el;
+    },
+
+    
+    onMouseDown : function(e){
+        if(!this.disabled && e.button === 0){
+            this.getClickEl(e).addClass('x-btn-click');
+            this.doc.on('mouseup', this.onMouseUp, this);
+        }
+    },
+    
+    onMouseUp : function(e){
+        if(e.button === 0){
+            this.getClickEl(e, true).removeClass('x-btn-click');
+            this.doc.un('mouseup', this.onMouseUp, this);
+        }
+    },
+    
+    onMenuShow : function(e){
+        if(this.menu.ownerCt == this){
+            this.menu.ownerCt = this;
+            this.ignoreNextClick = 0;
+            this.el.addClass('x-btn-menu-active');
+            this.fireEvent('menushow', this, this.menu);
+        }
+    },
+    
+    onMenuHide : function(e){
+        if(this.menu.ownerCt == this){
+            this.el.removeClass('x-btn-menu-active');
+            this.ignoreNextClick = this.restoreClick.defer(250, this);
+            this.fireEvent('menuhide', this, this.menu);
+            delete this.menu.ownerCt;
+        }
+    },
+
+    
+    restoreClick : function(){
+        this.ignoreNextClick = 0;
+    }
+
+    
+    
+    
+    
+    
+    
+});
+Ext.reg('button', Ext.Button);
+
+
+Ext.ButtonToggleMgr = function(){
+   var groups = {};
+
+   function toggleGroup(btn, state){
+       if(state){
+           var g = groups[btn.toggleGroup];
+           for(var i = 0, l = g.length; i < l; i++){
+               if(g[i] != btn){
+                   g[i].toggle(false);
+               }
+           }
+       }
+   }
+
+   return {
+       register : function(btn){
+           if(!btn.toggleGroup){
+               return;
+           }
+           var g = groups[btn.toggleGroup];
+           if(!g){
+               g = groups[btn.toggleGroup] = [];
+           }
+           g.push(btn);
+           btn.on('toggle', toggleGroup);
+       },
+
+       unregister : function(btn){
+           if(!btn.toggleGroup){
+               return;
+           }
+           var g = groups[btn.toggleGroup];
+           if(g){
+               g.remove(btn);
+               btn.un('toggle', toggleGroup);
+           }
+       },
+
+       
+       getPressed : function(group){
+           var g = groups[group];
+           if(g){
+               for(var i = 0, len = g.length; i < len; i++){
+                   if(g[i].pressed === true){
+                       return g[i];
+                   }
+               }
+           }
+           return null;
+       }
+   };
+}();
+
+Ext.SplitButton = Ext.extend(Ext.Button, {
+	
+    arrowSelector : 'em',
+    split: true,
+
+    
+    initComponent : function(){
+        Ext.SplitButton.superclass.initComponent.call(this);
+        
+        this.addEvents("arrowclick");
+    },
+
+    
+    onRender : function(){
+        Ext.SplitButton.superclass.onRender.apply(this, arguments);
+        if(this.arrowTooltip){
+            this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
+        }
+    },
+
+    
+    setArrowHandler : function(handler, scope){
+        this.arrowHandler = handler;
+        this.scope = scope;
+    },
+
+    getMenuClass : function(){
+        return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
+    },
+
+    isClickOnArrow : function(e){
+	if (this.arrowAlign != 'bottom') {
+	    var visBtn = this.el.child('em.x-btn-split');
+	    var right = visBtn.getRegion().right - visBtn.getPadding('r');
+	    return e.getPageX() > right;
+	} else {
+	    return e.getPageY() > this.btnEl.getRegion().bottom;
+	}
+    },
+
+    
+    onClick : function(e, t){
+        e.preventDefault();
+        if(!this.disabled){
+            if(this.isClickOnArrow(e)){
+                if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
+                    this.showMenu();
+                }
+                this.fireEvent("arrowclick", this, e);
+                if(this.arrowHandler){
+                    this.arrowHandler.call(this.scope || this, this, e);
+                }
+            }else{
+                this.doToggle();
+                this.fireEvent("click", this, e);
+                if(this.handler){
+                    this.handler.call(this.scope || this, this, e);
+                }
+            }
+        }
+    },
+
+    
+    isMenuTriggerOver : function(e){
+        return this.menu && e.target.tagName == this.arrowSelector;
+    },
+
+    
+    isMenuTriggerOut : function(e, internal){
+        return this.menu && e.target.tagName != this.arrowSelector;
+    }
+});
+
+Ext.reg('splitbutton', Ext.SplitButton);
+Ext.CycleButton = Ext.extend(Ext.SplitButton, {
+    
+    
+    
+    
+    
+    
+
+    
+    getItemText : function(item){
+        if(item && this.showText === true){
+            var text = '';
+            if(this.prependText){
+                text += this.prependText;
+            }
+            text += item.text;
+            return text;
+        }
+        return undefined;
+    },
+
+    
+    setActiveItem : function(item, suppressEvent){
+        if(!Ext.isObject(item)){
+            item = this.menu.getComponent(item);
+        }
+        if(item){
+            if(!this.rendered){
+                this.text = this.getItemText(item);
+                this.iconCls = item.iconCls;
+            }else{
+                var t = this.getItemText(item);
+                if(t){
+                    this.setText(t);
+                }
+                this.setIconClass(item.iconCls);
+            }
+            this.activeItem = item;
+            if(!item.checked){
+                item.setChecked(true, suppressEvent);
+            }
+            if(this.forceIcon){
+                this.setIconClass(this.forceIcon);
+            }
+            if(!suppressEvent){
+                this.fireEvent('change', this, item);
+            }
+        }
+    },
+
+    
+    getActiveItem : function(){
+        return this.activeItem;
+    },
+
+    
+    initComponent : function(){
+        this.addEvents(
+            
+            "change"
+        );
+
+        if(this.changeHandler){
+            this.on('change', this.changeHandler, this.scope||this);
+            delete this.changeHandler;
+        }
+
+        this.itemCount = this.items.length;
+
+        this.menu = {cls:'x-cycle-menu', items:[]};
+        var checked = 0;
+        Ext.each(this.items, function(item, i){
+            Ext.apply(item, {
+                group: item.group || this.id,
+                itemIndex: i,
+                checkHandler: this.checkHandler,
+                scope: this,
+                checked: item.checked || false
+            });
+            this.menu.items.push(item);
+            if(item.checked){
+                checked = i;
+            }
+        }, this);
+        Ext.CycleButton.superclass.initComponent.call(this);
+        this.on('click', this.toggleSelected, this);
+        this.setActiveItem(checked, true);
+    },
+
+    
+    checkHandler : function(item, pressed){
+        if(pressed){
+            this.setActiveItem(item);
+        }
+    },
+
+    
+    toggleSelected : function(){
+        var m = this.menu;
+        m.render();
+        
+        if(!m.hasLayout){
+            m.doLayout();
+        }
+        
+        var nextIdx, checkItem;
+        for (var i = 1; i < this.itemCount; i++) {
+            nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
+            
+            checkItem = m.items.itemAt(nextIdx);
+            
+            if (!checkItem.disabled) {
+                checkItem.setChecked(true);
+                break;
+            }
+        }
+    }
+});
+Ext.reg('cycle', Ext.CycleButton);
+Ext.Toolbar = function(config){
+    if(Ext.isArray(config)){
+        config = {items: config, layout: 'toolbar'};
+    } else {
+        config = Ext.apply({
+            layout: 'toolbar'
+        }, config);
+        if(config.buttons) {
+            config.items = config.buttons;
+        }
+    }
+    Ext.Toolbar.superclass.constructor.call(this, config);
+};
+
+(function(){
+
+var T = Ext.Toolbar;
+
+Ext.extend(T, Ext.Container, {
+
+    defaultType: 'button',
+
+    
+
+    enableOverflow : false,
+
+    
+    
+
+    trackMenus : true,
+    internalDefaults: {removeMode: 'container', hideParent: true},
+    toolbarCls: 'x-toolbar',
+
+    initComponent : function(){
+        T.superclass.initComponent.call(this);
+
+        
+        this.addEvents('overflowchange');
+    },
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            if(!this.autoCreate){
+                this.autoCreate = {
+                    cls: this.toolbarCls + ' x-small-editor'
+                };
+            }
+            this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
+            Ext.Toolbar.superclass.onRender.apply(this, arguments);
+        }
+    },
+
+    
+
+    
+    lookupComponent : function(c){
+        if(Ext.isString(c)){
+            if(c == '-'){
+                c = new T.Separator();
+            }else if(c == ' '){
+                c = new T.Spacer();
+            }else if(c == '->'){
+                c = new T.Fill();
+            }else{
+                c = new T.TextItem(c);
+            }
+            this.applyDefaults(c);
+        }else{
+            if(c.isFormField || c.render){ 
+                c = this.createComponent(c);
+            }else if(c.tag){ 
+                c = new T.Item({autoEl: c});
+            }else if(c.tagName){ 
+                c = new T.Item({el:c});
+            }else if(Ext.isObject(c)){ 
+                c = c.xtype ? this.createComponent(c) : this.constructButton(c);
+            }
+        }
+        return c;
+    },
+
+    
+    applyDefaults : function(c){
+        if(!Ext.isString(c)){
+            c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
+            var d = this.internalDefaults;
+            if(c.events){
+                Ext.applyIf(c.initialConfig, d);
+                Ext.apply(c, d);
+            }else{
+                Ext.applyIf(c, d);
+            }
+        }
+        return c;
+    },
+
+    
+    addSeparator : function(){
+        return this.add(new T.Separator());
+    },
+
+    
+    addSpacer : function(){
+        return this.add(new T.Spacer());
+    },
+
+    
+    addFill : function(){
+        this.add(new T.Fill());
+    },
+
+    
+    addElement : function(el){
+        return this.addItem(new T.Item({el:el}));
+    },
+
+    
+    addItem : function(item){
+        return this.add.apply(this, arguments);
+    },
+
+    
+    addButton : function(config){
+        if(Ext.isArray(config)){
+            var buttons = [];
+            for(var i = 0, len = config.length; i < len; i++) {
+                buttons.push(this.addButton(config[i]));
+            }
+            return buttons;
+        }
+        return this.add(this.constructButton(config));
+    },
+
+    
+    addText : function(text){
+        return this.addItem(new T.TextItem(text));
+    },
+
+    
+    addDom : function(config){
+        return this.add(new T.Item({autoEl: config}));
+    },
+
+    
+    addField : function(field){
+        return this.add(field);
+    },
+
+    
+    insertButton : function(index, item){
+        if(Ext.isArray(item)){
+            var buttons = [];
+            for(var i = 0, len = item.length; i < len; i++) {
+               buttons.push(this.insertButton(index + i, item[i]));
+            }
+            return buttons;
+        }
+        return Ext.Toolbar.superclass.insert.call(this, index, item);
+    },
+
+    
+    trackMenu : function(item, remove){
+        if(this.trackMenus && item.menu){
+            var method = remove ? 'mun' : 'mon';
+            this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
+            this[method](item, 'menushow', this.onButtonMenuShow, this);
+            this[method](item, 'menuhide', this.onButtonMenuHide, this);
+        }
+    },
+
+    
+    constructButton : function(item){
+        var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
+        return b;
+    },
+
+    
+    onAdd : function(c){
+        Ext.Toolbar.superclass.onAdd.call(this);
+        this.trackMenu(c);
+        if(this.disabled){
+            c.disable();
+        }
+    },
+
+    
+    onRemove : function(c){
+        Ext.Toolbar.superclass.onRemove.call(this);
+        if (c == this.activeMenuBtn) {
+            delete this.activeMenuBtn;
+        }
+        this.trackMenu(c, true);
+    },
+
+    
+    onDisable : function(){
+        this.items.each(function(item){
+             if(item.disable){
+                 item.disable();
+             }
+        });
+    },
+
+    
+    onEnable : function(){
+        this.items.each(function(item){
+             if(item.enable){
+                 item.enable();
+             }
+        });
+    },
+
+    
+    onButtonTriggerOver : function(btn){
+        if(this.activeMenuBtn && this.activeMenuBtn != btn){
+            this.activeMenuBtn.hideMenu();
+            btn.showMenu();
+            this.activeMenuBtn = btn;
+        }
+    },
+
+    
+    onButtonMenuShow : function(btn){
+        this.activeMenuBtn = btn;
+    },
+
+    
+    onButtonMenuHide : function(btn){
+        delete this.activeMenuBtn;
+    }
+});
+Ext.reg('toolbar', Ext.Toolbar);
+
+
+T.Item = Ext.extend(Ext.BoxComponent, {
+    hideParent: true, 
+    enable:Ext.emptyFn,
+    disable:Ext.emptyFn,
+    focus:Ext.emptyFn
+    
+});
+Ext.reg('tbitem', T.Item);
+
+
+T.Separator = Ext.extend(T.Item, {
+    onRender : function(ct, position){
+        this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
+    }
+});
+Ext.reg('tbseparator', T.Separator);
+
+
+T.Spacer = Ext.extend(T.Item, {
+    
+
+    onRender : function(ct, position){
+        this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
+    }
+});
+Ext.reg('tbspacer', T.Spacer);
+
+
+T.Fill = Ext.extend(T.Item, {
+    
+    render : Ext.emptyFn,
+    isFill : true
+});
+Ext.reg('tbfill', T.Fill);
+
+
+T.TextItem = Ext.extend(T.Item, {
+    
+
+    constructor: function(config){
+        T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
+    },
+
+    
+    onRender : function(ct, position) {
+        this.autoEl = {cls: 'xtb-text', html: this.text || ''};
+        T.TextItem.superclass.onRender.call(this, ct, position);
+    },
+
+    
+    setText : function(t) {
+        if(this.rendered){
+            this.el.update(t);
+        }else{
+            this.text = t;
+        }
+    }
+});
+Ext.reg('tbtext', T.TextItem);
+
+
+T.Button = Ext.extend(Ext.Button, {});
+T.SplitButton = Ext.extend(Ext.SplitButton, {});
+Ext.reg('tbbutton', T.Button);
+Ext.reg('tbsplit', T.SplitButton);
+
+})();
+
+Ext.ButtonGroup = Ext.extend(Ext.Panel, {
+    
+    
+    baseCls: 'x-btn-group',
+    
+    layout:'table',
+    defaultType: 'button',
+    
+    frame: true,
+    internalDefaults: {removeMode: 'container', hideParent: true},
+
+    initComponent : function(){
+        this.layoutConfig = this.layoutConfig || {};
+        Ext.applyIf(this.layoutConfig, {
+            columns : this.columns
+        });
+        if(!this.title){
+            this.addClass('x-btn-group-notitle');
+        }
+        this.on('afterlayout', this.onAfterLayout, this);
+        Ext.ButtonGroup.superclass.initComponent.call(this);
+    },
+
+    applyDefaults : function(c){
+        c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
+        var d = this.internalDefaults;
+        if(c.events){
+            Ext.applyIf(c.initialConfig, d);
+            Ext.apply(c, d);
+        }else{
+            Ext.applyIf(c, d);
+        }
+        return c;
+    },
+
+    onAfterLayout : function(){
+        var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
+        this.body.setWidth(bodyWidth);
+        this.el.setWidth(bodyWidth + this.getFrameWidth());
+    }
+    
+});
+
+Ext.reg('buttongroup', Ext.ButtonGroup);
+
+(function() {
+
+var T = Ext.Toolbar;
+
+Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
+    
+    
+    
+    pageSize : 20,
+    
+    
+    displayMsg : 'Displaying {0} - {1} of {2}',
+    
+    emptyMsg : 'No data to display',
+    
+    beforePageText : 'Page',
+    
+    afterPageText : 'of {0}',
+    
+    firstText : 'First Page',
+    
+    prevText : 'Previous Page',
+    
+    nextText : 'Next Page',
+    
+    lastText : 'Last Page',
+    
+    refreshText : 'Refresh',
+
+    
+
+    
+
+    
+
+    initComponent : function(){
+        var pagingItems = [this.first = new T.Button({
+            tooltip: this.firstText,
+            overflowText: this.firstText,
+            iconCls: 'x-tbar-page-first',
+            disabled: true,
+            handler: this.moveFirst,
+            scope: this
+        }), this.prev = new T.Button({
+            tooltip: this.prevText,
+            overflowText: this.prevText,
+            iconCls: 'x-tbar-page-prev',
+            disabled: true,
+            handler: this.movePrevious,
+            scope: this
+        }), '-', this.beforePageText,
+        this.inputItem = new Ext.form.NumberField({
+            cls: 'x-tbar-page-number',
+            allowDecimals: false,
+            allowNegative: false,
+            enableKeyEvents: true,
+            selectOnFocus: true,
+            submitValue: false,
+            listeners: {
+                scope: this,
+                keydown: this.onPagingKeyDown,
+                blur: this.onPagingBlur
+            }
+        }), this.afterTextItem = new T.TextItem({
+            text: String.format(this.afterPageText, 1)
+        }), '-', this.next = new T.Button({
+            tooltip: this.nextText,
+            overflowText: this.nextText,
+            iconCls: 'x-tbar-page-next',
+            disabled: true,
+            handler: this.moveNext,
+            scope: this
+        }), this.last = new T.Button({
+            tooltip: this.lastText,
+            overflowText: this.lastText,
+            iconCls: 'x-tbar-page-last',
+            disabled: true,
+            handler: this.moveLast,
+            scope: this
+        }), '-', this.refresh = new T.Button({
+            tooltip: this.refreshText,
+            overflowText: this.refreshText,
+            iconCls: 'x-tbar-loading',
+            handler: this.doRefresh,
+            scope: this
+        })];
+
+
+        var userItems = this.items || this.buttons || [];
+        if (this.prependButtons) {
+            this.items = userItems.concat(pagingItems);
+        }else{
+            this.items = pagingItems.concat(userItems);
+        }
+        delete this.buttons;
+        if(this.displayInfo){
+            this.items.push('->');
+            this.items.push(this.displayItem = new T.TextItem({}));
+        }
+        Ext.PagingToolbar.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'change',
+            
+            'beforechange'
+        );
+        this.on('afterlayout', this.onFirstLayout, this, {single: true});
+        this.cursor = 0;
+        this.bindStore(this.store, true);
+    },
+
+    
+    onFirstLayout : function(){
+        if(this.dsLoaded){
+            this.onLoad.apply(this, this.dsLoaded);
+        }
+    },
+
+    
+    updateInfo : function(){
+        if(this.displayItem){
+            var count = this.store.getCount();
+            var msg = count == 0 ?
+                this.emptyMsg :
+                String.format(
+                    this.displayMsg,
+                    this.cursor+1, this.cursor+count, this.store.getTotalCount()
+                );
+            this.displayItem.setText(msg);
+        }
+    },
+
+    
+    onLoad : function(store, r, o){
+        if(!this.rendered){
+            this.dsLoaded = [store, r, o];
+            return;
+        }
+        var p = this.getParams();
+        this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
+        var d = this.getPageData(), ap = d.activePage, ps = d.pages;
+
+        this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
+        this.inputItem.setValue(ap);
+        this.first.setDisabled(ap == 1);
+        this.prev.setDisabled(ap == 1);
+        this.next.setDisabled(ap == ps);
+        this.last.setDisabled(ap == ps);
+        this.refresh.enable();
+        this.updateInfo();
+        this.fireEvent('change', this, d);
+    },
+
+    
+    getPageData : function(){
+        var total = this.store.getTotalCount();
+        return {
+            total : total,
+            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
+            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
+        };
+    },
+
+    
+    changePage : function(page){
+        this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
+    },
+
+    
+    onLoadError : function(){
+        if(!this.rendered){
+            return;
+        }
+        this.refresh.enable();
+    },
+
+    
+    readPage : function(d){
+        var v = this.inputItem.getValue(), pageNum;
+        if (!v || isNaN(pageNum = parseInt(v, 10))) {
+            this.inputItem.setValue(d.activePage);
+            return false;
+        }
+        return pageNum;
+    },
+
+    onPagingFocus : function(){
+        this.inputItem.select();
+    },
+
+    
+    onPagingBlur : function(e){
+        this.inputItem.setValue(this.getPageData().activePage);
+    },
+
+    
+    onPagingKeyDown : function(field, e){
+        var k = e.getKey(), d = this.getPageData(), pageNum;
+        if (k == e.RETURN) {
+            e.stopEvent();
+            pageNum = this.readPage(d);
+            if(pageNum !== false){
+                pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
+                this.doLoad(pageNum * this.pageSize);
+            }
+        }else if (k == e.HOME || k == e.END){
+            e.stopEvent();
+            pageNum = k == e.HOME ? 1 : d.pages;
+            field.setValue(pageNum);
+        }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
+            e.stopEvent();
+            if((pageNum = this.readPage(d))){
+                var increment = e.shiftKey ? 10 : 1;
+                if(k == e.DOWN || k == e.PAGEDOWN){
+                    increment *= -1;
+                }
+                pageNum += increment;
+                if(pageNum >= 1 & pageNum <= d.pages){
+                    field.setValue(pageNum);
+                }
+            }
+        }
+    },
+
+    
+    getParams : function(){
+        
+        return this.paramNames || this.store.paramNames;
+    },
+
+    
+    beforeLoad : function(){
+        if(this.rendered && this.refresh){
+            this.refresh.disable();
+        }
+    },
+
+    
+    doLoad : function(start){
+        var o = {}, pn = this.getParams();
+        o[pn.start] = start;
+        o[pn.limit] = this.pageSize;
+        if(this.fireEvent('beforechange', this, o) !== false){
+            this.store.load({params:o});
+        }
+    },
+
+    
+    moveFirst : function(){
+        this.doLoad(0);
+    },
+
+    
+    movePrevious : function(){
+        this.doLoad(Math.max(0, this.cursor-this.pageSize));
+    },
+
+    
+    moveNext : function(){
+        this.doLoad(this.cursor+this.pageSize);
+    },
+
+    
+    moveLast : function(){
+        var total = this.store.getTotalCount(),
+            extra = total % this.pageSize;
+
+        this.doLoad(extra ? (total - extra) : total - this.pageSize);
+    },
+
+    
+    doRefresh : function(){
+        this.doLoad(this.cursor);
+    },
+
+    
+    bindStore : function(store, initial){
+        var doLoad;
+        if(!initial && this.store){
+            if(store !== this.store && this.store.autoDestroy){
+                this.store.destroy();
+            }else{
+                this.store.un('beforeload', this.beforeLoad, this);
+                this.store.un('load', this.onLoad, this);
+                this.store.un('exception', this.onLoadError, this);
+            }
+            if(!store){
+                this.store = null;
+            }
+        }
+        if(store){
+            store = Ext.StoreMgr.lookup(store);
+            store.on({
+                scope: this,
+                beforeload: this.beforeLoad,
+                load: this.onLoad,
+                exception: this.onLoadError
+            });
+            doLoad = true;
+        }
+        this.store = store;
+        if(doLoad){
+            this.onLoad(store, null, {});
+        }
+    },
+
+    
+    unbind : function(store){
+        this.bindStore(null);
+    },
+
+    
+    bind : function(store){
+        this.bindStore(store);
+    },
+
+    
+    onDestroy : function(){
+        this.bindStore(null);
+        Ext.PagingToolbar.superclass.onDestroy.call(this);
+    }
+});
+
+})();
+Ext.reg('paging', Ext.PagingToolbar);
+Ext.History = (function () {
+    var iframe, hiddenField;
+    var ready = false;
+    var currentToken;
+
+    function getHash() {
+        var href = location.href, i = href.indexOf("#"),
+            hash = i >= 0 ? href.substr(i + 1) : null;
+             
+        if (Ext.isGecko) {
+            hash = decodeURIComponent(hash);
+        }
+        return hash;
+    }
+
+    function doSave() {
+        hiddenField.value = currentToken;
+    }
+
+    function handleStateChange(token) {
+        currentToken = token;
+        Ext.History.fireEvent('change', token);
+    }
+
+    function updateIFrame (token) {
+        var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
+        try {
+            var doc = iframe.contentWindow.document;
+            doc.open();
+            doc.write(html);
+            doc.close();
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+
+    function checkIFrame() {
+        if (!iframe.contentWindow || !iframe.contentWindow.document) {
+            setTimeout(checkIFrame, 10);
+            return;
+        }
+
+        var doc = iframe.contentWindow.document;
+        var elem = doc.getElementById("state");
+        var token = elem ? elem.innerText : null;
+
+        var hash = getHash();
+
+        setInterval(function () {
+
+            doc = iframe.contentWindow.document;
+            elem = doc.getElementById("state");
+
+            var newtoken = elem ? elem.innerText : null;
+
+            var newHash = getHash();
+
+            if (newtoken !== token) {
+                token = newtoken;
+                handleStateChange(token);
+                location.hash = token;
+                hash = token;
+                doSave();
+            } else if (newHash !== hash) {
+                hash = newHash;
+                updateIFrame(newHash);
+            }
+
+        }, 50);
+
+        ready = true;
+
+        Ext.History.fireEvent('ready', Ext.History);
+    }
+
+    function startUp() {
+        currentToken = hiddenField.value ? hiddenField.value : getHash();
+
+        if (Ext.isIE) {
+            checkIFrame();
+        } else {
+            var hash = getHash();
+            setInterval(function () {
+                var newHash = getHash();
+                if (newHash !== hash) {
+                    hash = newHash;
+                    handleStateChange(hash);
+                    doSave();
+                }
+            }, 50);
+            ready = true;
+            Ext.History.fireEvent('ready', Ext.History);
+        }
+    }
+
+    return {
+        
+        fieldId: 'x-history-field',
+        
+        iframeId: 'x-history-frame',
+
+        events:{},
+
+        
+        init: function (onReady, scope) {
+            if(ready) {
+                Ext.callback(onReady, scope, [this]);
+                return;
+            }
+            if(!Ext.isReady){
+                Ext.onReady(function(){
+                    Ext.History.init(onReady, scope);
+                });
+                return;
+            }
+            hiddenField = Ext.getDom(Ext.History.fieldId);
+            if (Ext.isIE) {
+                iframe = Ext.getDom(Ext.History.iframeId);
+            }
+            this.addEvents(
+                
+                'ready',
+                
+                'change'
+            );
+            if(onReady){
+                this.on('ready', onReady, scope, {single:true});
+            }
+            startUp();
+        },
+
+        
+        add: function (token, preventDup) {
+            if(preventDup !== false){
+                if(this.getToken() == token){
+                    return true;
+                }
+            }
+            if (Ext.isIE) {
+                return updateIFrame(token);
+            } else {
+                location.hash = token;
+                return true;
+            }
+        },
+
+        
+        back: function(){
+            history.go(-1);
+        },
+
+        
+        forward: function(){
+            history.go(1);
+        },
+
+        
+        getToken: function() {
+            return ready ? currentToken : getHash();
+        }
+    };
+})();
+Ext.apply(Ext.History, new Ext.util.Observable());
+Ext.Tip = Ext.extend(Ext.Panel, {
+    
+    
+    
+    minWidth : 40,
+    
+    maxWidth : 300,
+    
+    shadow : "sides",
+    
+    defaultAlign : "tl-bl?",
+    autoRender: true,
+    quickShowInterval : 250,
+
+    
+    frame:true,
+    hidden:true,
+    baseCls: 'x-tip',
+    floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
+    autoHeight:true,
+
+    closeAction: 'hide',
+
+    
+    initComponent : function(){
+        Ext.Tip.superclass.initComponent.call(this);
+        if(this.closable && !this.title){
+            this.elements += ',header';
+        }
+    },
+
+    
+    afterRender : function(){
+        Ext.Tip.superclass.afterRender.call(this);
+        if(this.closable){
+            this.addTool({
+                id: 'close',
+                handler: this[this.closeAction],
+                scope: this
+            });
+        }
+    },
+
+    
+    showAt : function(xy){
+        Ext.Tip.superclass.show.call(this);
+        if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
+            this.doAutoWidth();
+        }
+        if(this.constrainPosition){
+            xy = this.el.adjustForConstraints(xy);
+        }
+        this.setPagePosition(xy[0], xy[1]);
+    },
+
+    
+    doAutoWidth : function(adjust){
+        adjust = adjust || 0;
+        var bw = this.body.getTextWidth();
+        if(this.title){
+            bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
+        }
+        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
+        this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
+        
+        
+        if(Ext.isIE7 && !this.repainted){
+            this.el.repaint();
+            this.repainted = true;
+        }
+    },
+
+    
+    showBy : function(el, pos){
+        if(!this.rendered){
+            this.render(Ext.getBody());
+        }
+        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
+    },
+
+    initDraggable : function(){
+        this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
+        this.header.addClass('x-tip-draggable');
+    }
+});
+
+Ext.reg('tip', Ext.Tip);
+
+
+Ext.Tip.DD = function(tip, config){
+    Ext.apply(this, config);
+    this.tip = tip;
+    Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
+    this.setHandleElId(tip.header.id);
+    this.scroll = false;
+};
+
+Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
+    moveOnly:true,
+    scroll:false,
+    headerOffsets:[100, 25],
+    startDrag : function(){
+        this.tip.el.disableShadow();
+    },
+    endDrag : function(e){
+        this.tip.el.enableShadow(true);
+    }
+});
+Ext.ToolTip = Ext.extend(Ext.Tip, {
+    
+    
+    
+    
+    showDelay : 500,
+    
+    hideDelay : 200,
+    
+    dismissDelay : 5000,
+    
+    
+    trackMouse : false,
+    
+    anchorToTarget : true,
+    
+    anchorOffset : 0,
+    
+
+    
+    targetCounter : 0,
+
+    constrainPosition : false,
+
+    
+    initComponent : function(){
+        Ext.ToolTip.superclass.initComponent.call(this);
+        this.lastActive = new Date();
+        this.initTarget(this.target);
+        this.origAnchor = this.anchor;
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.ToolTip.superclass.onRender.call(this, ct, position);
+        this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
+        this.anchorEl = this.el.createChild({
+            cls: 'x-tip-anchor ' + this.anchorCls
+        });
+    },
+
+    
+    afterRender : function(){
+        Ext.ToolTip.superclass.afterRender.call(this);
+        this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
+    },
+
+    
+    initTarget : function(target){
+        var t;
+        if((t = Ext.get(target))){
+            if(this.target){
+                var tg = Ext.get(this.target);
+                this.mun(tg, 'mouseover', this.onTargetOver, this);
+                this.mun(tg, 'mouseout', this.onTargetOut, this);
+                this.mun(tg, 'mousemove', this.onMouseMove, this);
+            }
+            this.mon(t, {
+                mouseover: this.onTargetOver,
+                mouseout: this.onTargetOut,
+                mousemove: this.onMouseMove,
+                scope: this
+            });
+            this.target = t;
+        }
+        if(this.anchor){
+            this.anchorTarget = this.target;
+        }
+    },
+
+    
+    onMouseMove : function(e){
+        var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
+        if (t) {
+            this.targetXY = e.getXY();
+            if (t === this.triggerElement) {
+                if(!this.hidden && this.trackMouse){
+                    this.setPagePosition(this.getTargetXY());
+                }
+            } else {
+                this.hide();
+                this.lastActive = new Date(0);
+                this.onTargetOver(e);
+            }
+        } else if (!this.closable && this.isVisible()) {
+            this.hide();
+        }
+    },
+
+    
+    getTargetXY : function(){
+        if(this.delegate){
+            this.anchorTarget = this.triggerElement;
+        }
+        if(this.anchor){
+            this.targetCounter++;
+            var offsets = this.getOffsets(),
+                xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
+                dw = Ext.lib.Dom.getViewWidth() - 5,
+                dh = Ext.lib.Dom.getViewHeight() - 5,
+                de = document.documentElement,
+                bd = document.body,
+                scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
+                scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
+                axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
+                sz = this.getSize();
+                
+            this.anchorEl.removeClass(this.anchorCls);
+
+            if(this.targetCounter < 2){
+                if(axy[0] < scrollX){
+                    if(this.anchorToTarget){
+                        this.defaultAlign = 'l-r';
+                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
+                    }
+                    this.anchor = 'left';
+                    return this.getTargetXY();
+                }
+                if(axy[0]+sz.width > dw){
+                    if(this.anchorToTarget){
+                        this.defaultAlign = 'r-l';
+                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
+                    }
+                    this.anchor = 'right';
+                    return this.getTargetXY();
+                }
+                if(axy[1] < scrollY){
+                    if(this.anchorToTarget){
+                        this.defaultAlign = 't-b';
+                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
+                    }
+                    this.anchor = 'top';
+                    return this.getTargetXY();
+                }
+                if(axy[1]+sz.height > dh){
+                    if(this.anchorToTarget){
+                        this.defaultAlign = 'b-t';
+                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
+                    }
+                    this.anchor = 'bottom';
+                    return this.getTargetXY();
+                }
+            }
+
+            this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
+            this.anchorEl.addClass(this.anchorCls);
+            this.targetCounter = 0;
+            return axy;
+        }else{
+            var mouseOffset = this.getMouseOffset();
+            return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
+        }
+    },
+
+    getMouseOffset : function(){
+        var offset = this.anchor ? [0,0] : [15,18];
+        if(this.mouseOffset){
+            offset[0] += this.mouseOffset[0];
+            offset[1] += this.mouseOffset[1];
+        }
+        return offset;
+    },
+
+    
+    getAnchorPosition : function(){
+        if(this.anchor){
+            this.tipAnchor = this.anchor.charAt(0);
+        }else{
+            var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+            if(!m){
+               throw 'AnchorTip.defaultAlign is invalid';
+            }
+            this.tipAnchor = m[1].charAt(0);
+        }
+
+        switch(this.tipAnchor){
+            case 't': return 'top';
+            case 'b': return 'bottom';
+            case 'r': return 'right';
+        }
+        return 'left';
+    },
+
+    
+    getAnchorAlign : function(){
+        switch(this.anchor){
+            case 'top'  : return 'tl-bl';
+            case 'left' : return 'tl-tr';
+            case 'right': return 'tr-tl';
+            default     : return 'bl-tl';
+        }
+    },
+
+    
+    getOffsets : function(){
+        var offsets, 
+            ap = this.getAnchorPosition().charAt(0);
+        if(this.anchorToTarget && !this.trackMouse){
+            switch(ap){
+                case 't':
+                    offsets = [0, 9];
+                    break;
+                case 'b':
+                    offsets = [0, -13];
+                    break;
+                case 'r':
+                    offsets = [-13, 0];
+                    break;
+                default:
+                    offsets = [9, 0];
+                    break;
+            }
+        }else{
+            switch(ap){
+                case 't':
+                    offsets = [-15-this.anchorOffset, 30];
+                    break;
+                case 'b':
+                    offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
+                    break;
+                case 'r':
+                    offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
+                    break;
+                default:
+                    offsets = [25, -13-this.anchorOffset];
+                    break;
+            }
+        }
+        var mouseOffset = this.getMouseOffset();
+        offsets[0] += mouseOffset[0];
+        offsets[1] += mouseOffset[1];
+
+        return offsets;
+    },
+
+    
+    onTargetOver : function(e){
+        if(this.disabled || e.within(this.target.dom, true)){
+            return;
+        }
+        var t = e.getTarget(this.delegate);
+        if (t) {
+            this.triggerElement = t;
+            this.clearTimer('hide');
+            this.targetXY = e.getXY();
+            this.delayShow();
+        }
+    },
+
+    
+    delayShow : function(){
+        if(this.hidden && !this.showTimer){
+            if(this.lastActive.getElapsed() < this.quickShowInterval){
+                this.show();
+            }else{
+                this.showTimer = this.show.defer(this.showDelay, this);
+            }
+        }else if(!this.hidden && this.autoHide !== false){
+            this.show();
+        }
+    },
+
+    
+    onTargetOut : function(e){
+        if(this.disabled || e.within(this.target.dom, true)){
+            return;
+        }
+        this.clearTimer('show');
+        if(this.autoHide !== false){
+            this.delayHide();
+        }
+    },
+
+    
+    delayHide : function(){
+        if(!this.hidden && !this.hideTimer){
+            this.hideTimer = this.hide.defer(this.hideDelay, this);
+        }
+    },
+
+    
+    hide: function(){
+        this.clearTimer('dismiss');
+        this.lastActive = new Date();
+        if(this.anchorEl){
+            this.anchorEl.hide();
+        }
+        Ext.ToolTip.superclass.hide.call(this);
+        delete this.triggerElement;
+    },
+
+    
+    show : function(){
+        if(this.anchor){
+            
+            
+            this.showAt([-1000,-1000]);
+            this.origConstrainPosition = this.constrainPosition;
+            this.constrainPosition = false;
+            this.anchor = this.origAnchor;
+        }
+        this.showAt(this.getTargetXY());
+
+        if(this.anchor){
+            this.anchorEl.show();
+            this.syncAnchor();
+            this.constrainPosition = this.origConstrainPosition;
+        }else{
+            this.anchorEl.hide();
+        }
+    },
+
+    
+    showAt : function(xy){
+        this.lastActive = new Date();
+        this.clearTimers();
+        Ext.ToolTip.superclass.showAt.call(this, xy);
+        if(this.dismissDelay && this.autoHide !== false){
+            this.dismissTimer = this.hide.defer(this.dismissDelay, this);
+        }
+        if(this.anchor && !this.anchorEl.isVisible()){
+            this.syncAnchor();
+            this.anchorEl.show();
+        }else{
+            this.anchorEl.hide();
+        }
+    },
+
+    
+    syncAnchor : function(){
+        var anchorPos, targetPos, offset;
+        switch(this.tipAnchor.charAt(0)){
+            case 't':
+                anchorPos = 'b';
+                targetPos = 'tl';
+                offset = [20+this.anchorOffset, 2];
+                break;
+            case 'r':
+                anchorPos = 'l';
+                targetPos = 'tr';
+                offset = [-2, 11+this.anchorOffset];
+                break;
+            case 'b':
+                anchorPos = 't';
+                targetPos = 'bl';
+                offset = [20+this.anchorOffset, -2];
+                break;
+            default:
+                anchorPos = 'r';
+                targetPos = 'tl';
+                offset = [2, 11+this.anchorOffset];
+                break;
+        }
+        this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
+    },
+
+    
+    setPagePosition : function(x, y){
+        Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
+        if(this.anchor){
+            this.syncAnchor();
+        }
+    },
+
+    
+    clearTimer : function(name){
+        name = name + 'Timer';
+        clearTimeout(this[name]);
+        delete this[name];
+    },
+
+    
+    clearTimers : function(){
+        this.clearTimer('show');
+        this.clearTimer('dismiss');
+        this.clearTimer('hide');
+    },
+
+    
+    onShow : function(){
+        Ext.ToolTip.superclass.onShow.call(this);
+        Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
+    },
+
+    
+    onHide : function(){
+        Ext.ToolTip.superclass.onHide.call(this);
+        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
+    },
+
+    
+    onDocMouseDown : function(e){
+        if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
+            this.disable();
+            this.doEnable.defer(100, this);
+        }
+    },
+    
+    
+    doEnable : function(){
+        if(!this.isDestroyed){
+            this.enable();
+        }
+    },
+
+    
+    onDisable : function(){
+        this.clearTimers();
+        this.hide();
+    },
+
+    
+    adjustPosition : function(x, y){
+        if(this.constrainPosition){
+            var ay = this.targetXY[1], h = this.getSize().height;
+            if(y <= ay && (y+h) >= ay){
+                y = ay-h-5;
+            }
+        }
+        return {x : x, y: y};
+    },
+    
+    beforeDestroy : function(){
+        this.clearTimers();
+        Ext.destroy(this.anchorEl);
+        delete this.anchorEl;
+        delete this.target;
+        delete this.anchorTarget;
+        delete this.triggerElement;
+        Ext.ToolTip.superclass.beforeDestroy.call(this);    
+    },
+
+    
+    onDestroy : function(){
+        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
+        Ext.ToolTip.superclass.onDestroy.call(this);
+    }
+});
+
+Ext.reg('tooltip', Ext.ToolTip);
+Ext.QuickTip = Ext.extend(Ext.ToolTip, {
+    
+    
+    interceptTitles : false,
+
+    
+    tagConfig : {
+        namespace : "ext",
+        attribute : "qtip",
+        width : "qwidth",
+        target : "target",
+        title : "qtitle",
+        hide : "hide",
+        cls : "qclass",
+        align : "qalign",
+        anchor : "anchor"
+    },
+
+    
+    initComponent : function(){
+        this.target = this.target || Ext.getDoc();
+        this.targets = this.targets || {};
+        Ext.QuickTip.superclass.initComponent.call(this);
+    },
+
+    
+    register : function(config){
+        var cs = Ext.isArray(config) ? config : arguments;
+        for(var i = 0, len = cs.length; i < len; i++){
+            var c = cs[i];
+            var target = c.target;
+            if(target){
+                if(Ext.isArray(target)){
+                    for(var j = 0, jlen = target.length; j < jlen; j++){
+                        this.targets[Ext.id(target[j])] = c;
+                    }
+                } else{
+                    this.targets[Ext.id(target)] = c;
+                }
+            }
+        }
+    },
+
+    
+    unregister : function(el){
+        delete this.targets[Ext.id(el)];
+    },
+    
+    
+    cancelShow: function(el){
+        var at = this.activeTarget;
+        el = Ext.get(el).dom;
+        if(this.isVisible()){
+            if(at && at.el == el){
+                this.hide();
+            }
+        }else if(at && at.el == el){
+            this.clearTimer('show');
+        }
+    },
+    
+    getTipCfg: function(e) {
+        var t = e.getTarget(), 
+            ttp, 
+            cfg;
+        if(this.interceptTitles && t.title && Ext.isString(t.title)){
+            ttp = t.title;
+            t.qtip = ttp;
+            t.removeAttribute("title");
+            e.preventDefault();
+        }else{
+            cfg = this.tagConfig;
+            ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
+        }
+        return ttp;
+    },
+
+    
+    onTargetOver : function(e){
+        if(this.disabled){
+            return;
+        }
+        this.targetXY = e.getXY();
+        var t = e.getTarget();
+        if(!t || t.nodeType !== 1 || t == document || t == document.body){
+            return;
+        }
+        if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
+            this.clearTimer('hide');
+            this.show();
+            return;
+        }
+        if(t && this.targets[t.id]){
+            this.activeTarget = this.targets[t.id];
+            this.activeTarget.el = t;
+            this.anchor = this.activeTarget.anchor;
+            if(this.anchor){
+                this.anchorTarget = t;
+            }
+            this.delayShow();
+            return;
+        }
+        var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
+        if(ttp = this.getTipCfg(e)){
+            var autoHide = et.getAttribute(cfg.hide, ns);
+            this.activeTarget = {
+                el: t,
+                text: ttp,
+                width: et.getAttribute(cfg.width, ns),
+                autoHide: autoHide != "user" && autoHide !== 'false',
+                title: et.getAttribute(cfg.title, ns),
+                cls: et.getAttribute(cfg.cls, ns),
+                align: et.getAttribute(cfg.align, ns)
+                
+            };
+            this.anchor = et.getAttribute(cfg.anchor, ns);
+            if(this.anchor){
+                this.anchorTarget = t;
+            }
+            this.delayShow();
+        }
+    },
+
+    
+    onTargetOut : function(e){
+
+        
+        if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
+            return;
+        }
+
+        this.clearTimer('show');
+        if(this.autoHide !== false){
+            this.delayHide();
+        }
+    },
+
+    
+    showAt : function(xy){
+        var t = this.activeTarget;
+        if(t){
+            if(!this.rendered){
+                this.render(Ext.getBody());
+                this.activeTarget = t;
+            }
+            if(t.width){
+                this.setWidth(t.width);
+                this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
+                this.measureWidth = false;
+            } else{
+                this.measureWidth = true;
+            }
+            this.setTitle(t.title || '');
+            this.body.update(t.text);
+            this.autoHide = t.autoHide;
+            this.dismissDelay = t.dismissDelay || this.dismissDelay;
+            if(this.lastCls){
+                this.el.removeClass(this.lastCls);
+                delete this.lastCls;
+            }
+            if(t.cls){
+                this.el.addClass(t.cls);
+                this.lastCls = t.cls;
+            }
+            if(this.anchor){
+                this.constrainPosition = false;
+            }else if(t.align){ 
+                xy = this.el.getAlignToXY(t.el, t.align);
+                this.constrainPosition = false;
+            }else{
+                this.constrainPosition = true;
+            }
+        }
+        Ext.QuickTip.superclass.showAt.call(this, xy);
+    },
+
+    
+    hide: function(){
+        delete this.activeTarget;
+        Ext.QuickTip.superclass.hide.call(this);
+    }
+});
+Ext.reg('quicktip', Ext.QuickTip);
+Ext.QuickTips = function(){
+    var tip,
+        disabled = false;
+        
+    return {
+        
+        init : function(autoRender){
+            if(!tip){
+                if(!Ext.isReady){
+                    Ext.onReady(function(){
+                        Ext.QuickTips.init(autoRender);
+                    });
+                    return;
+                }
+                tip = new Ext.QuickTip({
+                    elements:'header,body', 
+                    disabled: disabled
+                });
+                if(autoRender !== false){
+                    tip.render(Ext.getBody());
+                }
+            }
+        },
+        
+        
+        ddDisable : function(){
+            
+            if(tip && !disabled){
+                tip.disable();
+            }    
+        },
+        
+        
+        ddEnable : function(){
+            
+            if(tip && !disabled){
+                tip.enable();
+            }
+        },
+
+        
+        enable : function(){
+            if(tip){
+                tip.enable();
+            }
+            disabled = false;
+        },
+
+        
+        disable : function(){
+            if(tip){
+                tip.disable();
+            }
+            disabled = true;
+        },
+
+        
+        isEnabled : function(){
+            return tip !== undefined && !tip.disabled;
+        },
+
+        
+        getQuickTip : function(){
+            return tip;
+        },
+
+        
+        register : function(){
+            tip.register.apply(tip, arguments);
+        },
+
+        
+        unregister : function(){
+            tip.unregister.apply(tip, arguments);
+        },
+
+        
+        tips : function(){
+            tip.register.apply(tip, arguments);
+        }
+    };
+}();
+Ext.slider.Tip = Ext.extend(Ext.Tip, {
+    minWidth: 10,
+    offsets : [0, -10],
+    
+    init: function(slider) {
+        slider.on({
+            scope    : this,
+            dragstart: this.onSlide,
+            drag     : this.onSlide,
+            dragend  : this.hide,
+            destroy  : this.destroy
+        });
+    },
+    
+    
+    onSlide : function(slider, e, thumb) {
+        this.show();
+        this.body.update(this.getText(thumb));
+        this.doAutoWidth();
+        this.el.alignTo(thumb.el, 'b-t?', this.offsets);
+    },
+
+    
+    getText : function(thumb) {
+        return String(thumb.value);
+    }
+});
+
+
+Ext.ux.SliderTip = Ext.slider.Tip;
+Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
+    rootVisible : true,
+    animate : Ext.enableFx,
+    lines : true,
+    enableDD : false,
+    hlDrop : Ext.enableFx,
+    pathSeparator : '/',
+
+    
+    bubbleEvents : [],
+
+    initComponent : function(){
+        Ext.tree.TreePanel.superclass.initComponent.call(this);
+
+        if(!this.eventModel){
+            this.eventModel = new Ext.tree.TreeEventModel(this);
+        }
+
+        
+        var l = this.loader;
+        if(!l){
+            l = new Ext.tree.TreeLoader({
+                dataUrl: this.dataUrl,
+                requestMethod: this.requestMethod
+            });
+        }else if(Ext.isObject(l) && !l.load){
+            l = new Ext.tree.TreeLoader(l);
+        }
+        this.loader = l;
+
+        this.nodeHash = {};
+
+        
+        if(this.root){
+            var r = this.root;
+            delete this.root;
+            this.setRootNode(r);
+        }
+
+
+        this.addEvents(
+
+            
+           'append',
+           
+           'remove',
+           
+           'movenode',
+           
+           'insert',
+           
+           'beforeappend',
+           
+           'beforeremove',
+           
+           'beforemovenode',
+           
+            'beforeinsert',
+
+            
+            'beforeload',
+            
+            'load',
+            
+            'textchange',
+            
+            'beforeexpandnode',
+            
+            'beforecollapsenode',
+            
+            'expandnode',
+            
+            'disabledchange',
+            
+            'collapsenode',
+            
+            'beforeclick',
+            
+            'click',
+            
+            'containerclick',
+            
+            'checkchange',
+            
+            'beforedblclick',
+            
+            'dblclick',
+            
+            'containerdblclick',
+            
+            'contextmenu',
+            
+            'containercontextmenu',
+            
+            'beforechildrenrendered',
+           
+            'startdrag',
+            
+            'enddrag',
+            
+            'dragdrop',
+            
+            'beforenodedrop',
+            
+            'nodedrop',
+             
+            'nodedragover'
+        );
+        if(this.singleExpand){
+            this.on('beforeexpandnode', this.restrictExpand, this);
+        }
+    },
+
+    
+    proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
+        if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
+            ename = ename+'node';
+        }
+        
+        return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
+    },
+
+
+    
+    getRootNode : function(){
+        return this.root;
+    },
+
+    
+    setRootNode : function(node){
+        this.destroyRoot();
+        if(!node.render){ 
+            node = this.loader.createNode(node);
+        }
+        this.root = node;
+        node.ownerTree = this;
+        node.isRoot = true;
+        this.registerNode(node);
+        if(!this.rootVisible){
+            var uiP = node.attributes.uiProvider;
+            node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
+        }
+        if(this.innerCt){
+            this.clearInnerCt();
+            this.renderRoot();
+        }
+        return node;
+    },
+    
+    clearInnerCt : function(){
+        this.innerCt.update('');    
+    },
+    
+    
+    renderRoot : function(){
+        this.root.render();
+        if(!this.rootVisible){
+            this.root.renderChildren();
+        }
+    },
+
+    
+    getNodeById : function(id){
+        return this.nodeHash[id];
+    },
+
+    
+    registerNode : function(node){
+        this.nodeHash[node.id] = node;
+    },
+
+    
+    unregisterNode : function(node){
+        delete this.nodeHash[node.id];
+    },
+
+    
+    toString : function(){
+        return '[Tree'+(this.id?' '+this.id:'')+']';
+    },
+
+    
+    restrictExpand : function(node){
+        var p = node.parentNode;
+        if(p){
+            if(p.expandedChild && p.expandedChild.parentNode == p){
+                p.expandedChild.collapse();
+            }
+            p.expandedChild = node;
+        }
+    },
+
+    
+    getChecked : function(a, startNode){
+        startNode = startNode || this.root;
+        var r = [];
+        var f = function(){
+            if(this.attributes.checked){
+                r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
+            }
+        };
+        startNode.cascade(f);
+        return r;
+    },
+
+    
+    getLoader : function(){
+        return this.loader;
+    },
+
+    
+    expandAll : function(){
+        this.root.expand(true);
+    },
+
+    
+    collapseAll : function(){
+        this.root.collapse(true);
+    },
+
+    
+    getSelectionModel : function(){
+        if(!this.selModel){
+            this.selModel = new Ext.tree.DefaultSelectionModel();
+        }
+        return this.selModel;
+    },
+
+    
+    expandPath : function(path, attr, callback){
+        if(Ext.isEmpty(path)){
+            if(callback){
+                callback(false, undefined);
+            }
+            return;
+        }
+        attr = attr || 'id';
+        var keys = path.split(this.pathSeparator);
+        var curNode = this.root;
+        if(curNode.attributes[attr] != keys[1]){ 
+            if(callback){
+                callback(false, null);
+            }
+            return;
+        }
+        var index = 1;
+        var f = function(){
+            if(++index == keys.length){
+                if(callback){
+                    callback(true, curNode);
+                }
+                return;
+            }
+            var c = curNode.findChild(attr, keys[index]);
+            if(!c){
+                if(callback){
+                    callback(false, curNode);
+                }
+                return;
+            }
+            curNode = c;
+            c.expand(false, false, f);
+        };
+        curNode.expand(false, false, f);
+    },
+
+    
+    selectPath : function(path, attr, callback){
+        if(Ext.isEmpty(path)){
+            if(callback){
+                callback(false, undefined);
+            }
+            return;
+        }
+        attr = attr || 'id';
+        var keys = path.split(this.pathSeparator),
+            v = keys.pop();
+        if(keys.length > 1){
+            var f = function(success, node){
+                if(success && node){
+                    var n = node.findChild(attr, v);
+                    if(n){
+                        n.select();
+                        if(callback){
+                            callback(true, n);
+                        }
+                    }else if(callback){
+                        callback(false, n);
+                    }
+                }else{
+                    if(callback){
+                        callback(false, n);
+                    }
+                }
+            };
+            this.expandPath(keys.join(this.pathSeparator), attr, f);
+        }else{
+            this.root.select();
+            if(callback){
+                callback(true, this.root);
+            }
+        }
+    },
+
+    
+    getTreeEl : function(){
+        return this.body;
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
+        this.el.addClass('x-tree');
+        this.innerCt = this.body.createChild({tag:'ul',
+               cls:'x-tree-root-ct ' +
+               (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
+    },
+
+    
+    initEvents : function(){
+        Ext.tree.TreePanel.superclass.initEvents.call(this);
+
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.register(this.body);
+        }
+        if((this.enableDD || this.enableDrop) && !this.dropZone){
+           
+             this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
+               ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
+           });
+        }
+        if((this.enableDD || this.enableDrag) && !this.dragZone){
+           
+            this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
+               ddGroup: this.ddGroup || 'TreeDD',
+               scroll: this.ddScroll
+           });
+        }
+        this.getSelectionModel().init(this);
+    },
+
+    
+    afterRender : function(){
+        Ext.tree.TreePanel.superclass.afterRender.call(this);
+        this.renderRoot();
+    },
+
+    beforeDestroy : function(){
+        if(this.rendered){
+            Ext.dd.ScrollManager.unregister(this.body);
+            Ext.destroy(this.dropZone, this.dragZone);
+        }
+        this.destroyRoot();
+        Ext.destroy(this.loader);
+        this.nodeHash = this.root = this.loader = null;
+        Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
+    },
+    
+    
+    destroyRoot : function(){
+        if(this.root && this.root.destroy){
+            this.root.destroy(true);
+        }
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+});
+
+Ext.tree.TreePanel.nodeTypes = {};
+
+Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
+    this.tree = tree;
+    this.tree.on('render', this.initEvents, this);
+};
+
+Ext.tree.TreeEventModel.prototype = {
+    initEvents : function(){
+        var t = this.tree;
+
+        if(t.trackMouseOver !== false){
+            t.mon(t.innerCt, {
+                scope: this,
+                mouseover: this.delegateOver,
+                mouseout: this.delegateOut
+            });
+        }
+        t.mon(t.getTreeEl(), {
+            scope: this,
+            click: this.delegateClick,
+            dblclick: this.delegateDblClick,
+            contextmenu: this.delegateContextMenu
+        });
+    },
+
+    getNode : function(e){
+        var t;
+        if(t = e.getTarget('.x-tree-node-el', 10)){
+            var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
+            if(id){
+                return this.tree.getNodeById(id);
+            }
+        }
+        return null;
+    },
+
+    getNodeTarget : function(e){
+        var t = e.getTarget('.x-tree-node-icon', 1);
+        if(!t){
+            t = e.getTarget('.x-tree-node-el', 6);
+        }
+        return t;
+    },
+
+    delegateOut : function(e, t){
+        if(!this.beforeEvent(e)){
+            return;
+        }
+        if(e.getTarget('.x-tree-ec-icon', 1)){
+            var n = this.getNode(e);
+            this.onIconOut(e, n);
+            if(n == this.lastEcOver){
+                delete this.lastEcOver;
+            }
+        }
+        if((t = this.getNodeTarget(e)) && !e.within(t, true)){
+            this.onNodeOut(e, this.getNode(e));
+        }
+    },
+
+    delegateOver : function(e, t){
+        if(!this.beforeEvent(e)){
+            return;
+        }
+        if(Ext.isGecko && !this.trackingDoc){ 
+            Ext.getBody().on('mouseover', this.trackExit, this);
+            this.trackingDoc = true;
+        }
+        if(this.lastEcOver){ 
+            this.onIconOut(e, this.lastEcOver);
+            delete this.lastEcOver;
+        }
+        if(e.getTarget('.x-tree-ec-icon', 1)){
+            this.lastEcOver = this.getNode(e);
+            this.onIconOver(e, this.lastEcOver);
+        }
+        if(t = this.getNodeTarget(e)){
+            this.onNodeOver(e, this.getNode(e));
+        }
+    },
+
+    trackExit : function(e){
+        if(this.lastOverNode){
+            if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
+                this.onNodeOut(e, this.lastOverNode);
+            }
+            delete this.lastOverNode;
+            Ext.getBody().un('mouseover', this.trackExit, this);
+            this.trackingDoc = false;
+        }
+
+    },
+
+    delegateClick : function(e, t){
+        if(this.beforeEvent(e)){
+            if(e.getTarget('input[type=checkbox]', 1)){
+                this.onCheckboxClick(e, this.getNode(e));
+            }else if(e.getTarget('.x-tree-ec-icon', 1)){
+                this.onIconClick(e, this.getNode(e));
+            }else if(this.getNodeTarget(e)){
+                this.onNodeClick(e, this.getNode(e));
+            }
+        }else{
+            this.checkContainerEvent(e, 'click');
+        }
+    },
+
+    delegateDblClick : function(e, t){
+        if(this.beforeEvent(e)){
+            if(this.getNodeTarget(e)){
+                this.onNodeDblClick(e, this.getNode(e));
+            }
+        }else{
+            this.checkContainerEvent(e, 'dblclick');
+        }
+    },
+
+    delegateContextMenu : function(e, t){
+        if(this.beforeEvent(e)){
+            if(this.getNodeTarget(e)){
+                this.onNodeContextMenu(e, this.getNode(e));
+            }
+        }else{
+            this.checkContainerEvent(e, 'contextmenu');
+        }
+    },
+    
+    checkContainerEvent: function(e, type){
+        if(this.disabled){
+            e.stopEvent();
+            return false;
+        }
+        this.onContainerEvent(e, type);    
+    },
+
+    onContainerEvent: function(e, type){
+        this.tree.fireEvent('container' + type, this.tree, e);
+    },
+
+    onNodeClick : function(e, node){
+        node.ui.onClick(e);
+    },
+
+    onNodeOver : function(e, node){
+        this.lastOverNode = node;
+        node.ui.onOver(e);
+    },
+
+    onNodeOut : function(e, node){
+        node.ui.onOut(e);
+    },
+
+    onIconOver : function(e, node){
+        node.ui.addClass('x-tree-ec-over');
+    },
+
+    onIconOut : function(e, node){
+        node.ui.removeClass('x-tree-ec-over');
+    },
+
+    onIconClick : function(e, node){
+        node.ui.ecClick(e);
+    },
+
+    onCheckboxClick : function(e, node){
+        node.ui.onCheckChange(e);
+    },
+
+    onNodeDblClick : function(e, node){
+        node.ui.onDblClick(e);
+    },
+
+    onNodeContextMenu : function(e, node){
+        node.ui.onContextMenu(e);
+    },
+
+    beforeEvent : function(e){
+        var node = this.getNode(e);
+        if(this.disabled || !node || !node.ui){
+            e.stopEvent();
+            return false;
+        }
+        return true;
+    },
+
+    disable: function(){
+        this.disabled = true;
+    },
+
+    enable: function(){
+        this.disabled = false;
+    }
+};
+Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(config){
+        this.selNode = null;
+   
+        this.addEvents(
+            
+            'selectionchange',
+
+            
+            'beforeselect'
+        );
+
+        Ext.apply(this, config);
+        Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
+    },
+    
+    init : function(tree){
+        this.tree = tree;
+        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
+        tree.on('click', this.onNodeClick, this);
+    },
+    
+    onNodeClick : function(node, e){
+        this.select(node);
+    },
+    
+    
+    select : function(node,  selectNextNode){
+        
+        if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
+            return selectNextNode.call(this, node);
+        }
+        var last = this.selNode;
+        if(node == last){
+            node.ui.onSelectedChange(true);
+        }else if(this.fireEvent('beforeselect', this, node, last) !== false){
+            if(last && last.ui){
+                last.ui.onSelectedChange(false);
+            }
+            this.selNode = node;
+            node.ui.onSelectedChange(true);
+            this.fireEvent('selectionchange', this, node, last);
+        }
+        return node;
+    },
+    
+    
+    unselect : function(node, silent){
+        if(this.selNode == node){
+            this.clearSelections(silent);
+        }    
+    },
+    
+    
+    clearSelections : function(silent){
+        var n = this.selNode;
+        if(n){
+            n.ui.onSelectedChange(false);
+            this.selNode = null;
+            if(silent !== true){
+                this.fireEvent('selectionchange', this, null);
+            }
+        }
+        return n;
+    },
+    
+    
+    getSelectedNode : function(){
+        return this.selNode;    
+    },
+    
+    
+    isSelected : function(node){
+        return this.selNode == node;  
+    },
+
+    
+    selectPrevious : function( s){
+        if(!(s = s || this.selNode || this.lastSelNode)){
+            return null;
+        }
+        
+        var ps = s.previousSibling;
+        if(ps){
+            if(!ps.isExpanded() || ps.childNodes.length < 1){
+                return this.select(ps, this.selectPrevious);
+            } else{
+                var lc = ps.lastChild;
+                while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
+                    lc = lc.lastChild;
+                }
+                return this.select(lc, this.selectPrevious);
+            }
+        } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
+            return this.select(s.parentNode, this.selectPrevious);
+        }
+        return null;
+    },
+
+    
+    selectNext : function( s){
+        if(!(s = s || this.selNode || this.lastSelNode)){
+            return null;
+        }
+        
+        if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
+             return this.select(s.firstChild, this.selectNext);
+         }else if(s.nextSibling){
+             return this.select(s.nextSibling, this.selectNext);
+         }else if(s.parentNode){
+            var newS = null;
+            s.parentNode.bubble(function(){
+                if(this.nextSibling){
+                    newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
+                    return false;
+                }
+            });
+            return newS;
+         }
+        return null;
+    },
+
+    onKeyDown : function(e){
+        var s = this.selNode || this.lastSelNode;
+        
+        var sm = this;
+        if(!s){
+            return;
+        }
+        var k = e.getKey();
+        switch(k){
+             case e.DOWN:
+                 e.stopEvent();
+                 this.selectNext();
+             break;
+             case e.UP:
+                 e.stopEvent();
+                 this.selectPrevious();
+             break;
+             case e.RIGHT:
+                 e.preventDefault();
+                 if(s.hasChildNodes()){
+                     if(!s.isExpanded()){
+                         s.expand();
+                     }else if(s.firstChild){
+                         this.select(s.firstChild, e);
+                     }
+                 }
+             break;
+             case e.LEFT:
+                 e.preventDefault();
+                 if(s.hasChildNodes() && s.isExpanded()){
+                     s.collapse();
+                 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
+                     this.select(s.parentNode, e);
+                 }
+             break;
+        };
+    }
+});
+
+
+Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(config){
+        this.selNodes = [];
+        this.selMap = {};
+        this.addEvents(
+            
+            'selectionchange'
+        );
+        Ext.apply(this, config);
+        Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
+    },
+    
+    init : function(tree){
+        this.tree = tree;
+        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
+        tree.on('click', this.onNodeClick, this);
+    },
+    
+    onNodeClick : function(node, e){
+        if(e.ctrlKey && this.isSelected(node)){
+            this.unselect(node);
+        }else{
+            this.select(node, e, e.ctrlKey);
+        }
+    },
+    
+    
+    select : function(node, e, keepExisting){
+        if(keepExisting !== true){
+            this.clearSelections(true);
+        }
+        if(this.isSelected(node)){
+            this.lastSelNode = node;
+            return node;
+        }
+        this.selNodes.push(node);
+        this.selMap[node.id] = node;
+        this.lastSelNode = node;
+        node.ui.onSelectedChange(true);
+        this.fireEvent('selectionchange', this, this.selNodes);
+        return node;
+    },
+    
+    
+    unselect : function(node){
+        if(this.selMap[node.id]){
+            node.ui.onSelectedChange(false);
+            var sn = this.selNodes;
+            var index = sn.indexOf(node);
+            if(index != -1){
+                this.selNodes.splice(index, 1);
+            }
+            delete this.selMap[node.id];
+            this.fireEvent('selectionchange', this, this.selNodes);
+        }
+    },
+    
+    
+    clearSelections : function(suppressEvent){
+        var sn = this.selNodes;
+        if(sn.length > 0){
+            for(var i = 0, len = sn.length; i < len; i++){
+                sn[i].ui.onSelectedChange(false);
+            }
+            this.selNodes = [];
+            this.selMap = {};
+            if(suppressEvent !== true){
+                this.fireEvent('selectionchange', this, this.selNodes);
+            }
+        }
+    },
+    
+    
+    isSelected : function(node){
+        return this.selMap[node.id] ? true : false;  
+    },
+    
+    
+    getSelectedNodes : function(){
+        return this.selNodes.concat([]);
+    },
+
+    onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
+
+    selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
+
+    selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
+});
+Ext.data.Tree = Ext.extend(Ext.util.Observable, {
+    
+    constructor: function(root){
+        this.nodeHash = {};
+        
+        this.root = null;
+        if(root){
+            this.setRootNode(root);
+        }
+        this.addEvents(
+            
+            "append",
+            
+            "remove",
+            
+            "move",
+            
+            "insert",
+            
+            "beforeappend",
+            
+            "beforeremove",
+            
+            "beforemove",
+            
+            "beforeinsert"
+        );
+        Ext.data.Tree.superclass.constructor.call(this);        
+    },
+    
+    
+    pathSeparator: "/",
+
+    
+    proxyNodeEvent : function(){
+        return this.fireEvent.apply(this, arguments);
+    },
+
+    
+    getRootNode : function(){
+        return this.root;
+    },
+
+    
+    setRootNode : function(node){
+        this.root = node;
+        node.ownerTree = this;
+        node.isRoot = true;
+        this.registerNode(node);
+        return node;
+    },
+
+    
+    getNodeById : function(id){
+        return this.nodeHash[id];
+    },
+
+    
+    registerNode : function(node){
+        this.nodeHash[node.id] = node;
+    },
+
+    
+    unregisterNode : function(node){
+        delete this.nodeHash[node.id];
+    },
+
+    toString : function(){
+        return "[Tree"+(this.id?" "+this.id:"")+"]";
+    }
+});
+
+
+Ext.data.Node = Ext.extend(Ext.util.Observable, {
+    
+    constructor: function(attributes){
+        
+        this.attributes = attributes || {};
+        this.leaf = this.attributes.leaf;
+        
+        this.id = this.attributes.id;
+        if(!this.id){
+            this.id = Ext.id(null, "xnode-");
+            this.attributes.id = this.id;
+        }
+        
+        this.childNodes = [];
+        
+        this.parentNode = null;
+        
+        this.firstChild = null;
+        
+        this.lastChild = null;
+        
+        this.previousSibling = null;
+        
+        this.nextSibling = null;
+
+        this.addEvents({
+            
+            "append" : true,
+            
+            "remove" : true,
+            
+            "move" : true,
+            
+            "insert" : true,
+            
+            "beforeappend" : true,
+            
+            "beforeremove" : true,
+            
+            "beforemove" : true,
+             
+            "beforeinsert" : true
+        });
+        this.listeners = this.attributes.listeners;
+        Ext.data.Node.superclass.constructor.call(this);    
+    },
+    
+    
+    fireEvent : function(evtName){
+        
+        if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
+            return false;
+        }
+        
+        var ot = this.getOwnerTree();
+        if(ot){
+            if(ot.proxyNodeEvent.apply(ot, arguments) === false){
+                return false;
+            }
+        }
+        return true;
+    },
+
+    
+    isLeaf : function(){
+        return this.leaf === true;
+    },
+
+    
+    setFirstChild : function(node){
+        this.firstChild = node;
+    },
+
+    
+    setLastChild : function(node){
+        this.lastChild = node;
+    },
+
+
+    
+    isLast : function(){
+       return (!this.parentNode ? true : this.parentNode.lastChild == this);
+    },
+
+    
+    isFirst : function(){
+       return (!this.parentNode ? true : this.parentNode.firstChild == this);
+    },
+
+    
+    hasChildNodes : function(){
+        return !this.isLeaf() && this.childNodes.length > 0;
+    },
+
+    
+    isExpandable : function(){
+        return this.attributes.expandable || this.hasChildNodes();
+    },
+
+    
+    appendChild : function(node){
+        var multi = false;
+        if(Ext.isArray(node)){
+            multi = node;
+        }else if(arguments.length > 1){
+            multi = arguments;
+        }
+        
+        if(multi){
+            for(var i = 0, len = multi.length; i < len; i++) {
+                this.appendChild(multi[i]);
+            }
+        }else{
+            if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
+                return false;
+            }
+            var index = this.childNodes.length;
+            var oldParent = node.parentNode;
+            
+            if(oldParent){
+                if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
+                    return false;
+                }
+                oldParent.removeChild(node);
+            }
+            index = this.childNodes.length;
+            if(index === 0){
+                this.setFirstChild(node);
+            }
+            this.childNodes.push(node);
+            node.parentNode = this;
+            var ps = this.childNodes[index-1];
+            if(ps){
+                node.previousSibling = ps;
+                ps.nextSibling = node;
+            }else{
+                node.previousSibling = null;
+            }
+            node.nextSibling = null;
+            this.setLastChild(node);
+            node.setOwnerTree(this.getOwnerTree());
+            this.fireEvent("append", this.ownerTree, this, node, index);
+            if(oldParent){
+                node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
+            }
+            return node;
+        }
+    },
+
+    
+    removeChild : function(node, destroy){
+        var index = this.childNodes.indexOf(node);
+        if(index == -1){
+            return false;
+        }
+        if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
+            return false;
+        }
+
+        
+        this.childNodes.splice(index, 1);
+
+        
+        if(node.previousSibling){
+            node.previousSibling.nextSibling = node.nextSibling;
+        }
+        if(node.nextSibling){
+            node.nextSibling.previousSibling = node.previousSibling;
+        }
+
+        
+        if(this.firstChild == node){
+            this.setFirstChild(node.nextSibling);
+        }
+        if(this.lastChild == node){
+            this.setLastChild(node.previousSibling);
+        }
+
+        this.fireEvent("remove", this.ownerTree, this, node);
+        if(destroy){
+            node.destroy(true);
+        }else{
+            node.clear();
+        }
+        return node;
+    },
+
+    
+    clear : function(destroy){
+        
+        this.setOwnerTree(null, destroy);
+        this.parentNode = this.previousSibling = this.nextSibling = null;
+        if(destroy){
+            this.firstChild = this.lastChild = null;
+        }
+    },
+
+    
+    destroy : function( silent){
+        
+        if(silent === true){
+            this.purgeListeners();
+            this.clear(true);
+            Ext.each(this.childNodes, function(n){
+                n.destroy(true);
+            });
+            this.childNodes = null;
+        }else{
+            this.remove(true);
+        }
+    },
+
+    
+    insertBefore : function(node, refNode){
+        if(!refNode){ 
+            return this.appendChild(node);
+        }
+        
+        if(node == refNode){
+            return false;
+        }
+
+        if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
+            return false;
+        }
+        var index = this.childNodes.indexOf(refNode);
+        var oldParent = node.parentNode;
+        var refIndex = index;
+
+        
+        if(oldParent == this && this.childNodes.indexOf(node) < index){
+            refIndex--;
+        }
+
+        
+        if(oldParent){
+            if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
+                return false;
+            }
+            oldParent.removeChild(node);
+        }
+        if(refIndex === 0){
+            this.setFirstChild(node);
+        }
+        this.childNodes.splice(refIndex, 0, node);
+        node.parentNode = this;
+        var ps = this.childNodes[refIndex-1];
+        if(ps){
+            node.previousSibling = ps;
+            ps.nextSibling = node;
+        }else{
+            node.previousSibling = null;
+        }
+        node.nextSibling = refNode;
+        refNode.previousSibling = node;
+        node.setOwnerTree(this.getOwnerTree());
+        this.fireEvent("insert", this.ownerTree, this, node, refNode);
+        if(oldParent){
+            node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
+        }
+        return node;
+    },
+
+    
+    remove : function(destroy){
+        if (this.parentNode) {
+            this.parentNode.removeChild(this, destroy);
+        }
+        return this;
+    },
+
+    
+    removeAll : function(destroy){
+        var cn = this.childNodes,
+            n;
+        while((n = cn[0])){
+            this.removeChild(n, destroy);
+        }
+        return this;
+    },
+
+    
+    item : function(index){
+        return this.childNodes[index];
+    },
+
+    
+    replaceChild : function(newChild, oldChild){
+        var s = oldChild ? oldChild.nextSibling : null;
+        this.removeChild(oldChild);
+        this.insertBefore(newChild, s);
+        return oldChild;
+    },
+
+    
+    indexOf : function(child){
+        return this.childNodes.indexOf(child);
+    },
+
+    
+    getOwnerTree : function(){
+        
+        if(!this.ownerTree){
+            var p = this;
+            while(p){
+                if(p.ownerTree){
+                    this.ownerTree = p.ownerTree;
+                    break;
+                }
+                p = p.parentNode;
+            }
+        }
+        return this.ownerTree;
+    },
+
+    
+    getDepth : function(){
+        var depth = 0;
+        var p = this;
+        while(p.parentNode){
+            ++depth;
+            p = p.parentNode;
+        }
+        return depth;
+    },
+
+    
+    setOwnerTree : function(tree, destroy){
+        
+        if(tree != this.ownerTree){
+            if(this.ownerTree){
+                this.ownerTree.unregisterNode(this);
+            }
+            this.ownerTree = tree;
+            
+            if(destroy !== true){
+                Ext.each(this.childNodes, function(n){
+                    n.setOwnerTree(tree);
+                });
+            }
+            if(tree){
+                tree.registerNode(this);
+            }
+        }
+    },
+
+    
+    setId: function(id){
+        if(id !== this.id){
+            var t = this.ownerTree;
+            if(t){
+                t.unregisterNode(this);
+            }
+            this.id = this.attributes.id = id;
+            if(t){
+                t.registerNode(this);
+            }
+            this.onIdChange(id);
+        }
+    },
+
+    
+    onIdChange: Ext.emptyFn,
+
+    
+    getPath : function(attr){
+        attr = attr || "id";
+        var p = this.parentNode;
+        var b = [this.attributes[attr]];
+        while(p){
+            b.unshift(p.attributes[attr]);
+            p = p.parentNode;
+        }
+        var sep = this.getOwnerTree().pathSeparator;
+        return sep + b.join(sep);
+    },
+
+    
+    bubble : function(fn, scope, args){
+        var p = this;
+        while(p){
+            if(fn.apply(scope || p, args || [p]) === false){
+                break;
+            }
+            p = p.parentNode;
+        }
+    },
+
+    
+    cascade : function(fn, scope, args){
+        if(fn.apply(scope || this, args || [this]) !== false){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++) {
+                cs[i].cascade(fn, scope, args);
+            }
+        }
+    },
+
+    
+    eachChild : function(fn, scope, args){
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++) {
+            if(fn.apply(scope || cs[i], args || [cs[i]]) === false){
+                break;
+            }
+        }
+    },
+
+    
+    findChild : function(attribute, value, deep){
+        return this.findChildBy(function(){
+            return this.attributes[attribute] == value;
+        }, null, deep);
+    },
+
+    
+    findChildBy : function(fn, scope, deep){
+        var cs = this.childNodes,
+            len = cs.length,
+            i = 0,
+            n,
+            res;
+        for(; i < len; i++){
+            n = cs[i];
+            if(fn.call(scope || n, n) === true){
+                return n;
+            }else if (deep){
+                res = n.findChildBy(fn, scope, deep);
+                if(res != null){
+                    return res;
+                }
+            }
+            
+        }
+        return null;
+    },
+
+    
+    sort : function(fn, scope){
+        var cs = this.childNodes;
+        var len = cs.length;
+        if(len > 0){
+            var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
+            cs.sort(sortFn);
+            for(var i = 0; i < len; i++){
+                var n = cs[i];
+                n.previousSibling = cs[i-1];
+                n.nextSibling = cs[i+1];
+                if(i === 0){
+                    this.setFirstChild(n);
+                }
+                if(i == len-1){
+                    this.setLastChild(n);
+                }
+            }
+        }
+    },
+
+    
+    contains : function(node){
+        return node.isAncestor(this);
+    },
+
+    
+    isAncestor : function(node){
+        var p = this.parentNode;
+        while(p){
+            if(p == node){
+                return true;
+            }
+            p = p.parentNode;
+        }
+        return false;
+    },
+
+    toString : function(){
+        return "[Node"+(this.id?" "+this.id:"")+"]";
+    }
+});
+Ext.tree.TreeNode = Ext.extend(Ext.data.Node, {
+    
+    constructor : function(attributes){
+        attributes = attributes || {};
+        if(Ext.isString(attributes)){
+            attributes = {text: attributes};
+        }
+        this.childrenRendered = false;
+        this.rendered = false;
+        Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
+        this.expanded = attributes.expanded === true;
+        this.isTarget = attributes.isTarget !== false;
+        this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
+        this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
+
+        
+        this.text = attributes.text;
+        
+        this.disabled = attributes.disabled === true;
+        
+        this.hidden = attributes.hidden === true;
+    
+        this.addEvents(
+            
+            'textchange',
+            
+            'beforeexpand',
+            
+            'beforecollapse',
+            
+            'expand',
+            
+            'disabledchange',
+            
+            'collapse',
+            
+            'beforeclick',
+            
+            'click',
+            
+            'checkchange',
+            
+            'beforedblclick',
+            
+            'dblclick',
+            
+            'contextmenu',
+            
+            'beforechildrenrendered'
+        );
+    
+        var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
+    
+        
+        this.ui = new uiClass(this);    
+    },
+    
+    preventHScroll : true,
+    
+    isExpanded : function(){
+        return this.expanded;
+    },
+
+
+    getUI : function(){
+        return this.ui;
+    },
+
+    getLoader : function(){
+        var owner;
+        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
+    },
+
+    
+    setFirstChild : function(node){
+        var of = this.firstChild;
+        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
+        if(this.childrenRendered && of && node != of){
+            of.renderIndent(true, true);
+        }
+        if(this.rendered){
+            this.renderIndent(true, true);
+        }
+    },
+
+    
+    setLastChild : function(node){
+        var ol = this.lastChild;
+        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
+        if(this.childrenRendered && ol && node != ol){
+            ol.renderIndent(true, true);
+        }
+        if(this.rendered){
+            this.renderIndent(true, true);
+        }
+    },
+
+    
+    
+    appendChild : function(n){
+        if(!n.render && !Ext.isArray(n)){
+            n = this.getLoader().createNode(n);
+        }
+        var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
+        if(node && this.childrenRendered){
+            node.render();
+        }
+        this.ui.updateExpandIcon();
+        return node;
+    },
+
+    
+    removeChild : function(node, destroy){
+        this.ownerTree.getSelectionModel().unselect(node);
+        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
+        
+        if(!destroy){
+            var rendered = node.ui.rendered;
+            
+            if(rendered){
+                node.ui.remove();
+            }
+            if(rendered && this.childNodes.length < 1){
+                this.collapse(false, false);
+            }else{
+                this.ui.updateExpandIcon();
+            }
+            if(!this.firstChild && !this.isHiddenRoot()){
+                this.childrenRendered = false;
+            }
+        }
+        return node;
+    },
+
+    
+    insertBefore : function(node, refNode){
+        if(!node.render){
+            node = this.getLoader().createNode(node);
+        }
+        var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
+        if(newNode && refNode && this.childrenRendered){
+            node.render();
+        }
+        this.ui.updateExpandIcon();
+        return newNode;
+    },
+
+    
+    setText : function(text){
+        var oldText = this.text;
+        this.text = this.attributes.text = text;
+        if(this.rendered){ 
+            this.ui.onTextChange(this, text, oldText);
+        }
+        this.fireEvent('textchange', this, text, oldText);
+    },
+    
+    
+    setIconCls : function(cls){
+        var old = this.attributes.iconCls;
+        this.attributes.iconCls = cls;
+        if(this.rendered){
+            this.ui.onIconClsChange(this, cls, old);
+        }
+    },
+    
+    
+    setTooltip : function(tip, title){
+        this.attributes.qtip = tip;
+        this.attributes.qtipTitle = title;
+        if(this.rendered){
+            this.ui.onTipChange(this, tip, title);
+        }
+    },
+    
+    
+    setIcon : function(icon){
+        this.attributes.icon = icon;
+        if(this.rendered){
+            this.ui.onIconChange(this, icon);
+        }
+    },
+    
+    
+    setHref : function(href, target){
+        this.attributes.href = href;
+        this.attributes.hrefTarget = target;
+        if(this.rendered){
+            this.ui.onHrefChange(this, href, target);
+        }
+    },
+    
+    
+    setCls : function(cls){
+        var old = this.attributes.cls;
+        this.attributes.cls = cls;
+        if(this.rendered){
+            this.ui.onClsChange(this, cls, old);
+        }
+    },
+
+    
+    select : function(){
+        var t = this.getOwnerTree();
+        if(t){
+            t.getSelectionModel().select(this);
+        }
+    },
+
+    
+    unselect : function(silent){
+        var t = this.getOwnerTree();
+        if(t){
+            t.getSelectionModel().unselect(this, silent);
+        }
+    },
+
+    
+    isSelected : function(){
+        var t = this.getOwnerTree();
+        return t ? t.getSelectionModel().isSelected(this) : false;
+    },
+
+    
+    expand : function(deep, anim, callback, scope){
+        if(!this.expanded){
+            if(this.fireEvent('beforeexpand', this, deep, anim) === false){
+                return;
+            }
+            if(!this.childrenRendered){
+                this.renderChildren();
+            }
+            this.expanded = true;
+            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
+                this.ui.animExpand(function(){
+                    this.fireEvent('expand', this);
+                    this.runCallback(callback, scope || this, [this]);
+                    if(deep === true){
+                        this.expandChildNodes(true, true);
+                    }
+                }.createDelegate(this));
+                return;
+            }else{
+                this.ui.expand();
+                this.fireEvent('expand', this);
+                this.runCallback(callback, scope || this, [this]);
+            }
+        }else{
+           this.runCallback(callback, scope || this, [this]);
+        }
+        if(deep === true){
+            this.expandChildNodes(true);
+        }
+    },
+
+    runCallback : function(cb, scope, args){
+        if(Ext.isFunction(cb)){
+            cb.apply(scope, args);
+        }
+    },
+
+    isHiddenRoot : function(){
+        return this.isRoot && !this.getOwnerTree().rootVisible;
+    },
+
+    
+    collapse : function(deep, anim, callback, scope){
+        if(this.expanded && !this.isHiddenRoot()){
+            if(this.fireEvent('beforecollapse', this, deep, anim) === false){
+                return;
+            }
+            this.expanded = false;
+            if((this.getOwnerTree().animate && anim !== false) || anim){
+                this.ui.animCollapse(function(){
+                    this.fireEvent('collapse', this);
+                    this.runCallback(callback, scope || this, [this]);
+                    if(deep === true){
+                        this.collapseChildNodes(true);
+                    }
+                }.createDelegate(this));
+                return;
+            }else{
+                this.ui.collapse();
+                this.fireEvent('collapse', this);
+                this.runCallback(callback, scope || this, [this]);
+            }
+        }else if(!this.expanded){
+            this.runCallback(callback, scope || this, [this]);
+        }
+        if(deep === true){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++) {
+            	cs[i].collapse(true, false);
+            }
+        }
+    },
+
+    
+    delayedExpand : function(delay){
+        if(!this.expandProcId){
+            this.expandProcId = this.expand.defer(delay, this);
+        }
+    },
+
+    
+    cancelExpand : function(){
+        if(this.expandProcId){
+            clearTimeout(this.expandProcId);
+        }
+        this.expandProcId = false;
+    },
+
+    
+    toggle : function(){
+        if(this.expanded){
+            this.collapse();
+        }else{
+            this.expand();
+        }
+    },
+
+    
+    ensureVisible : function(callback, scope){
+        var tree = this.getOwnerTree();
+        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
+            var node = tree.getNodeById(this.id);  
+            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
+            this.runCallback(callback, scope || this, [this]);
+        }.createDelegate(this));
+    },
+
+    
+    expandChildNodes : function(deep, anim) {
+        var cs = this.childNodes,
+            i,
+            len = cs.length;
+        for (i = 0; i < len; i++) {
+        	cs[i].expand(deep, anim);
+        }
+    },
+
+    
+    collapseChildNodes : function(deep){
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++) {
+        	cs[i].collapse(deep);
+        }
+    },
+
+    
+    disable : function(){
+        this.disabled = true;
+        this.unselect();
+        if(this.rendered && this.ui.onDisableChange){ 
+            this.ui.onDisableChange(this, true);
+        }
+        this.fireEvent('disabledchange', this, true);
+    },
+
+    
+    enable : function(){
+        this.disabled = false;
+        if(this.rendered && this.ui.onDisableChange){ 
+            this.ui.onDisableChange(this, false);
+        }
+        this.fireEvent('disabledchange', this, false);
+    },
+
+    
+    renderChildren : function(suppressEvent){
+        if(suppressEvent !== false){
+            this.fireEvent('beforechildrenrendered', this);
+        }
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i].render(true);
+        }
+        this.childrenRendered = true;
+    },
+
+    
+    sort : function(fn, scope){
+        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
+        if(this.childrenRendered){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++){
+                cs[i].render(true);
+            }
+        }
+    },
+
+    
+    render : function(bulkRender){
+        this.ui.render(bulkRender);
+        if(!this.rendered){
+            
+            this.getOwnerTree().registerNode(this);
+            this.rendered = true;
+            if(this.expanded){
+                this.expanded = false;
+                this.expand(false, false);
+            }
+        }
+    },
+
+    
+    renderIndent : function(deep, refresh){
+        if(refresh){
+            this.ui.childIndent = null;
+        }
+        this.ui.renderIndent();
+        if(deep === true && this.childrenRendered){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++){
+                cs[i].renderIndent(true, refresh);
+            }
+        }
+    },
+
+    beginUpdate : function(){
+        this.childrenRendered = false;
+    },
+
+    endUpdate : function(){
+        if(this.expanded && this.rendered){
+            this.renderChildren();
+        }
+    },
+
+    
+    destroy : function(silent){
+        if(silent === true){
+            this.unselect(true);
+        }
+        Ext.tree.TreeNode.superclass.destroy.call(this, silent);
+        Ext.destroy(this.ui, this.loader);
+        this.ui = this.loader = null;
+    },
+
+    
+    onIdChange : function(id){
+        this.ui.onIdChange(id);
+    }
+});
+
+Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
+ Ext.tree.AsyncTreeNode = function(config){
+    this.loaded = config && config.loaded === true;
+    this.loading = false;
+    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
+    
+    this.addEvents('beforeload', 'load');
+    
+    
+};
+Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
+    expand : function(deep, anim, callback, scope){
+        if(this.loading){ 
+            var timer;
+            var f = function(){
+                if(!this.loading){ 
+                    clearInterval(timer);
+                    this.expand(deep, anim, callback, scope);
+                }
+            }.createDelegate(this);
+            timer = setInterval(f, 200);
+            return;
+        }
+        if(!this.loaded){
+            if(this.fireEvent("beforeload", this) === false){
+                return;
+            }
+            this.loading = true;
+            this.ui.beforeLoad(this);
+            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
+            if(loader){
+                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
+                return;
+            }
+        }
+        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
+    },
+    
+    
+    isLoading : function(){
+        return this.loading;  
+    },
+    
+    loadComplete : function(deep, anim, callback, scope){
+        this.loading = false;
+        this.loaded = true;
+        this.ui.afterLoad(this);
+        this.fireEvent("load", this);
+        this.expand(deep, anim, callback, scope);
+    },
+    
+    
+    isLoaded : function(){
+        return this.loaded;
+    },
+    
+    hasChildNodes : function(){
+        if(!this.isLeaf() && !this.loaded){
+            return true;
+        }else{
+            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
+        }
+    },
+
+    
+    reload : function(callback, scope){
+        this.collapse(false, false);
+        while(this.firstChild){
+            this.removeChild(this.firstChild).destroy();
+        }
+        this.childrenRendered = false;
+        this.loaded = false;
+        if(this.isHiddenRoot()){
+            this.expanded = false;
+        }
+        this.expand(false, false, callback, scope);
+    }
+});
+
+Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
+Ext.tree.TreeNodeUI = Ext.extend(Object, {
+    
+    constructor : function(node){
+        Ext.apply(this, {
+            node: node,
+            rendered: false,
+            animating: false,
+            wasLeaf: true,
+            ecc: 'x-tree-ec-icon x-tree-elbow',
+            emptyIcon: Ext.BLANK_IMAGE_URL    
+        });
+    },
+    
+    
+    removeChild : function(node){
+        if(this.rendered){
+            this.ctNode.removeChild(node.ui.getEl());
+        }
+    },
+
+    
+    beforeLoad : function(){
+         this.addClass("x-tree-node-loading");
+    },
+
+    
+    afterLoad : function(){
+         this.removeClass("x-tree-node-loading");
+    },
+
+    
+    onTextChange : function(node, text, oldText){
+        if(this.rendered){
+            this.textNode.innerHTML = text;
+        }
+    },
+    
+    
+    onIconClsChange : function(node, cls, oldCls){
+        if(this.rendered){
+            Ext.fly(this.iconNode).replaceClass(oldCls, cls);
+        }
+    },
+    
+    
+    onIconChange : function(node, icon){
+        if(this.rendered){
+            
+            var empty = Ext.isEmpty(icon);
+            this.iconNode.src = empty ? this.emptyIcon : icon;
+            Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon');
+        }
+    },
+    
+    
+    onTipChange : function(node, tip, title){
+        if(this.rendered){
+            var hasTitle = Ext.isDefined(title);
+            if(this.textNode.setAttributeNS){
+                this.textNode.setAttributeNS("ext", "qtip", tip);
+                if(hasTitle){
+                    this.textNode.setAttributeNS("ext", "qtitle", title);
+                }
+            }else{
+                this.textNode.setAttribute("ext:qtip", tip);
+                if(hasTitle){
+                    this.textNode.setAttribute("ext:qtitle", title);
+                }
+            }
+        }
+    },
+    
+    
+    onHrefChange : function(node, href, target){
+        if(this.rendered){
+            this.anchor.href = this.getHref(href);
+            if(Ext.isDefined(target)){
+                this.anchor.target = target;
+            }
+        }
+    },
+    
+    
+    onClsChange : function(node, cls, oldCls){
+        if(this.rendered){
+            Ext.fly(this.elNode).replaceClass(oldCls, cls);
+        }    
+    },
+
+    
+    onDisableChange : function(node, state){
+        this.disabled = state;
+        if (this.checkbox) {
+            this.checkbox.disabled = state;
+        }
+        this[state ? 'addClass' : 'removeClass']('x-tree-node-disabled');
+    },
+
+    
+    onSelectedChange : function(state){
+        if(state){
+            this.focus();
+            this.addClass("x-tree-selected");
+        }else{
+            
+            this.removeClass("x-tree-selected");
+        }
+    },
+
+    
+    onMove : function(tree, node, oldParent, newParent, index, refNode){
+        this.childIndent = null;
+        if(this.rendered){
+            var targetNode = newParent.ui.getContainer();
+            if(!targetNode){
+                this.holder = document.createElement("div");
+                this.holder.appendChild(this.wrap);
+                return;
+            }
+            var insertBefore = refNode ? refNode.ui.getEl() : null;
+            if(insertBefore){
+                targetNode.insertBefore(this.wrap, insertBefore);
+            }else{
+                targetNode.appendChild(this.wrap);
+            }
+            this.node.renderIndent(true, oldParent != newParent);
+        }
+    },
+
+
+    addClass : function(cls){
+        if(this.elNode){
+            Ext.fly(this.elNode).addClass(cls);
+        }
+    },
+
+
+    removeClass : function(cls){
+        if(this.elNode){
+            Ext.fly(this.elNode).removeClass(cls);
+        }
+    },
+
+    
+    remove : function(){
+        if(this.rendered){
+            this.holder = document.createElement("div");
+            this.holder.appendChild(this.wrap);
+        }
+    },
+
+    
+    fireEvent : function(){
+        return this.node.fireEvent.apply(this.node, arguments);
+    },
+
+    
+    initEvents : function(){
+        this.node.on("move", this.onMove, this);
+
+        if(this.node.disabled){
+            this.onDisableChange(this.node, true);
+        }
+        if(this.node.hidden){
+            this.hide();
+        }
+        var ot = this.node.getOwnerTree();
+        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
+        if(dd && (!this.node.isRoot || ot.rootVisible)){
+            Ext.dd.Registry.register(this.elNode, {
+                node: this.node,
+                handles: this.getDDHandles(),
+                isHandle: false
+            });
+        }
+    },
+
+    
+    getDDHandles : function(){
+        return [this.iconNode, this.textNode, this.elNode];
+    },
+
+
+    hide : function(){
+        this.node.hidden = true;
+        if(this.wrap){
+            this.wrap.style.display = "none";
+        }
+    },
+
+
+    show : function(){
+        this.node.hidden = false;
+        if(this.wrap){
+            this.wrap.style.display = "";
+        }
+    },
+
+    
+    onContextMenu : function(e){
+        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
+            e.preventDefault();
+            this.focus();
+            this.fireEvent("contextmenu", this.node, e);
+        }
+    },
+
+    
+    onClick : function(e){
+        if(this.dropping){
+            e.stopEvent();
+            return;
+        }
+        if(this.fireEvent("beforeclick", this.node, e) !== false){
+            var a = e.getTarget('a');
+            if(!this.disabled && this.node.attributes.href && a){
+                this.fireEvent("click", this.node, e);
+                return;
+            }else if(a && e.ctrlKey){
+                e.stopEvent();
+            }
+            e.preventDefault();
+            if(this.disabled){
+                return;
+            }
+
+            if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
+                this.node.toggle();
+            }
+
+            this.fireEvent("click", this.node, e);
+        }else{
+            e.stopEvent();
+        }
+    },
+
+    
+    onDblClick : function(e){
+        e.preventDefault();
+        if(this.disabled){
+            return;
+        }
+        if(this.fireEvent("beforedblclick", this.node, e) !== false){
+            if(this.checkbox){
+                this.toggleCheck();
+            }
+            if(!this.animating && this.node.isExpandable()){
+                this.node.toggle();
+            }
+            this.fireEvent("dblclick", this.node, e);
+        }
+    },
+
+    onOver : function(e){
+        this.addClass('x-tree-node-over');
+    },
+
+    onOut : function(e){
+        this.removeClass('x-tree-node-over');
+    },
+
+    
+    onCheckChange : function(){
+        var checked = this.checkbox.checked;
+        
+        this.checkbox.defaultChecked = checked;
+        this.node.attributes.checked = checked;
+        this.fireEvent('checkchange', this.node, checked);
+    },
+
+    
+    ecClick : function(e){
+        if(!this.animating && this.node.isExpandable()){
+            this.node.toggle();
+        }
+    },
+
+    
+    startDrop : function(){
+        this.dropping = true;
+    },
+
+    
+    endDrop : function(){
+       setTimeout(function(){
+           this.dropping = false;
+       }.createDelegate(this), 50);
+    },
+
+    
+    expand : function(){
+        this.updateExpandIcon();
+        this.ctNode.style.display = "";
+    },
+
+    
+    focus : function(){
+        if(!this.node.preventHScroll){
+            try{this.anchor.focus();
+            }catch(e){}
+        }else{
+            try{
+                var noscroll = this.node.getOwnerTree().getTreeEl().dom;
+                var l = noscroll.scrollLeft;
+                this.anchor.focus();
+                noscroll.scrollLeft = l;
+            }catch(e){}
+        }
+    },
+
+
+    toggleCheck : function(value){
+        var cb = this.checkbox;
+        if(cb){
+            cb.checked = (value === undefined ? !cb.checked : value);
+            this.onCheckChange();
+        }
+    },
+
+    
+    blur : function(){
+        try{
+            this.anchor.blur();
+        }catch(e){}
+    },
+
+    
+    animExpand : function(callback){
+        var ct = Ext.get(this.ctNode);
+        ct.stopFx();
+        if(!this.node.isExpandable()){
+            this.updateExpandIcon();
+            this.ctNode.style.display = "";
+            Ext.callback(callback);
+            return;
+        }
+        this.animating = true;
+        this.updateExpandIcon();
+
+        ct.slideIn('t', {
+           callback : function(){
+               this.animating = false;
+               Ext.callback(callback);
+            },
+            scope: this,
+            duration: this.node.ownerTree.duration || .25
+        });
+    },
+
+    
+    highlight : function(){
+        var tree = this.node.getOwnerTree();
+        Ext.fly(this.wrap).highlight(
+            tree.hlColor || "C3DAF9",
+            {endColor: tree.hlBaseColor}
+        );
+    },
+
+    
+    collapse : function(){
+        this.updateExpandIcon();
+        this.ctNode.style.display = "none";
+    },
+
+    
+    animCollapse : function(callback){
+        var ct = Ext.get(this.ctNode);
+        ct.enableDisplayMode('block');
+        ct.stopFx();
+
+        this.animating = true;
+        this.updateExpandIcon();
+
+        ct.slideOut('t', {
+            callback : function(){
+               this.animating = false;
+               Ext.callback(callback);
+            },
+            scope: this,
+            duration: this.node.ownerTree.duration || .25
+        });
+    },
+
+    
+    getContainer : function(){
+        return this.ctNode;
+    },
+
+
+    getEl : function(){
+        return this.wrap;
+    },
+
+    
+    appendDDGhost : function(ghostNode){
+        ghostNode.appendChild(this.elNode.cloneNode(true));
+    },
+
+    
+    getDDRepairXY : function(){
+        return Ext.lib.Dom.getXY(this.iconNode);
+    },
+
+    
+    onRender : function(){
+        this.render();
+    },
+
+    
+    render : function(bulkRender){
+        var n = this.node, a = n.attributes;
+        var targetNode = n.parentNode ?
+              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
+
+        if(!this.rendered){
+            this.rendered = true;
+
+            this.renderElements(n, a, targetNode, bulkRender);
+
+            if(a.qtip){
+                this.onTipChange(n, a.qtip, a.qtipTitle);
+            }else if(a.qtipCfg){
+                a.qtipCfg.target = Ext.id(this.textNode);
+                Ext.QuickTips.register(a.qtipCfg);
+            }
+            this.initEvents();
+            if(!this.node.expanded){
+                this.updateExpandIcon(true);
+            }
+        }else{
+            if(bulkRender === true) {
+                targetNode.appendChild(this.wrap);
+            }
+        }
+    },
+
+    
+    renderElements : function(n, a, targetNode, bulkRender){
+        
+        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
+
+        var cb = Ext.isBoolean(a.checked),
+            nel,
+            href = this.getHref(a.href),
+            buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
+            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
+            '<img alt="" src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
+            '<img alt="" src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
+            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
+            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
+             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
+            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
+            "</li>"].join('');
+
+        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
+            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
+        }else{
+            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
+        }
+
+        this.elNode = this.wrap.childNodes[0];
+        this.ctNode = this.wrap.childNodes[1];
+        var cs = this.elNode.childNodes;
+        this.indentNode = cs[0];
+        this.ecNode = cs[1];
+        this.iconNode = cs[2];
+        var index = 3;
+        if(cb){
+            this.checkbox = cs[3];
+            
+            this.checkbox.defaultChecked = this.checkbox.checked;
+            index++;
+        }
+        this.anchor = cs[index];
+        this.textNode = cs[index].firstChild;
+    },
+    
+    
+    getHref : function(href){
+        return Ext.isEmpty(href) ? (Ext.isGecko ? '' : '#') : href;
+    },
+
+
+    getAnchor : function(){
+        return this.anchor;
+    },
+
+
+    getTextEl : function(){
+        return this.textNode;
+    },
+
+
+    getIconEl : function(){
+        return this.iconNode;
+    },
+
+
+    isChecked : function(){
+        return this.checkbox ? this.checkbox.checked : false;
+    },
+
+    
+    updateExpandIcon : function(){
+        if(this.rendered){
+            var n = this.node,
+                c1,
+                c2,
+                cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
+                hasChild = n.hasChildNodes();
+            if(hasChild || n.attributes.expandable){
+                if(n.expanded){
+                    cls += "-minus";
+                    c1 = "x-tree-node-collapsed";
+                    c2 = "x-tree-node-expanded";
+                }else{
+                    cls += "-plus";
+                    c1 = "x-tree-node-expanded";
+                    c2 = "x-tree-node-collapsed";
+                }
+                if(this.wasLeaf){
+                    this.removeClass("x-tree-node-leaf");
+                    this.wasLeaf = false;
+                }
+                if(this.c1 != c1 || this.c2 != c2){
+                    Ext.fly(this.elNode).replaceClass(c1, c2);
+                    this.c1 = c1; this.c2 = c2;
+                }
+            }else{
+                if(!this.wasLeaf){
+                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
+                    delete this.c1;
+                    delete this.c2;
+                    this.wasLeaf = true;
+                }
+            }
+            var ecc = "x-tree-ec-icon "+cls;
+            if(this.ecc != ecc){
+                this.ecNode.className = ecc;
+                this.ecc = ecc;
+            }
+        }
+    },
+
+    
+    onIdChange: function(id){
+        if(this.rendered){
+            this.elNode.setAttribute('ext:tree-node-id', id);
+        }
+    },
+
+    
+    getChildIndent : function(){
+        if(!this.childIndent){
+            var buf = [],
+                p = this.node;
+            while(p){
+                if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
+                    if(!p.isLast()) {
+                        buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
+                    } else {
+                        buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-icon" />');
+                    }
+                }
+                p = p.parentNode;
+            }
+            this.childIndent = buf.join("");
+        }
+        return this.childIndent;
+    },
+
+    
+    renderIndent : function(){
+        if(this.rendered){
+            var indent = "",
+                p = this.node.parentNode;
+            if(p){
+                indent = p.ui.getChildIndent();
+            }
+            if(this.indentMarkup != indent){ 
+                this.indentNode.innerHTML = indent;
+                this.indentMarkup = indent;
+            }
+            this.updateExpandIcon();
+        }
+    },
+
+    destroy : function(){
+        if(this.elNode){
+            Ext.dd.Registry.unregister(this.elNode.id);
+        }
+
+        Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
+            if(this[el]){
+                Ext.fly(this[el]).remove();
+                delete this[el];
+            }
+        }, this);
+        delete this.node;
+    }
+});
+
+
+Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+    
+    render : function(){
+        if(!this.rendered){
+            var targetNode = this.node.ownerTree.innerCt.dom;
+            this.node.expanded = true;
+            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
+            this.wrap = this.ctNode = targetNode.firstChild;
+        }
+    },
+    collapse : Ext.emptyFn,
+    expand : Ext.emptyFn
+});
+Ext.tree.TreeLoader = function(config){
+    this.baseParams = {};
+    Ext.apply(this, config);
+
+    this.addEvents(
+        
+        "beforeload",
+        
+        "load",
+        
+        "loadexception"
+    );
+    Ext.tree.TreeLoader.superclass.constructor.call(this);
+    if(Ext.isString(this.paramOrder)){
+        this.paramOrder = this.paramOrder.split(/[\s,|]/);
+    }
+};
+
+Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
+    
+    
+    
+    
+    
+    
+    
+    uiProviders : {},
+
+    
+    clearOnLoad : true,
+
+    
+    paramOrder: undefined,
+
+    
+    paramsAsHash: false,
+
+    
+    nodeParameter: 'node',
+
+    
+    directFn : undefined,
+
+    
+    load : function(node, callback, scope){
+        if(this.clearOnLoad){
+            while(node.firstChild){
+                node.removeChild(node.firstChild);
+            }
+        }
+        if(this.doPreload(node)){ 
+            this.runCallback(callback, scope || node, [node]);
+        }else if(this.directFn || this.dataUrl || this.url){
+            this.requestData(node, callback, scope || node);
+        }
+    },
+
+    doPreload : function(node){
+        if(node.attributes.children){
+            if(node.childNodes.length < 1){ 
+                var cs = node.attributes.children;
+                node.beginUpdate();
+                for(var i = 0, len = cs.length; i < len; i++){
+                    var cn = node.appendChild(this.createNode(cs[i]));
+                    if(this.preloadChildren){
+                        this.doPreload(cn);
+                    }
+                }
+                node.endUpdate();
+            }
+            return true;
+        }
+        return false;
+    },
+
+    getParams: function(node){
+        var bp = Ext.apply({}, this.baseParams),
+            np = this.nodeParameter,
+            po = this.paramOrder;
+
+        np && (bp[ np ] = node.id);
+
+        if(this.directFn){
+            var buf = [node.id];
+            if(po){
+                
+                if(np && po.indexOf(np) > -1){
+                    buf = [];
+                }
+
+                for(var i = 0, len = po.length; i < len; i++){
+                    buf.push(bp[ po[i] ]);
+                }
+            }else if(this.paramsAsHash){
+                buf = [bp];
+            }
+            return buf;
+        }else{
+            return bp;
+        }
+    },
+
+    requestData : function(node, callback, scope){
+        if(this.fireEvent("beforeload", this, node, callback) !== false){
+            if(this.directFn){
+                var args = this.getParams(node);
+                args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
+                this.directFn.apply(window, args);
+            }else{
+                this.transId = Ext.Ajax.request({
+                    method:this.requestMethod,
+                    url: this.dataUrl||this.url,
+                    success: this.handleResponse,
+                    failure: this.handleFailure,
+                    scope: this,
+                    argument: {callback: callback, node: node, scope: scope},
+                    params: this.getParams(node)
+                });
+            }
+        }else{
+            
+            
+            this.runCallback(callback, scope || node, []);
+        }
+    },
+
+    processDirectResponse: function(result, response, args){
+        if(response.status){
+            this.handleResponse({
+                responseData: Ext.isArray(result) ? result : null,
+                responseText: result,
+                argument: args
+            });
+        }else{
+            this.handleFailure({
+                argument: args
+            });
+        }
+    },
+
+    
+    runCallback: function(cb, scope, args){
+        if(Ext.isFunction(cb)){
+            cb.apply(scope, args);
+        }
+    },
+
+    isLoading : function(){
+        return !!this.transId;
+    },
+
+    abort : function(){
+        if(this.isLoading()){
+            Ext.Ajax.abort(this.transId);
+        }
+    },
+
+    
+    createNode : function(attr){
+        
+        if(this.baseAttrs){
+            Ext.applyIf(attr, this.baseAttrs);
+        }
+        if(this.applyLoader !== false && !attr.loader){
+            attr.loader = this;
+        }
+        if(Ext.isString(attr.uiProvider)){
+           attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
+        }
+        if(attr.nodeType){
+            return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
+        }else{
+            return attr.leaf ?
+                        new Ext.tree.TreeNode(attr) :
+                        new Ext.tree.AsyncTreeNode(attr);
+        }
+    },
+
+    processResponse : function(response, node, callback, scope){
+        var json = response.responseText;
+        try {
+            var o = response.responseData || Ext.decode(json);
+            node.beginUpdate();
+            for(var i = 0, len = o.length; i < len; i++){
+                var n = this.createNode(o[i]);
+                if(n){
+                    node.appendChild(n);
+                }
+            }
+            node.endUpdate();
+            this.runCallback(callback, scope || node, [node]);
+        }catch(e){
+            this.handleFailure(response);
+        }
+    },
+
+    handleResponse : function(response){
+        this.transId = false;
+        var a = response.argument;
+        this.processResponse(response, a.node, a.callback, a.scope);
+        this.fireEvent("load", this, a.node, response);
+    },
+
+    handleFailure : function(response){
+        this.transId = false;
+        var a = response.argument;
+        this.fireEvent("loadexception", this, a.node, response);
+        this.runCallback(a.callback, a.scope || a.node, [a.node]);
+    },
+
+    destroy : function(){
+        this.abort();
+        this.purgeListeners();
+    }
+});
+Ext.tree.TreeFilter = function(tree, config){
+    this.tree = tree;
+    this.filtered = {};
+    Ext.apply(this, config);
+};
+
+Ext.tree.TreeFilter.prototype = {
+    clearBlank:false,
+    reverse:false,
+    autoClear:false,
+    remove:false,
+
+     
+    filter : function(value, attr, startNode){
+        attr = attr || "text";
+        var f;
+        if(typeof value == "string"){
+            var vlen = value.length;
+            
+            if(vlen == 0 && this.clearBlank){
+                this.clear();
+                return;
+            }
+            value = value.toLowerCase();
+            f = function(n){
+                return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
+            };
+        }else if(value.exec){ 
+            f = function(n){
+                return value.test(n.attributes[attr]);
+            };
+        }else{
+            throw 'Illegal filter type, must be string or regex';
+        }
+        this.filterBy(f, null, startNode);
+	},
+
+    
+    filterBy : function(fn, scope, startNode){
+        startNode = startNode || this.tree.root;
+        if(this.autoClear){
+            this.clear();
+        }
+        var af = this.filtered, rv = this.reverse;
+        var f = function(n){
+            if(n == startNode){
+                return true;
+            }
+            if(af[n.id]){
+                return false;
+            }
+            var m = fn.call(scope || n, n);
+            if(!m || rv){
+                af[n.id] = n;
+                n.ui.hide();
+                return false;
+            }
+            return true;
+        };
+        startNode.cascade(f);
+        if(this.remove){
+           for(var id in af){
+               if(typeof id != "function"){
+                   var n = af[id];
+                   if(n && n.parentNode){
+                       n.parentNode.removeChild(n);
+                   }
+               }
+           }
+        }
+    },
+
+    
+    clear : function(){
+        var t = this.tree;
+        var af = this.filtered;
+        for(var id in af){
+            if(typeof id != "function"){
+                var n = af[id];
+                if(n){
+                    n.ui.show();
+                }
+            }
+        }
+        this.filtered = {};
+    }
+};
+
+Ext.tree.TreeSorter = Ext.extend(Object, {
+    
+    constructor: function(tree, config){
+        
+    
+    
+    
+    
+    
+
+    Ext.apply(this, config);
+    tree.on({
+        scope: this,
+        beforechildrenrendered: this.doSort,
+        append: this.updateSort,
+        insert: this.updateSort,
+        textchange: this.updateSortParent
+    });
+
+    var desc = this.dir && this.dir.toLowerCase() == 'desc',
+        prop = this.property || 'text',
+        sortType = this.sortType,
+        folderSort = this.folderSort,
+        caseSensitive = this.caseSensitive === true,
+        leafAttr = this.leafAttr || 'leaf';
+
+    if(Ext.isString(sortType)){
+        sortType = Ext.data.SortTypes[sortType];
+    }
+    this.sortFn = function(n1, n2){
+        var attr1 = n1.attributes,
+            attr2 = n2.attributes;
+            
+        if(folderSort){
+            if(attr1[leafAttr] && !attr2[leafAttr]){
+                return 1;
+            }
+            if(!attr1[leafAttr] && attr2[leafAttr]){
+                return -1;
+            }
+        }
+        var prop1 = attr1[prop],
+            prop2 = attr2[prop],
+            v1 = sortType ? sortType(prop1) : (caseSensitive ? prop1 : prop1.toUpperCase()),
+            v2 = sortType ? sortType(prop2) : (caseSensitive ? prop2 : prop2.toUpperCase());
+            
+        if(v1 < v2){
+            return desc ? 1 : -1;
+        }else if(v1 > v2){
+            return desc ? -1 : 1;
+        }
+        return 0;
+    };
+    },
+    
+    doSort : function(node){
+        node.sort(this.sortFn);
+    },
+
+    updateSort : function(tree, node){
+        if(node.childrenRendered){
+            this.doSort.defer(1, this, [node]);
+        }
+    },
+
+    updateSortParent : function(node){
+        var p = node.parentNode;
+        if(p && p.childrenRendered){
+            this.doSort.defer(1, this, [p]);
+        }
+    }    
+});
+
+if(Ext.dd.DropZone){
+    
+Ext.tree.TreeDropZone = function(tree, config){
+    
+    this.allowParentInsert = config.allowParentInsert || false;
+    
+    this.allowContainerDrop = config.allowContainerDrop || false;
+    
+    this.appendOnly = config.appendOnly || false;
+
+    Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
+    
+    this.tree = tree;
+    
+    this.dragOverData = {};
+    
+    this.lastInsertClass = "x-tree-no-status";
+};
+
+Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
+    
+    ddGroup : "TreeDD",
+
+    
+    expandDelay : 1000,
+
+    
+    expandNode : function(node){
+        if(node.hasChildNodes() && !node.isExpanded()){
+            node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
+        }
+    },
+
+    
+    queueExpand : function(node){
+        this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
+    },
+
+    
+    cancelExpand : function(){
+        if(this.expandProcId){
+            clearTimeout(this.expandProcId);
+            this.expandProcId = false;
+        }
+    },
+
+    
+    isValidDropPoint : function(n, pt, dd, e, data){
+        if(!n || !data){ return false; }
+        var targetNode = n.node;
+        var dropNode = data.node;
+        
+        if(!(targetNode && targetNode.isTarget && pt)){
+            return false;
+        }
+        if(pt == "append" && targetNode.allowChildren === false){
+            return false;
+        }
+        if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
+            return false;
+        }
+        if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
+            return false;
+        }
+        
+        var overEvent = this.dragOverData;
+        overEvent.tree = this.tree;
+        overEvent.target = targetNode;
+        overEvent.data = data;
+        overEvent.point = pt;
+        overEvent.source = dd;
+        overEvent.rawEvent = e;
+        overEvent.dropNode = dropNode;
+        overEvent.cancel = false;  
+        var result = this.tree.fireEvent("nodedragover", overEvent);
+        return overEvent.cancel === false && result !== false;
+    },
+
+    
+    getDropPoint : function(e, n, dd){
+        var tn = n.node;
+        if(tn.isRoot){
+            return tn.allowChildren !== false ? "append" : false; 
+        }
+        var dragEl = n.ddel;
+        var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
+        var y = Ext.lib.Event.getPageY(e);
+        var noAppend = tn.allowChildren === false || tn.isLeaf();
+        if(this.appendOnly || tn.parentNode.allowChildren === false){
+            return noAppend ? false : "append";
+        }
+        var noBelow = false;
+        if(!this.allowParentInsert){
+            noBelow = tn.hasChildNodes() && tn.isExpanded();
+        }
+        var q = (b - t) / (noAppend ? 2 : 3);
+        if(y >= t && y < (t + q)){
+            return "above";
+        }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
+            return "below";
+        }else{
+            return "append";
+        }
+    },
+
+    
+    onNodeEnter : function(n, dd, e, data){
+        this.cancelExpand();
+    },
+    
+    onContainerOver : function(dd, e, data) {
+        if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
+            return this.dropAllowed;
+        }
+        return this.dropNotAllowed;
+    },
+
+    
+    onNodeOver : function(n, dd, e, data){
+        var pt = this.getDropPoint(e, n, dd);
+        var node = n.node;
+        
+        
+        if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
+            this.queueExpand(node);
+        }else if(pt != "append"){
+            this.cancelExpand();
+        }
+        
+        
+        var returnCls = this.dropNotAllowed;
+        if(this.isValidDropPoint(n, pt, dd, e, data)){
+           if(pt){
+               var el = n.ddel;
+               var cls;
+               if(pt == "above"){
+                   returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
+                   cls = "x-tree-drag-insert-above";
+               }else if(pt == "below"){
+                   returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
+                   cls = "x-tree-drag-insert-below";
+               }else{
+                   returnCls = "x-tree-drop-ok-append";
+                   cls = "x-tree-drag-append";
+               }
+               if(this.lastInsertClass != cls){
+                   Ext.fly(el).replaceClass(this.lastInsertClass, cls);
+                   this.lastInsertClass = cls;
+               }
+           }
+       }
+       return returnCls;
+    },
+
+    
+    onNodeOut : function(n, dd, e, data){
+        this.cancelExpand();
+        this.removeDropIndicators(n);
+    },
+
+    
+    onNodeDrop : function(n, dd, e, data){
+        var point = this.getDropPoint(e, n, dd);
+        var targetNode = n.node;
+        targetNode.ui.startDrop();
+        if(!this.isValidDropPoint(n, point, dd, e, data)){
+            targetNode.ui.endDrop();
+            return false;
+        }
+        
+        var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
+        return this.processDrop(targetNode, data, point, dd, e, dropNode);
+    },
+    
+    onContainerDrop : function(dd, e, data){
+        if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
+            var targetNode = this.tree.getRootNode();       
+            targetNode.ui.startDrop();
+            var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
+            return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
+        }
+        return false;
+    },
+    
+    
+    processDrop: function(target, data, point, dd, e, dropNode){
+        var dropEvent = {
+            tree : this.tree,
+            target: target,
+            data: data,
+            point: point,
+            source: dd,
+            rawEvent: e,
+            dropNode: dropNode,
+            cancel: !dropNode,
+            dropStatus: false
+        };
+        var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
+        if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
+            target.ui.endDrop();
+            return dropEvent.dropStatus;
+        }
+    
+        target = dropEvent.target;
+        if(point == 'append' && !target.isExpanded()){
+            target.expand(false, null, function(){
+                this.completeDrop(dropEvent);
+            }.createDelegate(this));
+        }else{
+            this.completeDrop(dropEvent);
+        }
+        return true;
+    },
+
+    
+    completeDrop : function(de){
+        var ns = de.dropNode, p = de.point, t = de.target;
+        if(!Ext.isArray(ns)){
+            ns = [ns];
+        }
+        var n;
+        for(var i = 0, len = ns.length; i < len; i++){
+            n = ns[i];
+            if(p == "above"){
+                t.parentNode.insertBefore(n, t);
+            }else if(p == "below"){
+                t.parentNode.insertBefore(n, t.nextSibling);
+            }else{
+                t.appendChild(n);
+            }
+        }
+        n.ui.focus();
+        if(Ext.enableFx && this.tree.hlDrop){
+            n.ui.highlight();
+        }
+        t.ui.endDrop();
+        this.tree.fireEvent("nodedrop", de);
+    },
+
+    
+    afterNodeMoved : function(dd, data, e, targetNode, dropNode){
+        if(Ext.enableFx && this.tree.hlDrop){
+            dropNode.ui.focus();
+            dropNode.ui.highlight();
+        }
+        this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
+    },
+
+    
+    getTree : function(){
+        return this.tree;
+    },
+
+    
+    removeDropIndicators : function(n){
+        if(n && n.ddel){
+            var el = n.ddel;
+            Ext.fly(el).removeClass([
+                    "x-tree-drag-insert-above",
+                    "x-tree-drag-insert-below",
+                    "x-tree-drag-append"]);
+            this.lastInsertClass = "_noclass";
+        }
+    },
+
+    
+    beforeDragDrop : function(target, e, id){
+        this.cancelExpand();
+        return true;
+    },
+
+    
+    afterRepair : function(data){
+        if(data && Ext.enableFx){
+            data.node.ui.highlight();
+        }
+        this.hideProxy();
+    }    
+});
+
+}
+if(Ext.dd.DragZone){
+Ext.tree.TreeDragZone = function(tree, config){
+    Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
+    
+    this.tree = tree;
+};
+
+Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
+    
+    ddGroup : "TreeDD",
+
+    
+    onBeforeDrag : function(data, e){
+        var n = data.node;
+        return n && n.draggable && !n.disabled;
+    },
+
+    
+    onInitDrag : function(e){
+        var data = this.dragData;
+        this.tree.getSelectionModel().select(data.node);
+        this.tree.eventModel.disable();
+        this.proxy.update("");
+        data.node.ui.appendDDGhost(this.proxy.ghost.dom);
+        this.tree.fireEvent("startdrag", this.tree, data.node, e);
+    },
+
+    
+    getRepairXY : function(e, data){
+        return data.node.ui.getDDRepairXY();
+    },
+
+    
+    onEndDrag : function(data, e){
+        this.tree.eventModel.enable.defer(100, this.tree.eventModel);
+        this.tree.fireEvent("enddrag", this.tree, data.node, e);
+    },
+
+    
+    onValidDrop : function(dd, e, id){
+        this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
+        this.hideProxy();
+    },
+
+    
+    beforeInvalidDrop : function(e, id){
+        
+        var sm = this.tree.getSelectionModel();
+        sm.clearSelections();
+        sm.select(this.dragData.node);
+    },
+    
+    
+    afterRepair : function(){
+        if (Ext.enableFx && this.tree.hlDrop) {
+            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
+        }
+        this.dragging = false;
+    }
+});
+}
+Ext.tree.TreeEditor = function(tree, fc, config){
+    fc = fc || {};
+    var field = fc.events ? fc : new Ext.form.TextField(fc);
+    
+    Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
+
+    this.tree = tree;
+
+    if(!tree.rendered){
+        tree.on('render', this.initEditor, this);
+    }else{
+        this.initEditor(tree);
+    }
+};
+
+Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
+    
+    alignment: "l-l",
+    
+    autoSize: false,
+    
+    hideEl : false,
+    
+    cls: "x-small-editor x-tree-editor",
+    
+    shim:false,
+    
+    shadow:"frame",
+    
+    maxWidth: 250,
+    
+    editDelay : 350,
+
+    initEditor : function(tree){
+        tree.on({
+            scope      : this,
+            beforeclick: this.beforeNodeClick,
+            dblclick   : this.onNodeDblClick
+        });
+        
+        this.on({
+            scope          : this,
+            complete       : this.updateNode,
+            beforestartedit: this.fitToTree,
+            specialkey     : this.onSpecialKey
+        });
+        
+        this.on('startedit', this.bindScroll, this, {delay:10});
+    },
+
+    
+    fitToTree : function(ed, el){
+        var td = this.tree.getTreeEl().dom, nd = el.dom;
+        if(td.scrollLeft >  nd.offsetLeft){ 
+            td.scrollLeft = nd.offsetLeft;
+        }
+        var w = Math.min(
+                this.maxWidth,
+                (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
+        this.setSize(w, '');
+    },
+
+    
+    triggerEdit : function(node, defer){
+        this.completeEdit();
+		if(node.attributes.editable !== false){
+           
+			this.editNode = node;
+            if(this.tree.autoScroll){
+                Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
+            }
+            var value = node.text || '';
+            if (!Ext.isGecko && Ext.isEmpty(node.text)){
+                node.setText('&#160;');
+            }
+            this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
+            return false;
+        }
+    },
+
+    
+    bindScroll : function(){
+        this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
+    },
+
+    
+    beforeNodeClick : function(node, e){
+        clearTimeout(this.autoEditTimer);
+        if(this.tree.getSelectionModel().isSelected(node)){
+            e.stopEvent();
+            return this.triggerEdit(node);
+        }
+    },
+
+    onNodeDblClick : function(node, e){
+        clearTimeout(this.autoEditTimer);
+    },
+
+    
+    updateNode : function(ed, value){
+        this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
+        this.editNode.setText(value);
+    },
+
+    
+    onHide : function(){
+        Ext.tree.TreeEditor.superclass.onHide.call(this);
+        if(this.editNode){
+            this.editNode.ui.focus.defer(50, this.editNode.ui);
+        }
+    },
+
+    
+    onSpecialKey : function(field, e){
+        var k = e.getKey();
+        if(k == e.ESC){
+            e.stopEvent();
+            this.cancelEdit();
+        }else if(k == e.ENTER && !e.hasModifier()){
+            e.stopEvent();
+            this.completeEdit();
+        }
+    },
+    
+    onDestroy : function(){
+        clearTimeout(this.autoEditTimer);
+        Ext.tree.TreeEditor.superclass.onDestroy.call(this);
+        var tree = this.tree;
+        tree.un('beforeclick', this.beforeNodeClick, this);
+        tree.un('dblclick', this.onNodeDblClick, this);
+    }
+});
+
+var swfobject = function() {
+    
+    var UNDEF = "undefined",
+        OBJECT = "object",
+        SHOCKWAVE_FLASH = "Shockwave Flash",
+        SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
+        FLASH_MIME_TYPE = "application/x-shockwave-flash",
+        EXPRESS_INSTALL_ID = "SWFObjectExprInst",
+        ON_READY_STATE_CHANGE = "onreadystatechange",
+        
+        win = window,
+        doc = document,
+        nav = navigator,
+        
+        plugin = false,
+        domLoadFnArr = [main],
+        regObjArr = [],
+        objIdArr = [],
+        listenersArr = [],
+        storedAltContent,
+        storedAltContentId,
+        storedCallbackFn,
+        storedCallbackObj,
+        isDomLoaded = false,
+        isExpressInstallActive = false,
+        dynamicStylesheet,
+        dynamicStylesheetMedia,
+        autoHideShow = true,
+    
+      
+    ua = function() {
+        var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
+            u = nav.userAgent.toLowerCase(),
+            p = nav.platform.toLowerCase(),
+            windows = p ? (/win/).test(p) : /win/.test(u),
+            mac = p ? (/mac/).test(p) : /mac/.test(u),
+            webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
+            ie = !+"\v1", 
+            playerVersion = [0,0,0],
+            d = null;
+        if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
+            d = nav.plugins[SHOCKWAVE_FLASH].description;
+            if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
+                plugin = true;
+                ie = false; 
+                d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
+                playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
+                playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
+                playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
+            }
+        }
+        else if (typeof win.ActiveXObject != UNDEF) {
+            try {
+                var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
+                if (a) { 
+                    d = a.GetVariable("$version");
+                    if (d) {
+                        ie = true; 
+                        d = d.split(" ")[1].split(",");
+                        playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
+                    }
+                }
+            }
+            catch(e) {}
+        }
+        return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
+    }(),
+    
+     
+    onDomLoad = function() {
+        if (!ua.w3) { return; }
+        if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
+            callDomLoadFunctions();
+        }
+        if (!isDomLoaded) {
+            if (typeof doc.addEventListener != UNDEF) {
+                doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
+            }       
+            if (ua.ie && ua.win) {
+                doc.attachEvent(ON_READY_STATE_CHANGE, function() {
+                    if (doc.readyState == "complete") {
+                        doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
+                        callDomLoadFunctions();
+                    }
+                });
+                if (win == top) { 
+                    (function(){
+                        if (isDomLoaded) { return; }
+                        try {
+                            doc.documentElement.doScroll("left");
+                        }
+                        catch(e) {
+                            setTimeout(arguments.callee, 0);
+                            return;
+                        }
+                        callDomLoadFunctions();
+                    })();
+                }
+            }
+            if (ua.wk) {
+                (function(){
+                    if (isDomLoaded) { return; }
+                    if (!(/loaded|complete/).test(doc.readyState)) {
+                        setTimeout(arguments.callee, 0);
+                        return;
+                    }
+                    callDomLoadFunctions();
+                })();
+            }
+            addLoadEvent(callDomLoadFunctions);
+        }
+    }();
+    
+    function callDomLoadFunctions() {
+        if (isDomLoaded) { return; }
+        try { 
+            var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
+            t.parentNode.removeChild(t);
+        }
+        catch (e) { return; }
+        isDomLoaded = true;
+        var dl = domLoadFnArr.length;
+        for (var i = 0; i < dl; i++) {
+            domLoadFnArr[i]();
+        }
+    }
+    
+    function addDomLoadEvent(fn) {
+        if (isDomLoaded) {
+            fn();
+        }
+        else { 
+            domLoadFnArr[domLoadFnArr.length] = fn; 
+        }
+    }
+    
+    
+    function addLoadEvent(fn) {
+        if (typeof win.addEventListener != UNDEF) {
+            win.addEventListener("load", fn, false);
+        }
+        else if (typeof doc.addEventListener != UNDEF) {
+            doc.addEventListener("load", fn, false);
+        }
+        else if (typeof win.attachEvent != UNDEF) {
+            addListener(win, "onload", fn);
+        }
+        else if (typeof win.onload == "function") {
+            var fnOld = win.onload;
+            win.onload = function() {
+                fnOld();
+                fn();
+            };
+        }
+        else {
+            win.onload = fn;
+        }
+    }
+    
+    
+    function main() { 
+        if (plugin) {
+            testPlayerVersion();
+        }
+        else {
+            matchVersions();
+        }
+    }
+    
+    
+    function testPlayerVersion() {
+        var b = doc.getElementsByTagName("body")[0];
+        var o = createElement(OBJECT);
+        o.setAttribute("type", FLASH_MIME_TYPE);
+        var t = b.appendChild(o);
+        if (t) {
+            var counter = 0;
+            (function(){
+                if (typeof t.GetVariable != UNDEF) {
+                    var d = t.GetVariable("$version");
+                    if (d) {
+                        d = d.split(" ")[1].split(",");
+                        ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
+                    }
+                }
+                else if (counter < 10) {
+                    counter++;
+                    setTimeout(arguments.callee, 10);
+                    return;
+                }
+                b.removeChild(o);
+                t = null;
+                matchVersions();
+            })();
+        }
+        else {
+            matchVersions();
+        }
+    }
+    
+    
+    function matchVersions() {
+        var rl = regObjArr.length;
+        if (rl > 0) {
+            for (var i = 0; i < rl; i++) { 
+                var id = regObjArr[i].id;
+                var cb = regObjArr[i].callbackFn;
+                var cbObj = {success:false, id:id};
+                if (ua.pv[0] > 0) {
+                    var obj = getElementById(id);
+                    if (obj) {
+                        if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
+                            setVisibility(id, true);
+                            if (cb) {
+                                cbObj.success = true;
+                                cbObj.ref = getObjectById(id);
+                                cb(cbObj);
+                            }
+                        }
+                        else if (regObjArr[i].expressInstall && canExpressInstall()) { 
+                            var att = {};
+                            att.data = regObjArr[i].expressInstall;
+                            att.width = obj.getAttribute("width") || "0";
+                            att.height = obj.getAttribute("height") || "0";
+                            if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
+                            if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
+                            
+                            var par = {};
+                            var p = obj.getElementsByTagName("param");
+                            var pl = p.length;
+                            for (var j = 0; j < pl; j++) {
+                                if (p[j].getAttribute("name").toLowerCase() != "movie") {
+                                    par[p[j].getAttribute("name")] = p[j].getAttribute("value");
+                                }
+                            }
+                            showExpressInstall(att, par, id, cb);
+                        }
+                        else { 
+                            displayAltContent(obj);
+                            if (cb) { cb(cbObj); }
+                        }
+                    }
+                }
+                else {  
+                    setVisibility(id, true);
+                    if (cb) {
+                        var o = getObjectById(id); 
+                        if (o && typeof o.SetVariable != UNDEF) { 
+                            cbObj.success = true;
+                            cbObj.ref = o;
+                        }
+                        cb(cbObj);
+                    }
+                }
+            }
+        }
+    }
+    
+    function getObjectById(objectIdStr) {
+        var r = null;
+        var o = getElementById(objectIdStr);
+        if (o && o.nodeName == "OBJECT") {
+            if (typeof o.SetVariable != UNDEF) {
+                r = o;
+            }
+            else {
+                var n = o.getElementsByTagName(OBJECT)[0];
+                if (n) {
+                    r = n;
+                }
+            }
+        }
+        return r;
+    }
+    
+    
+    function canExpressInstall() {
+        return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
+    }
+    
+    
+    function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
+        isExpressInstallActive = true;
+        storedCallbackFn = callbackFn || null;
+        storedCallbackObj = {success:false, id:replaceElemIdStr};
+        var obj = getElementById(replaceElemIdStr);
+        if (obj) {
+            if (obj.nodeName == "OBJECT") { 
+                storedAltContent = abstractAltContent(obj);
+                storedAltContentId = null;
+            }
+            else { 
+                storedAltContent = obj;
+                storedAltContentId = replaceElemIdStr;
+            }
+            att.id = EXPRESS_INSTALL_ID;
+            if (typeof att.width == UNDEF || (!(/%$/).test(att.width) && parseInt(att.width, 10) < 310)) {
+                att.width = "310";
+            }
+            
+            if (typeof att.height == UNDEF || (!(/%$/).test(att.height) && parseInt(att.height, 10) < 137)) {
+                att.height = "137";
+            }
+            doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
+            var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
+                fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
+            if (typeof par.flashvars != UNDEF) {
+                par.flashvars += "&" + fv;
+            }
+            else {
+                par.flashvars = fv;
+            }
+            
+            
+            if (ua.ie && ua.win && obj.readyState != 4) {
+                var newObj = createElement("div");
+                replaceElemIdStr += "SWFObjectNew";
+                newObj.setAttribute("id", replaceElemIdStr);
+                obj.parentNode.insertBefore(newObj, obj); 
+                obj.style.display = "none";
+                (function(){
+                    if (obj.readyState == 4) {
+                        obj.parentNode.removeChild(obj);
+                    }
+                    else {
+                        setTimeout(arguments.callee, 10);
+                    }
+                })();
+            }
+            createSWF(att, par, replaceElemIdStr);
+        }
+    }
+    
+    
+    function displayAltContent(obj) {
+        if (ua.ie && ua.win && obj.readyState != 4) {
+            
+            
+            var el = createElement("div");
+            obj.parentNode.insertBefore(el, obj); 
+            el.parentNode.replaceChild(abstractAltContent(obj), el);
+            obj.style.display = "none";
+            (function(){
+                if (obj.readyState == 4) {
+                    obj.parentNode.removeChild(obj);
+                }
+                else {
+                    setTimeout(arguments.callee, 10);
+                }
+            })();
+        }
+        else {
+            obj.parentNode.replaceChild(abstractAltContent(obj), obj);
+        }
+    } 
+
+    function abstractAltContent(obj) {
+        var ac = createElement("div");
+        if (ua.win && ua.ie) {
+            ac.innerHTML = obj.innerHTML;
+        }
+        else {
+            var nestedObj = obj.getElementsByTagName(OBJECT)[0];
+            if (nestedObj) {
+                var c = nestedObj.childNodes;
+                if (c) {
+                    var cl = c.length;
+                    for (var i = 0; i < cl; i++) {
+                        if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
+                            ac.appendChild(c[i].cloneNode(true));
+                        }
+                    }
+                }
+            }
+        }
+        return ac;
+    }
+    
+    
+    function createSWF(attObj, parObj, id) {
+        var r, el = getElementById(id);
+        if (ua.wk && ua.wk < 312) { return r; }
+        if (el) {
+            if (typeof attObj.id == UNDEF) { 
+                attObj.id = id;
+            }
+            if (ua.ie && ua.win) { 
+                var att = "";
+                for (var i in attObj) {
+                    if (attObj[i] != Object.prototype[i]) { 
+                        if (i.toLowerCase() == "data") {
+                            parObj.movie = attObj[i];
+                        }
+                        else if (i.toLowerCase() == "styleclass") { 
+                            att += ' class="' + attObj[i] + '"';
+                        }
+                        else if (i.toLowerCase() != "classid") {
+                            att += ' ' + i + '="' + attObj[i] + '"';
+                        }
+                    }
+                }
+                var par = "";
+                for (var j in parObj) {
+                    if (parObj[j] != Object.prototype[j]) { 
+                        par += '<param name="' + j + '" value="' + parObj[j] + '" />';
+                    }
+                }
+                el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
+                objIdArr[objIdArr.length] = attObj.id; 
+                r = getElementById(attObj.id);  
+            }
+            else { 
+                var o = createElement(OBJECT);
+                o.setAttribute("type", FLASH_MIME_TYPE);
+                for (var m in attObj) {
+                    if (attObj[m] != Object.prototype[m]) { 
+                        if (m.toLowerCase() == "styleclass") { 
+                            o.setAttribute("class", attObj[m]);
+                        }
+                        else if (m.toLowerCase() != "classid") { 
+                            o.setAttribute(m, attObj[m]);
+                        }
+                    }
+                }
+                for (var n in parObj) {
+                    if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
+                        createObjParam(o, n, parObj[n]);
+                    }
+                }
+                el.parentNode.replaceChild(o, el);
+                r = o;
+            }
+        }
+        return r;
+    }
+    
+    function createObjParam(el, pName, pValue) {
+        var p = createElement("param");
+        p.setAttribute("name", pName);  
+        p.setAttribute("value", pValue);
+        el.appendChild(p);
+    }
+    
+    
+    function removeSWF(id) {
+        var obj = getElementById(id);
+        if (obj && obj.nodeName == "OBJECT") {
+            if (ua.ie && ua.win) {
+                obj.style.display = "none";
+                (function(){
+                    if (obj.readyState == 4) {
+                        removeObjectInIE(id);
+                    }
+                    else {
+                        setTimeout(arguments.callee, 10);
+                    }
+                })();
+            }
+            else {
+                obj.parentNode.removeChild(obj);
+            }
+        }
+    }
+    
+    function removeObjectInIE(id) {
+        var obj = getElementById(id);
+        if (obj) {
+            for (var i in obj) {
+                if (typeof obj[i] == "function") {
+                    obj[i] = null;
+                }
+            }
+            obj.parentNode.removeChild(obj);
+        }
+    }
+    
+    
+    function getElementById(id) {
+        var el = null;
+        try {
+            el = doc.getElementById(id);
+        }
+        catch (e) {}
+        return el;
+    }
+    
+    function createElement(el) {
+        return doc.createElement(el);
+    }
+    
+      
+    function addListener(target, eventType, fn) {
+        target.attachEvent(eventType, fn);
+        listenersArr[listenersArr.length] = [target, eventType, fn];
+    }
+    
+    
+    function hasPlayerVersion(rv) {
+        var pv = ua.pv, v = rv.split(".");
+        v[0] = parseInt(v[0], 10);
+        v[1] = parseInt(v[1], 10) || 0; 
+        v[2] = parseInt(v[2], 10) || 0;
+        return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
+    }
+    
+      
+    function createCSS(sel, decl, media, newStyle) {
+        if (ua.ie && ua.mac) { return; }
+        var h = doc.getElementsByTagName("head")[0];
+        if (!h) { return; } 
+        var m = (media && typeof media == "string") ? media : "screen";
+        if (newStyle) {
+            dynamicStylesheet = null;
+            dynamicStylesheetMedia = null;
+        }
+        if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
+            
+            var s = createElement("style");
+            s.setAttribute("type", "text/css");
+            s.setAttribute("media", m);
+            dynamicStylesheet = h.appendChild(s);
+            if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
+                dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
+            }
+            dynamicStylesheetMedia = m;
+        }
+        
+        if (ua.ie && ua.win) {
+            if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
+                dynamicStylesheet.addRule(sel, decl);
+            }
+        }
+        else {
+            if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
+                dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
+            }
+        }
+    }
+    
+    function setVisibility(id, isVisible) {
+        if (!autoHideShow) { return; }
+        var v = isVisible ? "visible" : "hidden";
+        if (isDomLoaded && getElementById(id)) {
+            getElementById(id).style.visibility = v;
+        }
+        else {
+            createCSS("#" + id, "visibility:" + v);
+        }
+    }
+
+    
+    function urlEncodeIfNecessary(s) {
+        var regex = /[\\\"<>\.;]/;
+        var hasBadChars = regex.exec(s) != null;
+        return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
+    }
+    
+    
+    var cleanup = function() {
+        if (ua.ie && ua.win) {
+            window.attachEvent("onunload", function() {
+                
+                var ll = listenersArr.length;
+                for (var i = 0; i < ll; i++) {
+                    listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
+                }
+                
+                var il = objIdArr.length;
+                for (var j = 0; j < il; j++) {
+                    removeSWF(objIdArr[j]);
+                }
+                
+                for (var k in ua) {
+                    ua[k] = null;
+                }
+                ua = null;
+                for (var l in swfobject) {
+                    swfobject[l] = null;
+                }
+                swfobject = null;
+                window.detachEvent('onunload', arguments.callee);
+            });
+        }
+    }();
+    
+    return {
+         
+        registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
+            if (ua.w3 && objectIdStr && swfVersionStr) {
+                var regObj = {};
+                regObj.id = objectIdStr;
+                regObj.swfVersion = swfVersionStr;
+                regObj.expressInstall = xiSwfUrlStr;
+                regObj.callbackFn = callbackFn;
+                regObjArr[regObjArr.length] = regObj;
+                setVisibility(objectIdStr, false);
+            }
+            else if (callbackFn) {
+                callbackFn({success:false, id:objectIdStr});
+            }
+        },
+        
+        getObjectById: function(objectIdStr) {
+            if (ua.w3) {
+                return getObjectById(objectIdStr);
+            }
+        },
+        
+        embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
+            var callbackObj = {success:false, id:replaceElemIdStr};
+            if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
+                setVisibility(replaceElemIdStr, false);
+                addDomLoadEvent(function() {
+                    widthStr += ""; 
+                    heightStr += "";
+                    var att = {};
+                    if (attObj && typeof attObj === OBJECT) {
+                        for (var i in attObj) { 
+                            att[i] = attObj[i];
+                        }
+                    }
+                    att.data = swfUrlStr;
+                    att.width = widthStr;
+                    att.height = heightStr;
+                    var par = {}; 
+                    if (parObj && typeof parObj === OBJECT) {
+                        for (var j in parObj) { 
+                            par[j] = parObj[j];
+                        }
+                    }
+                    if (flashvarsObj && typeof flashvarsObj === OBJECT) {
+                        for (var k in flashvarsObj) { 
+                            if (typeof par.flashvars != UNDEF) {
+                                par.flashvars += "&" + k + "=" + flashvarsObj[k];
+                            }
+                            else {
+                                par.flashvars = k + "=" + flashvarsObj[k];
+                            }
+                        }
+                    }
+                    if (hasPlayerVersion(swfVersionStr)) { 
+                        var obj = createSWF(att, par, replaceElemIdStr);
+                        if (att.id == replaceElemIdStr) {
+                            setVisibility(replaceElemIdStr, true);
+                        }
+                        callbackObj.success = true;
+                        callbackObj.ref = obj;
+                    }
+                    else if (xiSwfUrlStr && canExpressInstall()) { 
+                        att.data = xiSwfUrlStr;
+                        showExpressInstall(att, par, replaceElemIdStr, callbackFn);
+                        return;
+                    }
+                    else { 
+                        setVisibility(replaceElemIdStr, true);
+                    }
+                    if (callbackFn) { callbackFn(callbackObj); }
+                });
+            }
+            else if (callbackFn) { callbackFn(callbackObj); }
+        },
+        
+        switchOffAutoHideShow: function() {
+            autoHideShow = false;
+        },
+        
+        ua: ua,
+        
+        getFlashPlayerVersion: function() {
+            return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
+        },
+        
+        hasFlashPlayerVersion: hasPlayerVersion,
+        
+        createSWF: function(attObj, parObj, replaceElemIdStr) {
+            if (ua.w3) {
+                return createSWF(attObj, parObj, replaceElemIdStr);
+            }
+            else {
+                return undefined;
+            }
+        },
+        
+        showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
+            if (ua.w3 && canExpressInstall()) {
+                showExpressInstall(att, par, replaceElemIdStr, callbackFn);
+            }
+        },
+        
+        removeSWF: function(objElemIdStr) {
+            if (ua.w3) {
+                removeSWF(objElemIdStr);
+            }
+        },
+        
+        createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
+            if (ua.w3) {
+                createCSS(selStr, declStr, mediaStr, newStyleBoolean);
+            }
+        },
+        
+        addDomLoadEvent: addDomLoadEvent,
+        
+        addLoadEvent: addLoadEvent,
+        
+        getQueryParamValue: function(param) {
+            var q = doc.location.search || doc.location.hash;
+            if (q) {
+                if (/\?/.test(q)) { q = q.split("?")[1]; } 
+                if (param == null) {
+                    return urlEncodeIfNecessary(q);
+                }
+                var pairs = q.split("&");
+                for (var i = 0; i < pairs.length; i++) {
+                    if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
+                        return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
+                    }
+                }
+            }
+            return "";
+        },
+        
+        
+        expressInstallCallback: function() {
+            if (isExpressInstallActive) {
+                var obj = getElementById(EXPRESS_INSTALL_ID);
+                if (obj && storedAltContent) {
+                    obj.parentNode.replaceChild(storedAltContent, obj);
+                    if (storedAltContentId) {
+                        setVisibility(storedAltContentId, true);
+                        if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
+                    }
+                    if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
+                }
+                isExpressInstallActive = false;
+            } 
+        }
+    };
+}();
+
+Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
+    
+    flashVersion : '9.0.115',
+
+    
+    backgroundColor: '#ffffff',
+
+    
+    wmode: 'opaque',
+
+    
+    flashVars: undefined,
+
+    
+    flashParams: undefined,
+
+    
+    url: undefined,
+    swfId : undefined,
+    swfWidth: '100%',
+    swfHeight: '100%',
+
+    
+    expressInstall: false,
+
+    initComponent : function(){
+        Ext.FlashComponent.superclass.initComponent.call(this);
+
+        this.addEvents(
+            
+            'initialize'
+        );
+    },
+
+    onRender : function(){
+        Ext.FlashComponent.superclass.onRender.apply(this, arguments);
+
+        var params = Ext.apply({
+            allowScriptAccess: 'always',
+            bgcolor: this.backgroundColor,
+            wmode: this.wmode
+        }, this.flashParams), vars = Ext.apply({
+            allowedDomain: document.location.hostname,
+            YUISwfId: this.getId(),
+            YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
+        }, this.flashVars);
+
+        new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
+            this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
+
+        this.swf = Ext.getDom(this.id);
+        this.el = Ext.get(this.swf);
+    },
+
+    getSwfId : function(){
+        return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
+    },
+
+    getId : function(){
+        return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
+    },
+
+    onFlashEvent : function(e){
+        switch(e.type){
+            case "swfReady":
+                this.initSwf();
+                return;
+            case "log":
+                return;
+        }
+        e.component = this;
+        this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
+    },
+
+    initSwf : function(){
+        this.onSwfReady(!!this.isInitialized);
+        this.isInitialized = true;
+        this.fireEvent('initialize', this);
+    },
+
+    beforeDestroy: function(){
+        if(this.rendered){
+            swfobject.removeSWF(this.swf.id);
+        }
+        Ext.FlashComponent.superclass.beforeDestroy.call(this);
+    },
+
+    onSwfReady : Ext.emptyFn
+});
+
+
+Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
+
+Ext.reg('flash', Ext.FlashComponent);
+Ext.FlashEventProxy = {
+    onEvent : function(id, e){
+        var fp = Ext.getCmp(id);
+        if(fp){
+            fp.onFlashEvent(e);
+        }else{
+            arguments.callee.defer(10, this, [id, e]);
+        }
+    }
+};
+
+ Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
+    refreshBuffer: 100,
+
+    
+
+    
+    chartStyle: {
+        padding: 10,
+        animationEnabled: true,
+        font: {
+            name: 'Tahoma',
+            color: 0x444444,
+            size: 11
+        },
+        dataTip: {
+            padding: 5,
+            border: {
+                color: 0x99bbe8,
+                size:1
+            },
+            background: {
+                color: 0xDAE7F6,
+                alpha: .9
+            },
+            font: {
+                name: 'Tahoma',
+                color: 0x15428B,
+                size: 10,
+                bold: true
+            }
+        }
+    },
+
+    
+
+    
+    extraStyle: null,
+
+    
+    seriesStyles: null,
+
+    
+    disableCaching: Ext.isIE || Ext.isOpera,
+    disableCacheParam: '_dc',
+
+    initComponent : function(){
+        Ext.chart.Chart.superclass.initComponent.call(this);
+        if(!this.url){
+            this.url = Ext.chart.Chart.CHART_URL;
+        }
+        if(this.disableCaching){
+            this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
+        }
+        this.addEvents(
+            'itemmouseover',
+            'itemmouseout',
+            'itemclick',
+            'itemdoubleclick',
+            'itemdragstart',
+            'itemdrag',
+            'itemdragend',
+            
+            'beforerefresh',
+            
+            'refresh'
+        );
+        this.store = Ext.StoreMgr.lookup(this.store);
+    },
+
+    
+     setStyle: function(name, value){
+         this.swf.setStyle(name, Ext.encode(value));
+     },
+
+    
+    setStyles: function(styles){
+        this.swf.setStyles(Ext.encode(styles));
+    },
+
+    
+    setSeriesStyles: function(styles){
+        this.seriesStyles = styles;
+        var s = [];
+        Ext.each(styles, function(style){
+            s.push(Ext.encode(style));
+        });
+        this.swf.setSeriesStyles(s);
+    },
+
+    setCategoryNames : function(names){
+        this.swf.setCategoryNames(names);
+    },
+
+    setLegendRenderer : function(fn, scope){
+        var chart = this;
+        scope = scope || chart;
+        chart.removeFnProxy(chart.legendFnName);
+        chart.legendFnName = chart.createFnProxy(function(name){
+            return fn.call(scope, name);
+        });
+        chart.swf.setLegendLabelFunction(chart.legendFnName);
+    },
+
+    setTipRenderer : function(fn, scope){
+        var chart = this;
+        scope = scope || chart;
+        chart.removeFnProxy(chart.tipFnName);
+        chart.tipFnName = chart.createFnProxy(function(item, index, series){
+            var record = chart.store.getAt(index);
+            return fn.call(scope, chart, record, index, series);
+        });
+        chart.swf.setDataTipFunction(chart.tipFnName);
+    },
+
+    setSeries : function(series){
+        this.series = series;
+        this.refresh();
+    },
+
+    
+    bindStore : function(store, initial){
+        if(!initial && this.store){
+            if(store !== this.store && this.store.autoDestroy){
+                this.store.destroy();
+            }else{
+                this.store.un("datachanged", this.refresh, this);
+                this.store.un("add", this.delayRefresh, this);
+                this.store.un("remove", this.delayRefresh, this);
+                this.store.un("update", this.delayRefresh, this);
+                this.store.un("clear", this.refresh, this);
+            }
+        }
+        if(store){
+            store = Ext.StoreMgr.lookup(store);
+            store.on({
+                scope: this,
+                datachanged: this.refresh,
+                add: this.delayRefresh,
+                remove: this.delayRefresh,
+                update: this.delayRefresh,
+                clear: this.refresh
+            });
+        }
+        this.store = store;
+        if(store && !initial){
+            this.refresh();
+        }
+    },
+
+    onSwfReady : function(isReset){
+        Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
+        var ref;
+        this.swf.setType(this.type);
+
+        if(this.chartStyle){
+            this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
+        }
+
+        if(this.categoryNames){
+            this.setCategoryNames(this.categoryNames);
+        }
+
+        if(this.tipRenderer){
+            ref = this.getFunctionRef(this.tipRenderer);
+            this.setTipRenderer(ref.fn, ref.scope);
+        }
+        if(this.legendRenderer){
+            ref = this.getFunctionRef(this.legendRenderer);
+            this.setLegendRenderer(ref.fn, ref.scope);
+        }
+        if(!isReset){
+            this.bindStore(this.store, true);
+        }
+        this.refresh.defer(10, this);
+    },
+
+    delayRefresh : function(){
+        if(!this.refreshTask){
+            this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
+        }
+        this.refreshTask.delay(this.refreshBuffer);
+    },
+
+    refresh : function(){
+        if(this.fireEvent('beforerefresh', this) !== false){
+            var styleChanged = false;
+            
+            var data = [], rs = this.store.data.items;
+            for(var j = 0, len = rs.length; j < len; j++){
+                data[j] = rs[j].data;
+            }
+            
+            
+            var dataProvider = [];
+            var seriesCount = 0;
+            var currentSeries = null;
+            var i = 0;
+            if(this.series){
+                seriesCount = this.series.length;
+                for(i = 0; i < seriesCount; i++){
+                    currentSeries = this.series[i];
+                    var clonedSeries = {};
+                    for(var prop in currentSeries){
+                        if(prop == "style" && currentSeries.style !== null){
+                            clonedSeries.style = Ext.encode(currentSeries.style);
+                            styleChanged = true;
+                            
+                            
+                            
+                            
+                        } else{
+                            clonedSeries[prop] = currentSeries[prop];
+                        }
+                    }
+                    dataProvider.push(clonedSeries);
+                }
+            }
+
+            if(seriesCount > 0){
+                for(i = 0; i < seriesCount; i++){
+                    currentSeries = dataProvider[i];
+                    if(!currentSeries.type){
+                        currentSeries.type = this.type;
+                    }
+                    currentSeries.dataProvider = data;
+                }
+            } else{
+                dataProvider.push({type: this.type, dataProvider: data});
+            }
+            this.swf.setDataProvider(dataProvider);
+            if(this.seriesStyles){
+                this.setSeriesStyles(this.seriesStyles);
+            }
+            this.fireEvent('refresh', this);
+        }
+    },
+
+    
+    createFnProxy : function(fn){
+        var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
+        Ext.chart.Chart.proxyFunction[fnName] = fn;
+        return 'Ext.chart.Chart.proxyFunction.' + fnName;
+    },
+
+    
+    removeFnProxy : function(fn){
+        if(!Ext.isEmpty(fn)){
+            fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
+            delete Ext.chart.Chart.proxyFunction[fn];
+        }
+    },
+
+    
+    getFunctionRef : function(val){
+        if(Ext.isFunction(val)){
+            return {
+                fn: val,
+                scope: this
+            };
+        }else{
+            return {
+                fn: val.fn,
+                scope: val.scope || this
+            };
+        }
+    },
+
+    
+    onDestroy: function(){
+        if (this.refreshTask && this.refreshTask.cancel){
+            this.refreshTask.cancel();
+        }
+        Ext.chart.Chart.superclass.onDestroy.call(this);
+        this.bindStore(null);
+        this.removeFnProxy(this.tipFnName);
+        this.removeFnProxy(this.legendFnName);
+    }
+});
+Ext.reg('chart', Ext.chart.Chart);
+Ext.chart.Chart.PROXY_FN_ID = 0;
+Ext.chart.Chart.proxyFunction = {};
+
+
+Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf';
+
+
+Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
+    type: 'pie',
+
+    onSwfReady : function(isReset){
+        Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
+
+        this.setDataField(this.dataField);
+        this.setCategoryField(this.categoryField);
+    },
+
+    setDataField : function(field){
+        this.dataField = field;
+        this.swf.setDataField(field);
+    },
+
+    setCategoryField : function(field){
+        this.categoryField = field;
+        this.swf.setCategoryField(field);
+    }
+});
+Ext.reg('piechart', Ext.chart.PieChart);
+
+
+Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
+    onSwfReady : function(isReset){
+        Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
+        this.labelFn = [];
+        if(this.xField){
+            this.setXField(this.xField);
+        }
+        if(this.yField){
+            this.setYField(this.yField);
+        }
+        if(this.xAxis){
+            this.setXAxis(this.xAxis);
+        }
+        if(this.xAxes){
+            this.setXAxes(this.xAxes);
+        }
+        if(this.yAxis){
+            this.setYAxis(this.yAxis);
+        }
+        if(this.yAxes){
+            this.setYAxes(this.yAxes);
+        }
+        if(Ext.isDefined(this.constrainViewport)){
+            this.swf.setConstrainViewport(this.constrainViewport);
+        }
+    },
+
+    setXField : function(value){
+        this.xField = value;
+        this.swf.setHorizontalField(value);
+    },
+
+    setYField : function(value){
+        this.yField = value;
+        this.swf.setVerticalField(value);
+    },
+
+    setXAxis : function(value){
+        this.xAxis = this.createAxis('xAxis', value);
+        this.swf.setHorizontalAxis(this.xAxis);
+    },
+
+    setXAxes : function(value){
+        var axis;
+        for(var i = 0; i < value.length; i++) {
+            axis = this.createAxis('xAxis' + i, value[i]);
+            this.swf.setHorizontalAxis(axis);
+        }
+    },
+
+    setYAxis : function(value){
+        this.yAxis = this.createAxis('yAxis', value);
+        this.swf.setVerticalAxis(this.yAxis);
+    },
+
+    setYAxes : function(value){
+        var axis;
+        for(var i = 0; i < value.length; i++) {
+            axis = this.createAxis('yAxis' + i, value[i]);
+            this.swf.setVerticalAxis(axis);
+        }
+    },
+
+    createAxis : function(axis, value){
+        var o = Ext.apply({}, value),
+            ref,
+            old;
+
+        if(this[axis]){
+            old = this[axis].labelFunction;
+            this.removeFnProxy(old);
+            this.labelFn.remove(old);
+        }
+        if(o.labelRenderer){
+            ref = this.getFunctionRef(o.labelRenderer);
+            o.labelFunction = this.createFnProxy(function(v){
+                return ref.fn.call(ref.scope, v);
+            });
+            delete o.labelRenderer;
+            this.labelFn.push(o.labelFunction);
+        }
+        if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
+            o.position = 'bottom';
+        }
+        return o;
+    },
+
+    onDestroy : function(){
+        Ext.chart.CartesianChart.superclass.onDestroy.call(this);
+        Ext.each(this.labelFn, function(fn){
+            this.removeFnProxy(fn);
+        }, this);
+    }
+});
+Ext.reg('cartesianchart', Ext.chart.CartesianChart);
+
+
+Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
+    type: 'line'
+});
+Ext.reg('linechart', Ext.chart.LineChart);
+
+
+Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
+    type: 'column'
+});
+Ext.reg('columnchart', Ext.chart.ColumnChart);
+
+
+Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
+    type: 'stackcolumn'
+});
+Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
+
+
+Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
+    type: 'bar'
+});
+Ext.reg('barchart', Ext.chart.BarChart);
+
+
+Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
+    type: 'stackbar'
+});
+Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
+
+
+
+
+Ext.chart.Axis = function(config){
+    Ext.apply(this, config);
+};
+
+Ext.chart.Axis.prototype =
+{
+    
+    type: null,
+
+    
+    orientation: "horizontal",
+
+    
+    reverse: false,
+
+    
+    labelFunction: null,
+
+    
+    hideOverlappingLabels: true,
+
+    
+    labelSpacing: 2
+};
+
+
+Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
+    type: "numeric",
+
+    
+    minimum: NaN,
+
+    
+    maximum: NaN,
+
+    
+    majorUnit: NaN,
+
+    
+    minorUnit: NaN,
+
+    
+    snapToUnits: true,
+
+    
+    alwaysShowZero: true,
+
+    
+    scale: "linear",
+
+    
+    roundMajorUnit: true,
+
+    
+    calculateByLabelSize: true,
+
+    
+    position: 'left',
+
+    
+    adjustMaximumByMajorUnit: true,
+
+    
+    adjustMinimumByMajorUnit: true
+
+});
+
+
+Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
+    type: "time",
+
+    
+    minimum: null,
+
+    
+    maximum: null,
+
+    
+    majorUnit: NaN,
+
+    
+    majorTimeUnit: null,
+
+    
+    minorUnit: NaN,
+
+    
+    minorTimeUnit: null,
+
+    
+    snapToUnits: true,
+
+    
+    stackingEnabled: false,
+
+    
+    calculateByLabelSize: true
+
+});
+
+
+Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
+    type: "category",
+
+    
+    categoryNames: null,
+
+    
+    calculateCategoryCount: false
+
+});
+
+
+Ext.chart.Series = function(config) { Ext.apply(this, config); };
+
+Ext.chart.Series.prototype =
+{
+    
+    type: null,
+
+    
+    displayName: null
+};
+
+
+Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
+    
+    xField: null,
+
+    
+    yField: null,
+
+    
+    showInLegend: true,
+
+    
+    axis: 'primary'
+});
+
+
+Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
+    type: "column"
+});
+
+
+Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
+    type: "line"
+});
+
+
+Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
+    type: "bar"
+});
+
+
+
+Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
+    type: "pie",
+    dataField: null,
+    categoryField: null
+});
+Ext.menu.Menu = Ext.extend(Ext.Container, {
+    
+    
+    
+    minWidth : 120,
+    
+    shadow : 'sides',
+    
+    subMenuAlign : 'tl-tr?',
+    
+    defaultAlign : 'tl-bl?',
+    
+    allowOtherMenus : false,
+    
+    ignoreParentClicks : false,
+    
+    enableScrolling : true,
+    
+    maxHeight : null,
+    
+    scrollIncrement : 24,
+    
+    showSeparator : true,
+    
+    defaultOffsets : [0, 0],
+
+    
+    plain : false,
+
+    
+    floating : true,
+
+
+    
+    zIndex: 15000,
+
+    
+    hidden : true,
+
+    
+    layout : 'menu',
+    hideMode : 'offsets',    
+    scrollerHeight : 8,
+    autoLayout : true,       
+    defaultType : 'menuitem',
+    bufferResize : false,
+
+    initComponent : function(){
+        if(Ext.isArray(this.initialConfig)){
+            Ext.apply(this, {items:this.initialConfig});
+        }
+        this.addEvents(
+            
+            'click',
+            
+            'mouseover',
+            
+            'mouseout',
+            
+            'itemclick'
+        );
+        Ext.menu.MenuMgr.register(this);
+        if(this.floating){
+            Ext.EventManager.onWindowResize(this.hide, this);
+        }else{
+            if(this.initialConfig.hidden !== false){
+                this.hidden = false;
+            }
+            this.internalDefaults = {hideOnClick: false};
+        }
+        Ext.menu.Menu.superclass.initComponent.call(this);
+        if(this.autoLayout){
+            var fn = this.doLayout.createDelegate(this, []);
+            this.on({
+                add: fn,
+                remove: fn
+            });
+        }
+    },
+
+    
+    getLayoutTarget : function() {
+        return this.ul;
+    },
+
+    
+    onRender : function(ct, position){
+        if(!ct){
+            ct = Ext.getBody();
+        }
+
+        var dh = {
+            id: this.getId(),
+            cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
+            style: this.style,
+            cn: [
+                {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
+                {tag: 'ul', cls: 'x-menu-list'}
+            ]
+        };
+        if(this.floating){
+            this.el = new Ext.Layer({
+                shadow: this.shadow,
+                dh: dh,
+                constrain: false,
+                parentEl: ct,
+                zindex: this.zIndex
+            });
+        }else{
+            this.el = ct.createChild(dh);
+        }
+        Ext.menu.Menu.superclass.onRender.call(this, ct, position);
+
+        if(!this.keyNav){
+            this.keyNav = new Ext.menu.MenuNav(this);
+        }
+        
+        this.focusEl = this.el.child('a.x-menu-focus');
+        this.ul = this.el.child('ul.x-menu-list');
+        this.mon(this.ul, {
+            scope: this,
+            click: this.onClick,
+            mouseover: this.onMouseOver,
+            mouseout: this.onMouseOut
+        });
+        if(this.enableScrolling){
+            this.mon(this.el, {
+                scope: this,
+                delegate: '.x-menu-scroller',
+                click: this.onScroll,
+                mouseover: this.deactivateActive
+            });
+        }
+    },
+
+    
+    findTargetItem : function(e){
+        var t = e.getTarget('.x-menu-list-item', this.ul, true);
+        if(t && t.menuItemId){
+            return this.items.get(t.menuItemId);
+        }
+    },
+
+    
+    onClick : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t.isFormField){
+                this.setActiveItem(t);
+            }else if(t instanceof Ext.menu.BaseItem){
+                if(t.menu && this.ignoreParentClicks){
+                    t.expandMenu();
+                    e.preventDefault();
+                }else if(t.onClick){
+                    t.onClick(e);
+                    this.fireEvent('click', this, t, e);
+                }
+            }
+        }
+    },
+
+    
+    setActiveItem : function(item, autoExpand){
+        if(item != this.activeItem){
+            this.deactivateActive();
+            if((this.activeItem = item).isFormField){
+                item.focus();
+            }else{
+                item.activate(autoExpand);
+            }
+        }else if(autoExpand){
+            item.expandMenu();
+        }
+    },
+
+    deactivateActive : function(){
+        var a = this.activeItem;
+        if(a){
+            if(a.isFormField){
+                
+                if(a.collapse){
+                    a.collapse();
+                }
+            }else{
+                a.deactivate();
+            }
+            delete this.activeItem;
+        }
+    },
+
+    
+    tryActivate : function(start, step){
+        var items = this.items;
+        for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
+            var item = items.get(i);
+            if(item.isVisible() && !item.disabled && (item.canActivate || item.isFormField)){
+                this.setActiveItem(item, false);
+                return item;
+            }
+        }
+        return false;
+    },
+
+    
+    onMouseOver : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t.canActivate && !t.disabled){
+                this.setActiveItem(t, true);
+            }
+        }
+        this.over = true;
+        this.fireEvent('mouseover', this, e, t);
+    },
+
+    
+    onMouseOut : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
+                this.activeItem.deactivate();
+                delete this.activeItem;
+            }
+        }
+        this.over = false;
+        this.fireEvent('mouseout', this, e, t);
+    },
+
+    
+    onScroll : function(e, t){
+        if(e){
+            e.stopEvent();
+        }
+        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
+        ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
+        if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
+           this.onScrollerOut(null, t);
+        }
+    },
+
+    
+    onScrollerIn : function(e, t){
+        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
+        if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
+            Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
+        }
+    },
+
+    
+    onScrollerOut : function(e, t){
+        Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
+    },
+
+    
+    show : function(el, pos, parentMenu){
+        if(this.floating){
+            this.parentMenu = parentMenu;
+            if(!this.el){
+                this.render();
+                this.doLayout(false, true);
+            }
+            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
+        }else{
+            Ext.menu.Menu.superclass.show.call(this);
+        }
+    },
+
+    
+    showAt : function(xy, parentMenu){
+        if(this.fireEvent('beforeshow', this) !== false){
+            this.parentMenu = parentMenu;
+            if(!this.el){
+                this.render();
+            }
+            if(this.enableScrolling){
+                
+                this.el.setXY(xy);
+                
+                xy[1] = this.constrainScroll(xy[1]);
+                xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
+            }else{
+                
+                xy = this.el.adjustForConstraints(xy);
+            }
+            this.el.setXY(xy);
+            this.el.show();
+            Ext.menu.Menu.superclass.onShow.call(this);
+            if(Ext.isIE){
+                
+                this.fireEvent('autosize', this);
+                if(!Ext.isIE8){
+                    this.el.repaint();
+                }
+            }
+            this.hidden = false;
+            this.focus();
+            this.fireEvent('show', this);
+        }
+    },
+
+    constrainScroll : function(y){
+        var max, full = this.ul.setHeight('auto').getHeight(),
+            returnY = y, normalY, parentEl, scrollTop, viewHeight;
+        if(this.floating){
+            parentEl = Ext.fly(this.el.dom.parentNode);
+            scrollTop = parentEl.getScroll().top;
+            viewHeight = parentEl.getViewSize().height;
+            
+            
+            normalY = y - scrollTop;
+            max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
+            if(full > viewHeight) {
+                max = viewHeight;
+                
+                returnY = y - normalY;
+            } else if(max < full) {
+                returnY = y - (full - max);
+                max = full;
+            }
+        }else{
+            max = this.getHeight();
+        }
+        
+        if (this.maxHeight){
+            max = Math.min(this.maxHeight, max);
+        }
+        if(full > max && max > 0){
+            this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
+            this.ul.setHeight(this.activeMax);
+            this.createScrollers();
+            this.el.select('.x-menu-scroller').setDisplayed('');
+        }else{
+            this.ul.setHeight(full);
+            this.el.select('.x-menu-scroller').setDisplayed('none');
+        }
+        this.ul.dom.scrollTop = 0;
+        return returnY;
+    },
+
+    createScrollers : function(){
+        if(!this.scroller){
+            this.scroller = {
+                pos: 0,
+                top: this.el.insertFirst({
+                    tag: 'div',
+                    cls: 'x-menu-scroller x-menu-scroller-top',
+                    html: '&#160;'
+                }),
+                bottom: this.el.createChild({
+                    tag: 'div',
+                    cls: 'x-menu-scroller x-menu-scroller-bottom',
+                    html: '&#160;'
+                })
+            };
+            this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
+            this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
+                listeners: {
+                    click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
+                }
+            });
+            this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
+            this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
+                listeners: {
+                    click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
+                }
+            });
+        }
+    },
+
+    onLayout : function(){
+        if(this.isVisible()){
+            if(this.enableScrolling){
+                this.constrainScroll(this.el.getTop());
+            }
+            if(this.floating){
+                this.el.sync();
+            }
+        }
+    },
+
+    focus : function(){
+        if(!this.hidden){
+            this.doFocus.defer(50, this);
+        }
+    },
+
+    doFocus : function(){
+        if(!this.hidden){
+            this.focusEl.focus();
+        }
+    },
+
+    
+    hide : function(deep){
+        if (!this.isDestroyed) {
+            this.deepHide = deep;
+            Ext.menu.Menu.superclass.hide.call(this);
+            delete this.deepHide;
+        }
+    },
+
+    
+    onHide : function(){
+        Ext.menu.Menu.superclass.onHide.call(this);
+        this.deactivateActive();
+        if(this.el && this.floating){
+            this.el.hide();
+        }
+        var pm = this.parentMenu;
+        if(this.deepHide === true && pm){
+            if(pm.floating){
+                pm.hide(true);
+            }else{
+                pm.deactivateActive();
+            }
+        }
+    },
+
+    
+    lookupComponent : function(c){
+         if(Ext.isString(c)){
+            c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
+             this.applyDefaults(c);
+         }else{
+            if(Ext.isObject(c)){
+                c = this.getMenuItem(c);
+            }else if(c.tagName || c.el){ 
+                c = new Ext.BoxComponent({
+                    el: c
+                });
+            }
+         }
+         return c;
+    },
+
+    applyDefaults : function(c) {
+        if (!Ext.isString(c)) {
+            c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
+            var d = this.internalDefaults;
+            if(d){
+                if(c.events){
+                    Ext.applyIf(c.initialConfig, d);
+                    Ext.apply(c, d);
+                }else{
+                    Ext.applyIf(c, d);
+                }
+            }
+        }
+        return c;
+    },
+
+    
+    getMenuItem : function(config) {
+        config.ownerCt = this;
+        
+        if (!config.isXType) {
+            if (!config.xtype && Ext.isBoolean(config.checked)) {
+                return new Ext.menu.CheckItem(config);
+            }
+            return Ext.create(config, this.defaultType);
+        }
+        return config;
+    },
+
+    
+    addSeparator : function() {
+        return this.add(new Ext.menu.Separator());
+    },
+
+    
+    addElement : function(el) {
+        return this.add(new Ext.menu.BaseItem({
+            el: el
+        }));
+    },
+
+    
+    addItem : function(item) {
+        return this.add(item);
+    },
+
+    
+    addMenuItem : function(config) {
+        return this.add(this.getMenuItem(config));
+    },
+
+    
+    addText : function(text){
+        return this.add(new Ext.menu.TextItem(text));
+    },
+
+    
+    onDestroy : function(){
+        Ext.EventManager.removeResizeListener(this.hide, this);
+        var pm = this.parentMenu;
+        if(pm && pm.activeChild == this){
+            delete pm.activeChild;
+        }
+        delete this.parentMenu;
+        Ext.menu.Menu.superclass.onDestroy.call(this);
+        Ext.menu.MenuMgr.unregister(this);
+        if(this.keyNav) {
+            this.keyNav.disable();
+        }
+        var s = this.scroller;
+        if(s){
+            Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
+        }
+        Ext.destroy(
+            this.el,
+            this.focusEl,
+            this.ul
+        );
+    }
+});
+
+Ext.reg('menu', Ext.menu.Menu);
+
+
+Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
+    function up(e, m){
+        if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
+            m.tryActivate(m.items.length-1, -1);
+        }
+    }
+    function down(e, m){
+        if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
+            m.tryActivate(0, 1);
+        }
+    }
+    return {
+        constructor : function(menu){
+            Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
+            this.scope = this.menu = menu;
+        },
+
+        doRelay : function(e, h){
+            var k = e.getKey();
+
+            if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
+                return false;
+            }
+            if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
+                this.menu.tryActivate(0, 1);
+                return false;
+            }
+            return h.call(this.scope || this, e, this.menu);
+        },
+
+        tab: function(e, m) {
+            e.stopEvent();
+            if (e.shiftKey) {
+                up(e, m);
+            } else {
+                down(e, m);
+            }
+        },
+
+        up : up,
+
+        down : down,
+
+        right : function(e, m){
+            if(m.activeItem){
+                m.activeItem.expandMenu(true);
+            }
+        },
+
+        left : function(e, m){
+            m.hide();
+            if(m.parentMenu && m.parentMenu.activeItem){
+                m.parentMenu.activeItem.activate();
+            }
+        },
+
+        enter : function(e, m){
+            if(m.activeItem){
+                e.stopPropagation();
+                m.activeItem.onClick(e);
+                m.fireEvent('click', this, m.activeItem);
+                return true;
+            }
+        }
+    };
+}());
+
+Ext.menu.MenuMgr = function(){
+   var menus, 
+       active, 
+       map,
+       groups = {}, 
+       attached = false, 
+       lastShow = new Date();
+   
+
+   
+   function init(){
+       menus = {};
+       active = new Ext.util.MixedCollection();
+       map = Ext.getDoc().addKeyListener(27, hideAll);
+       map.disable();
+   }
+
+   
+   function hideAll(){
+       if(active && active.length > 0){
+           var c = active.clone();
+           c.each(function(m){
+               m.hide();
+           });
+           return true;
+       }
+       return false;
+   }
+
+   
+   function onHide(m){
+       active.remove(m);
+       if(active.length < 1){
+           map.disable();
+           Ext.getDoc().un("mousedown", onMouseDown);
+           attached = false;
+       }
+   }
+
+   
+   function onShow(m){
+       var last = active.last();
+       lastShow = new Date();
+       active.add(m);
+       if(!attached){
+           map.enable();
+           Ext.getDoc().on("mousedown", onMouseDown);
+           attached = true;
+       }
+       if(m.parentMenu){
+          m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
+          m.parentMenu.activeChild = m;
+       }else if(last && !last.isDestroyed && last.isVisible()){
+          m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
+       }
+   }
+
+   
+   function onBeforeHide(m){
+       if(m.activeChild){
+           m.activeChild.hide();
+       }
+       if(m.autoHideTimer){
+           clearTimeout(m.autoHideTimer);
+           delete m.autoHideTimer;
+       }
+   }
+
+   
+   function onBeforeShow(m){
+       var pm = m.parentMenu;
+       if(!pm && !m.allowOtherMenus){
+           hideAll();
+       }else if(pm && pm.activeChild){
+           pm.activeChild.hide();
+       }
+   }
+
+   
+   function onMouseDown(e){
+       if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
+           hideAll();
+       }
+   }
+
+   return {
+
+       
+       hideAll : function(){
+            return hideAll();
+       },
+
+       
+       register : function(menu){
+           if(!menus){
+               init();
+           }
+           menus[menu.id] = menu;
+           menu.on({
+               beforehide: onBeforeHide,
+               hide: onHide,
+               beforeshow: onBeforeShow,
+               show: onShow
+           });
+       },
+
+        
+       get : function(menu){
+           if(typeof menu == "string"){ 
+               if(!menus){  
+                   return null;
+               }
+               return menus[menu];
+           }else if(menu.events){  
+               return menu;
+           }else if(typeof menu.length == 'number'){ 
+               return new Ext.menu.Menu({items:menu});
+           }else{ 
+               return Ext.create(menu, 'menu');
+           }
+       },
+
+       
+       unregister : function(menu){
+           delete menus[menu.id];
+           menu.un("beforehide", onBeforeHide);
+           menu.un("hide", onHide);
+           menu.un("beforeshow", onBeforeShow);
+           menu.un("show", onShow);
+       },
+
+       
+       registerCheckable : function(menuItem){
+           var g = menuItem.group;
+           if(g){
+               if(!groups[g]){
+                   groups[g] = [];
+               }
+               groups[g].push(menuItem);
+           }
+       },
+
+       
+       unregisterCheckable : function(menuItem){
+           var g = menuItem.group;
+           if(g){
+               groups[g].remove(menuItem);
+           }
+       },
+       
+       
+       onCheckChange: function(item, state){
+           if(item.group && state){
+               var group = groups[item.group],
+                   i = 0,
+                   len = group.length,
+                   current;
+                   
+               for(; i < len; i++){
+                   current = group[i];
+                   if(current != item){
+                       current.setChecked(false);
+                   }
+               }
+           }
+       },
+
+       getCheckedItem : function(groupId){
+           var g = groups[groupId];
+           if(g){
+               for(var i = 0, l = g.length; i < l; i++){
+                   if(g[i].checked){
+                       return g[i];
+                   }
+               }
+           }
+           return null;
+       },
+
+       setCheckedItem : function(groupId, itemId){
+           var g = groups[groupId];
+           if(g){
+               for(var i = 0, l = g.length; i < l; i++){
+                   if(g[i].id == itemId){
+                       g[i].setChecked(true);
+                   }
+               }
+           }
+           return null;
+       }
+   };
+}();
+
+Ext.menu.BaseItem = Ext.extend(Ext.Component, {
+    
+    
+    
+    
+    canActivate : false,
+    
+    activeClass : "x-menu-item-active",
+    
+    hideOnClick : true,
+    
+    clickHideDelay : 1,
+
+    
+    ctype : "Ext.menu.BaseItem",
+
+    
+    actionMode : "container",
+
+    initComponent : function(){
+        Ext.menu.BaseItem.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'click',
+            
+            'activate',
+            
+            'deactivate'
+        );
+        if(this.handler){
+            this.on("click", this.handler, this.scope);
+        }
+    },
+
+    
+    onRender : function(container, position){
+        Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
+        if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
+            this.parentMenu = this.ownerCt;
+        }else{
+            this.container.addClass('x-menu-list-item');
+            this.mon(this.el, {
+                scope: this,
+                click: this.onClick,
+                mouseenter: this.activate,
+                mouseleave: this.deactivate
+            });
+        }
+    },
+
+    
+    setHandler : function(handler, scope){
+        if(this.handler){
+            this.un("click", this.handler, this.scope);
+        }
+        this.on("click", this.handler = handler, this.scope = scope);
+    },
+
+    
+    onClick : function(e){
+        if(!this.disabled && this.fireEvent("click", this, e) !== false
+                && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
+            this.handleClick(e);
+        }else{
+            e.stopEvent();
+        }
+    },
+
+    
+    activate : function(){
+        if(this.disabled){
+            return false;
+        }
+        var li = this.container;
+        li.addClass(this.activeClass);
+        this.region = li.getRegion().adjust(2, 2, -2, -2);
+        this.fireEvent("activate", this);
+        return true;
+    },
+
+    
+    deactivate : function(){
+        this.container.removeClass(this.activeClass);
+        this.fireEvent("deactivate", this);
+    },
+
+    
+    shouldDeactivate : function(e){
+        return !this.region || !this.region.contains(e.getPoint());
+    },
+
+    
+    handleClick : function(e){
+        var pm = this.parentMenu;
+        if(this.hideOnClick){
+            if(pm.floating){
+                this.clickHideDelayTimer = pm.hide.defer(this.clickHideDelay, pm, [true]);
+            }else{
+                pm.deactivateActive();
+            }
+        }
+    },
+    
+    beforeDestroy: function(){
+        clearTimeout(this.clickHideDelayTimer);
+        Ext.menu.BaseItem.superclass.beforeDestroy.call(this);    
+    },
+
+    
+    expandMenu : Ext.emptyFn,
+
+    
+    hideMenu : Ext.emptyFn
+});
+Ext.reg('menubaseitem', Ext.menu.BaseItem);
+Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
+    
+    
+    hideOnClick : false,
+    
+    itemCls : "x-menu-text",
+    
+    constructor : function(config) {
+        if (typeof config == 'string') {
+            config = {
+                text: config
+            };
+        }
+        Ext.menu.TextItem.superclass.constructor.call(this, config);
+    },
+
+    
+    onRender : function() {
+        var s = document.createElement("span");
+        s.className = this.itemCls;
+        s.innerHTML = this.text;
+        this.el = s;
+        Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
+    }
+});
+Ext.reg('menutextitem', Ext.menu.TextItem);
+Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
+    
+    itemCls : "x-menu-sep",
+    
+    hideOnClick : false,
+    
+    
+    activeClass: '',
+
+    
+    onRender : function(li){
+        var s = document.createElement("span");
+        s.className = this.itemCls;
+        s.innerHTML = "&#160;";
+        this.el = s;
+        li.addClass("x-menu-sep-li");
+        Ext.menu.Separator.superclass.onRender.apply(this, arguments);
+    }
+});
+Ext.reg('menuseparator', Ext.menu.Separator);
+Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
+    
+    
+    
+    
+    
+    
+    
+    
+    itemCls : 'x-menu-item',
+    
+    canActivate : true,
+    
+    showDelay: 200,
+    
+    
+    altText: '',
+    
+    
+    hideDelay: 200,
+
+    
+    ctype: 'Ext.menu.Item',
+
+    initComponent : function(){
+        Ext.menu.Item.superclass.initComponent.call(this);
+        if(this.menu){
+            
+            
+            if (Ext.isArray(this.menu)){
+                this.menu = { items: this.menu };
+            }
+            
+            
+            
+            if (Ext.isObject(this.menu)){
+                this.menu.ownerCt = this;
+            }
+            
+            this.menu = Ext.menu.MenuMgr.get(this.menu);
+            this.menu.ownerCt = undefined;
+        }
+    },
+
+    
+    onRender : function(container, position){
+        if (!this.itemTpl) {
+            this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
+                '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
+                    '<tpl if="hrefTarget">',
+                        ' target="{hrefTarget}"',
+                    '</tpl>',
+                 '>',
+                     '<img alt="{altText}" src="{icon}" class="x-menu-item-icon {iconCls}"/>',
+                     '<span class="x-menu-item-text">{text}</span>',
+                 '</a>'
+             );
+        }
+        var a = this.getTemplateArgs();
+        this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
+        this.iconEl = this.el.child('img.x-menu-item-icon');
+        this.textEl = this.el.child('.x-menu-item-text');
+        if(!this.href) { 
+            this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
+        }
+        Ext.menu.Item.superclass.onRender.call(this, container, position);
+    },
+
+    getTemplateArgs: function() {
+        return {
+            id: this.id,
+            cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
+            href: this.href || '#',
+            hrefTarget: this.hrefTarget,
+            icon: this.icon || Ext.BLANK_IMAGE_URL,
+            iconCls: this.iconCls || '',
+            text: this.itemText||this.text||'&#160;',
+            altText: this.altText || ''
+        };
+    },
+
+    
+    setText : function(text){
+        this.text = text||'&#160;';
+        if(this.rendered){
+            this.textEl.update(this.text);
+            this.parentMenu.layout.doAutoSize();
+        }
+    },
+
+    
+    setIconClass : function(cls){
+        var oldCls = this.iconCls;
+        this.iconCls = cls;
+        if(this.rendered){
+            this.iconEl.replaceClass(oldCls, this.iconCls);
+        }
+    },
+
+    
+    beforeDestroy: function(){
+        clearTimeout(this.showTimer);
+        clearTimeout(this.hideTimer);
+        if (this.menu){
+            delete this.menu.ownerCt;
+            this.menu.destroy();
+        }
+        Ext.menu.Item.superclass.beforeDestroy.call(this);
+    },
+
+    
+    handleClick : function(e){
+        if(!this.href){ 
+            e.stopEvent();
+        }
+        Ext.menu.Item.superclass.handleClick.apply(this, arguments);
+    },
+
+    
+    activate : function(autoExpand){
+        if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
+            this.focus();
+            if(autoExpand){
+                this.expandMenu();
+            }
+        }
+        return true;
+    },
+
+    
+    shouldDeactivate : function(e){
+        if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
+            if(this.menu && this.menu.isVisible()){
+                return !this.menu.getEl().getRegion().contains(e.getPoint());
+            }
+            return true;
+        }
+        return false;
+    },
+
+    
+    deactivate : function(){
+        Ext.menu.Item.superclass.deactivate.apply(this, arguments);
+        this.hideMenu();
+    },
+
+    
+    expandMenu : function(autoActivate){
+        if(!this.disabled && this.menu){
+            clearTimeout(this.hideTimer);
+            delete this.hideTimer;
+            if(!this.menu.isVisible() && !this.showTimer){
+                this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
+            }else if (this.menu.isVisible() && autoActivate){
+                this.menu.tryActivate(0, 1);
+            }
+        }
+    },
+
+    
+    deferExpand : function(autoActivate){
+        delete this.showTimer;
+        this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
+        if(autoActivate){
+            this.menu.tryActivate(0, 1);
+        }
+    },
+
+    
+    hideMenu : function(){
+        clearTimeout(this.showTimer);
+        delete this.showTimer;
+        if(!this.hideTimer && this.menu && this.menu.isVisible()){
+            this.hideTimer = this.deferHide.defer(this.hideDelay, this);
+        }
+    },
+
+    
+    deferHide : function(){
+        delete this.hideTimer;
+        if(this.menu.over){
+            this.parentMenu.setActiveItem(this, false);
+        }else{
+            this.menu.hide();
+        }
+    }
+});
+Ext.reg('menuitem', Ext.menu.Item);
+Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
+    
+    
+    itemCls : "x-menu-item x-menu-check-item",
+    
+    groupClass : "x-menu-group-item",
+
+    
+    checked: false,
+
+    
+    ctype: "Ext.menu.CheckItem",
+    
+    initComponent : function(){
+        Ext.menu.CheckItem.superclass.initComponent.call(this);
+	    this.addEvents(
+	        
+	        "beforecheckchange" ,
+	        
+	        "checkchange"
+	    );
+	    
+	    if(this.checkHandler){
+	        this.on('checkchange', this.checkHandler, this.scope);
+	    }
+	    Ext.menu.MenuMgr.registerCheckable(this);
+    },
+
+    
+    onRender : function(c){
+        Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
+        if(this.group){
+            this.el.addClass(this.groupClass);
+        }
+        if(this.checked){
+            this.checked = false;
+            this.setChecked(true, true);
+        }
+    },
+
+    
+    destroy : function(){
+        Ext.menu.MenuMgr.unregisterCheckable(this);
+        Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
+    },
+
+    
+    setChecked : function(state, suppressEvent){
+        var suppress = suppressEvent === true;
+        if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
+            Ext.menu.MenuMgr.onCheckChange(this, state);
+            if(this.container){
+                this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
+            }
+            this.checked = state;
+            if(!suppress){
+                this.fireEvent("checkchange", this, state);
+            }
+        }
+    },
+
+    
+    handleClick : function(e){
+       if(!this.disabled && !(this.checked && this.group)){
+           this.setChecked(!this.checked);
+       }
+       Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
+    }
+});
+Ext.reg('menucheckitem', Ext.menu.CheckItem);
+ Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
+    
+    enableScrolling : false,
+    
+        
+    
+    hideOnClick : true,
+    
+    
+    pickerId : null,
+    
+    
+    
+    
+    cls : 'x-date-menu',
+    
+    
+    
+    
+
+    initComponent : function(){
+        this.on('beforeshow', this.onBeforeShow, this);
+        if(this.strict = (Ext.isIE7 && Ext.isStrict)){
+            this.on('show', this.onShow, this, {single: true, delay: 20});
+        }
+        Ext.apply(this, {
+            plain: true,
+            showSeparator: false,
+            items: this.picker = new Ext.DatePicker(Ext.applyIf({
+                internalRender: this.strict || !Ext.isIE,
+                ctCls: 'x-menu-date-item',
+                id: this.pickerId
+            }, this.initialConfig))
+        });
+        this.picker.purgeListeners();
+        Ext.menu.DateMenu.superclass.initComponent.call(this);
+        
+        this.relayEvents(this.picker, ['select']);
+        this.on('show', this.picker.focus, this.picker);
+        this.on('select', this.menuHide, this);
+        if(this.handler){
+            this.on('select', this.handler, this.scope || this);
+        }
+    },
+
+    menuHide : function() {
+        if(this.hideOnClick){
+            this.hide(true);
+        }
+    },
+
+    onBeforeShow : function(){
+        if(this.picker){
+            this.picker.hideMonthPicker(true);
+        }
+    },
+
+    onShow : function(){
+        var el = this.picker.getEl();
+        el.setWidth(el.getWidth()); 
+    }
+ });
+ Ext.reg('datemenu', Ext.menu.DateMenu);
+ 
+ Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
+    
+    enableScrolling : false,
+    
+        
+    
+    
+    hideOnClick : true,
+    
+    cls : 'x-color-menu',
+    
+    
+    paletteId : null,
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    initComponent : function(){
+        Ext.apply(this, {
+            plain: true,
+            showSeparator: false,
+            items: this.palette = new Ext.ColorPalette(Ext.applyIf({
+                id: this.paletteId
+            }, this.initialConfig))
+        });
+        this.palette.purgeListeners();
+        Ext.menu.ColorMenu.superclass.initComponent.call(this);
+        
+        this.relayEvents(this.palette, ['select']);
+        this.on('select', this.menuHide, this);
+        if(this.handler){
+            this.on('select', this.handler, this.scope || this);
+        }
+    },
+
+    menuHide : function(){
+        if(this.hideOnClick){
+            this.hide(true);
+        }
+    }
+});
+Ext.reg('colormenu', Ext.menu.ColorMenu);
+
+Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
+    
+    
+    
+    
+    
+    
+
+    
+    invalidClass : 'x-form-invalid',
+    
+    invalidText : 'The value in this field is invalid',
+    
+    focusClass : 'x-form-focus',
+    
+    
+    validationEvent : 'keyup',
+    
+    validateOnBlur : true,
+    
+    validationDelay : 250,
+    
+    defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
+    
+    fieldClass : 'x-form-field',
+    
+    msgTarget : 'qtip',
+    
+    msgFx : 'normal',
+    
+    readOnly : false,
+    
+    disabled : false,
+    
+    submitValue: true,
+
+    
+    isFormField : true,
+
+    
+    msgDisplay: '',
+
+    
+    hasFocus : false,
+
+    
+    initComponent : function(){
+        Ext.form.Field.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'focus',
+            
+            'blur',
+            
+            'specialkey',
+            
+            'change',
+            
+            'invalid',
+            
+            'valid'
+        );
+    },
+
+    
+    getName : function(){
+        return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
+    },
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            var cfg = this.getAutoCreate();
+
+            if(!cfg.name){
+                cfg.name = this.name || this.id;
+            }
+            if(this.inputType){
+                cfg.type = this.inputType;
+            }
+            this.autoEl = cfg;
+        }
+        Ext.form.Field.superclass.onRender.call(this, ct, position);
+        if(this.submitValue === false){
+            this.el.dom.removeAttribute('name');
+        }
+        var type = this.el.dom.type;
+        if(type){
+            if(type == 'password'){
+                type = 'text';
+            }
+            this.el.addClass('x-form-'+type);
+        }
+        if(this.readOnly){
+            this.setReadOnly(true);
+        }
+        if(this.tabIndex !== undefined){
+            this.el.dom.setAttribute('tabIndex', this.tabIndex);
+        }
+
+        this.el.addClass([this.fieldClass, this.cls]);
+    },
+
+    
+    getItemCt : function(){
+        return this.itemCt;
+    },
+
+    
+    initValue : function(){
+        if(this.value !== undefined){
+            this.setValue(this.value);
+        }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
+            this.setValue(this.el.dom.value);
+        }
+        
+        this.originalValue = this.getValue();
+    },
+
+    
+    isDirty : function() {
+        if(this.disabled || !this.rendered) {
+            return false;
+        }
+        return String(this.getValue()) !== String(this.originalValue);
+    },
+
+    
+    setReadOnly : function(readOnly){
+        if(this.rendered){
+            this.el.dom.readOnly = readOnly;
+        }
+        this.readOnly = readOnly;
+    },
+
+    
+    afterRender : function(){
+        Ext.form.Field.superclass.afterRender.call(this);
+        this.initEvents();
+        this.initValue();
+    },
+
+    
+    fireKey : function(e){
+        if(e.isSpecialKey()){
+            this.fireEvent('specialkey', this, e);
+        }
+    },
+
+    
+    reset : function(){
+        this.setValue(this.originalValue);
+        this.clearInvalid();
+    },
+
+    
+    initEvents : function(){
+        this.mon(this.el, Ext.EventManager.getKeyEvent(), this.fireKey,  this);
+        this.mon(this.el, 'focus', this.onFocus, this);
+
+        
+        
+        this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
+    },
+
+    
+    preFocus: Ext.emptyFn,
+
+    
+    onFocus : function(){
+        this.preFocus();
+        if(this.focusClass){
+            this.el.addClass(this.focusClass);
+        }
+        if(!this.hasFocus){
+            this.hasFocus = true;
+            
+            this.startValue = this.getValue();
+            this.fireEvent('focus', this);
+        }
+    },
+
+    
+    beforeBlur : Ext.emptyFn,
+
+    
+    onBlur : function(){
+        this.beforeBlur();
+        if(this.focusClass){
+            this.el.removeClass(this.focusClass);
+        }
+        this.hasFocus = false;
+        if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
+            this.validate();
+        }
+        var v = this.getValue();
+        if(String(v) !== String(this.startValue)){
+            this.fireEvent('change', this, v, this.startValue);
+        }
+        this.fireEvent('blur', this);
+        this.postBlur();
+    },
+
+    
+    postBlur : Ext.emptyFn,
+
+    
+    isValid : function(preventMark){
+        if(this.disabled){
+            return true;
+        }
+        var restore = this.preventMark;
+        this.preventMark = preventMark === true;
+        var v = this.validateValue(this.processValue(this.getRawValue()), preventMark);
+        this.preventMark = restore;
+        return v;
+    },
+
+    
+    validate : function(){
+        if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
+            this.clearInvalid();
+            return true;
+        }
+        return false;
+    },
+
+    
+    processValue : function(value){
+        return value;
+    },
+
+    
+     validateValue : function(value) {
+         
+         var error = this.getErrors(value)[0];
+
+         if (error == undefined) {
+             return true;
+         } else {
+             this.markInvalid(error);
+             return false;
+         }
+     },
+    
+    
+    getErrors: function() {
+        return [];
+    },
+
+    
+    getActiveError : function(){
+        return this.activeError || '';
+    },
+
+    
+    markInvalid : function(msg){
+        
+        if (this.rendered && !this.preventMark) {
+            msg = msg || this.invalidText;
+
+            var mt = this.getMessageHandler();
+            if(mt){
+                mt.mark(this, msg);
+            }else if(this.msgTarget){
+                this.el.addClass(this.invalidClass);
+                var t = Ext.getDom(this.msgTarget);
+                if(t){
+                    t.innerHTML = msg;
+                    t.style.display = this.msgDisplay;
+                }
+            }
+        }
+        
+        this.setActiveError(msg);
+    },
+    
+    
+    clearInvalid : function(){
+        
+        if (this.rendered && !this.preventMark) {
+            this.el.removeClass(this.invalidClass);
+            var mt = this.getMessageHandler();
+            if(mt){
+                mt.clear(this);
+            }else if(this.msgTarget){
+                this.el.removeClass(this.invalidClass);
+                var t = Ext.getDom(this.msgTarget);
+                if(t){
+                    t.innerHTML = '';
+                    t.style.display = 'none';
+                }
+            }
+        }
+        
+        this.unsetActiveError();
+    },
+
+    
+    setActiveError: function(msg, suppressEvent) {
+        this.activeError = msg;
+        if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
+    },
+    
+    
+    unsetActiveError: function(suppressEvent) {
+        delete this.activeError;
+        if (suppressEvent !== true) this.fireEvent('valid', this);
+    },
+
+    
+    getMessageHandler : function(){
+        return Ext.form.MessageTargets[this.msgTarget];
+    },
+
+    
+    getErrorCt : function(){
+        return this.el.findParent('.x-form-element', 5, true) || 
+            this.el.findParent('.x-form-field-wrap', 5, true);   
+    },
+
+    
+    alignErrorEl : function(){
+        this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
+    },
+
+    
+    alignErrorIcon : function(){
+        this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
+    },
+
+    
+    getRawValue : function(){
+        var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
+        if(v === this.emptyText){
+            v = '';
+        }
+        return v;
+    },
+
+    
+    getValue : function(){
+        if(!this.rendered) {
+            return this.value;
+        }
+        var v = this.el.getValue();
+        if(v === this.emptyText || v === undefined){
+            v = '';
+        }
+        return v;
+    },
+
+    
+    setRawValue : function(v){
+        return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
+    },
+
+    
+    setValue : function(v){
+        this.value = v;
+        if(this.rendered){
+            this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
+            this.validate();
+        }
+        return this;
+    },
+
+    
+    append : function(v){
+         this.setValue([this.getValue(), v].join(''));
+    }
+
+    
+    
+
+    
+});
+
+
+Ext.form.MessageTargets = {
+    'qtip' : {
+        mark: function(field, msg){
+            field.el.addClass(field.invalidClass);
+            field.el.dom.qtip = msg;
+            field.el.dom.qclass = 'x-form-invalid-tip';
+            if(Ext.QuickTips){ 
+                Ext.QuickTips.enable();
+            }
+        },
+        clear: function(field){
+            field.el.removeClass(field.invalidClass);
+            field.el.dom.qtip = '';
+        }
+    },
+    'title' : {
+        mark: function(field, msg){
+            field.el.addClass(field.invalidClass);
+            field.el.dom.title = msg;
+        },
+        clear: function(field){
+            field.el.dom.title = '';
+        }
+    },
+    'under' : {
+        mark: function(field, msg){
+            field.el.addClass(field.invalidClass);
+            if(!field.errorEl){
+                var elp = field.getErrorCt();
+                if(!elp){ 
+                    field.el.dom.title = msg;
+                    return;
+                }
+                field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
+                field.on('resize', field.alignErrorEl, field);
+                field.on('destroy', function(){
+                    Ext.destroy(this.errorEl);
+                }, field);
+            }
+            field.alignErrorEl();
+            field.errorEl.update(msg);
+            Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
+        },
+        clear: function(field){
+            field.el.removeClass(field.invalidClass);
+            if(field.errorEl){
+                Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
+            }else{
+                field.el.dom.title = '';
+            }
+        }
+    },
+    'side' : {
+        mark: function(field, msg){
+            field.el.addClass(field.invalidClass);
+            if(!field.errorIcon){
+                var elp = field.getErrorCt();
+                
+                if(!elp){
+                    field.el.dom.title = msg;
+                    return;
+                }
+                field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
+                if (field.ownerCt) {
+                    field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
+                    field.ownerCt.on('expand', field.alignErrorIcon, field);
+                }
+                field.on('resize', field.alignErrorIcon, field);
+                field.on('destroy', function(){
+                    Ext.destroy(this.errorIcon);
+                }, field);
+            }
+            field.alignErrorIcon();
+            field.errorIcon.dom.qtip = msg;
+            field.errorIcon.dom.qclass = 'x-form-invalid-tip';
+            field.errorIcon.show();
+        },
+        clear: function(field){
+            field.el.removeClass(field.invalidClass);
+            if(field.errorIcon){
+                field.errorIcon.dom.qtip = '';
+                field.errorIcon.hide();
+            }else{
+                field.el.dom.title = '';
+            }
+        }
+    }
+};
+
+
+Ext.form.Field.msgFx = {
+    normal : {
+        show: function(msgEl, f){
+            msgEl.setDisplayed('block');
+        },
+
+        hide : function(msgEl, f){
+            msgEl.setDisplayed(false).update('');
+        }
+    },
+
+    slide : {
+        show: function(msgEl, f){
+            msgEl.slideIn('t', {stopFx:true});
+        },
+
+        hide : function(msgEl, f){
+            msgEl.slideOut('t', {stopFx:true,useDisplay:true});
+        }
+    },
+
+    slideRight : {
+        show: function(msgEl, f){
+            msgEl.fixDisplay();
+            msgEl.alignTo(f.el, 'tl-tr');
+            msgEl.slideIn('l', {stopFx:true});
+        },
+
+        hide : function(msgEl, f){
+            msgEl.slideOut('l', {stopFx:true,useDisplay:true});
+        }
+    }
+};
+Ext.reg('field', Ext.form.Field);
+
+Ext.form.TextField = Ext.extend(Ext.form.Field,  {
+    
+    
+    
+    grow : false,
+    
+    growMin : 30,
+    
+    growMax : 800,
+    
+    vtype : null,
+    
+    maskRe : null,
+    
+    disableKeyFilter : false,
+    
+    allowBlank : true,
+    
+    minLength : 0,
+    
+    maxLength : Number.MAX_VALUE,
+    
+    minLengthText : 'The minimum length for this field is {0}',
+    
+    maxLengthText : 'The maximum length for this field is {0}',
+    
+    selectOnFocus : false,
+    
+    blankText : 'This field is required',
+    
+    validator : null,
+    
+    regex : null,
+    
+    regexText : '',
+    
+    emptyText : null,
+    
+    emptyClass : 'x-form-empty-field',
+
+    
+
+    initComponent : function(){
+        Ext.form.TextField.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'autosize',
+
+            
+            'keydown',
+            
+            'keyup',
+            
+            'keypress'
+        );
+    },
+
+    
+    initEvents : function(){
+        Ext.form.TextField.superclass.initEvents.call(this);
+        if(this.validationEvent == 'keyup'){
+            this.validationTask = new Ext.util.DelayedTask(this.validate, this);
+            this.mon(this.el, 'keyup', this.filterValidation, this);
+        }
+        else if(this.validationEvent !== false && this.validationEvent != 'blur'){
+        	this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
+        }
+        if(this.selectOnFocus || this.emptyText){            
+            this.mon(this.el, 'mousedown', this.onMouseDown, this);
+            
+            if(this.emptyText){
+                this.applyEmptyText();
+            }
+        }
+        if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
+        	this.mon(this.el, 'keypress', this.filterKeys, this);
+        }
+        if(this.grow){
+        	this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
+			this.mon(this.el, 'click', this.autoSize, this);
+        }
+        if(this.enableKeyEvents){
+            this.mon(this.el, {
+                scope: this,
+                keyup: this.onKeyUp,
+                keydown: this.onKeyDown,
+                keypress: this.onKeyPress
+            });
+        }
+    },
+    
+    onMouseDown: function(e){
+        if(!this.hasFocus){
+            this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
+        }
+    },
+
+    processValue : function(value){
+        if(this.stripCharsRe){
+            var newValue = value.replace(this.stripCharsRe, '');
+            if(newValue !== value){
+                this.setRawValue(newValue);
+                return newValue;
+            }
+        }
+        return value;
+    },
+
+    filterValidation : function(e){
+        if(!e.isNavKeyPress()){
+            this.validationTask.delay(this.validationDelay);
+        }
+    },
+    
+    
+    onDisable: function(){
+        Ext.form.TextField.superclass.onDisable.call(this);
+        if(Ext.isIE){
+            this.el.dom.unselectable = 'on';
+        }
+    },
+    
+    
+    onEnable: function(){
+        Ext.form.TextField.superclass.onEnable.call(this);
+        if(Ext.isIE){
+            this.el.dom.unselectable = '';
+        }
+    },
+
+    
+    onKeyUpBuffered : function(e){
+        if(this.doAutoSize(e)){
+            this.autoSize();
+        }
+    },
+    
+    
+    doAutoSize : function(e){
+        return !e.isNavKeyPress();
+    },
+
+    
+    onKeyUp : function(e){
+        this.fireEvent('keyup', this, e);
+    },
+
+    
+    onKeyDown : function(e){
+        this.fireEvent('keydown', this, e);
+    },
+
+    
+    onKeyPress : function(e){
+        this.fireEvent('keypress', this, e);
+    },
+
+    
+    reset : function(){
+        Ext.form.TextField.superclass.reset.call(this);
+        this.applyEmptyText();
+    },
+
+    applyEmptyText : function(){
+        if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
+            this.setRawValue(this.emptyText);
+            this.el.addClass(this.emptyClass);
+        }
+    },
+
+    
+    preFocus : function(){
+        var el = this.el,
+            isEmpty;
+        if(this.emptyText){
+            if(el.dom.value == this.emptyText){
+                this.setRawValue('');
+                isEmpty = true;
+            }
+            el.removeClass(this.emptyClass);
+        }
+        if(this.selectOnFocus || isEmpty){
+            el.dom.select();
+        }
+    },
+
+    
+    postBlur : function(){
+        this.applyEmptyText();
+    },
+
+    
+    filterKeys : function(e){
+        if(e.ctrlKey){
+            return;
+        }
+        var k = e.getKey();
+        if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
+            return;
+        }
+        var cc = String.fromCharCode(e.getCharCode());
+        if(!Ext.isGecko && e.isSpecialKey() && !cc){
+            return;
+        }
+        if(!this.maskRe.test(cc)){
+            e.stopEvent();
+        }
+    },
+
+    setValue : function(v){
+        if(this.emptyText && this.el && !Ext.isEmpty(v)){
+            this.el.removeClass(this.emptyClass);
+        }
+        Ext.form.TextField.superclass.setValue.apply(this, arguments);
+        this.applyEmptyText();
+        this.autoSize();
+        return this;
+    },
+
+    
+    getErrors: function(value) {
+        var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
+        
+        value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());        
+        
+        if (Ext.isFunction(this.validator)) {
+            var msg = this.validator(value);
+            if (msg !== true) {
+                errors.push(msg);
+            }
+        }
+        
+        if (value.length < 1 || value === this.emptyText) {
+            if (this.allowBlank) {
+                
+                return errors;
+            } else {
+                errors.push(this.blankText);
+            }
+        }
+        
+        if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
+            errors.push(this.blankText);
+        }
+        
+        if (value.length < this.minLength) {
+            errors.push(String.format(this.minLengthText, this.minLength));
+        }
+        
+        if (value.length > this.maxLength) {
+            errors.push(String.format(this.maxLengthText, this.maxLength));
+        }
+        
+        if (this.vtype) {
+            var vt = Ext.form.VTypes;
+            if(!vt[this.vtype](value, this)){
+                errors.push(this.vtypeText || vt[this.vtype +'Text']);
+            }
+        }
+        
+        if (this.regex && !this.regex.test(value)) {
+            errors.push(this.regexText);
+        }
+        
+        return errors;
+    },
+
+    
+    selectText : function(start, end){
+        var v = this.getRawValue();
+        var doFocus = false;
+        if(v.length > 0){
+            start = start === undefined ? 0 : start;
+            end = end === undefined ? v.length : end;
+            var d = this.el.dom;
+            if(d.setSelectionRange){
+                d.setSelectionRange(start, end);
+            }else if(d.createTextRange){
+                var range = d.createTextRange();
+                range.moveStart('character', start);
+                range.moveEnd('character', end-v.length);
+                range.select();
+            }
+            doFocus = Ext.isGecko || Ext.isOpera;
+        }else{
+            doFocus = true;
+        }
+        if(doFocus){
+            this.focus();
+        }
+    },
+
+    
+    autoSize : function(){
+        if(!this.grow || !this.rendered){
+            return;
+        }
+        if(!this.metrics){
+            this.metrics = Ext.util.TextMetrics.createInstance(this.el);
+        }
+        var el = this.el;
+        var v = el.dom.value;
+        var d = document.createElement('div');
+        d.appendChild(document.createTextNode(v));
+        v = d.innerHTML;
+        Ext.removeNode(d);
+        d = null;
+        v += '&#160;';
+        var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
+        this.el.setWidth(w);
+        this.fireEvent('autosize', this, w);
+    },
+	
+	onDestroy: function(){
+		if(this.validationTask){
+			this.validationTask.cancel();
+			this.validationTask = null;
+		}
+		Ext.form.TextField.superclass.onDestroy.call(this);
+	}
+});
+Ext.reg('textfield', Ext.form.TextField);
+
+Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
+    
+    
+    
+    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
+    
+    hideTrigger:false,
+    
+    editable: true,
+    
+    readOnly: false,
+    
+    wrapFocusClass: 'x-trigger-wrap-focus',
+    
+    autoSize: Ext.emptyFn,
+    
+    monitorTab : true,
+    
+    deferHeight : true,
+    
+    mimicing : false,
+
+    actionMode: 'wrap',
+
+    defaultTriggerWidth: 17,
+
+    
+    onResize : function(w, h){
+        Ext.form.TriggerField.superclass.onResize.call(this, w, h);
+        var tw = this.getTriggerWidth();
+        if(Ext.isNumber(w)){
+            this.el.setWidth(w - tw);
+        }
+        this.wrap.setWidth(this.el.getWidth() + tw);
+    },
+
+    getTriggerWidth: function(){
+        var tw = this.trigger.getWidth();
+        if(!this.hideTrigger && !this.readOnly && tw === 0){
+            tw = this.defaultTriggerWidth;
+        }
+        return tw;
+    },
+
+    
+    alignErrorIcon : function(){
+        if(this.wrap){
+            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
+        }
+    },
+
+    
+    onRender : function(ct, position){
+        this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
+        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
+
+        this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
+        this.trigger = this.wrap.createChild(this.triggerConfig ||
+                {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.triggerClass});
+        this.initTrigger();
+        if(!this.width){
+            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
+        }
+        this.resizeEl = this.positionEl = this.wrap;
+    },
+
+    getWidth: function() {
+        return(this.el.getWidth() + this.trigger.getWidth());
+    },
+
+    updateEditState: function(){
+        if(this.rendered){
+            if (this.readOnly) {
+                this.el.dom.readOnly = true;
+                this.el.addClass('x-trigger-noedit');
+                this.mun(this.el, 'click', this.onTriggerClick, this);
+                this.trigger.setDisplayed(false);
+            } else {
+                if (!this.editable) {
+                    this.el.dom.readOnly = true;
+                    this.el.addClass('x-trigger-noedit');
+                    this.mon(this.el, 'click', this.onTriggerClick, this);
+                } else {
+                    this.el.dom.readOnly = false;
+                    this.el.removeClass('x-trigger-noedit');
+                    this.mun(this.el, 'click', this.onTriggerClick, this);
+                }
+                this.trigger.setDisplayed(!this.hideTrigger);
+            }
+            this.onResize(this.width || this.wrap.getWidth());
+        }
+    },
+
+    
+    setHideTrigger: function(hideTrigger){
+        if(hideTrigger != this.hideTrigger){
+            this.hideTrigger = hideTrigger;
+            this.updateEditState();
+        }
+    },
+
+    
+    setEditable: function(editable){
+        if(editable != this.editable){
+            this.editable = editable;
+            this.updateEditState();
+        }
+    },
+
+    
+    setReadOnly: function(readOnly){
+        if(readOnly != this.readOnly){
+            this.readOnly = readOnly;
+            this.updateEditState();
+        }
+    },
+
+    afterRender : function(){
+        Ext.form.TriggerField.superclass.afterRender.call(this);
+        this.updateEditState();
+    },
+
+    
+    initTrigger : function(){
+        this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
+        this.trigger.addClassOnOver('x-form-trigger-over');
+        this.trigger.addClassOnClick('x-form-trigger-click');
+    },
+
+    
+    onDestroy : function(){
+        Ext.destroy(this.trigger, this.wrap);
+        if (this.mimicing){
+            this.doc.un('mousedown', this.mimicBlur, this);
+        }
+        delete this.doc;
+        Ext.form.TriggerField.superclass.onDestroy.call(this);
+    },
+
+    
+    onFocus : function(){
+        Ext.form.TriggerField.superclass.onFocus.call(this);
+        if(!this.mimicing){
+            this.wrap.addClass(this.wrapFocusClass);
+            this.mimicing = true;
+            this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
+            if(this.monitorTab){
+                this.on('specialkey', this.checkTab, this);
+            }
+        }
+    },
+
+    
+    checkTab : function(me, e){
+        if(e.getKey() == e.TAB){
+            this.triggerBlur();
+        }
+    },
+
+    
+    onBlur : Ext.emptyFn,
+
+    
+    mimicBlur : function(e){
+        if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
+            this.triggerBlur();
+        }
+    },
+
+    
+    triggerBlur : function(){
+        this.mimicing = false;
+        this.doc.un('mousedown', this.mimicBlur, this);
+        if(this.monitorTab && this.el){
+            this.un('specialkey', this.checkTab, this);
+        }
+        Ext.form.TriggerField.superclass.onBlur.call(this);
+        if(this.wrap){
+            this.wrap.removeClass(this.wrapFocusClass);
+        }
+    },
+
+    beforeBlur : Ext.emptyFn,
+
+    
+    
+    validateBlur : function(e){
+        return true;
+    },
+
+    
+    onTriggerClick : Ext.emptyFn
+
+    
+    
+    
+});
+
+
+Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
+    
+    
+    
+
+    initComponent : function(){
+        Ext.form.TwinTriggerField.superclass.initComponent.call(this);
+
+        this.triggerConfig = {
+            tag:'span', cls:'x-form-twin-triggers', cn:[
+            {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger1Class},
+            {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger2Class}
+        ]};
+    },
+
+    getTrigger : function(index){
+        return this.triggers[index];
+    },
+    
+    afterRender: function(){
+        Ext.form.TwinTriggerField.superclass.afterRender.call(this);
+        var triggers = this.triggers,
+            i = 0,
+            len = triggers.length;
+            
+        for(; i < len; ++i){
+            if(this['hideTrigger' + (i + 1)]){
+                    triggers[i].hide();
+                }
+
+        }    
+    },
+
+    initTrigger : function(){
+        var ts = this.trigger.select('.x-form-trigger', true),
+            triggerField = this;
+            
+        ts.each(function(t, all, index){
+            var triggerIndex = 'Trigger'+(index+1);
+            t.hide = function(){
+                var w = triggerField.wrap.getWidth();
+                this.dom.style.display = 'none';
+                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
+                triggerField['hidden' + triggerIndex] = true;
+            };
+            t.show = function(){
+                var w = triggerField.wrap.getWidth();
+                this.dom.style.display = '';
+                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
+                triggerField['hidden' + triggerIndex] = false;
+            };
+            this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
+            t.addClassOnOver('x-form-trigger-over');
+            t.addClassOnClick('x-form-trigger-click');
+        }, this);
+        this.triggers = ts.elements;
+    },
+
+    getTriggerWidth: function(){
+        var tw = 0;
+        Ext.each(this.triggers, function(t, index){
+            var triggerIndex = 'Trigger' + (index + 1),
+                w = t.getWidth();
+            if(w === 0 && !this['hidden' + triggerIndex]){
+                tw += this.defaultTriggerWidth;
+            }else{
+                tw += w;
+            }
+        }, this);
+        return tw;
+    },
+
+    
+    onDestroy : function() {
+        Ext.destroy(this.triggers);
+        Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
+    },
+
+    
+    onTrigger1Click : Ext.emptyFn,
+    
+    onTrigger2Click : Ext.emptyFn
+});
+Ext.reg('trigger', Ext.form.TriggerField);
+
+Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
+    
+    growMin : 60,
+    
+    growMax: 1000,
+    growAppend : '&#160;\n&#160;',
+
+    enterIsSpecial : false,
+
+    
+    preventScrollbars: false,
+    
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            this.defaultAutoCreate = {
+                tag: "textarea",
+                style:"width:100px;height:60px;",
+                autocomplete: "off"
+            };
+        }
+        Ext.form.TextArea.superclass.onRender.call(this, ct, position);
+        if(this.grow){
+            this.textSizeEl = Ext.DomHelper.append(document.body, {
+                tag: "pre", cls: "x-form-grow-sizer"
+            });
+            if(this.preventScrollbars){
+                this.el.setStyle("overflow", "hidden");
+            }
+            this.el.setHeight(this.growMin);
+        }
+    },
+
+    onDestroy : function(){
+        Ext.removeNode(this.textSizeEl);
+        Ext.form.TextArea.superclass.onDestroy.call(this);
+    },
+
+    fireKey : function(e){
+        if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
+            this.fireEvent("specialkey", this, e);
+        }
+    },
+    
+    
+    doAutoSize : function(e){
+        return !e.isNavKeyPress() || e.getKey() == e.ENTER;
+    },
+    
+    
+    filterValidation: function(e) {            
+        if(!e.isNavKeyPress() || (!this.enterIsSpecial && e.keyCode == e.ENTER)){
+            this.validationTask.delay(this.validationDelay);
+        }
+    },
+
+    
+    autoSize: function(){
+        if(!this.grow || !this.textSizeEl){
+            return;
+        }
+        var el = this.el,
+            v = Ext.util.Format.htmlEncode(el.dom.value),
+            ts = this.textSizeEl,
+            h;
+            
+        Ext.fly(ts).setWidth(this.el.getWidth());
+        if(v.length < 1){
+            v = "&#160;&#160;";
+        }else{
+            v += this.growAppend;
+            if(Ext.isIE){
+                v = v.replace(/\n/g, '&#160;<br />');
+            }
+        }
+        ts.innerHTML = v;
+        h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
+        if(h != this.lastHeight){
+            this.lastHeight = h;
+            this.el.setHeight(h);
+            this.fireEvent("autosize", this, h);
+        }
+    }
+});
+Ext.reg('textarea', Ext.form.TextArea);
+Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
+    
+    
+    
+    fieldClass: "x-form-field x-form-num-field",
+    
+    
+    allowDecimals : true,
+    
+    
+    decimalSeparator : ".",
+    
+    
+    decimalPrecision : 2,
+    
+    
+    allowNegative : true,
+    
+    
+    minValue : Number.NEGATIVE_INFINITY,
+    
+    
+    maxValue : Number.MAX_VALUE,
+    
+    
+    minText : "The minimum value for this field is {0}",
+    
+    
+    maxText : "The maximum value for this field is {0}",
+    
+    
+    nanText : "{0} is not a valid number",
+    
+    
+    baseChars : "0123456789",
+    
+    
+    autoStripChars: false,
+
+    
+    initEvents : function() {
+        var allowed = this.baseChars + '';
+        if (this.allowDecimals) {
+            allowed += this.decimalSeparator;
+        }
+        if (this.allowNegative) {
+            allowed += '-';
+        }
+        allowed = Ext.escapeRe(allowed);
+        this.maskRe = new RegExp('[' + allowed + ']');
+        if (this.autoStripChars) {
+            this.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
+        }
+        
+        Ext.form.NumberField.superclass.initEvents.call(this);
+    },
+    
+    
+    getErrors: function(value) {
+        var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
+        
+        value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
+        
+        if (value.length < 1) { 
+             return errors;
+        }
+        
+        value = String(value).replace(this.decimalSeparator, ".");
+        
+        if(isNaN(value)){
+            errors.push(String.format(this.nanText, value));
+        }
+        
+        var num = this.parseValue(value);
+        
+        if (num < this.minValue) {
+            errors.push(String.format(this.minText, this.minValue));
+        }
+        
+        if (num > this.maxValue) {
+            errors.push(String.format(this.maxText, this.maxValue));
+        }
+        
+        return errors;
+    },
+
+    getValue : function() {
+        return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
+    },
+
+    setValue : function(v) {
+    	v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
+        v = this.fixPrecision(v);
+        v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
+        return Ext.form.NumberField.superclass.setValue.call(this, v);
+    },
+    
+    
+    setMinValue : function(value) {
+        this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
+    },
+    
+    
+    setMaxValue : function(value) {
+        this.maxValue = Ext.num(value, Number.MAX_VALUE);    
+    },
+
+    
+    parseValue : function(value) {
+        value = parseFloat(String(value).replace(this.decimalSeparator, "."));
+        return isNaN(value) ? '' : value;
+    },
+
+    
+    fixPrecision : function(value) {
+        var nan = isNaN(value);
+        
+        if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
+            return nan ? '' : value;
+        }
+        
+        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
+    },
+
+    beforeBlur : function() {
+        var v = this.parseValue(this.getRawValue());
+        
+        if (!Ext.isEmpty(v)) {
+            this.setValue(v);
+        }
+    }
+});
+
+Ext.reg('numberfield', Ext.form.NumberField);
+
+Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
+    
+    format : "m/d/Y",
+    
+    altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
+    
+    disabledDaysText : "Disabled",
+    
+    disabledDatesText : "Disabled",
+    
+    minText : "The date in this field must be equal to or after {0}",
+    
+    maxText : "The date in this field must be equal to or before {0}",
+    
+    invalidText : "{0} is not a valid date - it must be in the format {1}",
+    
+    triggerClass : 'x-form-date-trigger',
+    
+    showToday : true,
+    
+    
+    startDay : 0,
+    
+    
+    
+    
+    
+    
+
+    
+    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
+
+    
+    
+    initTime: '12', 
+
+    initTimeFormat: 'H',
+
+    
+    safeParse : function(value, format) {
+        if (Date.formatContainsHourInfo(format)) {
+            
+            return Date.parseDate(value, format);
+        } else {
+            
+            var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
+ 
+            if (parsedDate) {
+                return parsedDate.clearTime();
+            }
+        }
+    },
+
+    initComponent : function(){
+        Ext.form.DateField.superclass.initComponent.call(this);
+
+        this.addEvents(
+            
+            'select'
+        );
+
+        if(Ext.isString(this.minValue)){
+            this.minValue = this.parseDate(this.minValue);
+        }
+        if(Ext.isString(this.maxValue)){
+            this.maxValue = this.parseDate(this.maxValue);
+        }
+        this.disabledDatesRE = null;
+        this.initDisabledDays();
+    },
+
+    initEvents: function() {
+        Ext.form.DateField.superclass.initEvents.call(this);
+        this.keyNav = new Ext.KeyNav(this.el, {
+            "down": function(e) {
+                this.onTriggerClick();
+            },
+            scope: this,
+            forceKeyDown: true
+        });
+    },
+
+
+    
+    initDisabledDays : function(){
+        if(this.disabledDates){
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = "(?:";
+
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
+                if(i != len){
+                    re += '|';
+                }
+            }, this);
+            this.disabledDatesRE = new RegExp(re + ')');
+        }
+    },
+
+    
+    setDisabledDates : function(dd){
+        this.disabledDates = dd;
+        this.initDisabledDays();
+        if(this.menu){
+            this.menu.picker.setDisabledDates(this.disabledDatesRE);
+        }
+    },
+
+    
+    setDisabledDays : function(dd){
+        this.disabledDays = dd;
+        if(this.menu){
+            this.menu.picker.setDisabledDays(dd);
+        }
+    },
+
+    
+    setMinValue : function(dt){
+        this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
+        if(this.menu){
+            this.menu.picker.setMinDate(this.minValue);
+        }
+    },
+
+    
+    setMaxValue : function(dt){
+        this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
+        if(this.menu){
+            this.menu.picker.setMaxDate(this.maxValue);
+        }
+    },
+
+    
+    getErrors: function(value) {
+        var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
+
+        value = this.formatDate(value || this.processValue(this.getRawValue()));
+
+        if (value.length < 1) { 
+             return errors;
+        }
+
+        var svalue = value;
+        value = this.parseDate(value);
+        if (!value) {
+            errors.push(String.format(this.invalidText, svalue, this.format));
+            return errors;
+        }
+
+        var time = value.getTime();
+        if (this.minValue && time < this.minValue.clearTime().getTime()) {
+            errors.push(String.format(this.minText, this.formatDate(this.minValue)));
+        }
+
+        if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
+            errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
+        }
+
+        if (this.disabledDays) {
+            var day = value.getDay();
+
+            for(var i = 0; i < this.disabledDays.length; i++) {
+                if (day === this.disabledDays[i]) {
+                    errors.push(this.disabledDaysText);
+                    break;
+                }
+            }
+        }
+
+        var fvalue = this.formatDate(value);
+        if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
+            errors.push(String.format(this.disabledDatesText, fvalue));
+        }
+
+        return errors;
+    },
+
+    
+    
+    validateBlur : function(){
+        return !this.menu || !this.menu.isVisible();
+    },
+
+    
+    getValue : function(){
+        return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
+    },
+
+    
+    setValue : function(date){
+        return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
+    },
+
+    
+    parseDate : function(value) {
+        if(!value || Ext.isDate(value)){
+            return value;
+        }
+
+        var v = this.safeParse(value, this.format),
+            af = this.altFormats,
+            afa = this.altFormatsArray;
+
+        if (!v && af) {
+            afa = afa || af.split("|");
+
+            for (var i = 0, len = afa.length; i < len && !v; i++) {
+                v = this.safeParse(value, afa[i]);
+            }
+        }
+        return v;
+    },
+
+    
+    onDestroy : function(){
+        Ext.destroy(this.menu, this.keyNav);
+        Ext.form.DateField.superclass.onDestroy.call(this);
+    },
+
+    
+    formatDate : function(date){
+        return Ext.isDate(date) ? date.dateFormat(this.format) : date;
+    },
+
+    
+    
+    
+    onTriggerClick : function(){
+        if(this.disabled){
+            return;
+        }
+        if(this.menu == null){
+            this.menu = new Ext.menu.DateMenu({
+                hideOnClick: false,
+                focusOnSelect: false
+            });
+        }
+        this.onFocus();
+        Ext.apply(this.menu.picker,  {
+            minDate : this.minValue,
+            maxDate : this.maxValue,
+            disabledDatesRE : this.disabledDatesRE,
+            disabledDatesText : this.disabledDatesText,
+            disabledDays : this.disabledDays,
+            disabledDaysText : this.disabledDaysText,
+            format : this.format,
+            showToday : this.showToday,
+            startDay: this.startDay,
+            minText : String.format(this.minText, this.formatDate(this.minValue)),
+            maxText : String.format(this.maxText, this.formatDate(this.maxValue))
+        });
+        this.menu.picker.setValue(this.getValue() || new Date());
+        this.menu.show(this.el, "tl-bl?");
+        this.menuEvents('on');
+    },
+
+    
+    menuEvents: function(method){
+        this.menu[method]('select', this.onSelect, this);
+        this.menu[method]('hide', this.onMenuHide, this);
+        this.menu[method]('show', this.onFocus, this);
+    },
+
+    onSelect: function(m, d){
+        this.setValue(d);
+        this.fireEvent('select', this, d);
+        this.menu.hide();
+    },
+
+    onMenuHide: function(){
+        this.focus(false, 60);
+        this.menuEvents('un');
+    },
+
+    
+    beforeBlur : function(){
+        var v = this.parseDate(this.getRawValue());
+        if(v){
+            this.setValue(v);
+        }
+    }
+
+    
+    
+    
+    
+});
+Ext.reg('datefield', Ext.form.DateField);
+
+Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
+    validationEvent : false,
+    validateOnBlur : false,
+    defaultAutoCreate : {tag: "div"},
+    
+    fieldClass : "x-form-display-field",
+    
+    htmlEncode: false,
+
+    
+    initEvents : Ext.emptyFn,
+
+    isValid : function(){
+        return true;
+    },
+
+    validate : function(){
+        return true;
+    },
+
+    getRawValue : function(){
+        var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
+        if(v === this.emptyText){
+            v = '';
+        }
+        if(this.htmlEncode){
+            v = Ext.util.Format.htmlDecode(v);
+        }
+        return v;
+    },
+
+    getValue : function(){
+        return this.getRawValue();
+    },
+    
+    getName: function() {
+        return this.name;
+    },
+
+    setRawValue : function(v){
+        if(this.htmlEncode){
+            v = Ext.util.Format.htmlEncode(v);
+        }
+        return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
+    },
+
+    setValue : function(v){
+        this.setRawValue(v);
+        return this;
+    }
+    
+    
+    
+    
+    
+    
+});
+
+Ext.reg('displayfield', Ext.form.DisplayField);
+
+Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
+    
+    
+    
+    
+    
+
+    
+    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
+    
+    
+    
+    
+    
+    
+    
+    listClass : '',
+    
+    selectedClass : 'x-combo-selected',
+    
+    listEmptyText: '',
+    
+    triggerClass : 'x-form-arrow-trigger',
+    
+    shadow : 'sides',
+    
+    listAlign : 'tl-bl?',
+    
+    maxHeight : 300,
+    
+    minHeight : 90,
+    
+    triggerAction : 'query',
+    
+    minChars : 4,
+    
+    autoSelect : true,
+    
+    typeAhead : false,
+    
+    queryDelay : 500,
+    
+    pageSize : 0,
+    
+    selectOnFocus : false,
+    
+    queryParam : 'query',
+    
+    loadingText : 'Loading...',
+    
+    resizable : false,
+    
+    handleHeight : 8,
+    
+    allQuery: '',
+    
+    mode: 'remote',
+    
+    minListWidth : 70,
+    
+    forceSelection : false,
+    
+    typeAheadDelay : 250,
+    
+
+    
+    lazyInit : true,
+
+    
+    clearFilterOnReset : true,
+
+    
+    submitValue: undefined,
+
+    
+
+    
+    initComponent : function(){
+        Ext.form.ComboBox.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'expand',
+            
+            'collapse',
+
+            
+            'beforeselect',
+            
+            'select',
+            
+            'beforequery'
+        );
+        if(this.transform){
+            var s = Ext.getDom(this.transform);
+            if(!this.hiddenName){
+                this.hiddenName = s.name;
+            }
+            if(!this.store){
+                this.mode = 'local';
+                var d = [], opts = s.options;
+                for(var i = 0, len = opts.length;i < len; i++){
+                    var o = opts[i],
+                        value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
+                    if(o.selected && Ext.isEmpty(this.value, true)) {
+                        this.value = value;
+                    }
+                    d.push([value, o.text]);
+                }
+                this.store = new Ext.data.ArrayStore({
+                    idIndex: 0,
+                    fields: ['value', 'text'],
+                    data : d,
+                    autoDestroy: true
+                });
+                this.valueField = 'value';
+                this.displayField = 'text';
+            }
+            s.name = Ext.id(); 
+            if(!this.lazyRender){
+                this.target = true;
+                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
+                this.render(this.el.parentNode, s);
+            }
+            Ext.removeNode(s);
+        }
+        
+        else if(this.store){
+            this.store = Ext.StoreMgr.lookup(this.store);
+            if(this.store.autoCreated){
+                this.displayField = this.valueField = 'field1';
+                if(!this.store.expandData){
+                    this.displayField = 'field2';
+                }
+                this.mode = 'local';
+            }
+        }
+
+        this.selectedIndex = -1;
+        if(this.mode == 'local'){
+            if(!Ext.isDefined(this.initialConfig.queryDelay)){
+                this.queryDelay = 10;
+            }
+            if(!Ext.isDefined(this.initialConfig.minChars)){
+                this.minChars = 0;
+            }
+        }
+    },
+
+    
+    onRender : function(ct, position){
+        if(this.hiddenName && !Ext.isDefined(this.submitValue)){
+            this.submitValue = false;
+        }
+        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
+        if(this.hiddenName){
+            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
+                    id: (this.hiddenId || Ext.id())}, 'before', true);
+
+        }
+        if(Ext.isGecko){
+            this.el.dom.setAttribute('autocomplete', 'off');
+        }
+
+        if(!this.lazyInit){
+            this.initList();
+        }else{
+            this.on('focus', this.initList, this, {single: true});
+        }
+    },
+
+    
+    initValue : function(){
+        Ext.form.ComboBox.superclass.initValue.call(this);
+        if(this.hiddenField){
+            this.hiddenField.value =
+                Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
+        }
+    },
+
+    getParentZIndex : function(){
+        var zindex;
+        if (this.ownerCt){
+            this.findParentBy(function(ct){
+                zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
+                return !!zindex;
+            });
+        }
+        return zindex;
+    },
+    
+    getZIndex : function(listParent){
+        listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
+        var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
+        if(!zindex){
+            zindex = this.getParentZIndex();
+        }
+        return (zindex || 12000) + 5;
+    },
+
+    
+    initList : function(){
+        if(!this.list){
+            var cls = 'x-combo-list',
+                listParent = Ext.getDom(this.getListParent() || Ext.getBody());
+
+            this.list = new Ext.Layer({
+                parentEl: listParent,
+                shadow: this.shadow,
+                cls: [cls, this.listClass].join(' '),
+                constrain:false,
+                zindex: this.getZIndex(listParent)
+            });
+
+            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
+            this.list.setSize(lw, 0);
+            this.list.swallowEvent('mousewheel');
+            this.assetHeight = 0;
+            if(this.syncFont !== false){
+                this.list.setStyle('font-size', this.el.getStyle('font-size'));
+            }
+            if(this.title){
+                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
+                this.assetHeight += this.header.getHeight();
+            }
+
+            this.innerList = this.list.createChild({cls:cls+'-inner'});
+            this.mon(this.innerList, 'mouseover', this.onViewOver, this);
+            this.mon(this.innerList, 'mousemove', this.onViewMove, this);
+            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
+
+            if(this.pageSize){
+                this.footer = this.list.createChild({cls:cls+'-ft'});
+                this.pageTb = new Ext.PagingToolbar({
+                    store: this.store,
+                    pageSize: this.pageSize,
+                    renderTo:this.footer
+                });
+                this.assetHeight += this.footer.getHeight();
+            }
+
+            if(!this.tpl){
+                
+                this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
+                
+            }
+
+            
+            this.view = new Ext.DataView({
+                applyTo: this.innerList,
+                tpl: this.tpl,
+                singleSelect: true,
+                selectedClass: this.selectedClass,
+                itemSelector: this.itemSelector || '.' + cls + '-item',
+                emptyText: this.listEmptyText,
+                deferEmptyText: false
+            });
+
+            this.mon(this.view, {
+                containerclick : this.onViewClick,
+                click : this.onViewClick,
+                scope :this
+            });
+
+            this.bindStore(this.store, true);
+
+            if(this.resizable){
+                this.resizer = new Ext.Resizable(this.list,  {
+                   pinned:true, handles:'se'
+                });
+                this.mon(this.resizer, 'resize', function(r, w, h){
+                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
+                    this.listWidth = w;
+                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
+                    this.restrictHeight();
+                }, this);
+
+                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
+            }
+        }
+    },
+
+    
+    getListParent : function() {
+        return document.body;
+    },
+
+    
+    getStore : function(){
+        return this.store;
+    },
+
+    
+    bindStore : function(store, initial){
+        if(this.store && !initial){
+            if(this.store !== store && this.store.autoDestroy){
+                this.store.destroy();
+            }else{
+                this.store.un('beforeload', this.onBeforeLoad, this);
+                this.store.un('load', this.onLoad, this);
+                this.store.un('exception', this.collapse, this);
+            }
+            if(!store){
+                this.store = null;
+                if(this.view){
+                    this.view.bindStore(null);
+                }
+                if(this.pageTb){
+                    this.pageTb.bindStore(null);
+                }
+            }
+        }
+        if(store){
+            if(!initial) {
+                this.lastQuery = null;
+                if(this.pageTb) {
+                    this.pageTb.bindStore(store);
+                }
+            }
+
+            this.store = Ext.StoreMgr.lookup(store);
+            this.store.on({
+                scope: this,
+                beforeload: this.onBeforeLoad,
+                load: this.onLoad,
+                exception: this.collapse
+            });
+
+            if(this.view){
+                this.view.bindStore(store);
+            }
+        }
+    },
+
+    reset : function(){
+        if(this.clearFilterOnReset && this.mode == 'local'){
+            this.store.clearFilter();
+        }
+        Ext.form.ComboBox.superclass.reset.call(this);
+    },
+
+    
+    initEvents : function(){
+        Ext.form.ComboBox.superclass.initEvents.call(this);
+
+        
+        this.keyNav = new Ext.KeyNav(this.el, {
+            "up" : function(e){
+                this.inKeyMode = true;
+                this.selectPrev();
+            },
+
+            "down" : function(e){
+                if(!this.isExpanded()){
+                    this.onTriggerClick();
+                }else{
+                    this.inKeyMode = true;
+                    this.selectNext();
+                }
+            },
+
+            "enter" : function(e){
+                this.onViewClick();
+            },
+
+            "esc" : function(e){
+                this.collapse();
+            },
+
+            "tab" : function(e){
+                if (this.forceSelection === true) {
+                    this.collapse();
+                } else {
+                    this.onViewClick(false);
+                }
+                return true;
+            },
+
+            scope : this,
+
+            doRelay : function(e, h, hname){
+                if(hname == 'down' || this.scope.isExpanded()){
+                    
+                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
+                    if(!Ext.isIE && Ext.EventManager.useKeydown){
+                        
+                        this.scope.fireKey(e);
+                    }
+                    return relay;
+                }
+                return true;
+            },
+
+            forceKeyDown : true,
+            defaultEventAction: 'stopEvent'
+        });
+        this.queryDelay = Math.max(this.queryDelay || 10,
+                this.mode == 'local' ? 10 : 250);
+        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
+        if(this.typeAhead){
+            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
+        }
+        if(!this.enableKeyEvents){
+            this.mon(this.el, 'keyup', this.onKeyUp, this);
+        }
+    },
+
+
+    
+    onDestroy : function(){
+        if (this.dqTask){
+            this.dqTask.cancel();
+            this.dqTask = null;
+        }
+        this.bindStore(null);
+        Ext.destroy(
+            this.resizer,
+            this.view,
+            this.pageTb,
+            this.list
+        );
+        Ext.destroyMembers(this, 'hiddenField');
+        Ext.form.ComboBox.superclass.onDestroy.call(this);
+    },
+
+    
+    fireKey : function(e){
+        if (!this.isExpanded()) {
+            Ext.form.ComboBox.superclass.fireKey.call(this, e);
+        }
+    },
+
+    
+    onResize : function(w, h){
+        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
+        if(!isNaN(w) && this.isVisible() && this.list){
+            this.doResize(w);
+        }else{
+            this.bufferSize = w;
+        }
+    },
+
+    doResize: function(w){
+        if(!Ext.isDefined(this.listWidth)){
+            var lw = Math.max(w, this.minListWidth);
+            this.list.setWidth(lw);
+            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
+        }
+    },
+
+    
+    onEnable : function(){
+        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
+        if(this.hiddenField){
+            this.hiddenField.disabled = false;
+        }
+    },
+
+    
+    onDisable : function(){
+        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
+        if(this.hiddenField){
+            this.hiddenField.disabled = true;
+        }
+    },
+
+    
+    onBeforeLoad : function(){
+        if(!this.hasFocus){
+            return;
+        }
+        this.innerList.update(this.loadingText ?
+               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
+        this.restrictHeight();
+        this.selectedIndex = -1;
+    },
+
+    
+    onLoad : function(){
+        if(!this.hasFocus){
+            return;
+        }
+        if(this.store.getCount() > 0 || this.listEmptyText){
+            this.expand();
+            this.restrictHeight();
+            if(this.lastQuery == this.allQuery){
+                if(this.editable){
+                    this.el.dom.select();
+                }
+
+                if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
+                    this.select(0, true);
+                }
+            }else{
+                if(this.autoSelect !== false){
+                    this.selectNext();
+                }
+                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
+                    this.taTask.delay(this.typeAheadDelay);
+                }
+            }
+        }else{
+            this.collapse();
+        }
+
+    },
+
+    
+    onTypeAhead : function(){
+        if(this.store.getCount() > 0){
+            var r = this.store.getAt(0);
+            var newValue = r.data[this.displayField];
+            var len = newValue.length;
+            var selStart = this.getRawValue().length;
+            if(selStart != len){
+                this.setRawValue(newValue);
+                this.selectText(selStart, newValue.length);
+            }
+        }
+    },
+
+    
+    assertValue : function(){
+        var val = this.getRawValue(),
+            rec;
+
+        if(this.valueField && Ext.isDefined(this.value)){
+            rec = this.findRecord(this.valueField, this.value);
+        }
+        if(!rec || rec.get(this.displayField) != val){
+            rec = this.findRecord(this.displayField, val);
+        }
+        if(!rec && this.forceSelection){
+            if(val.length > 0 && val != this.emptyText){
+                this.el.dom.value = Ext.value(this.lastSelectionText, '');
+                this.applyEmptyText();
+            }else{
+                this.clearValue();
+            }
+        }else{
+            if(rec && this.valueField){
+                
+                
+                
+                if (this.value == val){
+                    return;
+                }
+                val = rec.get(this.valueField || this.displayField);
+            }
+            this.setValue(val);
+        }
+    },
+
+    
+    onSelect : function(record, index){
+        if(this.fireEvent('beforeselect', this, record, index) !== false){
+            this.setValue(record.data[this.valueField || this.displayField]);
+            this.collapse();
+            this.fireEvent('select', this, record, index);
+        }
+    },
+
+    
+    getName: function(){
+        var hf = this.hiddenField;
+        return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
+    },
+
+    
+    getValue : function(){
+        if(this.valueField){
+            return Ext.isDefined(this.value) ? this.value : '';
+        }else{
+            return Ext.form.ComboBox.superclass.getValue.call(this);
+        }
+    },
+
+    
+    clearValue : function(){
+        if(this.hiddenField){
+            this.hiddenField.value = '';
+        }
+        this.setRawValue('');
+        this.lastSelectionText = '';
+        this.applyEmptyText();
+        this.value = '';
+    },
+
+    
+    setValue : function(v){
+        var text = v;
+        if(this.valueField){
+            var r = this.findRecord(this.valueField, v);
+            if(r){
+                text = r.data[this.displayField];
+            }else if(Ext.isDefined(this.valueNotFoundText)){
+                text = this.valueNotFoundText;
+            }
+        }
+        this.lastSelectionText = text;
+        if(this.hiddenField){
+            this.hiddenField.value = Ext.value(v, '');
+        }
+        Ext.form.ComboBox.superclass.setValue.call(this, text);
+        this.value = v;
+        return this;
+    },
+
+    
+    findRecord : function(prop, value){
+        var record;
+        if(this.store.getCount() > 0){
+            this.store.each(function(r){
+                if(r.data[prop] == value){
+                    record = r;
+                    return false;
+                }
+            });
+        }
+        return record;
+    },
+
+    
+    onViewMove : function(e, t){
+        this.inKeyMode = false;
+    },
+
+    
+    onViewOver : function(e, t){
+        if(this.inKeyMode){ 
+            return;
+        }
+        var item = this.view.findItemFromChild(t);
+        if(item){
+            var index = this.view.indexOf(item);
+            this.select(index, false);
+        }
+    },
+
+    
+    onViewClick : function(doFocus){
+        var index = this.view.getSelectedIndexes()[0],
+            s = this.store,
+            r = s.getAt(index);
+        if(r){
+            this.onSelect(r, index);
+        }else {
+            this.collapse();
+        }
+        if(doFocus !== false){
+            this.el.focus();
+        }
+    },
+
+
+    
+    restrictHeight : function(){
+        this.innerList.dom.style.height = '';
+        var inner = this.innerList.dom,
+            pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
+            h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
+            ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
+            hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
+            space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
+
+        h = Math.min(h, space, this.maxHeight);
+
+        this.innerList.setHeight(h);
+        this.list.beginUpdate();
+        this.list.setHeight(h+pad);
+        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
+        this.list.endUpdate();
+    },
+
+    
+    isExpanded : function(){
+        return this.list && this.list.isVisible();
+    },
+
+    
+    selectByValue : function(v, scrollIntoView){
+        if(!Ext.isEmpty(v, true)){
+            var r = this.findRecord(this.valueField || this.displayField, v);
+            if(r){
+                this.select(this.store.indexOf(r), scrollIntoView);
+                return true;
+            }
+        }
+        return false;
+    },
+
+    
+    select : function(index, scrollIntoView){
+        this.selectedIndex = index;
+        this.view.select(index);
+        if(scrollIntoView !== false){
+            var el = this.view.getNode(index);
+            if(el){
+                this.innerList.scrollChildIntoView(el, false);
+            }
+        }
+
+    },
+
+    
+    selectNext : function(){
+        var ct = this.store.getCount();
+        if(ct > 0){
+            if(this.selectedIndex == -1){
+                this.select(0);
+            }else if(this.selectedIndex < ct-1){
+                this.select(this.selectedIndex+1);
+            }
+        }
+    },
+
+    
+    selectPrev : function(){
+        var ct = this.store.getCount();
+        if(ct > 0){
+            if(this.selectedIndex == -1){
+                this.select(0);
+            }else if(this.selectedIndex !== 0){
+                this.select(this.selectedIndex-1);
+            }
+        }
+    },
+
+    
+    onKeyUp : function(e){
+        var k = e.getKey();
+        if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
+
+            this.lastKey = k;
+            this.dqTask.delay(this.queryDelay);
+        }
+        Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
+    },
+
+    
+    validateBlur : function(){
+        return !this.list || !this.list.isVisible();
+    },
+
+    
+    initQuery : function(){
+        this.doQuery(this.getRawValue());
+    },
+
+    
+    beforeBlur : function(){
+        this.assertValue();
+    },
+
+    
+    postBlur  : function(){
+        Ext.form.ComboBox.superclass.postBlur.call(this);
+        this.collapse();
+        this.inKeyMode = false;
+    },
+
+    
+    doQuery : function(q, forceAll){
+        q = Ext.isEmpty(q) ? '' : q;
+        var qe = {
+            query: q,
+            forceAll: forceAll,
+            combo: this,
+            cancel:false
+        };
+        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
+            return false;
+        }
+        q = qe.query;
+        forceAll = qe.forceAll;
+        if(forceAll === true || (q.length >= this.minChars)){
+            if(this.lastQuery !== q){
+                this.lastQuery = q;
+                if(this.mode == 'local'){
+                    this.selectedIndex = -1;
+                    if(forceAll){
+                        this.store.clearFilter();
+                    }else{
+                        this.store.filter(this.displayField, q);
+                    }
+                    this.onLoad();
+                }else{
+                    this.store.baseParams[this.queryParam] = q;
+                    this.store.load({
+                        params: this.getParams(q)
+                    });
+                    this.expand();
+                }
+            }else{
+                this.selectedIndex = -1;
+                this.onLoad();
+            }
+        }
+    },
+
+    
+    getParams : function(q){
+        var params = {},
+            paramNames = this.store.paramNames;
+        if(this.pageSize){
+            params[paramNames.start] = 0;
+            params[paramNames.limit] = this.pageSize;
+        }
+        return params;
+    },
+
+    
+    collapse : function(){
+        if(!this.isExpanded()){
+            return;
+        }
+        this.list.hide();
+        Ext.getDoc().un('mousewheel', this.collapseIf, this);
+        Ext.getDoc().un('mousedown', this.collapseIf, this);
+        this.fireEvent('collapse', this);
+    },
+
+    
+    collapseIf : function(e){
+        if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
+            this.collapse();
+        }
+    },
+
+    
+    expand : function(){
+        if(this.isExpanded() || !this.hasFocus){
+            return;
+        }
+
+        if(this.title || this.pageSize){
+            this.assetHeight = 0;
+            if(this.title){
+                this.assetHeight += this.header.getHeight();
+            }
+            if(this.pageSize){
+                this.assetHeight += this.footer.getHeight();
+            }
+        }
+
+        if(this.bufferSize){
+            this.doResize(this.bufferSize);
+            delete this.bufferSize;
+        }
+        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
+
+        
+        this.list.setZIndex(this.getZIndex());
+        this.list.show();
+        if(Ext.isGecko2){
+            this.innerList.setOverflow('auto'); 
+        }
+        this.mon(Ext.getDoc(), {
+            scope: this,
+            mousewheel: this.collapseIf,
+            mousedown: this.collapseIf
+        });
+        this.fireEvent('expand', this);
+    },
+
+    
+    
+    
+    onTriggerClick : function(){
+        if(this.readOnly || this.disabled){
+            return;
+        }
+        if(this.isExpanded()){
+            this.collapse();
+            this.el.focus();
+        }else {
+            this.onFocus({});
+            if(this.triggerAction == 'all') {
+                this.doQuery(this.allQuery, true);
+            } else {
+                this.doQuery(this.getRawValue());
+            }
+            this.el.focus();
+        }
+    }
+
+    
+    
+    
+    
+
+});
+Ext.reg('combo', Ext.form.ComboBox);
+
+Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
+    
+    focusClass : undefined,
+    
+    fieldClass : 'x-form-field',
+    
+    checked : false,
+    
+    boxLabel: '&#160;',
+    
+    defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
+    
+    
+    
+
+    
+    actionMode : 'wrap',
+
+	
+    initComponent : function(){
+        Ext.form.Checkbox.superclass.initComponent.call(this);
+        this.addEvents(
+            
+            'check'
+        );
+    },
+
+    
+    onResize : function(){
+        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
+        if(!this.boxLabel && !this.fieldLabel){
+            this.el.alignTo(this.wrap, 'c-c');
+        }
+    },
+
+    
+    initEvents : function(){
+        Ext.form.Checkbox.superclass.initEvents.call(this);
+        this.mon(this.el, {
+            scope: this,
+            click: this.onClick,
+            change: this.onClick
+        });
+    },
+
+    
+    markInvalid : Ext.emptyFn,
+    
+    clearInvalid : Ext.emptyFn,
+
+    
+    onRender : function(ct, position){
+        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
+        if(this.inputValue !== undefined){
+            this.el.dom.value = this.inputValue;
+        }
+        this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
+        if(this.boxLabel){
+            this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
+        }
+        if(this.checked){
+            this.setValue(true);
+        }else{
+            this.checked = this.el.dom.checked;
+        }
+        
+        if (Ext.isIE && !Ext.isStrict) {
+            this.wrap.repaint();
+        }
+        this.resizeEl = this.positionEl = this.wrap;
+    },
+
+    
+    onDestroy : function(){
+        Ext.destroy(this.wrap);
+        Ext.form.Checkbox.superclass.onDestroy.call(this);
+    },
+
+    
+    initValue : function() {
+        this.originalValue = this.getValue();
+    },
+
+    
+    getValue : function(){
+        if(this.rendered){
+            return this.el.dom.checked;
+        }
+        return this.checked;
+    },
+
+	
+    onClick : function(){
+        if(this.el.dom.checked != this.checked){
+            this.setValue(this.el.dom.checked);
+        }
+    },
+
+    
+    setValue : function(v){
+        var checked = this.checked,
+            inputVal = this.inputValue;
+            
+        if (v === false) {
+            this.checked = false;
+        } else {
+            this.checked = (v === true || v === 'true' || v == '1' || (inputVal ? v == inputVal : String(v).toLowerCase() == 'on'));
+        }
+        
+        if(this.rendered){
+            this.el.dom.checked = this.checked;
+            this.el.dom.defaultChecked = this.checked;
+        }
+        if(checked != this.checked){
+            this.fireEvent('check', this, this.checked);
+            if(this.handler){
+                this.handler.call(this.scope || this, this, this.checked);
+            }
+        }
+        return this;
+    }
+});
+Ext.reg('checkbox', Ext.form.Checkbox);
+
+Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
+    
+    
+    columns : 'auto',
+    
+    vertical : false,
+    
+    allowBlank : true,
+    
+    blankText : "You must select at least one item in this group",
+
+    
+    defaultType : 'checkbox',
+
+    
+    groupCls : 'x-form-check-group',
+
+    
+    initComponent: function(){
+        this.addEvents(
+            
+            'change'
+        );
+        this.on('change', this.validate, this);
+        Ext.form.CheckboxGroup.superclass.initComponent.call(this);
+    },
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            var panelCfg = {
+                autoEl: {
+                    id: this.id
+                },
+                cls: this.groupCls,
+                layout: 'column',
+                renderTo: ct,
+                bufferResize: false 
+            };
+            var colCfg = {
+                xtype: 'container',
+                defaultType: this.defaultType,
+                layout: 'form',
+                defaults: {
+                    hideLabel: true,
+                    anchor: '100%'
+                }
+            };
+
+            if(this.items[0].items){
+
+                
+
+                Ext.apply(panelCfg, {
+                    layoutConfig: {columns: this.items.length},
+                    defaults: this.defaults,
+                    items: this.items
+                });
+                for(var i=0, len=this.items.length; i<len; i++){
+                    Ext.applyIf(this.items[i], colCfg);
+                }
+
+            }else{
+
+                
+                
+
+                var numCols, cols = [];
+
+                if(typeof this.columns == 'string'){ 
+                    this.columns = this.items.length;
+                }
+                if(!Ext.isArray(this.columns)){
+                    var cs = [];
+                    for(var i=0; i<this.columns; i++){
+                        cs.push((100/this.columns)*.01); 
+                    }
+                    this.columns = cs;
+                }
+
+                numCols = this.columns.length;
+
+                
+                for(var i=0; i<numCols; i++){
+                    var cc = Ext.apply({items:[]}, colCfg);
+                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
+                    if(this.defaults){
+                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
+                    }
+                    cols.push(cc);
+                };
+
+                
+                if(this.vertical){
+                    var rows = Math.ceil(this.items.length / numCols), ri = 0;
+                    for(var i=0, len=this.items.length; i<len; i++){
+                        if(i>0 && i%rows==0){
+                            ri++;
+                        }
+                        if(this.items[i].fieldLabel){
+                            this.items[i].hideLabel = false;
+                        }
+                        cols[ri].items.push(this.items[i]);
+                    };
+                }else{
+                    for(var i=0, len=this.items.length; i<len; i++){
+                        var ci = i % numCols;
+                        if(this.items[i].fieldLabel){
+                            this.items[i].hideLabel = false;
+                        }
+                        cols[ci].items.push(this.items[i]);
+                    };
+                }
+
+                Ext.apply(panelCfg, {
+                    layoutConfig: {columns: numCols},
+                    items: cols
+                });
+            }
+
+            this.panel = new Ext.Container(panelCfg);
+            this.panel.ownerCt = this;
+            this.el = this.panel.getEl();
+
+            if(this.forId && this.itemCls){
+                var l = this.el.up(this.itemCls).child('label', true);
+                if(l){
+                    l.setAttribute('htmlFor', this.forId);
+                }
+            }
+
+            var fields = this.panel.findBy(function(c){
+                return c.isFormField;
+            }, this);
+
+            this.items = new Ext.util.MixedCollection();
+            this.items.addAll(fields);
+        }
+        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
+    },
+
+    initValue : function(){
+        if(this.value){
+            this.setValue.apply(this, this.buffered ? this.value : [this.value]);
+            delete this.buffered;
+            delete this.value;
+        }
+    },
+
+    afterRender : function(){
+        Ext.form.CheckboxGroup.superclass.afterRender.call(this);
+        this.eachItem(function(item){
+            item.on('check', this.fireChecked, this);
+            item.inGroup = true;
+        });
+    },
+
+    
+    doLayout: function(){
+        
+        if(this.rendered){
+            this.panel.forceLayout = this.ownerCt.forceLayout;
+            this.panel.doLayout();
+        }
+    },
+
+    
+    fireChecked: function(){
+        var arr = [];
+        this.eachItem(function(item){
+            if(item.checked){
+                arr.push(item);
+            }
+        });
+        this.fireEvent('change', this, arr);
+    },
+    
+    
+    getErrors: function() {
+        var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
+        
+        if (!this.allowBlank) {
+            var blank = true;
+            
+            this.eachItem(function(f){
+                if (f.checked) {
+                    return (blank = false);
+                }
+            });
+            
+            if (blank) errors.push(this.blankText);
+        }
+        
+        return errors;
+    },
+
+    
+    isDirty: function(){
+        
+        if (this.disabled || !this.rendered) {
+            return false;
+        }
+
+        var dirty = false;
+        
+        this.eachItem(function(item){
+            if(item.isDirty()){
+                dirty = true;
+                return false;
+            }
+        });
+        
+        return dirty;
+    },
+
+    
+    setReadOnly : function(readOnly){
+        if(this.rendered){
+            this.eachItem(function(item){
+                item.setReadOnly(readOnly);
+            });
+        }
+        this.readOnly = readOnly;
+    },
+
+    
+    onDisable : function(){
+        this.eachItem(function(item){
+            item.disable();
+        });
+    },
+
+    
+    onEnable : function(){
+        this.eachItem(function(item){
+            item.enable();
+        });
+    },
+
+    
+    onResize : function(w, h){
+        this.panel.setSize(w, h);
+        this.panel.doLayout();
+    },
+
+    
+    reset : function(){
+        if (this.originalValue) {
+            
+            this.eachItem(function(c){
+                if(c.setValue){
+                    c.setValue(false);
+                    c.originalValue = c.getValue();
+                }
+            });
+            
+            
+            this.resetOriginal = true;
+            this.setValue(this.originalValue);
+            delete this.resetOriginal;
+        } else {
+            this.eachItem(function(c){
+                if(c.reset){
+                    c.reset();
+                }
+            });
+        }
+        
+        
+        (function() {
+            this.clearInvalid();
+        }).defer(50, this);
+    },
+
+    
+    setValue: function(){
+        if(this.rendered){
+            this.onSetValue.apply(this, arguments);
+        }else{
+            this.buffered = true;
+            this.value = arguments;
+        }
+        return this;
+    },
+
+    
+    onSetValue: function(id, value){
+        if(arguments.length == 1){
+            if(Ext.isArray(id)){
+                Ext.each(id, function(val, idx){
+                    if (Ext.isObject(val) && val.setValue){ 
+                        val.setValue(true);
+                        if (this.resetOriginal === true) {
+                            val.originalValue = val.getValue();
+                        }
+                    } else { 
+                        var item = this.items.itemAt(idx);
+                        if(item){
+                            item.setValue(val);
+                        }
+                    }
+                }, this);
+            }else if(Ext.isObject(id)){
+                
+                for(var i in id){
+                    var f = this.getBox(i);
+                    if(f){
+                        f.setValue(id[i]);
+                    }
+                }
+            }else{
+                this.setValueForItem(id);
+            }
+        }else{
+            var f = this.getBox(id);
+            if(f){
+                f.setValue(value);
+            }
+        }
+    },
+
+    
+    beforeDestroy: function(){
+        Ext.destroy(this.panel);
+        if (!this.rendered) {
+            Ext.destroy(this.items);
+        }
+        Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
+
+    },
+
+    setValueForItem : function(val){
+        val = String(val).split(',');
+        this.eachItem(function(item){
+            if(val.indexOf(item.inputValue)> -1){
+                item.setValue(true);
+            }
+        });
+    },
+
+    
+    getBox : function(id){
+        var box = null;
+        this.eachItem(function(f){
+            if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
+                box = f;
+                return false;
+            }
+        });
+        return box;
+    },
+
+    
+    getValue : function(){
+        var out = [];
+        this.eachItem(function(item){
+            if(item.checked){
+                out.push(item);
+            }
+        });
+        return out;
+    },
+
+    
+    eachItem: function(fn, scope) {
+        if(this.items && this.items.each){
+            this.items.each(fn, scope || this);
+        }
+    },
+
+    
+
+    
+    getRawValue : Ext.emptyFn,
+
+    
+    setRawValue : Ext.emptyFn
+
+});
+
+Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
+
+Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
+
+    
+    defaultMargins: '0 5 0 0',
+
+    
+    skipLastItemMargin: true,
+
+    
+    isComposite: true,
+
+    
+    combineErrors: true,
+    
+    
+    labelConnector: ', ',
+    
+    
+
+    
+    
+    initComponent: function() {
+        var labels = [],
+            items  = this.items,
+            item;
+
+        for (var i=0, j = items.length; i < j; i++) {
+            item = items[i];
+            
+            if (!Ext.isEmpty(item.ref)){
+                item.ref = '../' + item.ref;
+            }
+
+            labels.push(item.fieldLabel);
+
+            
+            Ext.applyIf(item, this.defaults);
+
+            
+            if (!(i == j - 1 && this.skipLastItemMargin)) {
+                Ext.applyIf(item, {margins: this.defaultMargins});
+            }
+        }
+
+        this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
+
+        
+        this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
+            return item.field;
+        });
+
+        this.fieldErrors.on({
+            scope  : this,
+            add    : this.updateInvalidMark,
+            remove : this.updateInvalidMark,
+            replace: this.updateInvalidMark
+        });
+
+        Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
+        
+        this.innerCt = new Ext.Container({
+            layout  : 'hbox',
+            items   : this.items,
+            cls     : 'x-form-composite',
+            defaultMargins: '0 3 0 0',
+            ownerCt: this
+        });
+        this.innerCt.ownerCt = undefined;
+        
+        var fields = this.innerCt.findBy(function(c) {
+            return c.isFormField;
+        }, this);
+
+        
+        this.items = new Ext.util.MixedCollection();
+        this.items.addAll(fields);
+        
+    },
+
+    
+    onRender: function(ct, position) {
+        if (!this.el) {
+            
+            var innerCt = this.innerCt;
+            innerCt.render(ct);
+
+            this.el = innerCt.getEl();
+
+            
+            
+            if (this.combineErrors) {
+                this.eachItem(function(field) {
+                    Ext.apply(field, {
+                        markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
+                        clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
+                    });
+                });
+            }
+
+            
+            var l = this.el.parent().parent().child('label', true);
+            if (l) {
+                l.setAttribute('for', this.items.items[0].id);
+            }
+        }
+
+        Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
+    },
+
+    
+    onFieldMarkInvalid: function(field, message) {
+        var name  = field.getName(),
+            error = {
+                field: name, 
+                errorName: field.fieldLabel || name,
+                error: message
+            };
+
+        this.fieldErrors.replace(name, error);
+
+        if (!field.preventMark) {
+            field.el.addClass(field.invalidClass);
+        }
+    },
+
+    
+    onFieldClearInvalid: function(field) {
+        this.fieldErrors.removeKey(field.getName());
+
+        field.el.removeClass(field.invalidClass);
+    },
+
+    
+    updateInvalidMark: function() {
+        var ieStrict = Ext.isIE6 && Ext.isStrict;
+
+        if (this.fieldErrors.length == 0) {
+            this.clearInvalid();
+
+            
+            if (ieStrict) {
+                this.clearInvalid.defer(50, this);
+            }
+        } else {
+            var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
+
+            this.sortErrors();
+            this.markInvalid(message);
+
+            
+            if (ieStrict) {
+                this.markInvalid(message);
+            }
+        }
+    },
+
+    
+    validateValue: function(value, preventMark) {
+        var valid = true;
+
+        this.eachItem(function(field) {
+            if (!field.isValid(preventMark)) {
+                valid = false;
+            }
+        });
+
+        return valid;
+    },
+
+    
+    buildCombinedErrorMessage: function(errors) {
+        var combined = [],
+            error;
+
+        for (var i = 0, j = errors.length; i < j; i++) {
+            error = errors[i];
+
+            combined.push(String.format("{0}: {1}", error.errorName, error.error));
+        }
+
+        return combined.join("<br />");
+    },
+
+    
+    sortErrors: function() {
+        var fields = this.items;
+
+        this.fieldErrors.sort("ASC", function(a, b) {
+            var findByName = function(key) {
+                return function(field) {
+                    return field.getName() == key;
+                };
+            };
+
+            var aIndex = fields.findIndexBy(findByName(a.field)),
+                bIndex = fields.findIndexBy(findByName(b.field));
+
+            return aIndex < bIndex ? -1 : 1;
+        });
+    },
+
+    
+    reset: function() {
+        this.eachItem(function(item) {
+            item.reset();
+        });
+
+        
+        
+        (function() {
+            this.clearInvalid();
+        }).defer(50, this);
+    },
+    
+    
+    clearInvalidChildren: function() {
+        this.eachItem(function(item) {
+            item.clearInvalid();
+        });
+    },
+
+    
+    buildLabel: function(segments) {
+        return Ext.clean(segments).join(this.labelConnector);
+    },
+
+    
+    isDirty: function(){
+        
+        if (this.disabled || !this.rendered) {
+            return false;
+        }
+
+        var dirty = false;
+        this.eachItem(function(item){
+            if(item.isDirty()){
+                dirty = true;
+                return false;
+            }
+        });
+        return dirty;
+    },
+
+    
+    eachItem: function(fn, scope) {
+        if(this.items && this.items.each){
+            this.items.each(fn, scope || this);
+        }
+    },
+
+    
+    onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
+        var innerCt = this.innerCt;
+
+        if (this.rendered && innerCt.rendered) {
+            innerCt.setSize(adjWidth, adjHeight);
+        }
+
+        Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
+    },
+
+    
+    doLayout: function(shallow, force) {
+        if (this.rendered) {
+            var innerCt = this.innerCt;
+
+            innerCt.forceLayout = this.ownerCt.forceLayout;
+            innerCt.doLayout(shallow, force);
+        }
+    },
+
+    
+    beforeDestroy: function(){
+        Ext.destroy(this.innerCt);
+
+        Ext.form.CompositeField.superclass.beforeDestroy.call(this);
+    },
+
+    
+    setReadOnly : function(readOnly) {
+        if (readOnly == undefined) {
+            readOnly = true;
+        }
+        readOnly = !!readOnly;
+
+        if(this.rendered){
+            this.eachItem(function(item){
+                item.setReadOnly(readOnly);
+            });
+        }
+        this.readOnly = readOnly;
+    },
+
+    onShow : function() {
+        Ext.form.CompositeField.superclass.onShow.call(this);
+        this.doLayout();
+    },
+
+    
+    onDisable : function(){
+        this.eachItem(function(item){
+            item.disable();
+        });
+    },
+
+    
+    onEnable : function(){
+        this.eachItem(function(item){
+            item.enable();
+        });
+    }
+});
+
+Ext.reg('compositefield', Ext.form.CompositeField);
+Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
+    inputType: 'radio',
+
+    
+    markInvalid : Ext.emptyFn,
+    
+    clearInvalid : Ext.emptyFn,
+
+    
+    getGroupValue : function(){
+    	var p = this.el.up('form') || Ext.getBody();
+        var c = p.child('input[name="'+this.el.dom.name+'"]:checked', true);
+        return c ? c.value : null;
+    },
+
+    
+    setValue : function(v){
+    	var checkEl,
+            els,
+            radio;
+    	if (typeof v == 'boolean') {
+            Ext.form.Radio.superclass.setValue.call(this, v);
+        } else if (this.rendered) {
+            checkEl = this.getCheckEl();
+            radio = checkEl.child('input[name="' + this.el.dom.name + '"][value="' + v + '"]', true);
+            if(radio){
+                Ext.getCmp(radio.id).setValue(true);
+            }
+        }
+        if(this.rendered && this.checked){
+            checkEl = checkEl || this.getCheckEl();
+            els = this.getCheckEl().select('input[name="' + this.el.dom.name + '"]');
+			els.each(function(el){
+				if(el.dom.id != this.id){
+					Ext.getCmp(el.dom.id).setValue(false);
+				}
+			}, this);
+        }
+        return this;
+    },
+
+    
+    getCheckEl: function(){
+        if(this.inGroup){
+            return this.el.up('.x-form-radio-group');
+        }
+        return this.el.up('form') || Ext.getBody();
+    }
+});
+Ext.reg('radio', Ext.form.Radio);
+
+Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
+    
+    
+    allowBlank : true,
+    
+    blankText : 'You must select one item in this group',
+    
+    
+    defaultType : 'radio',
+    
+    
+    groupCls : 'x-form-radio-group',
+    
+    
+    
+    
+    getValue : function(){
+        var out = null;
+        this.eachItem(function(item){
+            if(item.checked){
+                out = item;
+                return false;
+            }
+        });
+        return out;
+    },
+    
+    
+    onSetValue : function(id, value){
+        if(arguments.length > 1){
+            var f = this.getBox(id);
+            if(f){
+                f.setValue(value);
+                if(f.checked){
+                    this.eachItem(function(item){
+                        if (item !== f){
+                            item.setValue(false);
+                        }
+                    });
+                }
+            }
+        }else{
+            this.setValueForItem(id);
+        }
+    },
+    
+    setValueForItem : function(val){
+        val = String(val).split(',')[0];
+        this.eachItem(function(item){
+            item.setValue(val == item.inputValue);
+        });
+    },
+    
+    
+    fireChecked : function(){
+        if(!this.checkTask){
+            this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
+        }
+        this.checkTask.delay(10);
+    },
+    
+    
+    bufferChecked : function(){
+        var out = null;
+        this.eachItem(function(item){
+            if(item.checked){
+                out = item;
+                return false;
+            }
+        });
+        this.fireEvent('change', this, out);
+    },
+    
+    onDestroy : function(){
+        if(this.checkTask){
+            this.checkTask.cancel();
+            this.checkTask = null;
+        }
+        Ext.form.RadioGroup.superclass.onDestroy.call(this);
+    }
+
+});
+
+Ext.reg('radiogroup', Ext.form.RadioGroup);
+
+Ext.form.Hidden = Ext.extend(Ext.form.Field, {
+    
+    inputType : 'hidden',
+    
+    shouldLayout: false,
+
+    
+    onRender : function(){
+        Ext.form.Hidden.superclass.onRender.apply(this, arguments);
+    },
+
+    
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
+
+    
+    setSize : Ext.emptyFn,
+    setWidth : Ext.emptyFn,
+    setHeight : Ext.emptyFn,
+    setPosition : Ext.emptyFn,
+    setPagePosition : Ext.emptyFn,
+    markInvalid : Ext.emptyFn,
+    clearInvalid : Ext.emptyFn
+});
+Ext.reg('hidden', Ext.form.Hidden);
+Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
+
+    constructor: function(el, config){
+        Ext.apply(this, config);
+        if(Ext.isString(this.paramOrder)){
+            this.paramOrder = this.paramOrder.split(/[\s,|]/);
+        }
+        
+        this.items = new Ext.util.MixedCollection(false, function(o){
+            return o.getItemId();
+        });
+        this.addEvents(
+            
+            'beforeaction',
+            
+            'actionfailed',
+            
+            'actioncomplete'
+        );
+
+        if(el){
+            this.initEl(el);
+        }
+        Ext.form.BasicForm.superclass.constructor.call(this);
+    },
+
+    
+    
+    
+    
+    
+    
+    
+    timeout: 30,
+
+    
+
+    
+    paramOrder: undefined,
+
+    
+    paramsAsHash: false,
+
+    
+    waitTitle: 'Please Wait...',
+
+    
+    activeAction : null,
+
+    
+    trackResetOnLoad : false,
+
+    
+    
+
+    
+    initEl : function(el){
+        this.el = Ext.get(el);
+        this.id = this.el.id || Ext.id();
+        if(!this.standardSubmit){
+            this.el.on('submit', this.onSubmit, this);
+        }
+        this.el.addClass('x-form');
+    },
+
+    
+    getEl: function(){
+        return this.el;
+    },
+
+    
+    onSubmit : function(e){
+        e.stopEvent();
+    },
+
+    
+    destroy: function(bound){
+        if(bound !== true){
+            this.items.each(function(f){
+                Ext.destroy(f);
+            });
+            Ext.destroy(this.el);
+        }
+        this.items.clear();
+        this.purgeListeners();
+    },
+
+    
+    isValid : function(){
+        var valid = true;
+        this.items.each(function(f){
+           if(!f.validate()){
+               valid = false;
+           }
+        });
+        return valid;
+    },
+
+    
+    isDirty : function(){
+        var dirty = false;
+        this.items.each(function(f){
+           if(f.isDirty()){
+               dirty = true;
+               return false;
+           }
+        });
+        return dirty;
+    },
+
+    
+    doAction : function(action, options){
+        if(Ext.isString(action)){
+            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
+        }
+        if(this.fireEvent('beforeaction', this, action) !== false){
+            this.beforeAction(action);
+            action.run.defer(100, action);
+        }
+        return this;
+    },
+
+    
+    submit : function(options){
+        options = options || {};
+        if(this.standardSubmit){
+            var v = options.clientValidation === false || this.isValid();
+            if(v){
+                var el = this.el.dom;
+                if(this.url && Ext.isEmpty(el.action)){
+                    el.action = this.url;
+                }
+                el.submit();
+            }
+            return v;
+        }
+        var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
+        this.doAction(submitAction, options);
+        return this;
+    },
+
+    
+    load : function(options){
+        var loadAction = String.format('{0}load', this.api ? 'direct' : '');
+        this.doAction(loadAction, options);
+        return this;
+    },
+
+    
+    updateRecord : function(record){
+        record.beginEdit();
+        var fs = record.fields,
+            field,
+            value;
+        fs.each(function(f){
+            field = this.findField(f.name);
+            if(field){
+                value = field.getValue();
+                if (Ext.type(value) !== false && value.getGroupValue) {
+                    value = value.getGroupValue();
+                } else if ( field.eachItem ) {
+                    value = [];
+                    field.eachItem(function(item){
+                        value.push(item.getValue());
+                    });
+                }
+                record.set(f.name, value);
+            }
+        }, this);
+        record.endEdit();
+        return this;
+    },
+
+    
+    loadRecord : function(record){
+        this.setValues(record.data);
+        return this;
+    },
+
+    
+    beforeAction : function(action){
+        
+        this.items.each(function(f){
+            if(f.isFormField && f.syncValue){
+                f.syncValue();
+            }
+        });
+        var o = action.options;
+        if(o.waitMsg){
+            if(this.waitMsgTarget === true){
+                this.el.mask(o.waitMsg, 'x-mask-loading');
+            }else if(this.waitMsgTarget){
+                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
+                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
+            }else{
+                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
+            }
+        }
+    },
+
+    
+    afterAction : function(action, success){
+        this.activeAction = null;
+        var o = action.options;
+        if(o.waitMsg){
+            if(this.waitMsgTarget === true){
+                this.el.unmask();
+            }else if(this.waitMsgTarget){
+                this.waitMsgTarget.unmask();
+            }else{
+                Ext.MessageBox.updateProgress(1);
+                Ext.MessageBox.hide();
+            }
+        }
+        if(success){
+            if(o.reset){
+                this.reset();
+            }
+            Ext.callback(o.success, o.scope, [this, action]);
+            this.fireEvent('actioncomplete', this, action);
+        }else{
+            Ext.callback(o.failure, o.scope, [this, action]);
+            this.fireEvent('actionfailed', this, action);
+        }
+    },
+
+    
+    findField : function(id) {
+        var field = this.items.get(id);
+
+        if (!Ext.isObject(field)) {
+            
+            var findMatchingField = function(f) {
+                if (f.isFormField) {
+                    if (f.dataIndex == id || f.id == id || f.getName() == id) {
+                        field = f;
+                        return false;
+                    } else if (f.isComposite) {
+                        return f.items.each(findMatchingField);
+                    } else if (f instanceof Ext.form.CheckboxGroup && f.rendered) {
+                        return f.eachItem(findMatchingField);
+                    }
+                }
+            };
+
+            this.items.each(findMatchingField);
+        }
+        return field || null;
+    },
+
+
+    
+    markInvalid : function(errors){
+        if (Ext.isArray(errors)) {
+            for(var i = 0, len = errors.length; i < len; i++){
+                var fieldError = errors[i];
+                var f = this.findField(fieldError.id);
+                if(f){
+                    f.markInvalid(fieldError.msg);
+                }
+            }
+        } else {
+            var field, id;
+            for(id in errors){
+                if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
+                    field.markInvalid(errors[id]);
+                }
+            }
+        }
+
+        return this;
+    },
+
+    
+    setValues : function(values){
+        if(Ext.isArray(values)){ 
+            for(var i = 0, len = values.length; i < len; i++){
+                var v = values[i];
+                var f = this.findField(v.id);
+                if(f){
+                    f.setValue(v.value);
+                    if(this.trackResetOnLoad){
+                        f.originalValue = f.getValue();
+                    }
+                }
+            }
+        }else{ 
+            var field, id;
+            for(id in values){
+                if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
+                    field.setValue(values[id]);
+                    if(this.trackResetOnLoad){
+                        field.originalValue = field.getValue();
+                    }
+                }
+            }
+        }
+        return this;
+    },
+
+    
+    getValues : function(asString){
+        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
+        if(asString === true){
+            return fs;
+        }
+        return Ext.urlDecode(fs);
+    },
+
+    
+    getFieldValues : function(dirtyOnly){
+        var o = {},
+            n,
+            key,
+            val;
+        this.items.each(function(f) {
+            if (!f.disabled && (dirtyOnly !== true || f.isDirty())) {
+                n = f.getName();
+                key = o[n];
+                val = f.getValue();
+
+                if(Ext.isDefined(key)){
+                    if(Ext.isArray(key)){
+                        o[n].push(val);
+                    }else{
+                        o[n] = [key, val];
+                    }
+                }else{
+                    o[n] = val;
+                }
+            }
+        });
+        return o;
+    },
+
+    
+    clearInvalid : function(){
+        this.items.each(function(f){
+           f.clearInvalid();
+        });
+        return this;
+    },
+
+    
+    reset : function(){
+        this.items.each(function(f){
+            f.reset();
+        });
+        return this;
+    },
+
+    
+    add : function(){
+        this.items.addAll(Array.prototype.slice.call(arguments, 0));
+        return this;
+    },
+
+    
+    remove : function(field){
+        this.items.remove(field);
+        return this;
+    },
+
+    
+    cleanDestroyed : function() {
+        this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
+    },
+
+    
+    render : function(){
+        this.items.each(function(f){
+            if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
+                f.applyToMarkup(f.id);
+            }
+        });
+        return this;
+    },
+
+    
+    applyToFields : function(o){
+        this.items.each(function(f){
+           Ext.apply(f, o);
+        });
+        return this;
+    },
+
+    
+    applyIfToFields : function(o){
+        this.items.each(function(f){
+           Ext.applyIf(f, o);
+        });
+        return this;
+    },
+
+    callFieldMethod : function(fnName, args){
+        args = args || [];
+        this.items.each(function(f){
+            if(Ext.isFunction(f[fnName])){
+                f[fnName].apply(f, args);
+            }
+        });
+        return this;
+    }
+});
+
+
+Ext.BasicForm = Ext.form.BasicForm;
+
+Ext.FormPanel = Ext.extend(Ext.Panel, {
+    
+    
+    
+    
+    
+    
+    
+
+
+    
+    minButtonWidth : 75,
+
+    
+    labelAlign : 'left',
+
+    
+    monitorValid : false,
+
+    
+    monitorPoll : 200,
+
+    
+    layout : 'form',
+
+    
+    initComponent : function(){
+        this.form = this.createForm();
+        Ext.FormPanel.superclass.initComponent.call(this);
+
+        this.bodyCfg = {
+            tag: 'form',
+            cls: this.baseCls + '-body',
+            method : this.method || 'POST',
+            id : this.formId || Ext.id()
+        };
+        if(this.fileUpload) {
+            this.bodyCfg.enctype = 'multipart/form-data';
+        }
+        this.initItems();
+
+        this.addEvents(
+            
+            'clientvalidation'
+        );
+
+        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
+    },
+
+    
+    createForm : function(){
+        var config = Ext.applyIf({listeners: {}}, this.initialConfig);
+        return new Ext.form.BasicForm(null, config);
+    },
+
+    
+    initFields : function(){
+        var f = this.form;
+        var formPanel = this;
+        var fn = function(c){
+            if(formPanel.isField(c)){
+                f.add(c);
+            }else if(c.findBy && c != formPanel){
+                formPanel.applySettings(c);
+                
+                if(c.items && c.items.each){
+                    c.items.each(fn, this);
+                }
+            }
+        };
+        this.items.each(fn, this);
+    },
+
+    
+    applySettings: function(c){
+        var ct = c.ownerCt;
+        Ext.applyIf(c, {
+            labelAlign: ct.labelAlign,
+            labelWidth: ct.labelWidth,
+            itemCls: ct.itemCls
+        });
+    },
+
+    
+    getLayoutTarget : function(){
+        return this.form.el;
+    },
+
+    
+    getForm : function(){
+        return this.form;
+    },
+
+    
+    onRender : function(ct, position){
+        this.initFields();
+        Ext.FormPanel.superclass.onRender.call(this, ct, position);
+        this.form.initEl(this.body);
+    },
+
+    
+    beforeDestroy : function(){
+        this.stopMonitoring();
+        this.form.destroy(true);
+        Ext.FormPanel.superclass.beforeDestroy.call(this);
+    },
+
+    
+    isField : function(c) {
+        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
+    },
+
+    
+    initEvents : function(){
+        Ext.FormPanel.superclass.initEvents.call(this);
+        
+        this.on({
+            scope: this,
+            add: this.onAddEvent,
+            remove: this.onRemoveEvent
+        });
+        if(this.monitorValid){ 
+            this.startMonitoring();
+        }
+    },
+
+    
+    onAdd: function(c){
+        Ext.FormPanel.superclass.onAdd.call(this, c);
+        this.processAdd(c);
+    },
+
+    
+    onAddEvent: function(ct, c){
+        if(ct !== this){
+            this.processAdd(c);
+        }
+    },
+
+    
+    processAdd : function(c){
+        
+        if(this.isField(c)){
+            this.form.add(c);
+        
+        }else if(c.findBy){
+            this.applySettings(c);
+            this.form.add.apply(this.form, c.findBy(this.isField));
+        }
+    },
+
+    
+    onRemove: function(c){
+        Ext.FormPanel.superclass.onRemove.call(this, c);
+        this.processRemove(c);
+    },
+
+    onRemoveEvent: function(ct, c){
+        if(ct !== this){
+            this.processRemove(c);
+        }
+    },
+
+    
+    processRemove: function(c){
+        if(!this.destroying){
+            
+            if(this.isField(c)){
+                this.form.remove(c);
+            
+            }else if (c.findBy){
+                Ext.each(c.findBy(this.isField), this.form.remove, this.form);
+                
+                this.form.cleanDestroyed();
+            }
+        }
+    },
+
+    
+    startMonitoring : function(){
+        if(!this.validTask){
+            this.validTask = new Ext.util.TaskRunner();
+            this.validTask.start({
+                run : this.bindHandler,
+                interval : this.monitorPoll || 200,
+                scope: this
+            });
+        }
+    },
+
+    
+    stopMonitoring : function(){
+        if(this.validTask){
+            this.validTask.stopAll();
+            this.validTask = null;
+        }
+    },
+
+    
+    load : function(){
+        this.form.load.apply(this.form, arguments);
+    },
+
+    
+    onDisable : function(){
+        Ext.FormPanel.superclass.onDisable.call(this);
+        if(this.form){
+            this.form.items.each(function(){
+                 this.disable();
+            });
+        }
+    },
+
+    
+    onEnable : function(){
+        Ext.FormPanel.superclass.onEnable.call(this);
+        if(this.form){
+            this.form.items.each(function(){
+                 this.enable();
+            });
+        }
+    },
+
+    
+    bindHandler : function(){
+        var valid = true;
+        this.form.items.each(function(f){
+            if(!f.isValid(true)){
+                valid = false;
+                return false;
+            }
+        });
+        if(this.fbar){
+            var fitems = this.fbar.items.items;
+            for(var i = 0, len = fitems.length; i < len; i++){
+                var btn = fitems[i];
+                if(btn.formBind === true && btn.disabled === valid){
+                    btn.setDisabled(!valid);
+                }
+            }
+        }
+        this.fireEvent('clientvalidation', this, valid);
+    }
+});
+Ext.reg('form', Ext.FormPanel);
+
+Ext.form.FormPanel = Ext.FormPanel;
+
+Ext.form.FieldSet = Ext.extend(Ext.Panel, {
+    
+    
+    
+    
+    
+    
+    baseCls : 'x-fieldset',
+    
+    layout : 'form',
+    
+    animCollapse : false,
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            this.el = document.createElement('fieldset');
+            this.el.id = this.id;
+            if (this.title || this.header || this.checkboxToggle) {
+                this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
+            }
+        }
+
+        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
+
+        if(this.checkboxToggle){
+            var o = typeof this.checkboxToggle == 'object' ?
+                    this.checkboxToggle :
+                    {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
+            this.checkbox = this.header.insertFirst(o);
+            this.checkbox.dom.checked = !this.collapsed;
+            this.mon(this.checkbox, 'click', this.onCheckClick, this);
+        }
+    },
+
+    
+    onCollapse : function(doAnim, animArg){
+        if(this.checkbox){
+            this.checkbox.dom.checked = false;
+        }
+        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
+
+    },
+
+    
+    onExpand : function(doAnim, animArg){
+        if(this.checkbox){
+            this.checkbox.dom.checked = true;
+        }
+        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
+    },
+
+    
+    onCheckClick : function(){
+        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+});
+Ext.reg('fieldset', Ext.form.FieldSet);
+
+Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
+    
+    enableFormat : true,
+    
+    enableFontSize : true,
+    
+    enableColors : true,
+    
+    enableAlignments : true,
+    
+    enableLists : true,
+    
+    enableSourceEdit : true,
+    
+    enableLinks : true,
+    
+    enableFont : true,
+    
+    createLinkText : 'Please enter the URL for the link:',
+    
+    defaultLinkValue : 'http:/'+'/',
+    
+    fontFamilies : [
+        'Arial',
+        'Courier New',
+        'Tahoma',
+        'Times New Roman',
+        'Verdana'
+    ],
+    defaultFont: 'tahoma',
+    
+    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
+
+    
+    actionMode: 'wrap',
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    onFocus : Ext.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
+    defaultAutoCreate : {
+        tag: "textarea",
+        style:"width:500px;height:300px;",
+        autocomplete: "off"
+    },
+
+    
+    initComponent : function(){
+        this.addEvents(
+            
+            'initialize',
+            
+            'activate',
+             
+            'beforesync',
+             
+            'beforepush',
+             
+            'sync',
+             
+            'push',
+             
+            'editmodechange'
+        );
+        Ext.form.HtmlEditor.superclass.initComponent.call(this);
+    },
+
+    
+    createFontOptions : function(){
+        var buf = [], fs = this.fontFamilies, ff, lc;
+        for(var i = 0, len = fs.length; i< len; i++){
+            ff = fs[i];
+            lc = ff.toLowerCase();
+            buf.push(
+                '<option value="',lc,'" style="font-family:',ff,';"',
+                    (this.defaultFont == lc ? ' selected="true">' : '>'),
+                    ff,
+                '</option>'
+            );
+        }
+        return buf.join('');
+    },
+
+    
+    createToolbar : function(editor){
+        var items = [];
+        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
+
+
+        function btn(id, toggle, handler){
+            return {
+                itemId : id,
+                cls : 'x-btn-icon',
+                iconCls: 'x-edit-'+id,
+                enableToggle:toggle !== false,
+                scope: editor,
+                handler:handler||editor.relayBtnCmd,
+                clickEvent:'mousedown',
+                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
+                overflowText: editor.buttonTips[id].title || undefined,
+                tabIndex:-1
+            };
+        }
+
+
+        if(this.enableFont && !Ext.isSafari2){
+            var fontSelectItem = new Ext.Toolbar.Item({
+               autoEl: {
+                    tag:'select',
+                    cls:'x-font-select',
+                    html: this.createFontOptions()
+               }
+            });
+
+            items.push(
+                fontSelectItem,
+                '-'
+            );
+        }
+
+        if(this.enableFormat){
+            items.push(
+                btn('bold'),
+                btn('italic'),
+                btn('underline')
+            );
+        }
+
+        if(this.enableFontSize){
+            items.push(
+                '-',
+                btn('increasefontsize', false, this.adjustFont),
+                btn('decreasefontsize', false, this.adjustFont)
+            );
+        }
+
+        if(this.enableColors){
+            items.push(
+                '-', {
+                    itemId:'forecolor',
+                    cls:'x-btn-icon',
+                    iconCls: 'x-edit-forecolor',
+                    clickEvent:'mousedown',
+                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
+                    tabIndex:-1,
+                    menu : new Ext.menu.ColorMenu({
+                        allowReselect: true,
+                        focus: Ext.emptyFn,
+                        value:'000000',
+                        plain:true,
+                        listeners: {
+                            scope: this,
+                            select: function(cp, color){
+                                this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                this.deferFocus();
+                            }
+                        },
+                        clickEvent:'mousedown'
+                    })
+                }, {
+                    itemId:'backcolor',
+                    cls:'x-btn-icon',
+                    iconCls: 'x-edit-backcolor',
+                    clickEvent:'mousedown',
+                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
+                    tabIndex:-1,
+                    menu : new Ext.menu.ColorMenu({
+                        focus: Ext.emptyFn,
+                        value:'FFFFFF',
+                        plain:true,
+                        allowReselect: true,
+                        listeners: {
+                            scope: this,
+                            select: function(cp, color){
+                                if(Ext.isGecko){
+                                    this.execCmd('useCSS', false);
+                                    this.execCmd('hilitecolor', color);
+                                    this.execCmd('useCSS', true);
+                                    this.deferFocus();
+                                }else{
+                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                    this.deferFocus();
+                                }
+                            }
+                        },
+                        clickEvent:'mousedown'
+                    })
+                }
+            );
+        }
+
+        if(this.enableAlignments){
+            items.push(
+                '-',
+                btn('justifyleft'),
+                btn('justifycenter'),
+                btn('justifyright')
+            );
+        }
+
+        if(!Ext.isSafari2){
+            if(this.enableLinks){
+                items.push(
+                    '-',
+                    btn('createlink', false, this.createLink)
+                );
+            }
+
+            if(this.enableLists){
+                items.push(
+                    '-',
+                    btn('insertorderedlist'),
+                    btn('insertunorderedlist')
+                );
+            }
+            if(this.enableSourceEdit){
+                items.push(
+                    '-',
+                    btn('sourceedit', true, function(btn){
+                        this.toggleSourceEdit(!this.sourceEditMode);
+                    })
+                );
+            }
+        }
+
+        
+        var tb = new Ext.Toolbar({
+            renderTo: this.wrap.dom.firstChild,
+            items: items
+        });
+
+        if (fontSelectItem) {
+            this.fontSelect = fontSelectItem.el;
+
+            this.mon(this.fontSelect, 'change', function(){
+                var font = this.fontSelect.dom.value;
+                this.relayCmd('fontname', font);
+                this.deferFocus();
+            }, this);
+        }
+
+        
+        this.mon(tb.el, 'click', function(e){
+            e.preventDefault();
+        });
+
+        this.tb = tb;
+        this.tb.doLayout();
+    },
+
+    onDisable: function(){
+        this.wrap.mask();
+        Ext.form.HtmlEditor.superclass.onDisable.call(this);
+    },
+
+    onEnable: function(){
+        this.wrap.unmask();
+        Ext.form.HtmlEditor.superclass.onEnable.call(this);
+    },
+
+    setReadOnly: function(readOnly){
+
+        Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
+        if(this.initialized){
+            if(Ext.isIE){
+                this.getEditorBody().contentEditable = !readOnly;
+            }else{
+                this.setDesignMode(!readOnly);
+            }
+            var bd = this.getEditorBody();
+            if(bd){
+                bd.style.cursor = this.readOnly ? 'default' : 'text';
+            }
+            this.disableItems(readOnly);
+        }
+    },
+
+    
+    getDocMarkup : function(){
+        var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
+        return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, h);
+    },
+
+    
+    getEditorBody : function(){
+        var doc = this.getDoc();
+        return doc.body || doc.documentElement;
+    },
+
+    
+    getDoc : function(){
+        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
+    },
+
+    
+    getWin : function(){
+        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden');
+        if(Ext.isIE){ 
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
+        }
+        this.wrap = this.el.wrap({
+            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+        });
+
+        this.createToolbar(this);
+
+        this.disableItems(true);
+
+        this.tb.doLayout();
+
+        this.createIFrame();
+
+        if(!this.width){
+            var sz = this.el.getSize();
+            this.setSize(sz.width, this.height || sz.height);
+        }
+        this.resizeEl = this.positionEl = this.wrap;
+    },
+
+    createIFrame: function(){
+        var iframe = document.createElement('iframe');
+        iframe.name = Ext.id();
+        iframe.frameBorder = '0';
+        iframe.style.overflow = 'auto';
+        iframe.src = Ext.SSL_SECURE_URL;
+
+        this.wrap.dom.appendChild(iframe);
+        this.iframe = iframe;
+
+        this.monitorTask = Ext.TaskMgr.start({
+            run: this.checkDesignMode,
+            scope: this,
+            interval:100
+        });
+    },
+
+    initFrame : function(){
+        Ext.TaskMgr.stop(this.monitorTask);
+        var doc = this.getDoc();
+        this.win = this.getWin();
+
+        doc.open();
+        doc.write(this.getDocMarkup());
+        doc.close();
+
+        var task = { 
+            run : function(){
+                var doc = this.getDoc();
+                if(doc.body || doc.readyState == 'complete'){
+                    Ext.TaskMgr.stop(task);
+                    this.setDesignMode(true);
+                    this.initEditor.defer(10, this);
+                }
+            },
+            interval : 10,
+            duration:10000,
+            scope: this
+        };
+        Ext.TaskMgr.start(task);
+    },
+
+
+    checkDesignMode : function(){
+        if(this.wrap && this.wrap.dom.offsetWidth){
+            var doc = this.getDoc();
+            if(!doc){
+                return;
+            }
+            if(!doc.editorInitialized || this.getDesignMode() != 'on'){
+                this.initFrame();
+            }
+        }
+    },
+
+    
+    setDesignMode : function(mode){
+        var doc = this.getDoc();
+        if (doc) {
+            if(this.readOnly){
+                mode = false;
+            }
+            doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
+        }
+
+    },
+
+    
+    getDesignMode : function(){
+        var doc = this.getDoc();
+        if(!doc){ return ''; }
+        return String(doc.designMode).toLowerCase();
+
+    },
+
+    disableItems: function(disabled){
+        if(this.fontSelect){
+            this.fontSelect.dom.disabled = disabled;
+        }
+        this.tb.items.each(function(item){
+            if(item.getItemId() != 'sourceedit'){
+                item.setDisabled(disabled);
+            }
+        });
+    },
+
+    
+    onResize : function(w, h){
+        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
+        if(this.el && this.iframe){
+            if(Ext.isNumber(w)){
+                var aw = w - this.wrap.getFrameWidth('lr');
+                this.el.setWidth(aw);
+                this.tb.setWidth(aw);
+                this.iframe.style.width = Math.max(aw, 0) + 'px';
+            }
+            if(Ext.isNumber(h)){
+                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
+                this.el.setHeight(ah);
+                this.iframe.style.height = Math.max(ah, 0) + 'px';
+                var bd = this.getEditorBody();
+                if(bd){
+                    bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
+                }
+            }
+        }
+    },
+
+    
+    toggleSourceEdit : function(sourceEditMode){
+        var iframeHeight,
+            elHeight;
+
+        if (sourceEditMode === undefined) {
+            sourceEditMode = !this.sourceEditMode;
+        }
+        this.sourceEditMode = sourceEditMode === true;
+        var btn = this.tb.getComponent('sourceedit');
+
+        if (btn.pressed !== this.sourceEditMode) {
+            btn.toggle(this.sourceEditMode);
+            if (!btn.xtbHidden) {
+                return;
+            }
+        }
+        if (this.sourceEditMode) {
+            
+            this.previousSize = this.getSize();
+
+            iframeHeight = Ext.get(this.iframe).getHeight();
+
+            this.disableItems(true);
+            this.syncValue();
+            this.iframe.className = 'x-hidden';
+            this.el.removeClass('x-hidden');
+            this.el.dom.removeAttribute('tabIndex');
+            this.el.focus();
+            this.el.dom.style.height = iframeHeight + 'px';
+        }
+        else {
+            elHeight = parseInt(this.el.dom.style.height, 10);
+            if (this.initialized) {
+                this.disableItems(this.readOnly);
+            }
+            this.pushValue();
+            this.iframe.className = '';
+            this.el.addClass('x-hidden');
+            this.el.dom.setAttribute('tabIndex', -1);
+            this.deferFocus();
+
+            this.setSize(this.previousSize);
+            delete this.previousSize;
+            this.iframe.style.height = elHeight + 'px';
+        }
+        this.fireEvent('editmodechange', this, this.sourceEditMode);
+    },
+
+    
+    createLink : function() {
+        var url = prompt(this.createLinkText, this.defaultLinkValue);
+        if(url && url != 'http:/'+'/'){
+            this.relayCmd('createlink', url);
+        }
+    },
+
+    
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
+
+    
+    markInvalid : Ext.emptyFn,
+
+    
+    clearInvalid : Ext.emptyFn,
+
+    
+    setValue : function(v){
+        Ext.form.HtmlEditor.superclass.setValue.call(this, v);
+        this.pushValue();
+        return this;
+    },
+
+    
+    cleanHtml: function(html) {
+        html = String(html);
+        if(Ext.isWebKit){ 
+            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+        }
+
+        
+        if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
+            html = html.substring(1);
+        }
+        return html;
+    },
+
+    
+    syncValue : function(){
+        if(this.initialized){
+            var bd = this.getEditorBody();
+            var html = bd.innerHTML;
+            if(Ext.isWebKit){
+                var bs = bd.getAttribute('style'); 
+                var m = bs.match(/text-align:(.*?);/i);
+                if(m && m[1]){
+                    html = '<div style="'+m[0]+'">' + html + '</div>';
+                }
+            }
+            html = this.cleanHtml(html);
+            if(this.fireEvent('beforesync', this, html) !== false){
+                this.el.dom.value = html;
+                this.fireEvent('sync', this, html);
+            }
+        }
+    },
+
+    
+    getValue : function() {
+        this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
+        return Ext.form.HtmlEditor.superclass.getValue.call(this);
+    },
+
+    
+    pushValue : function(){
+        if(this.initialized){
+            var v = this.el.dom.value;
+            if(!this.activated && v.length < 1){
+                v = this.defaultValue;
+            }
+            if(this.fireEvent('beforepush', this, v) !== false){
+                this.getEditorBody().innerHTML = v;
+                if(Ext.isGecko){
+                    
+                    this.setDesignMode(false);  
+                    this.setDesignMode(true);
+                }
+                this.fireEvent('push', this, v);
+            }
+
+        }
+    },
+
+    
+    deferFocus : function(){
+        this.focus.defer(10, this);
+    },
+
+    
+    focus : function(){
+        if(this.win && !this.sourceEditMode){
+            this.win.focus();
+        }else{
+            this.el.focus();
+        }
+    },
+
+    
+    initEditor : function(){
+        
+        try{
+            var dbody = this.getEditorBody(),
+                ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
+                doc,
+                fn;
+
+            ss['background-attachment'] = 'fixed'; 
+            dbody.bgProperties = 'fixed'; 
+
+            Ext.DomHelper.applyStyles(dbody, ss);
+
+            doc = this.getDoc();
+
+            if(doc){
+                try{
+                    Ext.EventManager.removeAll(doc);
+                }catch(e){}
+            }
+
+            
+            fn = this.onEditorEvent.createDelegate(this);
+            Ext.EventManager.on(doc, {
+                mousedown: fn,
+                dblclick: fn,
+                click: fn,
+                keyup: fn,
+                buffer:100
+            });
+
+            if(Ext.isGecko){
+                Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
+            }
+            if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
+                Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
+            }
+            doc.editorInitialized = true;
+            this.initialized = true;
+            this.pushValue();
+            this.setReadOnly(this.readOnly);
+            this.fireEvent('initialize', this);
+        }catch(e){}
+    },
+
+    
+    beforeDestroy : function(){
+        if(this.monitorTask){
+            Ext.TaskMgr.stop(this.monitorTask);
+        }
+        if(this.rendered){
+            Ext.destroy(this.tb);
+            var doc = this.getDoc();
+            if(doc){
+                try{
+                    Ext.EventManager.removeAll(doc);
+                    for (var prop in doc){
+                        delete doc[prop];
+                    }
+                }catch(e){}
+            }
+            if(this.wrap){
+                this.wrap.dom.innerHTML = '';
+                this.wrap.remove();
+            }
+        }
+        Ext.form.HtmlEditor.superclass.beforeDestroy.call(this);
+    },
+
+    
+    onFirstFocus : function(){
+        this.activated = true;
+        this.disableItems(this.readOnly);
+        if(Ext.isGecko){ 
+            this.win.focus();
+            var s = this.win.getSelection();
+            if(!s.focusNode || s.focusNode.nodeType != 3){
+                var r = s.getRangeAt(0);
+                r.selectNodeContents(this.getEditorBody());
+                r.collapse(true);
+                this.deferFocus();
+            }
+            try{
+                this.execCmd('useCSS', true);
+                this.execCmd('styleWithCSS', false);
+            }catch(e){}
+        }
+        this.fireEvent('activate', this);
+    },
+
+    
+    adjustFont: function(btn){
+        var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
+            doc = this.getDoc(),
+            v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
+        if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
+            
+            
+            if(v <= 10){
+                v = 1 + adjust;
+            }else if(v <= 13){
+                v = 2 + adjust;
+            }else if(v <= 16){
+                v = 3 + adjust;
+            }else if(v <= 18){
+                v = 4 + adjust;
+            }else if(v <= 24){
+                v = 5 + adjust;
+            }else {
+                v = 6 + adjust;
+            }
+            v = v.constrain(1, 6);
+        }else{
+            if(Ext.isSafari){ 
+                adjust *= 2;
+            }
+            v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
+        }
+        this.execCmd('FontSize', v);
+    },
+
+    
+    onEditorEvent : function(e){
+        this.updateToolbar();
+    },
+
+
+    
+    updateToolbar: function(){
+
+        if(this.readOnly){
+            return;
+        }
+
+        if(!this.activated){
+            this.onFirstFocus();
+            return;
+        }
+
+        var btns = this.tb.items.map,
+            doc = this.getDoc();
+
+        if(this.enableFont && !Ext.isSafari2){
+            var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
+            if(name != this.fontSelect.dom.value){
+                this.fontSelect.dom.value = name;
+            }
+        }
+        if(this.enableFormat){
+            btns.bold.toggle(doc.queryCommandState('bold'));
+            btns.italic.toggle(doc.queryCommandState('italic'));
+            btns.underline.toggle(doc.queryCommandState('underline'));
+        }
+        if(this.enableAlignments){
+            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
+            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
+            btns.justifyright.toggle(doc.queryCommandState('justifyright'));
+        }
+        if(!Ext.isSafari2 && this.enableLists){
+            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
+            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
+        }
+
+        Ext.menu.MenuMgr.hideAll();
+
+        this.syncValue();
+    },
+
+    
+    relayBtnCmd : function(btn){
+        this.relayCmd(btn.getItemId());
+    },
+
+    
+    relayCmd : function(cmd, value){
+        (function(){
+            this.focus();
+            this.execCmd(cmd, value);
+            this.updateToolbar();
+        }).defer(10, this);
+    },
+
+    
+    execCmd : function(cmd, value){
+        var doc = this.getDoc();
+        doc.execCommand(cmd, false, value === undefined ? null : value);
+        this.syncValue();
+    },
+
+    
+    applyCommand : function(e){
+        if(e.ctrlKey){
+            var c = e.getCharCode(), cmd;
+            if(c > 0){
+                c = String.fromCharCode(c);
+                switch(c){
+                    case 'b':
+                        cmd = 'bold';
+                    break;
+                    case 'i':
+                        cmd = 'italic';
+                    break;
+                    case 'u':
+                        cmd = 'underline';
+                    break;
+                }
+                if(cmd){
+                    this.win.focus();
+                    this.execCmd(cmd);
+                    this.deferFocus();
+                    e.preventDefault();
+                }
+            }
+        }
+    },
+
+    
+    insertAtCursor : function(text){
+        if(!this.activated){
+            return;
+        }
+        if(Ext.isIE){
+            this.win.focus();
+            var doc = this.getDoc(),
+                r = doc.selection.createRange();
+            if(r){
+                r.pasteHTML(text);
+                this.syncValue();
+                this.deferFocus();
+            }
+        }else{
+            this.win.focus();
+            this.execCmd('InsertHTML', text);
+            this.deferFocus();
+        }
+    },
+
+    
+    fixKeys : function(){ 
+        if(Ext.isIE){
+            return function(e){
+                var k = e.getKey(),
+                    doc = this.getDoc(),
+                        r;
+                if(k == e.TAB){
+                    e.stopEvent();
+                    r = doc.selection.createRange();
+                    if(r){
+                        r.collapse(true);
+                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
+                        this.deferFocus();
+                    }
+                }else if(k == e.ENTER){
+                    r = doc.selection.createRange();
+                    if(r){
+                        var target = r.parentElement();
+                        if(!target || target.tagName.toLowerCase() != 'li'){
+                            e.stopEvent();
+                            r.pasteHTML('<br />');
+                            r.collapse(false);
+                            r.select();
+                        }
+                    }
+                }
+            };
+        }else if(Ext.isOpera){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.win.focus();
+                    this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
+                    this.deferFocus();
+                }
+            };
+        }else if(Ext.isWebKit){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.execCmd('InsertText','\t');
+                    this.deferFocus();
+                }else if(k == e.ENTER){
+                    e.stopEvent();
+                    this.execCmd('InsertHtml','<br /><br />');
+                    this.deferFocus();
+                }
+             };
+        }
+    }(),
+
+    
+    getToolbar : function(){
+        return this.tb;
+    },
+
+    
+    buttonTips : {
+        bold : {
+            title: 'Bold (Ctrl+B)',
+            text: 'Make the selected text bold.',
+            cls: 'x-html-editor-tip'
+        },
+        italic : {
+            title: 'Italic (Ctrl+I)',
+            text: 'Make the selected text italic.',
+            cls: 'x-html-editor-tip'
+        },
+        underline : {
+            title: 'Underline (Ctrl+U)',
+            text: 'Underline the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        increasefontsize : {
+            title: 'Grow Text',
+            text: 'Increase the font size.',
+            cls: 'x-html-editor-tip'
+        },
+        decreasefontsize : {
+            title: 'Shrink Text',
+            text: 'Decrease the font size.',
+            cls: 'x-html-editor-tip'
+        },
+        backcolor : {
+            title: 'Text Highlight Color',
+            text: 'Change the background color of the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        forecolor : {
+            title: 'Font Color',
+            text: 'Change the color of the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        justifyleft : {
+            title: 'Align Text Left',
+            text: 'Align text to the left.',
+            cls: 'x-html-editor-tip'
+        },
+        justifycenter : {
+            title: 'Center Text',
+            text: 'Center text in the editor.',
+            cls: 'x-html-editor-tip'
+        },
+        justifyright : {
+            title: 'Align Text Right',
+            text: 'Align text to the right.',
+            cls: 'x-html-editor-tip'
+        },
+        insertunorderedlist : {
+            title: 'Bullet List',
+            text: 'Start a bulleted list.',
+            cls: 'x-html-editor-tip'
+        },
+        insertorderedlist : {
+            title: 'Numbered List',
+            text: 'Start a numbered list.',
+            cls: 'x-html-editor-tip'
+        },
+        createlink : {
+            title: 'Hyperlink',
+            text: 'Make the selected text a hyperlink.',
+            cls: 'x-html-editor-tip'
+        },
+        sourceedit : {
+            title: 'Source Edit',
+            text: 'Switch to source editing mode.',
+            cls: 'x-html-editor-tip'
+        }
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+});
+Ext.reg('htmleditor', Ext.form.HtmlEditor);
+
+Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
+    
+    minValue : undefined,
+    
+    maxValue : undefined,
+    
+    minText : "The time in this field must be equal to or after {0}",
+    
+    maxText : "The time in this field must be equal to or before {0}",
+    
+    invalidText : "{0} is not a valid time",
+    
+    format : "g:i A",
+    
+    altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
+    
+    increment: 15,
+
+    
+    mode: 'local',
+    
+    triggerAction: 'all',
+    
+    typeAhead: false,
+
+    
+    
+    
+    initDate: '1/1/2008',
+
+    initDateFormat: 'j/n/Y',
+
+    
+    initComponent : function(){
+        if(Ext.isDefined(this.minValue)){
+            this.setMinValue(this.minValue, true);
+        }
+        if(Ext.isDefined(this.maxValue)){
+            this.setMaxValue(this.maxValue, true);
+        }
+        if(!this.store){
+            this.generateStore(true);
+        }
+        Ext.form.TimeField.superclass.initComponent.call(this);
+    },
+
+    
+    setMinValue: function(value,  initial){
+        this.setLimit(value, true, initial);
+        return this;
+    },
+
+    
+    setMaxValue: function(value,  initial){
+        this.setLimit(value, false, initial);
+        return this;
+    },
+
+    
+    generateStore: function(initial){
+        var min = this.minValue || new Date(this.initDate).clearTime(),
+            max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
+            times = [];
+
+        while(min <= max){
+            times.push(min.dateFormat(this.format));
+            min = min.add('mi', this.increment);
+        }
+        this.bindStore(times, initial);
+    },
+
+    
+    setLimit: function(value, isMin, initial){
+        var d;
+        if(Ext.isString(value)){
+            d = this.parseDate(value);
+        }else if(Ext.isDate(value)){
+            d = value;
+        }
+        if(d){
+            var val = new Date(this.initDate).clearTime();
+            val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
+            this[isMin ? 'minValue' : 'maxValue'] = val;
+            if(!initial){
+                this.generateStore();
+            }
+        }
+    },
+
+    
+    getValue : function(){
+        var v = Ext.form.TimeField.superclass.getValue.call(this);
+        return this.formatDate(this.parseDate(v)) || '';
+    },
+
+    
+    setValue : function(value){
+        return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
+    },
+
+    
+    validateValue : Ext.form.DateField.prototype.validateValue,
+
+    formatDate : Ext.form.DateField.prototype.formatDate,
+
+    parseDate: function(value) {
+        if (!value || Ext.isDate(value)) {
+            return value;
+        }
+
+        var id = this.initDate + ' ',
+            idf = this.initDateFormat + ' ',
+            v = Date.parseDate(id + value, idf + this.format), 
+            af = this.altFormats;
+
+        if (!v && af) {
+            if (!this.altFormatsArray) {
+                this.altFormatsArray = af.split("|");
+            }
+            for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
+                v = Date.parseDate(id + value, idf + afa[i]);
+            }
+        }
+
+        return v;
+    }
+});
+Ext.reg('timefield', Ext.form.TimeField);
+Ext.form.SliderField = Ext.extend(Ext.form.Field, {
+    
+    
+    useTips : true,
+    
+    
+    tipText : null,
+    
+    
+    actionMode: 'wrap',
+    
+    
+    initComponent : function() {
+        var cfg = Ext.copyTo({
+            id: this.id + '-slider'
+        }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
+        
+        
+        if (this.useTips) {
+            var plug = this.tipText ? {getText: this.tipText} : {};
+            cfg.plugins = [new Ext.slider.Tip(plug)];
+        }
+        this.slider = new Ext.Slider(cfg);
+        Ext.form.SliderField.superclass.initComponent.call(this);
+    },    
+    
+    
+    onRender : function(ct, position){
+        this.autoCreate = {
+            id: this.id,
+            name: this.name,
+            type: 'hidden',
+            tag: 'input'    
+        };
+        Ext.form.SliderField.superclass.onRender.call(this, ct, position);
+        this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
+        this.resizeEl = this.positionEl = this.wrap;
+        this.slider.render(this.wrap);
+    },
+    
+    
+    onResize : function(w, h, aw, ah){
+        Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
+        this.slider.setSize(w, h);    
+    },
+    
+    
+    initEvents : function(){
+        Ext.form.SliderField.superclass.initEvents.call(this);
+        this.slider.on('change', this.onChange, this);   
+    },
+    
+    
+    onChange : function(slider, v){
+        this.setValue(v, undefined, true);
+    },
+    
+    
+    onEnable : function(){
+        Ext.form.SliderField.superclass.onEnable.call(this);
+        this.slider.enable();
+    },
+    
+    
+    onDisable : function(){
+        Ext.form.SliderField.superclass.onDisable.call(this);
+        this.slider.disable();    
+    },
+    
+    
+    beforeDestroy : function(){
+        Ext.destroy(this.slider);
+        Ext.form.SliderField.superclass.beforeDestroy.call(this);
+    },
+    
+    
+    alignErrorIcon : function(){
+        this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
+    },
+    
+    
+    setMinValue : function(v){
+        this.slider.setMinValue(v);
+        return this;    
+    },
+    
+    
+    setMaxValue : function(v){
+        this.slider.setMaxValue(v);
+        return this;    
+    },
+    
+    
+    setValue : function(v, animate,  silent){
+        
+        
+        if(!silent){
+            this.slider.setValue(v, animate);
+        }
+        return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
+    },
+    
+    
+    getValue : function(){
+        return this.slider.getValue();    
+    }
+});
+
+Ext.reg('sliderfield', Ext.form.SliderField);
+Ext.form.Label = Ext.extend(Ext.BoxComponent, {
+    
+    
+    
+
+    
+    onRender : function(ct, position){
+        if(!this.el){
+            this.el = document.createElement('label');
+            this.el.id = this.getId();
+            this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
+            if(this.forId){
+                this.el.setAttribute('for', this.forId);
+            }
+        }
+        Ext.form.Label.superclass.onRender.call(this, ct, position);
+    },
+
+    
+    setText : function(t, encode){
+        var e = encode === false;
+        this[!e ? 'text' : 'html'] = t;
+        delete this[e ? 'text' : 'html'];
+        if(this.rendered){
+            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
+        }
+        return this;
+    }
+});
+
+Ext.reg('label', Ext.form.Label);
+Ext.form.Action = function(form, options){
+    this.form = form;
+    this.options = options || {};
+};
+
+
+Ext.form.Action.CLIENT_INVALID = 'client';
+
+Ext.form.Action.SERVER_INVALID = 'server';
+
+Ext.form.Action.CONNECT_FAILURE = 'connect';
+
+Ext.form.Action.LOAD_FAILURE = 'load';
+
+Ext.form.Action.prototype = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    type : 'default',
+
+ 
+ 
+
+    
+    run : function(options){
+
+    },
+
+    
+    success : function(response){
+
+    },
+
+    
+    handleResponse : function(response){
+
+    },
+
+    
+    failure : function(response){
+        this.response = response;
+        this.failureType = Ext.form.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
+    },
+
+    
+    
+    
+    processResponse : function(response){
+        this.response = response;
+        if(!response.responseText && !response.responseXML){
+            return true;
+        }
+        this.result = this.handleResponse(response);
+        return this.result;
+    },
+    
+    decodeResponse: function(response) {
+        try {
+            return Ext.decode(response.responseText);
+        } catch(e) {
+            return false;
+        } 
+    },
+
+    
+    getUrl : function(appendParams){
+        var url = this.options.url || this.form.url || this.form.el.dom.action;
+        if(appendParams){
+            var p = this.getParams();
+            if(p){
+                url = Ext.urlAppend(url, p);
+            }
+        }
+        return url;
+    },
+
+    
+    getMethod : function(){
+        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
+    },
+
+    
+    getParams : function(){
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        if(p){
+            if(typeof p == "object"){
+                p = Ext.urlEncode(Ext.applyIf(p, bp));
+            }else if(typeof p == 'string' && bp){
+                p += '&' + Ext.urlEncode(bp);
+            }
+        }else if(bp){
+            p = Ext.urlEncode(bp);
+        }
+        return p;
+    },
+
+    
+    createCallback : function(opts){
+        var opts = opts || {};
+        return {
+            success: this.success,
+            failure: this.failure,
+            scope: this,
+            timeout: (opts.timeout*1000) || (this.form.timeout*1000),
+            upload: this.form.fileUpload ? this.success : undefined
+        };
+    }
+};
+
+
+Ext.form.Action.Submit = function(form, options){
+    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
+};
+
+Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
+    
+    
+    type : 'submit',
+
+    
+    run : function(){
+        var o = this.options,
+            method = this.getMethod(),
+            isGet = method == 'GET';
+        if(o.clientValidation === false || this.form.isValid()){
+            if (o.submitEmptyText === false) {
+                var fields = this.form.items,
+                    emptyFields = [],
+                    setupEmptyFields = function(f){
+                        if (f.el.getValue() == f.emptyText) {
+                            emptyFields.push(f);
+                            f.el.dom.value = "";
+                        }
+                        if(f.isComposite && f.rendered){
+                            f.items.each(setupEmptyFields);
+                        }
+                    };
+                    
+                fields.each(setupEmptyFields);
+            }
+            Ext.Ajax.request(Ext.apply(this.createCallback(o), {
+                form:this.form.el.dom,
+                url:this.getUrl(isGet),
+                method: method,
+                headers: o.headers,
+                params:!isGet ? this.getParams() : null,
+                isUpload: this.form.fileUpload
+            }));
+            if (o.submitEmptyText === false) {
+                Ext.each(emptyFields, function(f) {
+                    if (f.applyEmptyText) {
+                        f.applyEmptyText();
+                    }
+                });
+            }
+        }else if (o.clientValidation !== false){ 
+            this.failureType = Ext.form.Action.CLIENT_INVALID;
+            this.form.afterAction(this, false);
+        }
+    },
+
+    
+    success : function(response){
+        var result = this.processResponse(response);
+        if(result === true || result.success){
+            this.form.afterAction(this, true);
+            return;
+        }
+        if(result.errors){
+            this.form.markInvalid(result.errors);
+        }
+        this.failureType = Ext.form.Action.SERVER_INVALID;
+        this.form.afterAction(this, false);
+    },
+
+    
+    handleResponse : function(response){
+        if(this.form.errorReader){
+            var rs = this.form.errorReader.read(response);
+            var errors = [];
+            if(rs.records){
+                for(var i = 0, len = rs.records.length; i < len; i++) {
+                    var r = rs.records[i];
+                    errors[i] = r.data;
+                }
+            }
+            if(errors.length < 1){
+                errors = null;
+            }
+            return {
+                success : rs.success,
+                errors : errors
+            };
+        }
+        return this.decodeResponse(response);
+    }
+});
+
+
+
+Ext.form.Action.Load = function(form, options){
+    Ext.form.Action.Load.superclass.constructor.call(this, form, options);
+    this.reader = this.form.reader;
+};
+
+Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
+    
+    type : 'load',
+
+    
+    run : function(){
+        Ext.Ajax.request(Ext.apply(
+                this.createCallback(this.options), {
+                    method:this.getMethod(),
+                    url:this.getUrl(false),
+                    headers: this.options.headers,
+                    params:this.getParams()
+        }));
+    },
+
+    
+    success : function(response){
+        var result = this.processResponse(response);
+        if(result === true || !result.success || !result.data){
+            this.failureType = Ext.form.Action.LOAD_FAILURE;
+            this.form.afterAction(this, false);
+            return;
+        }
+        this.form.clearInvalid();
+        this.form.setValues(result.data);
+        this.form.afterAction(this, true);
+    },
+
+    
+    handleResponse : function(response){
+        if(this.form.reader){
+            var rs = this.form.reader.read(response);
+            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
+            return {
+                success : rs.success,
+                data : data
+            };
+        }
+        return this.decodeResponse(response);
+    }
+});
+
+
+
+
+Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
+    constructor: function(form, opts) {
+        Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
+    },
+    type : 'directload',
+
+    run : function(){
+        var args = this.getParams();
+        args.push(this.success, this);
+        this.form.api.load.apply(window, args);
+    },
+
+    getParams : function() {
+        var buf = [], o = {};
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        Ext.apply(o, p, bp);
+        var paramOrder = this.form.paramOrder;
+        if(paramOrder){
+            for(var i = 0, len = paramOrder.length; i < len; i++){
+                buf.push(o[paramOrder[i]]);
+            }
+        }else if(this.form.paramsAsHash){
+            buf.push(o);
+        }
+        return buf;
+    },
+    
+    
+    
+    processResponse : function(result) {
+        this.result = result;
+        return result;
+    },
+
+    success : function(response, trans){
+        if(trans.type == Ext.Direct.exceptions.SERVER){
+            response = {};
+        }
+        Ext.form.Action.DirectLoad.superclass.success.call(this, response);
+    }
+});
+
+
+Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
+    constructor : function(form, opts) {
+        Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
+    },
+    type : 'directsubmit',
+    
+    run : function(){
+        var o = this.options;
+        if(o.clientValidation === false || this.form.isValid()){
+            
+            
+            this.success.params = this.getParams();
+            this.form.api.submit(this.form.el.dom, this.success, this);
+        }else if (o.clientValidation !== false){ 
+            this.failureType = Ext.form.Action.CLIENT_INVALID;
+            this.form.afterAction(this, false);
+        }
+    },
+
+    getParams : function() {
+        var o = {};
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        Ext.apply(o, p, bp);
+        return o;
+    },
+    
+    
+    
+    processResponse : function(result) {
+        this.result = result;
+        return result;
+    },
+
+    success : function(response, trans){
+        if(trans.type == Ext.Direct.exceptions.SERVER){
+            response = {};
+        }
+        Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
+    }
+});
+
+Ext.form.Action.ACTION_TYPES = {
+    'load' : Ext.form.Action.Load,
+    'submit' : Ext.form.Action.Submit,
+    'directload' : Ext.form.Action.DirectLoad,
+    'directsubmit' : Ext.form.Action.DirectSubmit
+};
+
+Ext.form.VTypes = function(){
+    
+    var alpha = /^[a-zA-Z_]+$/,
+        alphanum = /^[a-zA-Z0-9_]+$/,
+        email = /^(\w+)([\-+.\'][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
+        url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+
+    
+    return {
+        
+        'email' : function(v){
+            return email.test(v);
+        },
+        
+        'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
+        
+        'emailMask' : /[a-z0-9_\.\-\+\'@]/i,
+
+        /**
+         * The function used to validate URLs
+         * @param {String} value The URL
+         * @return {Boolean} true if the RegExp test passed, and false if not.
+         */
+        'url' : function(v){
+            return url.test(v);
+        },
+        /**
+         * The error text to display when the url validation function returns false.  Defaults to:
+         * <tt>'This field should be a URL in the format "http:/'+'/www.example.com"'</tt>
+         * @type String
+         */
+        'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
+
+        /**
+         * The function used to validate alpha values
+         * @param {String} value The value
+         * @return {Boolean} true if the RegExp test passed, and false if not.
+         */
+        'alpha' : function(v){
+            return alpha.test(v);
+        },
+        /**
+         * The error text to display when the alpha validation function returns false.  Defaults to:
+         * <tt>'This field should only contain letters and _'</tt>
+         * @type String
+         */
+        'alphaText' : 'This field should only contain letters and _',
+        /**
+         * The keystroke filter mask to be applied on alpha input.  Defaults to:
+         * <tt>/[a-z_]/i</tt>
+         * @type RegExp
+         */
+        'alphaMask' : /[a-z_]/i,
+
+        /**
+         * The function used to validate alphanumeric values
+         * @param {String} value The value
+         * @return {Boolean} true if the RegExp test passed, and false if not.
+         */
+        'alphanum' : function(v){
+            return alphanum.test(v);
+        },
+        /**
+         * The error text to display when the alphanumeric validation function returns false.  Defaults to:
+         * <tt>'This field should only contain letters, numbers and _'</tt>
+         * @type String
+         */
+        'alphanumText' : 'This field should only contain letters, numbers and _',
+        /**
+         * The keystroke filter mask to be applied on alphanumeric input.  Defaults to:
+         * <tt>/[a-z0-9_]/i</tt>
+         * @type RegExp
+         */
+        'alphanumMask' : /[a-z0-9_]/i
+    };
+}();
+/**
+ * @class Ext.grid.GridPanel
+ * @extends Ext.Panel
+ * <p>This class represents the primary interface of a component based grid control to represent data
+ * in a tabular format of rows and columns. The GridPanel is composed of the following:</p>
+ * <div class="mdetail-params"><ul>
+ * <li><b>{@link Ext.data.Store Store}</b> : The Model holding the data records (rows)
+ * <div class="sub-desc"></div></li>
+ * <li><b>{@link Ext.grid.ColumnModel Column model}</b> : Column makeup
+ * <div class="sub-desc"></div></li>
+ * <li><b>{@link Ext.grid.GridView View}</b> : Encapsulates the user interface
+ * <div class="sub-desc"></div></li>
+ * <li><b>{@link Ext.grid.AbstractSelectionModel selection model}</b> : Selection behavior
+ * <div class="sub-desc"></div></li>
+ * </ul></div>
+ * <p>Example usage:</p>
+ * <pre><code>
+var grid = new Ext.grid.GridPanel({
+    {@link #store}: new {@link Ext.data.Store}({
+        {@link Ext.data.Store#autoDestroy autoDestroy}: true,
+        {@link Ext.data.Store#reader reader}: reader,
+        {@link Ext.data.Store#data data}: xg.dummyData
+    }),
+    {@link #colModel}: new {@link Ext.grid.ColumnModel}({
+        {@link Ext.grid.ColumnModel#defaults defaults}: {
+            width: 120,
+            sortable: true
+        },
+        {@link Ext.grid.ColumnModel#columns columns}: [
+            {id: 'company', header: 'Company', width: 200, sortable: true, dataIndex: 'company'},
+            {header: 'Price', renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
+            {header: 'Change', dataIndex: 'change'},
+            {header: '% Change', dataIndex: 'pctChange'},
+            // instead of specifying renderer: Ext.util.Format.dateRenderer('m/d/Y') use xtype
+            {
+                header: 'Last Updated', width: 135, dataIndex: 'lastChange',
+                xtype: 'datecolumn', format: 'M d, Y'
+            }
+        ]
+    }),
+    {@link #viewConfig}: {
+        {@link Ext.grid.GridView#forceFit forceFit}: true,
+
+//      Return CSS class to apply to rows depending upon data values
+        {@link Ext.grid.GridView#getRowClass getRowClass}: function(record, index) {
+            var c = record.{@link Ext.data.Record#get get}('change');
+            if (c < 0) {
+                return 'price-fall';
+            } else if (c > 0) {
+                return 'price-rise';
+            }
+        }
+    },
+    {@link #sm}: new Ext.grid.RowSelectionModel({singleSelect:true}),
+    width: 600,
+    height: 300,
+    frame: true,
+    title: 'Framed with Row Selection and Horizontal Scrolling',
+    iconCls: 'icon-grid'
+});
+ * </code></pre>
+ * <p><b><u>Notes:</u></b></p>
+ * <div class="mdetail-params"><ul>
+ * <li>Although this class inherits many configuration options from base classes, some of them
+ * (such as autoScroll, autoWidth, layout, items, etc) are not used by this class, and will
+ * have no effect.</li>
+ * <li>A grid <b>requires</b> a width in which to scroll its columns, and a height in which to
+ * scroll its rows. These dimensions can either be set explicitly through the
+ * <tt>{@link Ext.BoxComponent#height height}</tt> and <tt>{@link Ext.BoxComponent#width width}</tt>
+ * configuration options or implicitly set by using the grid as a child item of a
+ * {@link Ext.Container Container} which will have a {@link Ext.Container#layout layout manager}
+ * provide the sizing of its child items (for example the Container of the Grid may specify
+ * <tt>{@link Ext.Container#layout layout}:'fit'</tt>).</li>
+ * <li>To access the data in a Grid, it is necessary to use the data model encapsulated
+ * by the {@link #store Store}. See the {@link #cellclick} event for more details.</li>
+ * </ul></div>
+ * @constructor
+ * @param {Object} config The config object
+ * @xtype grid
+ */
+Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
+    /**
+     * @cfg {String} autoExpandColumn
+     * <p>The <tt>{@link Ext.grid.Column#id id}</tt> of a {@link Ext.grid.Column column} in
+     * this grid that should expand to fill unused space. This value specified here can not
+     * be <tt>0</tt>.</p>
+     * <br><p><b>Note</b>: If the Grid's {@link Ext.grid.GridView view} is configured with
+     * <tt>{@link Ext.grid.GridView#forceFit forceFit}=true</tt> the <tt>autoExpandColumn</tt>
+     * is ignored. See {@link Ext.grid.Column}.<tt>{@link Ext.grid.Column#width width}</tt>
+     * for additional details.</p>
+     * <p>See <tt>{@link #autoExpandMax}</tt> and <tt>{@link #autoExpandMin}</tt> also.</p>
+     */
+    autoExpandColumn : false,
+    
+    
+    autoExpandMax : 1000,
+    
+    
+    autoExpandMin : 50,
+    
+    
+    columnLines : false,
+    
+    
+    
+    
+    
+    
+    ddText : '{0} selected row{1}',
+    
+    
+    deferRowRender : true,
+    
+    
+    
+    
+    enableColumnHide : true,
+    
+    
+    enableColumnMove : true,
+    
+    
+    enableDragDrop : false,
+    
+    
+    enableHdMenu : true,
+    
+    
+    
+    loadMask : false,
+    
+    
+    
+    minColumnWidth : 25,
+    
+    
+    
+    
+    
+    stripeRows : false,
+    
+    
+    trackMouseOver : true,
+    
+    
+    stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
+    
+    
+    view : null,
+
+    
+    bubbleEvents: [],
+
+    
+
+    
+    rendered : false,
+    
+    
+    viewReady : false,
+
+    
+    initComponent : function() {
+        Ext.grid.GridPanel.superclass.initComponent.call(this);
+
+        if (this.columnLines) {
+            this.cls = (this.cls || '') + ' x-grid-with-col-lines';
+        }
+        
+        
+        this.autoScroll = false;
+        this.autoWidth = false;
+
+        if(Ext.isArray(this.columns)){
+            this.colModel = new Ext.grid.ColumnModel(this.columns);
+            delete this.columns;
+        }
+
+        
+        if(this.ds){
+            this.store = this.ds;
+            delete this.ds;
+        }
+        if(this.cm){
+            this.colModel = this.cm;
+            delete this.cm;
+        }
+        if(this.sm){
+            this.selModel = this.sm;
+            delete this.sm;
+        }
+        this.store = Ext.StoreMgr.lookup(this.store);
+
+        this.addEvents(
+            
+            
+            'click',
+            
+            'dblclick',
+            
+            'contextmenu',
+            
+            'mousedown',
+            
+            'mouseup',
+            
+            'mouseover',
+            
+            'mouseout',
+            
+            'keypress',
+            
+            'keydown',
+
+            
+            
+            'cellmousedown',
+            
+            'rowmousedown',
+            
+            'headermousedown',
+
+            
+            'groupmousedown',
+
+            
+            'rowbodymousedown',
+
+            
+            'containermousedown',
+
+            
+            'cellclick',
+            
+            'celldblclick',
+            
+            'rowclick',
+            
+            'rowdblclick',
+            
+            'headerclick',
+            
+            'headerdblclick',
+            
+            'groupclick',
+            
+            'groupdblclick',
+            
+            'containerclick',
+            
+            'containerdblclick',
+
+            
+            'rowbodyclick',
+            
+            'rowbodydblclick',
+
+            
+            'rowcontextmenu',
+            
+            'cellcontextmenu',
+            
+            'headercontextmenu',
+            
+            'groupcontextmenu',
+            
+            'containercontextmenu',
+            
+            'rowbodycontextmenu',
+            
+            'bodyscroll',
+            
+            'columnresize',
+            
+            'columnmove',
+            
+            'sortchange',
+            
+            'groupchange',
+            
+            'reconfigure',
+            
+            'viewready'
+        );
+    },
+
+    
+    onRender : function(ct, position){
+        Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
+
+        var c = this.getGridEl();
+
+        this.el.addClass('x-grid-panel');
+
+        this.mon(c, {
+            scope: this,
+            mousedown: this.onMouseDown,
+            click: this.onClick,
+            dblclick: this.onDblClick,
+            contextmenu: this.onContextMenu
+        });
+
+        this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
+
+        var view = this.getView();
+        view.init(this);
+        view.render();
+        this.getSelectionModel().init(this);
+    },
+
+    
+    initEvents : function(){
+        Ext.grid.GridPanel.superclass.initEvents.call(this);
+
+        if(this.loadMask){
+            this.loadMask = new Ext.LoadMask(this.bwrap,
+                    Ext.apply({store:this.store}, this.loadMask));
+        }
+    },
+
+    initStateEvents : function(){
+        Ext.grid.GridPanel.superclass.initStateEvents.call(this);
+        this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
+    },
+
+    applyState : function(state){
+        var cm = this.colModel,
+            cs = state.columns,
+            store = this.store,
+            s,
+            c,
+            colIndex;
+
+        if(cs){
+            for(var i = 0, len = cs.length; i < len; i++){
+                s = cs[i];
+                c = cm.getColumnById(s.id);
+                if(c){
+                    colIndex = cm.getIndexById(s.id);
+                    cm.setState(colIndex, {
+                        hidden: s.hidden,
+                        width: s.width,
+                        sortable: s.sortable
+                    });
+                    if(colIndex != i){
+                        cm.moveColumn(colIndex, i);
+                    }
+                }
+            }
+        }
+        if(store){
+            s = state.sort;
+            if(s){
+                store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
+            }
+            s = state.group;
+            if(store.groupBy){
+                if(s){
+                    store.groupBy(s);
+                }else{
+                    store.clearGrouping();
+                }
+            }
+
+        }
+        var o = Ext.apply({}, state);
+        delete o.columns;
+        delete o.sort;
+        Ext.grid.GridPanel.superclass.applyState.call(this, o);
+    },
+
+    getState : function(){
+        var o = {columns: []},
+            store = this.store,
+            ss,
+            gs;
+
+        for(var i = 0, c; (c = this.colModel.config[i]); i++){
+            o.columns[i] = {
+                id: c.id,
+                width: c.width
+            };
+            if(c.hidden){
+                o.columns[i].hidden = true;
+            }
+            if(c.sortable){
+                o.columns[i].sortable = true;
+            }
+        }
+        if(store){
+            ss = store.getSortState();
+            if(ss){
+                o.sort = ss;
+            }
+            if(store.getGroupState){
+                gs = store.getGroupState();
+                if(gs){
+                    o.group = gs;
+                }
+            }
+        }
+        return o;
+    },
+
+    
+    afterRender : function(){
+        Ext.grid.GridPanel.superclass.afterRender.call(this);
+        var v = this.view;
+        this.on('bodyresize', v.layout, v);
+        v.layout(true);
+        if(this.deferRowRender){
+            if (!this.deferRowRenderTask){
+                this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
+            }
+            this.deferRowRenderTask.delay(10);
+        }else{
+            v.afterRender();
+        }
+        this.viewReady = true;
+    },
+
+    
+    reconfigure : function(store, colModel){
+        var rendered = this.rendered;
+        if(rendered){
+            if(this.loadMask){
+                this.loadMask.destroy();
+                this.loadMask = new Ext.LoadMask(this.bwrap,
+                        Ext.apply({}, {store:store}, this.initialConfig.loadMask));
+            }
+        }
+        if(this.view){
+            this.view.initData(store, colModel);
+        }
+        this.store = store;
+        this.colModel = colModel;
+        if(rendered){
+            this.view.refresh(true);
+        }
+        this.fireEvent('reconfigure', this, store, colModel);
+    },
+
+    
+    onDestroy : function(){
+        if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
+            this.deferRowRenderTask.cancel();
+        }
+        if(this.rendered){
+            Ext.destroy(this.view, this.loadMask);
+        }else if(this.store && this.store.autoDestroy){
+            this.store.destroy();
+        }
+        Ext.destroy(this.colModel, this.selModel);
+        this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
+        Ext.grid.GridPanel.superclass.onDestroy.call(this);
+    },
+
+    
+    processEvent : function(name, e){
+        this.view.processEvent(name, e);
+    },
+
+    
+    onClick : function(e){
+        this.processEvent('click', e);
+    },
+
+    
+    onMouseDown : function(e){
+        this.processEvent('mousedown', e);
+    },
+
+    
+    onContextMenu : function(e, t){
+        this.processEvent('contextmenu', e);
+    },
+
+    
+    onDblClick : function(e){
+        this.processEvent('dblclick', e);
+    },
+
+    
+    walkCells : function(row, col, step, fn, scope){
+        var cm    = this.colModel,
+            clen  = cm.getColumnCount(),
+            ds    = this.store,
+            rlen  = ds.getCount(),
+            first = true;
+
+        if(step < 0){
+            if(col < 0){
+                row--;
+                first = false;
+            }
+            while(row >= 0){
+                if(!first){
+                    col = clen-1;
+                }
+                first = false;
+                while(col >= 0){
+                    if(fn.call(scope || this, row, col, cm) === true){
+                        return [row, col];
+                    }
+                    col--;
+                }
+                row--;
+            }
+        } else {
+            if(col >= clen){
+                row++;
+                first = false;
+            }
+            while(row < rlen){
+                if(!first){
+                    col = 0;
+                }
+                first = false;
+                while(col < clen){
+                    if(fn.call(scope || this, row, col, cm) === true){
+                        return [row, col];
+                    }
+                    col++;
+                }
+                row++;
+            }
+        }
+        return null;
+    },
+
+    
+    getGridEl : function(){
+        return this.body;
+    },
+
+    
+    stopEditing : Ext.emptyFn,
+
+    
+    getSelectionModel : function(){
+        if(!this.selModel){
+            this.selModel = new Ext.grid.RowSelectionModel(
+                    this.disableSelection ? {selectRow: Ext.emptyFn} : null);
+        }
+        return this.selModel;
+    },
+
+    
+    getStore : function(){
+        return this.store;
+    },
+
+    
+    getColumnModel : function(){
+        return this.colModel;
+    },
+
+    
+    getView : function() {
+        if (!this.view) {
+            this.view = new Ext.grid.GridView(this.viewConfig);
+        }
+        
+        return this.view;
+    },
+    
+    getDragDropText : function(){
+        var count = this.selModel.getCount();
+        return String.format(this.ddText, count, count == 1 ? '' : 's');
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+});
+Ext.reg('grid', Ext.grid.GridPanel);
+Ext.grid.PivotGrid = Ext.extend(Ext.grid.GridPanel, {
+    
+    
+    aggregator: 'sum',
+    
+    
+    renderer: undefined,
+    
+    
+    
+    
+    
+    
+    
+    
+    initComponent: function() {
+        Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);
+        
+        this.initAxes();
+        
+        
+        this.enableColumnResize = false;
+        
+        this.viewConfig = Ext.apply(this.viewConfig || {}, {
+            forceFit: true
+        });
+        
+        
+        
+        this.colModel = new Ext.grid.ColumnModel({});
+    },
+    
+    
+    getAggregator: function() {
+        if (typeof this.aggregator == 'string') {
+            return Ext.grid.PivotAggregatorMgr.types[this.aggregator];
+        } else {
+            return this.aggregator;
+        }
+    },
+    
+    
+    setAggregator: function(aggregator) {
+        this.aggregator = aggregator;
+    },
+    
+    
+    setMeasure: function(measure) {
+        this.measure = measure;
+    },
+    
+    
+    setLeftAxis: function(axis, refresh) {
+        
+        this.leftAxis = axis;
+        
+        if (refresh) {
+            this.view.refresh();
+        }
+    },
+    
+    
+    setTopAxis: function(axis, refresh) {
+        
+        this.topAxis = axis;
+        
+        if (refresh) {
+            this.view.refresh();
+        }
+    },
+    
+    
+    initAxes: function() {
+        var PivotAxis = Ext.grid.PivotAxis;
+        
+        if (!(this.leftAxis instanceof PivotAxis)) {
+            this.setLeftAxis(new PivotAxis({
+                orientation: 'vertical',
+                dimensions : this.leftAxis || [],
+                store      : this.store
+            }));
+        };
+        
+        if (!(this.topAxis instanceof PivotAxis)) {
+            this.setTopAxis(new PivotAxis({
+                orientation: 'horizontal',
+                dimensions : this.topAxis || [],
+                store      : this.store
+            }));
+        };
+    },
+    
+    
+    extractData: function() {
+        var records  = this.store.data.items,
+            recCount = records.length,
+            cells    = [],
+            record, i, j, k;
+        
+        if (recCount == 0) {
+            return [];
+        }
+        
+        var leftTuples = this.leftAxis.getTuples(),
+            leftCount  = leftTuples.length,
+            topTuples  = this.topAxis.getTuples(),
+            topCount   = topTuples.length,
+            aggregator = this.getAggregator();
+        
+        for (i = 0; i < recCount; i++) {
+            record = records[i];
+            
+            for (j = 0; j < leftCount; j++) {
+                cells[j] = cells[j] || [];
+                
+                if (leftTuples[j].matcher(record) === true) {
+                    for (k = 0; k < topCount; k++) {
+                        cells[j][k] = cells[j][k] || [];
+                        
+                        if (topTuples[k].matcher(record)) {
+                            cells[j][k].push(record);
+                        }
+                    }
+                }
+            }
+        }
+        
+        var rowCount = cells.length,
+            colCount, row;
+        
+        for (i = 0; i < rowCount; i++) {
+            row = cells[i];
+            colCount = row.length;
+            
+            for (j = 0; j < colCount; j++) {
+                cells[i][j] = aggregator(cells[i][j], this.measure);
+            }
+        }
+        
+        return cells;
+    },
+    
+    
+    getView: function() {
+        if (!this.view) {
+            this.view = new Ext.grid.PivotGridView(this.viewConfig);
+        }
+        
+        return this.view;
+    }
+});
+
+Ext.reg('pivotgrid', Ext.grid.PivotGrid);
+
+
+Ext.grid.PivotAggregatorMgr = new Ext.AbstractManager();
+
+Ext.grid.PivotAggregatorMgr.registerType('sum', function(records, measure) {
+    var length = records.length,
+        total  = 0,
+        i;
+    
+    for (i = 0; i < length; i++) {
+        total += records[i].get(measure);
+    }
+    
+    return total;
+});
+
+Ext.grid.PivotAggregatorMgr.registerType('avg', function(records, measure) {
+    var length = records.length,
+        total  = 0,
+        i;
+    
+    for (i = 0; i < length; i++) {
+        total += records[i].get(measure);
+    }
+    
+    return (total / length) || 'n/a';
+});
+
+Ext.grid.PivotAggregatorMgr.registerType('min', function(records, measure) {
+    var data   = [],
+        length = records.length,
+        i;
+    
+    for (i = 0; i < length; i++) {
+        data.push(records[i].get(measure));
+    }
+    
+    return Math.min.apply(this, data) || 'n/a';
+});
+
+Ext.grid.PivotAggregatorMgr.registerType('max', function(records, measure) {
+    var data   = [],
+        length = records.length,
+        i;
+    
+    for (i = 0; i < length; i++) {
+        data.push(records[i].get(measure));
+    }
+    
+    return Math.max.apply(this, data) || 'n/a';
+});
+
+Ext.grid.PivotAggregatorMgr.registerType('count', function(records, measure) {
+    return records.length;
+});
+Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    deferEmptyText : true,
+
+    
+    scrollOffset : undefined,
+
+    
+    autoFill : false,
+
+    
+    forceFit : false,
+
+    
+    sortClasses : ['sort-asc', 'sort-desc'],
+
+    
+    sortAscText : 'Sort Ascending',
+
+    
+    sortDescText : 'Sort Descending',
+
+    
+    columnsText : 'Columns',
+
+    
+    selectedRowClass : 'x-grid3-row-selected',
+
+    
+    borderWidth : 2,
+    tdClass : 'x-grid3-cell',
+    hdCls : 'x-grid3-hd',
+    
+    
+    
+    markDirty : true,
+
+    
+    cellSelectorDepth : 4,
+    
+    
+    rowSelectorDepth : 10,
+
+    
+    rowBodySelectorDepth : 10,
+
+    
+    cellSelector : 'td.x-grid3-cell',
+    
+    
+    rowSelector : 'div.x-grid3-row',
+
+    
+    rowBodySelector : 'div.x-grid3-row-body',
+
+    
+    firstRowCls: 'x-grid3-row-first',
+    lastRowCls: 'x-grid3-row-last',
+    rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
+    
+    
+    headerMenuOpenCls: 'x-grid3-hd-menu-open',
+    
+    
+    rowOverCls: 'x-grid3-row-over',
+
+    constructor : function(config) {
+        Ext.apply(this, config);
+        
+        
+        this.addEvents(
+            
+            'beforerowremoved',
+            
+            
+            'beforerowsinserted',
+            
+            
+            'beforerefresh',
+            
+            
+            'rowremoved',
+            
+            
+            'rowsinserted',
+            
+            
+            'rowupdated',
+            
+            
+            'refresh'
+        );
+        
+        Ext.grid.GridView.superclass.constructor.call(this);
+    },
+
+    
+    
+    
+    masterTpl: new Ext.Template(
+        '<div class="x-grid3" hidefocus="true">',
+            '<div class="x-grid3-viewport">',
+                '<div class="x-grid3-header">',
+                    '<div class="x-grid3-header-inner">',
+                        '<div class="x-grid3-header-offset" style="{ostyle}">{header}</div>',
+                    '</div>',
+                    '<div class="x-clear"></div>',
+                '</div>',
+                '<div class="x-grid3-scroller">',
+                    '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
+                    '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
+                '</div>',
+            '</div>',
+            '<div class="x-grid3-resize-marker">&#160;</div>',
+            '<div class="x-grid3-resize-proxy">&#160;</div>',
+        '</div>'
+    ),
+    
+    
+    headerTpl: new Ext.Template(
+        '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
+            '<thead>',
+                '<tr class="x-grid3-hd-row">{cells}</tr>',
+            '</thead>',
+        '</table>'
+    ),
+    
+    
+    bodyTpl: new Ext.Template('{rows}'),
+    
+    
+    cellTpl: new Ext.Template(
+        '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
+            '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
+        '</td>'
+    ),
+    
+    
+    initTemplates : function() {
+        var templates = this.templates || {},
+            template, name,
+            
+            headerCellTpl = new Ext.Template(
+                '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
+                    '<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
+                        this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
+                        '{value}',
+                        '<img alt="" class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
+                    '</div>',
+                '</td>'
+            ),
+        
+            rowBodyText = [
+                '<tr class="x-grid3-row-body-tr" style="{bodyStyle}">',
+                    '<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">',
+                        '<div class="x-grid3-row-body">{body}</div>',
+                    '</td>',
+                '</tr>'
+            ].join(""),
+        
+            innerText = [
+                '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
+                     '<tbody>',
+                        '<tr>{cells}</tr>',
+                        this.enableRowBody ? rowBodyText : '',
+                     '</tbody>',
+                '</table>'
+            ].join("");
+        
+        Ext.applyIf(templates, {
+            hcell   : headerCellTpl,
+            cell    : this.cellTpl,
+            body    : this.bodyTpl,
+            header  : this.headerTpl,
+            master  : this.masterTpl,
+            row     : new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}">' + innerText + '</div>'),
+            rowInner: new Ext.Template(innerText)
+        });
+
+        for (name in templates) {
+            template = templates[name];
+            
+            if (template && Ext.isFunction(template.compile) && !template.compiled) {
+                template.disableFormats = true;
+                template.compile();
+            }
+        }
+
+        this.templates = templates;
+        this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
+    },
+
+    
+    fly : function(el) {
+        if (!this._flyweight) {
+            this._flyweight = new Ext.Element.Flyweight(document.body);
+        }
+        this._flyweight.dom = el;
+        return this._flyweight;
+    },
+
+    
+    getEditorParent : function() {
+        return this.scroller.dom;
+    },
+
+    
+    initElements : function() {
+        var Element  = Ext.Element,
+            el       = Ext.get(this.grid.getGridEl().dom.firstChild),
+            mainWrap = new Element(el.child('div.x-grid3-viewport')),
+            mainHd   = new Element(mainWrap.child('div.x-grid3-header')),
+            scroller = new Element(mainWrap.child('div.x-grid3-scroller'));
+        
+        if (this.grid.hideHeaders) {
+            mainHd.setDisplayed(false);
+        }
+        
+        if (this.forceFit) {
+            scroller.setStyle('overflow-x', 'hidden');
+        }
+        
+        
+        
+        Ext.apply(this, {
+            el      : el,
+            mainWrap: mainWrap,
+            scroller: scroller,
+            mainHd  : mainHd,
+            innerHd : mainHd.child('div.x-grid3-header-inner').dom,
+            mainBody: new Element(Element.fly(scroller).child('div.x-grid3-body')),
+            focusEl : new Element(Element.fly(scroller).child('a')),
+            
+            resizeMarker: new Element(el.child('div.x-grid3-resize-marker')),
+            resizeProxy : new Element(el.child('div.x-grid3-resize-proxy'))
+        });
+        
+        this.focusEl.swallowEvent('click', true);
+    },
+
+    
+    getRows : function() {
+        return this.hasRows() ? this.mainBody.dom.childNodes : [];
+    },
+
+    
+
+    
+    findCell : function(el) {
+        if (!el) {
+            return false;
+        }
+        return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
+    },
+
+    
+    findCellIndex : function(el, requiredCls) {
+        var cell = this.findCell(el),
+            hasCls;
+        
+        if (cell) {
+            hasCls = this.fly(cell).hasClass(requiredCls);
+            if (!requiredCls || hasCls) {
+                return this.getCellIndex(cell);
+            }
+        }
+        return false;
+    },
+
+    
+    getCellIndex : function(el) {
+        if (el) {
+            var match = el.className.match(this.colRe);
+            
+            if (match && match[1]) {
+                return this.cm.getIndexById(match[1]);
+            }
+        }
+        return false;
+    },
+
+    
+    findHeaderCell : function(el) {
+        var cell = this.findCell(el);
+        return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
+    },
+
+    
+    findHeaderIndex : function(el){
+        return this.findCellIndex(el, this.hdCls);
+    },
+
+    
+    findRow : function(el) {
+        if (!el) {
+            return false;
+        }
+        return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
+    },
+
+    
+    findRowIndex : function(el) {
+        var row = this.findRow(el);
+        return row ? row.rowIndex : false;
+    },
+
+    
+    findRowBody : function(el) {
+        if (!el) {
+            return false;
+        }
+        
+        return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
+    },
+
+    
+
+    
+    getRow : function(row) {
+        return this.getRows()[row];
+    },
+
+    
+    getCell : function(row, col) {
+        return Ext.fly(this.getRow(row)).query(this.cellSelector)[col]; 
+    },
+
+    
+    getHeaderCell : function(index) {
+        return this.mainHd.dom.getElementsByTagName('td')[index];
+    },
+
+    
+
+    
+    addRowClass : function(rowId, cls) {
+        var row = this.getRow(rowId);
+        if (row) {
+            this.fly(row).addClass(cls);
+        }
+    },
+
+    
+    removeRowClass : function(row, cls) {
+        var r = this.getRow(row);
+        if(r){
+            this.fly(r).removeClass(cls);
+        }
+    },
+
+    
+    removeRow : function(row) {
+        Ext.removeNode(this.getRow(row));
+        this.syncFocusEl(row);
+    },
+
+    
+    removeRows : function(firstRow, lastRow) {
+        var bd = this.mainBody.dom,
+            rowIndex;
+            
+        for (rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
+            Ext.removeNode(bd.childNodes[firstRow]);
+        }
+        
+        this.syncFocusEl(firstRow);
+    },
+
+    
+    
+    
+    getScrollState : function() {
+        var sb = this.scroller.dom;
+        
+        return {
+            left: sb.scrollLeft, 
+            top : sb.scrollTop
+        };
+    },
+
+    
+    restoreScroll : function(state) {
+        var sb = this.scroller.dom;
+        sb.scrollLeft = state.left;
+        sb.scrollTop  = state.top;
+    },
+
+    
+    scrollToTop : function() {
+        var dom = this.scroller.dom;
+        
+        dom.scrollTop  = 0;
+        dom.scrollLeft = 0;
+    },
+
+    
+    syncScroll : function() {
+        this.syncHeaderScroll();
+        var mb = this.scroller.dom;
+        this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
+    },
+
+    
+    syncHeaderScroll : function() {
+        var innerHd    = this.innerHd,
+            scrollLeft = this.scroller.dom.scrollLeft;
+        
+        innerHd.scrollLeft = scrollLeft;
+        innerHd.scrollLeft = scrollLeft; 
+    },
+    
+    
+    updateSortIcon : function(col, dir) {
+        var sortClasses = this.sortClasses,
+            sortClass   = sortClasses[dir == "DESC" ? 1 : 0],
+            headers     = this.mainHd.select('td').removeClass(sortClasses);
+        
+        headers.item(col).addClass(sortClass);
+    },
+
+    
+    updateAllColumnWidths : function() {
+        var totalWidth = this.getTotalWidth(),
+            colCount   = this.cm.getColumnCount(),
+            rows       = this.getRows(),
+            rowCount   = rows.length,
+            widths     = [],
+            row, rowFirstChild, trow, i, j;
+        
+        for (i = 0; i < colCount; i++) {
+            widths[i] = this.getColumnWidth(i);
+            this.getHeaderCell(i).style.width = widths[i];
+        }
+        
+        this.updateHeaderWidth();
+        
+        for (i = 0; i < rowCount; i++) {
+            row = rows[i];
+            row.style.width = totalWidth;
+            rowFirstChild = row.firstChild;
+            
+            if (rowFirstChild) {
+                rowFirstChild.style.width = totalWidth;
+                trow = rowFirstChild.rows[0];
+                
+                for (j = 0; j < colCount; j++) {
+                    trow.childNodes[j].style.width = widths[j];
+                }
+            }
+        }
+        
+        this.onAllColumnWidthsUpdated(widths, totalWidth);
+    },
+
+    
+    updateColumnWidth : function(column, width) {
+        var columnWidth = this.getColumnWidth(column),
+            totalWidth  = this.getTotalWidth(),
+            headerCell  = this.getHeaderCell(column),
+            nodes       = this.getRows(),
+            nodeCount   = nodes.length,
+            row, i, firstChild;
+        
+        this.updateHeaderWidth();
+        headerCell.style.width = columnWidth;
+        
+        for (i = 0; i < nodeCount; i++) {
+            row = nodes[i];
+            firstChild = row.firstChild;
+            
+            row.style.width = totalWidth;
+            if (firstChild) {
+                firstChild.style.width = totalWidth;
+                firstChild.rows[0].childNodes[column].style.width = columnWidth;
+            }
+        }
+        
+        this.onColumnWidthUpdated(column, columnWidth, totalWidth);
+    },
+    
+    
+    updateColumnHidden : function(col, hidden) {
+        var totalWidth = this.getTotalWidth(),
+            display    = hidden ? 'none' : '',
+            headerCell = this.getHeaderCell(col),
+            nodes      = this.getRows(),
+            nodeCount  = nodes.length,
+            row, rowFirstChild, i;
+        
+        this.updateHeaderWidth();
+        headerCell.style.display = display;
+        
+        for (i = 0; i < nodeCount; i++) {
+            row = nodes[i];
+            row.style.width = totalWidth;
+            rowFirstChild = row.firstChild;
+            
+            if (rowFirstChild) {
+                rowFirstChild.style.width = totalWidth;
+                rowFirstChild.rows[0].childNodes[col].style.display = display;
+            }
+        }
+        
+        this.onColumnHiddenUpdated(col, hidden, totalWidth);
+        delete this.lastViewWidth; 
+        this.layout();
+    },
+
+    
+    doRender : function(columns, records, store, startRow, colCount, stripe) {
+        var templates = this.templates,
+            cellTemplate = templates.cell,
+            rowTemplate = templates.row,
+            last = colCount - 1,
+            tstyle = 'width:' + this.getTotalWidth() + ';',
+            
+            rowBuffer = [],
+            colBuffer = [],
+            rowParams = {tstyle: tstyle},
+            meta = {},
+            len  = records.length,
+            alt,
+            column,
+            record, i, j, rowIndex;
+
+        
+        for (j = 0; j < len; j++) {
+            record    = records[j];
+            colBuffer = [];
+
+            rowIndex = j + startRow;
+
+            
+            for (i = 0; i < colCount; i++) {
+                column = columns[i];
+                
+                meta.id    = column.id;
+                meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
+                meta.attr  = meta.cellAttr = '';
+                meta.style = column.style;
+                meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
+
+                if (Ext.isEmpty(meta.value)) {
+                    meta.value = '&#160;';
+                }
+
+                if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
+                    meta.css += ' x-grid3-dirty-cell';
+                }
+
+                colBuffer[colBuffer.length] = cellTemplate.apply(meta);
+            }
+
+            alt = [];
+            
+            if (stripe && ((rowIndex + 1) % 2 === 0)) {
+                alt[0] = 'x-grid3-row-alt';
+            }
+
+            if (record.dirty) {
+                alt[1] = ' x-grid3-dirty-row';
+            }
+
+            rowParams.cols = colCount;
+
+            if (this.getRowClass) {
+                alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
+            }
+
+            rowParams.alt   = alt.join(' ');
+            rowParams.cells = colBuffer.join('');
+
+            rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
+        }
+
+        return rowBuffer.join('');
+    },
+
+    
+    processRows : function(startRow, skipStripe) {
+        if (!this.ds || this.ds.getCount() < 1) {
+            return;
+        }
+
+        var rows   = this.getRows(),
+            length = rows.length,
+            row, i;
+
+        skipStripe = skipStripe || !this.grid.stripeRows;
+        startRow   = startRow   || 0;
+
+        for (i = 0; i < length; i++) {
+            row = rows[i];
+            if (row) {
+                row.rowIndex = i;
+                if (!skipStripe) {
+                    row.className = row.className.replace(this.rowClsRe, ' ');
+                    if ((i + 1) % 2 === 0){
+                        row.className += ' x-grid3-row-alt';
+                    }
+                }
+            }
+        }
+
+        
+        if (startRow === 0) {
+            Ext.fly(rows[0]).addClass(this.firstRowCls);
+        }
+
+        Ext.fly(rows[length - 1]).addClass(this.lastRowCls);
+    },
+    
+    
+    afterRender : function() {
+        if (!this.ds || !this.cm) {
+            return;
+        }
+        
+        this.mainBody.dom.innerHTML = this.renderBody() || '&#160;';
+        this.processRows(0, true);
+
+        if (this.deferEmptyText !== true) {
+            this.applyEmptyText();
+        }
+        
+        this.grid.fireEvent('viewready', this.grid);
+    },
+    
+    
+    afterRenderUI: function() {
+        var grid = this.grid;
+        
+        this.initElements();
+
+        
+        Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
+
+        this.mainHd.on({
+            scope    : this,
+            mouseover: this.handleHdOver,
+            mouseout : this.handleHdOut,
+            mousemove: this.handleHdMove
+        });
+
+        this.scroller.on('scroll', this.syncScroll,  this);
+        
+        if (grid.enableColumnResize !== false) {
+            this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
+        }
+
+        if (grid.enableColumnMove) {
+            this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
+            this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
+        }
+
+        if (grid.enableHdMenu !== false) {
+            this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
+            this.hmenu.add(
+                {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
+                {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
+            );
+
+            if (grid.enableColumnHide !== false) {
+                this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
+                this.colMenu.on({
+                    scope     : this,
+                    beforeshow: this.beforeColMenuShow,
+                    itemclick : this.handleHdMenuClick
+                });
+                this.hmenu.add('-', {
+                    itemId:'columns',
+                    hideOnClick: false,
+                    text: this.columnsText,
+                    menu: this.colMenu,
+                    iconCls: 'x-cols-icon'
+                });
+            }
+
+            this.hmenu.on('itemclick', this.handleHdMenuClick, this);
+        }
+
+        if (grid.trackMouseOver) {
+            this.mainBody.on({
+                scope    : this,
+                mouseover: this.onRowOver,
+                mouseout : this.onRowOut
+            });
+        }
+
+        if (grid.enableDragDrop || grid.enableDrag) {
+            this.dragZone = new Ext.grid.GridDragZone(grid, {
+                ddGroup : grid.ddGroup || 'GridDD'
+            });
+        }
+
+        this.updateHeaderSortState();
+    },
+
+    
+    renderUI : function() {
+        var templates = this.templates;
+
+        return templates.master.apply({
+            body  : templates.body.apply({rows:'&#160;'}),
+            header: this.renderHeaders(),
+            ostyle: 'width:' + this.getOffsetWidth() + ';',
+            bstyle: 'width:' + this.getTotalWidth()  + ';'
+        });
+    },
+
+    
+    processEvent : function(name, e) {
+        var target = e.getTarget(),
+            grid   = this.grid,
+            header = this.findHeaderIndex(target),
+            row, cell, col, body;
+
+        grid.fireEvent(name, e);
+
+        if (header !== false) {
+            grid.fireEvent('header' + name, grid, header, e);
+        } else {
+            row = this.findRowIndex(target);
+
+
+
+
+            if (row !== false) {
+                cell = this.findCellIndex(target);
+                if (cell !== false) {
+                    col = grid.colModel.getColumnAt(cell);
+                    if (grid.fireEvent('cell' + name, grid, row, cell, e) !== false) {
+                        if (!col || (col.processEvent && (col.processEvent(name, e, grid, row, cell) !== false))) {
+                            grid.fireEvent('row' + name, grid, row, e);
+                        }
+                    }
+                } else {
+                    if (grid.fireEvent('row' + name, grid, row, e) !== false) {
+                        (body = this.findRowBody(target)) && grid.fireEvent('rowbody' + name, grid, row, e);
+                    }
+                }
+            } else {
+                grid.fireEvent('container' + name, grid, e);
+            }
+        }
+    },
+
+    
+    layout : function(initial) {
+        if (!this.mainBody) {
+            return; 
+        }
+
+        var grid       = this.grid,
+            gridEl     = grid.getGridEl(),
+            gridSize   = gridEl.getSize(true),
+            gridWidth  = gridSize.width,
+            gridHeight = gridSize.height,
+            scroller   = this.scroller,
+            scrollStyle, headerHeight, scrollHeight;
+        
+        if (gridWidth < 20 || gridHeight < 20) {
+            return;
+        }
+        
+        if (grid.autoHeight) {
+            scrollStyle = scroller.dom.style;
+            scrollStyle.overflow = 'visible';
+            
+            if (Ext.isWebKit) {
+                scrollStyle.position = 'static';
+            }
+        } else {
+            this.el.setSize(gridWidth, gridHeight);
+            
+            headerHeight = this.mainHd.getHeight();
+            scrollHeight = gridHeight - headerHeight;
+            
+            scroller.setSize(gridWidth, scrollHeight);
+            
+            if (this.innerHd) {
+                this.innerHd.style.width = (gridWidth) + "px";
+            }
+        }
+        
+        if (this.forceFit || (initial === true && this.autoFill)) {
+            if (this.lastViewWidth != gridWidth) {
+                this.fitColumns(false, false);
+                this.lastViewWidth = gridWidth;
+            }
+        } else {
+            this.autoExpand();
+            this.syncHeaderScroll();
+        }
+        
+        this.onLayout(gridWidth, scrollHeight);
+    },
+
+    
+    
+    onLayout : function(vw, vh) {
+        
+    },
+
+    onColumnWidthUpdated : function(col, w, tw) {
+        
+    },
+
+    onAllColumnWidthsUpdated : function(ws, tw) {
+        
+    },
+
+    onColumnHiddenUpdated : function(col, hidden, tw) {
+        
+    },
+
+    updateColumnText : function(col, text) {
+        
+    },
+
+    afterMove : function(colIndex) {
+        
+    },
+
+    
+    
+    init : function(grid) {
+        this.grid = grid;
+
+        this.initTemplates();
+        this.initData(grid.store, grid.colModel);
+        this.initUI(grid);
+    },
+
+    
+    getColumnId : function(index){
+        return this.cm.getColumnId(index);
+    },
+
+    
+    getOffsetWidth : function() {
+        return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
+    },
+
+    
+    getScrollOffset: function() {
+        return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
+    },
+
+    
+    renderHeaders : function() {
+        var colModel   = this.cm,
+            templates  = this.templates,
+            headerTpl  = templates.hcell,
+            properties = {},
+            colCount   = colModel.getColumnCount(),
+            last       = colCount - 1,
+            cells      = [],
+            i, cssCls;
+        
+        for (i = 0; i < colCount; i++) {
+            if (i == 0) {
+                cssCls = 'x-grid3-cell-first ';
+            } else {
+                cssCls = i == last ? 'x-grid3-cell-last ' : '';
+            }
+            
+            properties = {
+                id     : colModel.getColumnId(i),
+                value  : colModel.getColumnHeader(i) || '',
+                style  : this.getColumnStyle(i, true),
+                css    : cssCls,
+                tooltip: this.getColumnTooltip(i)
+            };
+            
+            if (colModel.config[i].align == 'right') {
+                properties.istyle = 'padding-right: 16px;';
+            } else {
+                delete properties.istyle;
+            }
+            
+            cells[i] = headerTpl.apply(properties);
+        }
+        
+        return templates.header.apply({
+            cells : cells.join(""),
+            tstyle: String.format("width: {0};", this.getTotalWidth())
+        });
+    },
+
+    
+    getColumnTooltip : function(i) {
+        var tooltip = this.cm.getColumnTooltip(i);
+        if (tooltip) {
+            if (Ext.QuickTips.isEnabled()) {
+                return 'ext:qtip="' + tooltip + '"';
+            } else {
+                return 'title="' + tooltip + '"';
+            }
+        }
+        
+        return '';
+    },
+
+    
+    beforeUpdate : function() {
+        this.grid.stopEditing(true);
+    },
+
+    
+    updateHeaders : function() {
+        this.innerHd.firstChild.innerHTML = this.renderHeaders();
+        
+        this.updateHeaderWidth(false);
+    },
+    
+    
+    updateHeaderWidth: function(updateMain) {
+        var innerHdChild = this.innerHd.firstChild,
+            totalWidth   = this.getTotalWidth();
+        
+        innerHdChild.style.width = this.getOffsetWidth();
+        innerHdChild.firstChild.style.width = totalWidth;
+        
+        if (updateMain !== false) {
+            this.mainBody.dom.style.width = totalWidth;
+        }
+    },
+
+    
+    focusRow : function(row) {
+        this.focusCell(row, 0, false);
+    },
+
+    
+    focusCell : function(row, col, hscroll) {
+        this.syncFocusEl(this.ensureVisible(row, col, hscroll));
+        
+        var focusEl = this.focusEl;
+        
+        if (Ext.isGecko) {
+            focusEl.focus();
+        } else {
+            focusEl.focus.defer(1, focusEl);
+        }
+    },
+
+    
+    resolveCell : function(row, col, hscroll) {
+        if (!Ext.isNumber(row)) {
+            row = row.rowIndex;
+        }
+        
+        if (!this.ds) {
+            return null;
+        }
+        
+        if (row < 0 || row >= this.ds.getCount()) {
+            return null;
+        }
+        col = (col !== undefined ? col : 0);
+
+        var rowEl    = this.getRow(row),
+            colModel = this.cm,
+            colCount = colModel.getColumnCount(),
+            cellEl;
+            
+        if (!(hscroll === false && col === 0)) {
+            while (col < colCount && colModel.isHidden(col)) {
+                col++;
+            }
+            
+            cellEl = this.getCell(row, col);
+        }
+
+        return {row: rowEl, cell: cellEl};
+    },
+
+    
+    getResolvedXY : function(resolved) {
+        if (!resolved) {
+            return null;
+        }
+        
+        var cell = resolved.cell,
+            row  = resolved.row;
+        
+        if (cell) {
+            return Ext.fly(cell).getXY();
+        } else {
+            return [this.el.getX(), Ext.fly(row).getY()];
+        }
+    },
+
+    
+    syncFocusEl : function(row, col, hscroll) {
+        var xy = row;
+        
+        if (!Ext.isArray(xy)) {
+            row = Math.min(row, Math.max(0, this.getRows().length-1));
+            
+            if (isNaN(row)) {
+                return;
+            }
+            
+            xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
+        }
+        
+        this.focusEl.setXY(xy || this.scroller.getXY());
+    },
+
+    
+    ensureVisible : function(row, col, hscroll) {
+        var resolved = this.resolveCell(row, col, hscroll);
+        
+        if (!resolved || !resolved.row) {
+            return null;
+        }
+
+        var rowEl  = resolved.row,
+            cellEl = resolved.cell,
+            c = this.scroller.dom,
+            p = rowEl,
+            ctop = 0,
+            stop = this.el.dom;
+
+        while (p && p != stop) {
+            ctop += p.offsetTop;
+            p = p.offsetParent;
+        }
+
+        ctop -= this.mainHd.dom.offsetHeight;
+        stop = parseInt(c.scrollTop, 10);
+
+        var cbot = ctop + rowEl.offsetHeight,
+            ch = c.clientHeight,
+            sbot = stop + ch;
+
+
+        if (ctop < stop) {
+          c.scrollTop = ctop;
+        } else if(cbot > sbot) {
+            c.scrollTop = cbot-ch;
+        }
+
+        if (hscroll !== false) {
+            var cleft  = parseInt(cellEl.offsetLeft, 10),
+                cright = cleft + cellEl.offsetWidth,
+                sleft  = parseInt(c.scrollLeft, 10),
+                sright = sleft + c.clientWidth;
+                
+            if (cleft < sleft) {
+                c.scrollLeft = cleft;
+            } else if(cright > sright) {
+                c.scrollLeft = cright-c.clientWidth;
+            }
+        }
+        
+        return this.getResolvedXY(resolved);
+    },
+
+    
+    insertRows : function(dm, firstRow, lastRow, isUpdate) {
+        var last = dm.getCount() - 1;
+        if( !isUpdate && firstRow === 0 && lastRow >= last) {
+            this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
+                this.refresh();
+            this.fireEvent('rowsinserted', this, firstRow, lastRow);
+        } else {
+            if (!isUpdate) {
+                this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
+            }
+            var html = this.renderRows(firstRow, lastRow),
+                before = this.getRow(firstRow);
+            if (before) {
+                if(firstRow === 0){
+                    Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
+                }
+                Ext.DomHelper.insertHtml('beforeBegin', before, html);
+            } else {
+                var r = this.getRow(last - 1);
+                if(r){
+                    Ext.fly(r).removeClass(this.lastRowCls);
+                }
+                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
+            }
+            if (!isUpdate) {
+                this.processRows(firstRow);
+                this.fireEvent('rowsinserted', this, firstRow, lastRow);
+            } else if (firstRow === 0 || firstRow >= last) {
+                
+                Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
+            }
+        }
+        this.syncFocusEl(firstRow);
+    },
+
+    
+    deleteRows : function(dm, firstRow, lastRow) {
+        if (dm.getRowCount() < 1) {
+            this.refresh();
+        } else {
+            this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
+
+            this.removeRows(firstRow, lastRow);
+
+            this.processRows(firstRow);
+            this.fireEvent('rowsdeleted', this, firstRow, lastRow);
+        }
+    },
+
+    
+    getColumnStyle : function(colIndex, isHeader) {
+        var colModel  = this.cm,
+            colConfig = colModel.config,
+            style     = isHeader ? '' : colConfig[colIndex].css || '',
+            align     = colConfig[colIndex].align;
+        
+        style += String.format("width: {0};", this.getColumnWidth(colIndex));
+        
+        if (colModel.isHidden(colIndex)) {
+            style += 'display: none; ';
+        }
+        
+        if (align) {
+            style += String.format("text-align: {0};", align);
+        }
+        
+        return style;
+    },
+
+    
+    getColumnWidth : function(column) {
+        var columnWidth = this.cm.getColumnWidth(column),
+            borderWidth = this.borderWidth;
+        
+        if (Ext.isNumber(columnWidth)) {
+            if (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2)) {
+                return columnWidth + "px";
+            } else {
+                return Math.max(columnWidth - borderWidth, 0) + "px";
+            }
+        } else {
+            return columnWidth;
+        }
+    },
+
+    
+    getTotalWidth : function() {
+        return this.cm.getTotalWidth() + 'px';
+    },
+
+    
+    fitColumns : function(preventRefresh, onlyExpand, omitColumn) {
+        var grid          = this.grid,
+            colModel      = this.cm,
+            totalColWidth = colModel.getTotalWidth(false),
+            gridWidth     = this.getGridInnerWidth(),
+            extraWidth    = gridWidth - totalColWidth,
+            columns       = [],
+            extraCol      = 0,
+            width         = 0,
+            colWidth, fraction, i;
+        
+        
+        if (gridWidth < 20 || extraWidth === 0) {
+            return false;
+        }
+        
+        var visibleColCount = colModel.getColumnCount(true),
+            totalColCount   = colModel.getColumnCount(false),
+            adjCount        = visibleColCount - (Ext.isNumber(omitColumn) ? 1 : 0);
+        
+        if (adjCount === 0) {
+            adjCount = 1;
+            omitColumn = undefined;
+        }
+        
+        
+        for (i = 0; i < totalColCount; i++) {
+            if (!colModel.isFixed(i) && i !== omitColumn) {
+                colWidth = colModel.getColumnWidth(i);
+                columns.push(i, colWidth);
+                
+                if (!colModel.isHidden(i)) {
+                    extraCol = i;
+                    width += colWidth;
+                }
+            }
+        }
+        
+        fraction = (gridWidth - colModel.getTotalWidth()) / width;
+        
+        while (columns.length) {
+            colWidth = columns.pop();
+            i        = columns.pop();
+            
+            colModel.setColumnWidth(i, Math.max(grid.minColumnWidth, Math.floor(colWidth + colWidth * fraction)), true);
+        }
+        
+        
+        totalColWidth = colModel.getTotalWidth(false);
+        
+        if (totalColWidth > gridWidth) {
+            var adjustCol = (adjCount == visibleColCount) ? extraCol : omitColumn,
+                newWidth  = Math.max(1, colModel.getColumnWidth(adjustCol) - (totalColWidth - gridWidth));
+            
+            colModel.setColumnWidth(adjustCol, newWidth, true);
+        }
+        
+        if (preventRefresh !== true) {
+            this.updateAllColumnWidths();
+        }
+        
+        return true;
+    },
+
+    
+    autoExpand : function(preventUpdate) {
+        var grid             = this.grid,
+            colModel         = this.cm,
+            gridWidth        = this.getGridInnerWidth(),
+            totalColumnWidth = colModel.getTotalWidth(false),
+            autoExpandColumn = grid.autoExpandColumn;
+        
+        if (!this.userResized && autoExpandColumn) {
+            if (gridWidth != totalColumnWidth) {
+                
+                var colIndex     = colModel.getIndexById(autoExpandColumn),
+                    currentWidth = colModel.getColumnWidth(colIndex),
+                    desiredWidth = gridWidth - totalColumnWidth + currentWidth,
+                    newWidth     = Math.min(Math.max(desiredWidth, grid.autoExpandMin), grid.autoExpandMax);
+                
+                if (currentWidth != newWidth) {
+                    colModel.setColumnWidth(colIndex, newWidth, true);
+                    
+                    if (preventUpdate !== true) {
+                        this.updateColumnWidth(colIndex, newWidth);
+                    }
+                }
+            }
+        }
+    },
+    
+    
+    getGridInnerWidth: function() {
+        return this.grid.getGridEl().getWidth(true) - this.getScrollOffset();
+    },
+
+    
+    getColumnData : function() {
+        var columns  = [],
+            colModel = this.cm,
+            colCount = colModel.getColumnCount(),
+            fields   = this.ds.fields,
+            i, name;
+        
+        for (i = 0; i < colCount; i++) {
+            name = colModel.getDataIndex(i);
+            
+            columns[i] = {
+                name    : Ext.isDefined(name) ? name : (fields.get(i) ? fields.get(i).name : undefined),
+                renderer: colModel.getRenderer(i),
+                scope   : colModel.getRendererScope(i),
+                id      : colModel.getColumnId(i),
+                style   : this.getColumnStyle(i)
+            };
+        }
+        
+        return columns;
+    },
+
+    
+    renderRows : function(startRow, endRow) {
+        var grid     = this.grid,
+            store    = grid.store,
+            stripe   = grid.stripeRows,
+            colModel = grid.colModel,
+            colCount = colModel.getColumnCount(),
+            rowCount = store.getCount(),
+            records;
+        
+        if (rowCount < 1) {
+            return '';
+        }
+        
+        startRow = startRow || 0;
+        endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
+        records  = store.getRange(startRow, endRow);
+        
+        return this.doRender(this.getColumnData(), records, store, startRow, colCount, stripe);
+    },
+
+    
+    renderBody : function(){
+        var markup = this.renderRows() || '&#160;';
+        return this.templates.body.apply({rows: markup});
+    },
+
+    
+    refreshRow: function(record) {
+        var store     = this.ds,
+            colCount  = this.cm.getColumnCount(),
+            columns   = this.getColumnData(),
+            last      = colCount - 1,
+            cls       = ['x-grid3-row'],
+            rowParams = {
+                tstyle: String.format("width: {0};", this.getTotalWidth())
+            },
+            colBuffer = [],
+            cellTpl   = this.templates.cell,
+            rowIndex, row, column, meta, css, i;
+        
+        if (Ext.isNumber(record)) {
+            rowIndex = record;
+            record   = store.getAt(rowIndex);
+        } else {
+            rowIndex = store.indexOf(record);
+        }
+        
+        
+        if (!record || rowIndex < 0) {
+            return;
+        }
+        
+        
+        for (i = 0; i < colCount; i++) {
+            column = columns[i];
+            
+            if (i == 0) {
+                css = 'x-grid3-cell-first';
+            } else {
+                css = (i == last) ? 'x-grid3-cell-last ' : '';
+            }
+            
+            meta = {
+                id      : column.id,
+                style   : column.style,
+                css     : css,
+                attr    : "",
+                cellAttr: ""
+            };
+            
+            meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
+            
+            if (Ext.isEmpty(meta.value)) {
+                meta.value = '&#160;';
+            }
+            
+            if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
+                meta.css += ' x-grid3-dirty-cell';
+            }
+            
+            colBuffer[i] = cellTpl.apply(meta);
+        }
+        
+        row = this.getRow(rowIndex);
+        row.className = '';
+        
+        if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
+            cls.push('x-grid3-row-alt');
+        }
+        
+        if (this.getRowClass) {
+            rowParams.cols = colCount;
+            cls.push(this.getRowClass(record, rowIndex, rowParams, store));
+        }
+        
+        this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
+        rowParams.cells = colBuffer.join("");
+        row.innerHTML = this.templates.rowInner.apply(rowParams);
+        
+        this.fireEvent('rowupdated', this, rowIndex, record);
+    },
+
+    
+    refresh : function(headersToo) {
+        this.fireEvent('beforerefresh', this);
+        this.grid.stopEditing(true);
+
+        var result = this.renderBody();
+        this.mainBody.update(result).setWidth(this.getTotalWidth());
+        if (headersToo === true) {
+            this.updateHeaders();
+            this.updateHeaderSortState();
+        }
+        this.processRows(0, true);
+        this.layout();
+        this.applyEmptyText();
+        this.fireEvent('refresh', this);
+    },
+
+    
+    applyEmptyText : function() {
+        if (this.emptyText && !this.hasRows()) {
+            this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
+        }
+    },
+
+    
+    updateHeaderSortState : function() {
+        var state = this.ds.getSortState();
+        if (!state) {
+            return;
+        }
+
+        if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
+            this.grid.fireEvent('sortchange', this.grid, state);
+        }
+
+        this.sortState = state;
+
+        var sortColumn = this.cm.findColumnIndex(state.field);
+        if (sortColumn != -1) {
+            var sortDir = state.direction;
+            this.updateSortIcon(sortColumn, sortDir);
+        }
+    },
+
+    
+    clearHeaderSortState : function() {
+        if (!this.sortState) {
+            return;
+        }
+        this.grid.fireEvent('sortchange', this.grid, null);
+        this.mainHd.select('td').removeClass(this.sortClasses);
+        delete this.sortState;
+    },
+
+    
+    destroy : function() {
+        var me              = this,
+            grid            = me.grid,
+            gridEl          = grid.getGridEl(),
+            dragZone        = me.dragZone,
+            splitZone       = me.splitZone,
+            columnDrag      = me.columnDrag,
+            columnDrop      = me.columnDrop,
+            scrollToTopTask = me.scrollToTopTask,
+            columnDragData,
+            columnDragProxy;
+        
+        if (scrollToTopTask && scrollToTopTask.cancel) {
+            scrollToTopTask.cancel();
+        }
+        
+        Ext.destroyMembers(me, 'colMenu', 'hmenu');
+
+        me.initData(null, null);
+        me.purgeListeners();
+        
+        Ext.fly(me.innerHd).un("click", me.handleHdDown, me);
+
+        if (grid.enableColumnMove) {
+            columnDragData = columnDrag.dragData;
+            columnDragProxy = columnDrag.proxy;
+            Ext.destroy(
+                columnDrag.el,
+                columnDragProxy.ghost,
+                columnDragProxy.el,
+                columnDrop.el,
+                columnDrop.proxyTop,
+                columnDrop.proxyBottom,
+                columnDragData.ddel,
+                columnDragData.header
+            );
+            
+            if (columnDragProxy.anim) {
+                Ext.destroy(columnDragProxy.anim);
+            }
+            
+            delete columnDragProxy.ghost;
+            delete columnDragData.ddel;
+            delete columnDragData.header;
+            columnDrag.destroy();
+            
+            delete Ext.dd.DDM.locationCache[columnDrag.id];
+            delete columnDrag._domRef;
+
+            delete columnDrop.proxyTop;
+            delete columnDrop.proxyBottom;
+            columnDrop.destroy();
+            delete Ext.dd.DDM.locationCache["gridHeader" + gridEl.id];
+            delete columnDrop._domRef;
+            delete Ext.dd.DDM.ids[columnDrop.ddGroup];
+        }
+
+        if (splitZone) { 
+            splitZone.destroy();
+            delete splitZone._domRef;
+            delete Ext.dd.DDM.ids["gridSplitters" + gridEl.id];
+        }
+
+        Ext.fly(me.innerHd).removeAllListeners();
+        Ext.removeNode(me.innerHd);
+        delete me.innerHd;
+
+        Ext.destroy(
+            me.el,
+            me.mainWrap,
+            me.mainHd,
+            me.scroller,
+            me.mainBody,
+            me.focusEl,
+            me.resizeMarker,
+            me.resizeProxy,
+            me.activeHdBtn,
+            me._flyweight,
+            dragZone,
+            splitZone
+        );
+
+        delete grid.container;
+
+        if (dragZone) {
+            dragZone.destroy();
+        }
+
+        Ext.dd.DDM.currentTarget = null;
+        delete Ext.dd.DDM.locationCache[gridEl.id];
+
+        Ext.EventManager.removeResizeListener(me.onWindowResize, me);
+    },
+
+    
+    onDenyColumnHide : function() {
+
+    },
+
+    
+    render : function() {
+        if (this.autoFill) {
+            var ct = this.grid.ownerCt;
+            
+            if (ct && ct.getLayout()) {
+                ct.on('afterlayout', function() {
+                    this.fitColumns(true, true);
+                    this.updateHeaders();
+                    this.updateHeaderSortState();
+                }, this, {single: true});
+            }
+        } else if (this.forceFit) {
+            this.fitColumns(true, false);
+        } else if (this.grid.autoExpandColumn) {
+            this.autoExpand(true);
+        }
+        
+        this.grid.getGridEl().dom.innerHTML = this.renderUI();
+        
+        this.afterRenderUI();
+    },
+
+    
+    
+    
+    initData : function(newStore, newColModel) {
+        var me = this;
+        
+        if (me.ds) {
+            var oldStore = me.ds;
+            
+            oldStore.un('add', me.onAdd, me);
+            oldStore.un('load', me.onLoad, me);
+            oldStore.un('clear', me.onClear, me);
+            oldStore.un('remove', me.onRemove, me);
+            oldStore.un('update', me.onUpdate, me);
+            oldStore.un('datachanged', me.onDataChange, me);
+            
+            if (oldStore !== newStore && oldStore.autoDestroy) {
+                oldStore.destroy();
+            }
+        }
+        
+        if (newStore) {
+            newStore.on({
+                scope      : me,
+                load       : me.onLoad,
+                add        : me.onAdd,
+                remove     : me.onRemove,
+                update     : me.onUpdate,
+                clear      : me.onClear,
+                datachanged: me.onDataChange
+            });
+        }
+        
+        if (me.cm) {
+            var oldColModel = me.cm;
+            
+            oldColModel.un('configchange', me.onColConfigChange, me);
+            oldColModel.un('widthchange',  me.onColWidthChange, me);
+            oldColModel.un('headerchange', me.onHeaderChange, me);
+            oldColModel.un('hiddenchange', me.onHiddenChange, me);
+            oldColModel.un('columnmoved',  me.onColumnMove, me);
+        }
+        
+        if (newColModel) {
+            delete me.lastViewWidth;
+            
+            newColModel.on({
+                scope       : me,
+                configchange: me.onColConfigChange,
+                widthchange : me.onColWidthChange,
+                headerchange: me.onHeaderChange,
+                hiddenchange: me.onHiddenChange,
+                columnmoved : me.onColumnMove
+            });
+        }
+        
+        me.ds = newStore;
+        me.cm = newColModel;
+    },
+
+    
+    onDataChange : function(){
+        this.refresh(true);
+        this.updateHeaderSortState();
+        this.syncFocusEl(0);
+    },
+
+    
+    onClear : function() {
+        this.refresh();
+        this.syncFocusEl(0);
+    },
+
+    
+    onUpdate : function(store, record) {
+        this.refreshRow(record);
+    },
+
+    
+    onAdd : function(store, records, index) {
+        this.insertRows(store, index, index + (records.length-1));
+    },
+
+    
+    onRemove : function(store, record, index, isUpdate) {
+        if (isUpdate !== true) {
+            this.fireEvent('beforerowremoved', this, index, record);
+        }
+        
+        this.removeRow(index);
+        
+        if (isUpdate !== true) {
+            this.processRows(index);
+            this.applyEmptyText();
+            this.fireEvent('rowremoved', this, index, record);
+        }
+    },
+
+    
+    onLoad : function() {
+        if (Ext.isGecko) {
+            if (!this.scrollToTopTask) {
+                this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
+            }
+            this.scrollToTopTask.delay(1);
+        } else {
+            this.scrollToTop();
+        }
+    },
+
+    
+    onColWidthChange : function(cm, col, width) {
+        this.updateColumnWidth(col, width);
+    },
+
+    
+    onHeaderChange : function(cm, col, text) {
+        this.updateHeaders();
+    },
+
+    
+    onHiddenChange : function(cm, col, hidden) {
+        this.updateColumnHidden(col, hidden);
+    },
+
+    
+    onColumnMove : function(cm, oldIndex, newIndex) {
+        this.indexMap = null;
+        this.refresh(true);
+        this.restoreScroll(this.getScrollState());
+        
+        this.afterMove(newIndex);
+        this.grid.fireEvent('columnmove', oldIndex, newIndex);
+    },
+
+    
+    onColConfigChange : function() {
+        delete this.lastViewWidth;
+        this.indexMap = null;
+        this.refresh(true);
+    },
+
+    
+    
+    initUI : function(grid) {
+        grid.on('headerclick', this.onHeaderClick, this);
+    },
+
+    
+    initEvents : Ext.emptyFn,
+
+    
+    onHeaderClick : function(g, index) {
+        if (this.headersDisabled || !this.cm.isSortable(index)) {
+            return;
+        }
+        g.stopEditing(true);
+        g.store.sort(this.cm.getDataIndex(index));
+    },
+
+    
+    onRowOver : function(e, target) {
+        var row = this.findRowIndex(target);
+        
+        if (row !== false) {
+            this.addRowClass(row, this.rowOverCls);
+        }
+    },
+
+    
+    onRowOut : function(e, target) {
+        var row = this.findRowIndex(target);
+        
+        if (row !== false && !e.within(this.getRow(row), true)) {
+            this.removeRowClass(row, this.rowOverCls);
+        }
+    },
+
+    
+    onRowSelect : function(row) {
+        this.addRowClass(row, this.selectedRowClass);
+    },
+
+    
+    onRowDeselect : function(row) {
+        this.removeRowClass(row, this.selectedRowClass);
+    },
+
+    
+    onCellSelect : function(row, col) {
+        var cell = this.getCell(row, col);
+        if (cell) {
+            this.fly(cell).addClass('x-grid3-cell-selected');
+        }
+    },
+
+    
+    onCellDeselect : function(row, col) {
+        var cell = this.getCell(row, col);
+        if (cell) {
+            this.fly(cell).removeClass('x-grid3-cell-selected');
+        }
+    },
+
+    
+    handleWheel : function(e) {
+        e.stopPropagation();
+    },
+
+    
+    onColumnSplitterMoved : function(cellIndex, width) {
+        this.userResized = true;
+        this.grid.colModel.setColumnWidth(cellIndex, width, true);
+
+        if (this.forceFit) {
+            this.fitColumns(true, false, cellIndex);
+            this.updateAllColumnWidths();
+        } else {
+            this.updateColumnWidth(cellIndex, width);
+            this.syncHeaderScroll();
+        }
+
+        this.grid.fireEvent('columnresize', cellIndex, width);
+    },
+
+    
+    beforeColMenuShow : function() {
+        var colModel = this.cm,
+            colCount = colModel.getColumnCount(),
+            colMenu  = this.colMenu,
+            i;
+
+        colMenu.removeAll();
+
+        for (i = 0; i < colCount; i++) {
+            if (colModel.config[i].hideable !== false) {
+                colMenu.add(new Ext.menu.CheckItem({
+                    text       : colModel.getColumnHeader(i),
+                    itemId     : 'col-' + colModel.getColumnId(i),
+                    checked    : !colModel.isHidden(i),
+                    disabled   : colModel.config[i].hideable === false,
+                    hideOnClick: false
+                }));
+            }
+        }
+    },
+    
+    
+    handleHdMenuClick : function(item) {
+        var store     = this.ds,
+            dataIndex = this.cm.getDataIndex(this.hdCtxIndex);
+
+        switch (item.getItemId()) {
+            case 'asc':
+                store.sort(dataIndex, 'ASC');
+                break;
+            case 'desc':
+                store.sort(dataIndex, 'DESC');
+                break;
+            default:
+                this.handleHdMenuClickDefault(item);
+        }
+        return true;
+    },
+    
+    
+    handleHdMenuClickDefault: function(item) {
+        var colModel = this.cm,
+            itemId   = item.getItemId(),
+            index    = colModel.getIndexById(itemId.substr(4));
+
+        if (index != -1) {
+            if (item.checked && colModel.getColumnsBy(this.isHideableColumn, this).length <= 1) {
+                this.onDenyColumnHide();
+                return;
+            }
+            colModel.setHidden(index, item.checked);
+        }
+    },
+
+    
+    handleHdDown : function(e, target) {
+        if (Ext.fly(target).hasClass('x-grid3-hd-btn')) {
+            e.stopEvent();
+            
+            var colModel  = this.cm,
+                header    = this.findHeaderCell(target),
+                index     = this.getCellIndex(header),
+                sortable  = colModel.isSortable(index),
+                menu      = this.hmenu,
+                menuItems = menu.items,
+                menuCls   = this.headerMenuOpenCls;
+            
+            this.hdCtxIndex = index;
+            
+            Ext.fly(header).addClass(menuCls);
+            menuItems.get('asc').setDisabled(!sortable);
+            menuItems.get('desc').setDisabled(!sortable);
+            
+            menu.on('hide', function() {
+                Ext.fly(header).removeClass(menuCls);
+            }, this, {single:true});
+            
+            menu.show(target, 'tl-bl?');
+        }
+    },
+
+    
+    handleHdMove : function(e) {
+        var header = this.findHeaderCell(this.activeHdRef);
+        
+        if (header && !this.headersDisabled) {
+            var handleWidth  = this.splitHandleWidth || 5,
+                activeRegion = this.activeHdRegion,
+                headerStyle  = header.style,
+                colModel     = this.cm,
+                cursor       = '',
+                pageX        = e.getPageX();
+                
+            if (this.grid.enableColumnResize !== false) {
+                var activeHeaderIndex = this.activeHdIndex,
+                    previousVisible   = this.getPreviousVisible(activeHeaderIndex),
+                    currentResizable  = colModel.isResizable(activeHeaderIndex),
+                    previousResizable = previousVisible && colModel.isResizable(previousVisible),
+                    inLeftResizer     = pageX - activeRegion.left <= handleWidth,
+                    inRightResizer    = activeRegion.right - pageX <= (!this.activeHdBtn ? handleWidth : 2);
+                
+                if (inLeftResizer && previousResizable) {
+                    cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
+                } else if (inRightResizer && currentResizable) {
+                    cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
+                }
+            }
+            
+            headerStyle.cursor = cursor;
+        }
+    },
+    
+    
+    getPreviousVisible: function(index) {
+        while (index > 0) {
+            if (!this.cm.isHidden(index - 1)) {
+                return index;
+            }
+            index--;
+        }
+        return undefined;
+    },
+
+    
+    handleHdOver : function(e, target) {
+        var header = this.findHeaderCell(target);
+        
+        if (header && !this.headersDisabled) {
+            var fly = this.fly(header);
+            
+            this.activeHdRef = target;
+            this.activeHdIndex = this.getCellIndex(header);
+            this.activeHdRegion = fly.getRegion();
+            
+            if (!this.isMenuDisabled(this.activeHdIndex, fly)) {
+                fly.addClass('x-grid3-hd-over');
+                this.activeHdBtn = fly.child('.x-grid3-hd-btn');
+                
+                if (this.activeHdBtn) {
+                    this.activeHdBtn.dom.style.height = (header.firstChild.offsetHeight - 1) + 'px';
+                }
+            }
+        }
+    },
+
+    
+    handleHdOut : function(e, target) {
+        var header = this.findHeaderCell(target);
+        
+        if (header && (!Ext.isIE || !e.within(header, true))) {
+            this.activeHdRef = null;
+            this.fly(header).removeClass('x-grid3-hd-over');
+            header.style.cursor = '';
+        }
+    },
+    
+    
+    isMenuDisabled: function(cellIndex, el) {
+        return this.cm.isMenuDisabled(cellIndex);
+    },
+
+    
+    hasRows : function() {
+        var fc = this.mainBody.dom.firstChild;
+        return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
+    },
+    
+    
+    isHideableColumn : function(c) {
+        return !c.hidden;
+    },
+
+    
+    bind : function(d, c) {
+        this.initData(d, c);
+    }
+});
+
+
+
+
+Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
+
+    constructor: function(grid, hd){
+        this.grid = grid;
+        this.view = grid.getView();
+        this.marker = this.view.resizeMarker;
+        this.proxy = this.view.resizeProxy;
+        Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
+            'gridSplitters' + this.grid.getGridEl().id, {
+            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
+        });
+        this.scroll = false;
+        this.hw = this.view.splitHandleWidth || 5;
+    },
+
+    b4StartDrag : function(x, y){
+        this.dragHeadersDisabled = this.view.headersDisabled;
+        this.view.headersDisabled = true;
+        var h = this.view.mainWrap.getHeight();
+        this.marker.setHeight(h);
+        this.marker.show();
+        this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
+        this.proxy.setHeight(h);
+        var w = this.cm.getColumnWidth(this.cellIndex),
+            minw = Math.max(w-this.grid.minColumnWidth, 0);
+        this.resetConstraints();
+        this.setXConstraint(minw, 1000);
+        this.setYConstraint(0, 0);
+        this.minX = x - minw;
+        this.maxX = x + 1000;
+        this.startPos = x;
+        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
+    },
+
+    allowHeaderDrag : function(e){
+        return true;
+    },
+
+    handleMouseDown : function(e){
+        var t = this.view.findHeaderCell(e.getTarget());
+        if(t && this.allowHeaderDrag(e)){
+            var xy = this.view.fly(t).getXY(), 
+                x = xy[0],
+                exy = e.getXY(), 
+                ex = exy[0],
+                w = t.offsetWidth, 
+                adjust = false;
+                
+            if((ex - x) <= this.hw){
+                adjust = -1;
+            }else if((x+w) - ex <= this.hw){
+                adjust = 0;
+            }
+            if(adjust !== false){
+                this.cm = this.grid.colModel;
+                var ci = this.view.getCellIndex(t);
+                if(adjust == -1){
+                  if (ci + adjust < 0) {
+                    return;
+                  }
+                    while(this.cm.isHidden(ci+adjust)){
+                        --adjust;
+                        if(ci+adjust < 0){
+                            return;
+                        }
+                    }
+                }
+                this.cellIndex = ci+adjust;
+                this.split = t.dom;
+                if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
+                    Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
+                }
+            }else if(this.view.columnDrag){
+                this.view.columnDrag.callHandleMouseDown(e);
+            }
+        }
+    },
+
+    endDrag : function(e){
+        this.marker.hide();
+        var v = this.view,
+            endX = Math.max(this.minX, e.getPageX()),
+            diff = endX - this.startPos,
+            disabled = this.dragHeadersDisabled;
+            
+        v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
+        setTimeout(function(){
+            v.headersDisabled = disabled;
+        }, 50);
+    },
+
+    autoOffset : function(){
+        this.setDelta(0,0);
+    }
+});
+
+Ext.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {
+    
+    
+    colHeaderCellCls: 'grid-hd-group-cell',
+    
+    
+    title: '',
+    
+    
+    
+    
+    getColumnHeaders: function() {
+        return this.grid.topAxis.buildHeaders();;
+    },
+    
+    
+    getRowHeaders: function() {
+        return this.grid.leftAxis.buildHeaders();
+    },
+    
+    
+    renderRows : function(startRow, endRow) {
+        var grid          = this.grid,
+            rows          = grid.extractData(),
+            rowCount      = rows.length,
+            templates     = this.templates,
+            renderer      = grid.renderer,
+            hasRenderer   = typeof renderer == 'function',
+            getCellCls    = this.getCellCls,
+            hasGetCellCls = typeof getCellCls == 'function',
+            cellTemplate  = templates.cell,
+            rowTemplate   = templates.row,
+            rowBuffer     = [],
+            meta          = {},
+            tstyle        = 'width:' + this.getGridInnerWidth() + 'px;',
+            colBuffer, colCount, column, i, row;
+        
+        startRow = startRow || 0;
+        endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
+        
+        for (i = 0; i < rowCount; i++) {
+            row = rows[i];
+            colCount  = row.length;
+            colBuffer = [];
+            
+            
+            for (var j = 0; j < colCount; j++) {
+                
+                meta.id    = i + '-' + j;
+                meta.css   = j === 0 ? 'x-grid3-cell-first ' : (j == (colCount - 1) ? 'x-grid3-cell-last ' : '');
+                meta.attr  = meta.cellAttr = '';
+                meta.value = row[j];
+
+                if (Ext.isEmpty(meta.value)) {
+                    meta.value = '&#160;';
+                }
+                
+                if (hasRenderer) {
+                    meta.value = renderer(meta.value);
+                }
+                
+                if (hasGetCellCls) {
+                    meta.css += getCellCls(meta.value) + ' ';
+                }
+
+                colBuffer[colBuffer.length] = cellTemplate.apply(meta);
+            }
+            
+            rowBuffer[rowBuffer.length] = rowTemplate.apply({
+                tstyle: tstyle,
+                cols  : colCount,
+                cells : colBuffer.join(""),
+                alt   : ''
+            });
+        }
+        
+        return rowBuffer.join("");
+    },
+    
+    
+    masterTpl: new Ext.Template(
+        '<div class="x-grid3 x-pivotgrid" hidefocus="true">',
+            '<div class="x-grid3-viewport">',
+                '<div class="x-grid3-header">',
+                    '<div class="x-grid3-header-title"><span>{title}</span></div>',
+                    '<div class="x-grid3-header-inner">',
+                        '<div class="x-grid3-header-offset" style="{ostyle}"></div>',
+                    '</div>',
+                    '<div class="x-clear"></div>',
+                '</div>',
+                '<div class="x-grid3-scroller">',
+                    '<div class="x-grid3-row-headers"></div>',
+                    '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
+                    '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
+                '</div>',
+            '</div>',
+            '<div class="x-grid3-resize-marker">&#160;</div>',
+            '<div class="x-grid3-resize-proxy">&#160;</div>',
+        '</div>'
+    ),
+    
+    
+    initTemplates: function() {
+        Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);
+        
+        var templates = this.templates || {};
+        if (!templates.gcell) {
+            templates.gcell = new Ext.XTemplate(
+                '<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '" style="{style}">',
+                    '<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
+                        this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', '{value}',
+                    '</div>',
+                '</td>'
+            );
+        }
+        
+        this.templates = templates;
+        this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "");
+    },
+    
+    
+    initElements: function() {
+        Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);
+        
+        
+        this.rowHeadersEl = new Ext.Element(this.scroller.child('div.x-grid3-row-headers'));
+        
+        
+        this.headerTitleEl = new Ext.Element(this.mainHd.child('div.x-grid3-header-title'));
+    },
+    
+    
+    getGridInnerWidth: function() {
+        var previousWidth = Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);
+        
+        return previousWidth - this.getTotalRowHeaderWidth();
+    },
+    
+    
+    getTotalRowHeaderWidth: function() {
+        var headers = this.getRowHeaders(),
+            length  = headers.length,
+            total   = 0,
+            i;
+        
+        for (i = 0; i< length; i++) {
+            total += headers[i].width;
+        }
+        
+        return total;
+    },
+    
+    
+    getTotalColumnHeaderHeight: function() {
+        return this.getColumnHeaders().length * 21;
+    },
+    
+    
+    getCellIndex : function(el) {
+        if (el) {
+            var match = el.className.match(this.colRe),
+                data;
+ 
+            if (match && (data = match[1])) {
+                return parseInt(data.split('-')[1], 10);
+            }
+        }
+        return false;
+    },
+    
+    
+    
+    renderUI : function() {
+        var templates  = this.templates,
+            innerWidth = this.getGridInnerWidth();
+            
+        return templates.master.apply({
+            body  : templates.body.apply({rows:'&#160;'}),
+            ostyle: 'width:' + innerWidth + 'px',
+            bstyle: 'width:' + innerWidth + 'px'
+        });
+    },
+    
+    
+    onLayout: function(width, height) {
+        Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);
+        
+        var width = this.getGridInnerWidth();
+        
+        this.resizeColumnHeaders(width);
+        this.resizeAllRows(width);
+    },
+    
+    
+    refresh : function(headersToo) {
+        this.fireEvent('beforerefresh', this);
+        this.grid.stopEditing(true);
+        
+        var result = this.renderBody();
+        this.mainBody.update(result).setWidth(this.getGridInnerWidth());
+        if (headersToo === true) {
+            this.updateHeaders();
+            this.updateHeaderSortState();
+        }
+        this.processRows(0, true);
+        this.layout();
+        this.applyEmptyText();
+        this.fireEvent('refresh', this);
+    },
+    
+    
+    renderHeaders: Ext.emptyFn,
+    
+    
+    fitColumns: Ext.emptyFn,
+    
+    
+    resizeColumnHeaders: function(width) {
+        var topAxis = this.grid.topAxis;
+        
+        if (topAxis.rendered) {
+            topAxis.el.setWidth(width);
+        }
+    },
+    
+    
+    resizeRowHeaders: function() {
+        var rowHeaderWidth = this.getTotalRowHeaderWidth(),
+            marginStyle    = String.format("margin-left: {0}px;", rowHeaderWidth);
+        
+        this.rowHeadersEl.setWidth(rowHeaderWidth);
+        this.mainBody.applyStyles(marginStyle);
+        Ext.fly(this.innerHd).applyStyles(marginStyle);
+        
+        this.headerTitleEl.setWidth(rowHeaderWidth);
+        this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight());
+    },
+    
+    
+    resizeAllRows: function(width) {
+        var rows   = this.getRows(),
+            length = rows.length,
+            i;
+        
+        for (i = 0; i < length; i++) {
+            Ext.fly(rows[i]).setWidth(width);
+            Ext.fly(rows[i]).child('table').setWidth(width);
+        }
+    },
+    
+    
+    updateHeaders: function() {
+        this.renderGroupRowHeaders();
+        this.renderGroupColumnHeaders();
+    },
+    
+    
+    renderGroupRowHeaders: function() {
+        var leftAxis = this.grid.leftAxis;
+        
+        this.resizeRowHeaders();
+        leftAxis.rendered = false;
+        leftAxis.render(this.rowHeadersEl);
+        
+        this.setTitle(this.title);
+    },
+    
+    
+    setTitle: function(title) {
+        this.headerTitleEl.child('span').dom.innerHTML = title;
+    },
+    
+    
+    renderGroupColumnHeaders: function() {
+        var topAxis = this.grid.topAxis;
+        
+        topAxis.rendered = false;
+        topAxis.render(this.innerHd.firstChild);
+    },
+    
+    
+    isMenuDisabled: function(cellIndex, el) {
+        return true;
+    }
+});
+Ext.grid.PivotAxis = Ext.extend(Ext.Component, {
+    
+    orientation: 'horizontal',
+    
+    
+    defaultHeaderWidth: 80,
+    
+    
+    paddingWidth: 7,
+    
+    
+    setDimensions: function(dimensions) {
+        this.dimensions = dimensions;
+    },
+    
+    
+    onRender: function(ct, position) {
+        var rows = this.orientation == 'horizontal'
+                 ? this.renderHorizontalRows()
+                 : this.renderVerticalRows();
+        
+        this.el = Ext.DomHelper.overwrite(ct.dom, {tag: 'table', cn: rows}, true);
+    },
+    
+    
+    renderHorizontalRows: function() {
+        var headers  = this.buildHeaders(),
+            rowCount = headers.length,
+            rows     = [],
+            cells, cols, colCount, i, j;
+        
+        for (i = 0; i < rowCount; i++) {
+            cells = [];
+            cols  = headers[i].items;
+            colCount = cols.length;
+
+            for (j = 0; j < colCount; j++) {
+                cells.push({
+                    tag: 'td',
+                    html: cols[j].header,
+                    colspan: cols[j].span
+                });
+            }
+
+            rows[i] = {
+                tag: 'tr',
+                cn: cells
+            };
+        }
+        
+        return rows;
+    },
+    
+    
+    renderVerticalRows: function() {
+        var headers  = this.buildHeaders(),
+            colCount = headers.length,
+            rowCells = [],
+            rows     = [],
+            rowCount, col, row, colWidth, i, j;
+        
+        for (i = 0; i < colCount; i++) {
+            col = headers[i];
+            colWidth = col.width || 80;
+            rowCount = col.items.length;
+            
+            for (j = 0; j < rowCount; j++) {
+                row = col.items[j];
+                
+                rowCells[row.start] = rowCells[row.start] || [];
+                rowCells[row.start].push({
+                    tag    : 'td',
+                    html   : row.header,
+                    rowspan: row.span,
+                    width  : Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
+                });
+            }
+        }
+        
+        rowCount = rowCells.length;
+        for (i = 0; i < rowCount; i++) {
+            rows[i] = {
+                tag: 'tr',
+                cn : rowCells[i]
+            };
+        }
+        
+        return rows;
+    },
+    
+    
+    getTuples: function() {
+        var newStore = new Ext.data.Store({});
+        
+        newStore.data = this.store.data.clone();
+        newStore.fields = this.store.fields;
+        
+        var sorters    = [],
+            dimensions = this.dimensions,
+            length     = dimensions.length,
+            i;
+        
+        for (i = 0; i < length; i++) {
+            sorters.push({
+                field    : dimensions[i].dataIndex,
+                direction: dimensions[i].direction || 'ASC'
+            });
+        }
+        
+        newStore.sort(sorters);
+        
+        var records = newStore.data.items,
+            hashes  = [],
+            tuples  = [],
+            recData, hash, info, data, key;
+        
+        length = records.length;
+        
+        for (i = 0; i < length; i++) {
+            info = this.getRecordInfo(records[i]);
+            data = info.data;
+            hash = "";
+            
+            for (key in data) {
+                hash += data[key] + '---';
+            }
+            
+            if (hashes.indexOf(hash) == -1) {
+                hashes.push(hash);
+                tuples.push(info);
+            }
+        }
+        
+        newStore.destroy();
+        
+        return tuples;
+    },
+    
+    
+    getRecordInfo: function(record) {
+        var dimensions = this.dimensions,
+            length  = dimensions.length,
+            data    = {},
+            dimension, dataIndex, i;
+        
+        
+        for (i = 0; i < length; i++) {
+            dimension = dimensions[i];
+            dataIndex = dimension.dataIndex;
+            
+            data[dataIndex] = record.get(dataIndex);
+        }
+        
+        
+        
+        var createMatcherFunction = function(data) {
+            return function(record) {
+                for (var dataIndex in data) {
+                    if (record.get(dataIndex) != data[dataIndex]) {
+                        return false;
+                    }
+                }
+                
+                return true;
+            };
+        };
+        
+        return {
+            data: data,
+            matcher: createMatcherFunction(data)
+        };
+    },
+    
+    
+    buildHeaders: function() {
+        var tuples     = this.getTuples(),
+            rowCount   = tuples.length,
+            dimensions = this.dimensions,
+            dimension,
+            colCount   = dimensions.length,
+            headers    = [],
+            tuple, rows, currentHeader, previousHeader, span, start, isLast, changed, i, j;
+        
+        for (i = 0; i < colCount; i++) {
+            dimension = dimensions[i];
+            rows  = [];
+            span  = 0;
+            start = 0;
+            
+            for (j = 0; j < rowCount; j++) {
+                tuple  = tuples[j];
+                isLast = j == (rowCount - 1);
+                currentHeader = tuple.data[dimension.dataIndex];
+                
+                
+                changed = previousHeader != undefined && previousHeader != currentHeader;
+                if (i > 0 && j > 0) {
+                    changed = changed || tuple.data[dimensions[i-1].dataIndex] != tuples[j-1].data[dimensions[i-1].dataIndex];
+                }
+                
+                if (changed) {                    
+                    rows.push({
+                        header: previousHeader,
+                        span  : span,
+                        start : start
+                    });
+                    
+                    start += span;
+                    span = 0;
+                }
+                
+                if (isLast) {
+                    rows.push({
+                        header: currentHeader,
+                        span  : span + 1,
+                        start : start
+                    });
+                    
+                    start += span;
+                    span = 0;
+                }
+                
+                previousHeader = currentHeader;
+                span++;
+            }
+            
+            headers.push({
+                items: rows,
+                width: dimension.width || this.defaultHeaderWidth
+            });
+            
+            previousHeader = undefined;
+        }
+        
+        return headers;
+    }
+});
+
+
+Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
+    maxDragWidth: 120,
+    
+    constructor : function(grid, hd, hd2){
+        this.grid = grid;
+        this.view = grid.getView();
+        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
+        Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
+        if(hd2){
+            this.setHandleElId(Ext.id(hd));
+            this.setOuterHandleElId(Ext.id(hd2));
+        }
+        this.scroll = false;
+    },
+    
+    getDragData : function(e){
+        var t = Ext.lib.Event.getTarget(e),
+            h = this.view.findHeaderCell(t);
+        if(h){
+            return {ddel: h.firstChild, header:h};
+        }
+        return false;
+    },
+
+    onInitDrag : function(e){
+        
+        this.dragHeadersDisabled = this.view.headersDisabled;
+        this.view.headersDisabled = true;
+        var clone = this.dragData.ddel.cloneNode(true);
+        clone.id = Ext.id();
+        clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
+        this.proxy.update(clone);
+        return true;
+    },
+
+    afterValidDrop : function(){
+        this.completeDrop();
+    },
+
+    afterInvalidDrop : function(){
+        this.completeDrop();
+    },
+    
+    completeDrop: function(){
+        var v = this.view,
+            disabled = this.dragHeadersDisabled;
+        setTimeout(function(){
+            v.headersDisabled = disabled;
+        }, 50);
+    }
+});
+
+
+
+Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
+    proxyOffsets : [-4, -9],
+    fly: Ext.Element.fly,
+    
+    constructor : function(grid, hd, hd2){
+        this.grid = grid;
+        this.view = grid.getView();
+        
+        this.proxyTop = Ext.DomHelper.append(document.body, {
+            cls:"col-move-top", html:"&#160;"
+        }, true);
+        this.proxyBottom = Ext.DomHelper.append(document.body, {
+            cls:"col-move-bottom", html:"&#160;"
+        }, true);
+        this.proxyTop.hide = this.proxyBottom.hide = function(){
+            this.setLeftTop(-100,-100);
+            this.setStyle("visibility", "hidden");
+        };
+        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
+        
+        
+        Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
+    },
+
+    getTargetFromEvent : function(e){
+        var t = Ext.lib.Event.getTarget(e),
+            cindex = this.view.findCellIndex(t);
+        if(cindex !== false){
+            return this.view.getHeaderCell(cindex);
+        }
+    },
+
+    nextVisible : function(h){
+        var v = this.view, cm = this.grid.colModel;
+        h = h.nextSibling;
+        while(h){
+            if(!cm.isHidden(v.getCellIndex(h))){
+                return h;
+            }
+            h = h.nextSibling;
+        }
+        return null;
+    },
+
+    prevVisible : function(h){
+        var v = this.view, cm = this.grid.colModel;
+        h = h.prevSibling;
+        while(h){
+            if(!cm.isHidden(v.getCellIndex(h))){
+                return h;
+            }
+            h = h.prevSibling;
+        }
+        return null;
+    },
+
+    positionIndicator : function(h, n, e){
+        var x = Ext.lib.Event.getPageX(e),
+            r = Ext.lib.Dom.getRegion(n.firstChild),
+            px, 
+            pt, 
+            py = r.top + this.proxyOffsets[1];
+        if((r.right - x) <= (r.right-r.left)/2){
+            px = r.right+this.view.borderWidth;
+            pt = "after";
+        }else{
+            px = r.left;
+            pt = "before";
+        }
+
+        if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
+            return false;
+        }
+
+        px +=  this.proxyOffsets[0];
+        this.proxyTop.setLeftTop(px, py);
+        this.proxyTop.show();
+        if(!this.bottomOffset){
+            this.bottomOffset = this.view.mainHd.getHeight();
+        }
+        this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
+        this.proxyBottom.show();
+        return pt;
+    },
+
+    onNodeEnter : function(n, dd, e, data){
+        if(data.header != n){
+            this.positionIndicator(data.header, n, e);
+        }
+    },
+
+    onNodeOver : function(n, dd, e, data){
+        var result = false;
+        if(data.header != n){
+            result = this.positionIndicator(data.header, n, e);
+        }
+        if(!result){
+            this.proxyTop.hide();
+            this.proxyBottom.hide();
+        }
+        return result ? this.dropAllowed : this.dropNotAllowed;
+    },
+
+    onNodeOut : function(n, dd, e, data){
+        this.proxyTop.hide();
+        this.proxyBottom.hide();
+    },
+
+    onNodeDrop : function(n, dd, e, data){
+        var h = data.header;
+        if(h != n){
+            var cm = this.grid.colModel,
+                x = Ext.lib.Event.getPageX(e),
+                r = Ext.lib.Dom.getRegion(n.firstChild),
+                pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
+                oldIndex = this.view.getCellIndex(h),
+                newIndex = this.view.getCellIndex(n);
+            if(pt == "after"){
+                newIndex++;
+            }
+            if(oldIndex < newIndex){
+                newIndex--;
+            }
+            cm.moveColumn(oldIndex, newIndex);
+            return true;
+        }
+        return false;
+    }
+});
+
+Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
+    
+    constructor : function(grid, hd){
+        Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
+        this.proxy.el.addClass('x-grid3-col-dd');
+    },
+    
+    handleMouseDown : function(e){
+    },
+
+    callHandleMouseDown : function(e){
+        Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
+    }
+});
+
+Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
+    fly: Ext.Element.fly,
+    
+    constructor : function(grid, hd, hd2){
+        this.grid = grid;
+        this.view = grid.getView();
+        this.proxy = this.view.resizeProxy;
+        Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
+            "gridSplitters" + this.grid.getGridEl().id, {
+            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
+        });
+        this.setHandleElId(Ext.id(hd));
+        this.setOuterHandleElId(Ext.id(hd2));
+        this.scroll = false;
+    },
+
+    b4StartDrag : function(x, y){
+        this.view.headersDisabled = true;
+        this.proxy.setHeight(this.view.mainWrap.getHeight());
+        var w = this.cm.getColumnWidth(this.cellIndex);
+        var minw = Math.max(w-this.grid.minColumnWidth, 0);
+        this.resetConstraints();
+        this.setXConstraint(minw, 1000);
+        this.setYConstraint(0, 0);
+        this.minX = x - minw;
+        this.maxX = x + 1000;
+        this.startPos = x;
+        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
+    },
+
+
+    handleMouseDown : function(e){
+        var ev = Ext.EventObject.setEvent(e);
+        var t = this.fly(ev.getTarget());
+        if(t.hasClass("x-grid-split")){
+            this.cellIndex = this.view.getCellIndex(t.dom);
+            this.split = t.dom;
+            this.cm = this.grid.colModel;
+            if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
+                Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
+            }
+        }
+    },
+
+    endDrag : function(e){
+        this.view.headersDisabled = false;
+        var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
+        var diff = endX - this.startPos;
+        this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
+    },
+
+    autoOffset : function(){
+        this.setDelta(0,0);
+    }
+});
+Ext.grid.GridDragZone = function(grid, config){
+    this.view = grid.getView();
+    Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
+    this.scroll = false;
+    this.grid = grid;
+    this.ddel = document.createElement('div');
+    this.ddel.className = 'x-grid-dd-wrap';
+};
+
+Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
+    ddGroup : "GridDD",
+
+    
+    getDragData : function(e){
+        var t = Ext.lib.Event.getTarget(e);
+        var rowIndex = this.view.findRowIndex(t);
+        if(rowIndex !== false){
+            var sm = this.grid.selModel;
+            if(!sm.isSelected(rowIndex) || e.hasModifier()){
+                sm.handleMouseDown(this.grid, rowIndex, e);
+            }
+            return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
+        }
+        return false;
+    },
+
+    
+    onInitDrag : function(e){
+        var data = this.dragData;
+        this.ddel.innerHTML = this.grid.getDragDropText();
+        this.proxy.update(this.ddel);
+        
+    },
+
+    
+    afterRepair : function(){
+        this.dragging = false;
+    },
+
+    
+    getRepairXY : function(e, data){
+        return false;
+    },
+
+    onEndDrag : function(data, e){
+        
+    },
+
+    onValidDrop : function(dd, e, id){
+        
+        this.hideProxy();
+    },
+
+    beforeInvalidDrop : function(e, id){
+
+    }
+});
+
+Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
+    
+    defaultWidth: 100,
+
+    
+    defaultSortable: false,
+
+    
+
+    
+
+    constructor : function(config) {
+        
+	    if (config.columns) {
+	        Ext.apply(this, config);
+	        this.setConfig(config.columns, true);
+	    } else {
+	        this.setConfig(config, true);
+	    }
+	    
+	    this.addEvents(
+	        
+	        "widthchange",
+	        
+	        
+	        "headerchange",
+	        
+	        
+	        "hiddenchange",
+	        
+	        
+	        "columnmoved",
+	        
+	        
+	        "configchange"
+	    );
+	    
+	    Ext.grid.ColumnModel.superclass.constructor.call(this);
+    },
+
+    
+    getColumnId : function(index) {
+        return this.config[index].id;
+    },
+
+    getColumnAt : function(index) {
+        return this.config[index];
+    },
+
+    
+    setConfig : function(config, initial) {
+        var i, c, len;
+        
+        if (!initial) { 
+            delete this.totalWidth;
+            
+            for (i = 0, len = this.config.length; i < len; i++) {
+                c = this.config[i];
+                
+                if (c.setEditor) {
+                    
+                    c.setEditor(null);
+                }
+            }
+        }
+
+        
+        this.defaults = Ext.apply({
+            width: this.defaultWidth,
+            sortable: this.defaultSortable
+        }, this.defaults);
+
+        this.config = config;
+        this.lookup = {};
+
+        for (i = 0, len = config.length; i < len; i++) {
+            c = Ext.applyIf(config[i], this.defaults);
+            
+            
+            if (Ext.isEmpty(c.id)) {
+                c.id = i;
+            }
+            
+            if (!c.isColumn) {
+                var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
+                c = new Cls(c);
+                config[i] = c;
+            }
+            
+            this.lookup[c.id] = c;
+        }
+        
+        if (!initial) {
+            this.fireEvent('configchange', this);
+        }
+    },
+
+    
+    getColumnById : function(id) {
+        return this.lookup[id];
+    },
+
+    
+    getIndexById : function(id) {
+        for (var i = 0, len = this.config.length; i < len; i++) {
+            if (this.config[i].id == id) {
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    
+    moveColumn : function(oldIndex, newIndex) {
+        var config = this.config,
+            c      = config[oldIndex];
+            
+        config.splice(oldIndex, 1);
+        config.splice(newIndex, 0, c);
+        this.dataMap = null;
+        this.fireEvent("columnmoved", this, oldIndex, newIndex);
+    },
+
+    
+    getColumnCount : function(visibleOnly) {
+        var length = this.config.length,
+            c = 0,
+            i;
+        
+        if (visibleOnly === true) {
+            for (i = 0; i < length; i++) {
+                if (!this.isHidden(i)) {
+                    c++;
+                }
+            }
+            
+            return c;
+        }
+        
+        return length;
+    },
+
+    
+    getColumnsBy : function(fn, scope) {
+        var config = this.config,
+            length = config.length,
+            result = [],
+            i, c;
+            
+        for (i = 0; i < length; i++){
+            c = config[i];
+            
+            if (fn.call(scope || this, c, i) === true) {
+                result[result.length] = c;
+            }
+        }
+        
+        return result;
+    },
+
+    
+    isSortable : function(col) {
+        return !!this.config[col].sortable;
+    },
+
+    
+    isMenuDisabled : function(col) {
+        return !!this.config[col].menuDisabled;
+    },
+
+    
+    getRenderer : function(col) {
+        return this.config[col].renderer || Ext.grid.ColumnModel.defaultRenderer;
+    },
+
+    getRendererScope : function(col) {
+        return this.config[col].scope;
+    },
+
+    
+    setRenderer : function(col, fn) {
+        this.config[col].renderer = fn;
+    },
+
+    
+    getColumnWidth : function(col) {
+        var width = this.config[col].width;
+        if(typeof width != 'number'){
+            width = this.defaultWidth;
+        }
+        return width;
+    },
+
+    
+    setColumnWidth : function(col, width, suppressEvent) {
+        this.config[col].width = width;
+        this.totalWidth = null;
+        
+        if (!suppressEvent) {
+             this.fireEvent("widthchange", this, col, width);
+        }
+    },
+
+    
+    getTotalWidth : function(includeHidden) {
+        if (!this.totalWidth) {
+            this.totalWidth = 0;
+            for (var i = 0, len = this.config.length; i < len; i++) {
+                if (includeHidden || !this.isHidden(i)) {
+                    this.totalWidth += this.getColumnWidth(i);
+                }
+            }
+        }
+        return this.totalWidth;
+    },
+
+    
+    getColumnHeader : function(col) {
+        return this.config[col].header;
+    },
+
+    
+    setColumnHeader : function(col, header) {
+        this.config[col].header = header;
+        this.fireEvent("headerchange", this, col, header);
+    },
+
+    
+    getColumnTooltip : function(col) {
+            return this.config[col].tooltip;
+    },
+    
+    setColumnTooltip : function(col, tooltip) {
+            this.config[col].tooltip = tooltip;
+    },
+
+    
+    getDataIndex : function(col) {
+        return this.config[col].dataIndex;
+    },
+
+    
+    setDataIndex : function(col, dataIndex) {
+        this.config[col].dataIndex = dataIndex;
+    },
+
+    
+    findColumnIndex : function(dataIndex) {
+        var c = this.config;
+        for(var i = 0, len = c.length; i < len; i++){
+            if(c[i].dataIndex == dataIndex){
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    
+    isCellEditable : function(colIndex, rowIndex) {
+        var c = this.config[colIndex],
+            ed = c.editable;
+
+        
+        return !!(ed || (!Ext.isDefined(ed) && c.editor));
+    },
+
+    
+    getCellEditor : function(colIndex, rowIndex) {
+        return this.config[colIndex].getCellEditor(rowIndex);
+    },
+
+    
+    setEditable : function(col, editable) {
+        this.config[col].editable = editable;
+    },
+
+    
+    isHidden : function(colIndex) {
+        return !!this.config[colIndex].hidden; 
+    },
+
+    
+    isFixed : function(colIndex) {
+        return !!this.config[colIndex].fixed;
+    },
+
+    
+    isResizable : function(colIndex) {
+        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
+    },
+    
+    
+    setHidden : function(colIndex, hidden) {
+        var c = this.config[colIndex];
+        if(c.hidden !== hidden){
+            c.hidden = hidden;
+            this.totalWidth = null;
+            this.fireEvent("hiddenchange", this, colIndex, hidden);
+        }
+    },
+
+    
+    setEditor : function(col, editor) {
+        this.config[col].setEditor(editor);
+    },
+
+    
+    destroy : function() {
+        var length = this.config.length,
+            i = 0;
+
+        for (; i < length; i++){
+            this.config[i].destroy(); 
+        }
+        delete this.config;
+        delete this.lookup;
+        this.purgeListeners();
+    },
+
+    
+    setState : function(col, state) {
+        state = Ext.applyIf(state, this.defaults);
+        Ext.apply(this.config[col], state);
+    }
+});
+
+
+Ext.grid.ColumnModel.defaultRenderer = function(value) {
+    if (typeof value == "string" && value.length < 1) {
+        return "&#160;";
+    }
+    return value;
+};
+Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
+    
+
+    constructor : function(){
+        this.locked = false;
+        Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
+    },
+
+    
+    init : function(grid){
+        this.grid = grid;
+        if(this.lockOnInit){
+            delete this.lockOnInit;
+            this.locked = false;
+            this.lock();
+        }
+        this.initEvents();
+    },
+
+    
+    lock : function(){
+        if(!this.locked){
+            this.locked = true;
+            
+            var g = this.grid;
+            if(g){
+                g.getView().on({
+                    scope: this,
+                    beforerefresh: this.sortUnLock,
+                    refresh: this.sortLock
+                });
+            }else{
+                this.lockOnInit = true;
+            }
+        }
+    },
+
+    
+    sortLock : function() {
+        this.locked = true;
+    },
+
+    
+    sortUnLock : function() {
+        this.locked = false;
+    },
+
+    
+    unlock : function(){
+        if(this.locked){
+            this.locked = false;
+            var g = this.grid,
+                gv;
+                
+            
+            if(g){
+                gv = g.getView();
+                gv.un('beforerefresh', this.sortUnLock, this);
+                gv.un('refresh', this.sortLock, this);    
+            }else{
+                delete this.lockOnInit;
+            }
+        }
+    },
+
+    
+    isLocked : function(){
+        return this.locked;
+    },
+
+    destroy: function(){
+        this.unlock();
+        this.purgeListeners();
+    }
+});
+Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
+    
+    singleSelect : false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+        this.selections = new Ext.util.MixedCollection(false, function(o){
+            return o.id;
+        });
+
+        this.last = false;
+        this.lastActive = false;
+
+        this.addEvents(
+	        
+	        'selectionchange',
+	        
+	        'beforerowselect',
+	        
+	        'rowselect',
+	        
+	        'rowdeselect'
+        );
+        Ext.grid.RowSelectionModel.superclass.constructor.call(this);
+    },
+
+    
+    
+    initEvents : function(){
+
+        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
+            this.grid.on('rowmousedown', this.handleMouseDown, this);
+        }
+
+        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
+            up: this.onKeyPress, 
+            down: this.onKeyPress,
+            scope: this
+        });
+
+        this.grid.getView().on({
+            scope: this,
+            refresh: this.onRefresh,
+            rowupdated: this.onRowUpdated,
+            rowremoved: this.onRemove
+        });
+    },
+    
+    onKeyPress : function(e, name){
+        var up = name == 'up',
+            method = up ? 'selectPrevious' : 'selectNext',
+            add = up ? -1 : 1,
+            last;
+        if(!e.shiftKey || this.singleSelect){
+            this[method](false);
+        }else if(this.last !== false && this.lastActive !== false){
+            last = this.last;
+            this.selectRange(this.last,  this.lastActive + add);
+            this.grid.getView().focusRow(this.lastActive);
+            if(last !== false){
+                this.last = last;
+            }
+        }else{
+           this.selectFirstRow();
+        }
+    },
+
+    
+    onRefresh : function(){
+        var ds = this.grid.store,
+            s = this.getSelections(),
+            i = 0,
+            len = s.length, 
+            index, r;
+            
+        this.silent = true;
+        this.clearSelections(true);
+        for(; i < len; i++){
+            r = s[i];
+            if((index = ds.indexOfId(r.id)) != -1){
+                this.selectRow(index, true);
+            }
+        }
+        if(s.length != this.selections.getCount()){
+            this.fireEvent('selectionchange', this);
+        }
+        this.silent = false;
+    },
+
+    
+    onRemove : function(v, index, r){
+        if(this.selections.remove(r) !== false){
+            this.fireEvent('selectionchange', this);
+        }
+    },
+
+    
+    onRowUpdated : function(v, index, r){
+        if(this.isSelected(r)){
+            v.onRowSelect(index);
+        }
+    },
+
+    
+    selectRecords : function(records, keepExisting){
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        var ds = this.grid.store,
+            i = 0,
+            len = records.length;
+        for(; i < len; i++){
+            this.selectRow(ds.indexOf(records[i]), true);
+        }
+    },
+
+    
+    getCount : function(){
+        return this.selections.length;
+    },
+
+    
+    selectFirstRow : function(){
+        this.selectRow(0);
+    },
+
+    
+    selectLastRow : function(keepExisting){
+        this.selectRow(this.grid.store.getCount() - 1, keepExisting);
+    },
+
+    
+    selectNext : function(keepExisting){
+        if(this.hasNext()){
+            this.selectRow(this.last+1, keepExisting);
+            this.grid.getView().focusRow(this.last);
+            return true;
+        }
+        return false;
+    },
+
+    
+    selectPrevious : function(keepExisting){
+        if(this.hasPrevious()){
+            this.selectRow(this.last-1, keepExisting);
+            this.grid.getView().focusRow(this.last);
+            return true;
+        }
+        return false;
+    },
+
+    
+    hasNext : function(){
+        return this.last !== false && (this.last+1) < this.grid.store.getCount();
+    },
+
+    
+    hasPrevious : function(){
+        return !!this.last;
+    },
+
+
+    
+    getSelections : function(){
+        return [].concat(this.selections.items);
+    },
+
+    
+    getSelected : function(){
+        return this.selections.itemAt(0);
+    },
+
+    
+    each : function(fn, scope){
+        var s = this.getSelections(),
+            i = 0,
+            len = s.length;
+            
+        for(; i < len; i++){
+            if(fn.call(scope || this, s[i], i) === false){
+                return false;
+            }
+        }
+        return true;
+    },
+
+    
+    clearSelections : function(fast){
+        if(this.isLocked()){
+            return;
+        }
+        if(fast !== true){
+            var ds = this.grid.store,
+                s = this.selections;
+            s.each(function(r){
+                this.deselectRow(ds.indexOfId(r.id));
+            }, this);
+            s.clear();
+        }else{
+            this.selections.clear();
+        }
+        this.last = false;
+    },
+
+
+    
+    selectAll : function(){
+        if(this.isLocked()){
+            return;
+        }
+        this.selections.clear();
+        for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
+            this.selectRow(i, true);
+        }
+    },
+
+    
+    hasSelection : function(){
+        return this.selections.length > 0;
+    },
+
+    
+    isSelected : function(index){
+        var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
+        return (r && this.selections.key(r.id) ? true : false);
+    },
+
+    
+    isIdSelected : function(id){
+        return (this.selections.key(id) ? true : false);
+    },
+
+    
+    handleMouseDown : function(g, rowIndex, e){
+        if(e.button !== 0 || this.isLocked()){
+            return;
+        }
+        var view = this.grid.getView();
+        if(e.shiftKey && !this.singleSelect && this.last !== false){
+            var last = this.last;
+            this.selectRange(last, rowIndex, e.ctrlKey);
+            this.last = last; 
+            view.focusRow(rowIndex);
+        }else{
+            var isSelected = this.isSelected(rowIndex);
+            if(e.ctrlKey && isSelected){
+                this.deselectRow(rowIndex);
+            }else if(!isSelected || this.getCount() > 1){
+                this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
+                view.focusRow(rowIndex);
+            }
+        }
+    },
+
+    
+    selectRows : function(rows, keepExisting){
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        for(var i = 0, len = rows.length; i < len; i++){
+            this.selectRow(rows[i], true);
+        }
+    },
+
+    
+    selectRange : function(startRow, endRow, keepExisting){
+        var i;
+        if(this.isLocked()){
+            return;
+        }
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        if(startRow <= endRow){
+            for(i = startRow; i <= endRow; i++){
+                this.selectRow(i, true);
+            }
+        }else{
+            for(i = startRow; i >= endRow; i--){
+                this.selectRow(i, true);
+            }
+        }
+    },
+
+    
+    deselectRange : function(startRow, endRow, preventViewNotify){
+        if(this.isLocked()){
+            return;
+        }
+        for(var i = startRow; i <= endRow; i++){
+            this.deselectRow(i, preventViewNotify);
+        }
+    },
+
+    
+    selectRow : function(index, keepExisting, preventViewNotify){
+        if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
+            return;
+        }
+        var r = this.grid.store.getAt(index);
+        if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
+            if(!keepExisting || this.singleSelect){
+                this.clearSelections();
+            }
+            this.selections.add(r);
+            this.last = this.lastActive = index;
+            if(!preventViewNotify){
+                this.grid.getView().onRowSelect(index);
+            }
+            if(!this.silent){
+                this.fireEvent('rowselect', this, index, r);
+                this.fireEvent('selectionchange', this);
+            }
+        }
+    },
+
+    
+    deselectRow : function(index, preventViewNotify){
+        if(this.isLocked()){
+            return;
+        }
+        if(this.last == index){
+            this.last = false;
+        }
+        if(this.lastActive == index){
+            this.lastActive = false;
+        }
+        var r = this.grid.store.getAt(index);
+        if(r){
+            this.selections.remove(r);
+            if(!preventViewNotify){
+                this.grid.getView().onRowDeselect(index);
+            }
+            this.fireEvent('rowdeselect', this, index, r);
+            this.fireEvent('selectionchange', this);
+        }
+    },
+
+    
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    },
+
+    
+    onEditorKey : function(field, e){
+        var k = e.getKey(), 
+            newCell, 
+            g = this.grid, 
+            last = g.lastEdit,
+            ed = g.activeEditor,
+            shift = e.shiftKey,
+            ae, last, r, c;
+            
+        if(k == e.TAB){
+            e.stopEvent();
+            ed.completeEdit();
+            if(shift){
+                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ENTER){
+            if(this.moveEditorOnEnter !== false){
+                if(shift){
+                    newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
+                }else{
+                    newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
+                }
+            }
+        }
+        if(newCell){
+            r = newCell[0];
+            c = newCell[1];
+
+            this.onEditorSelect(r, last.row);
+
+            if(g.isEditor && g.editing){ 
+                ae = g.activeEditor;
+                if(ae && ae.field.triggerBlur){
+                    
+                    ae.field.triggerBlur();
+                }
+            }
+            g.startEditing(r, c);
+        }
+    },
+    
+    onEditorSelect: function(row, lastRow){
+        if(lastRow != row){
+            this.selectRow(row); 
+        }
+    },
+    
+    destroy : function(){
+        Ext.destroy(this.rowNav);
+        this.rowNav = null;
+        Ext.grid.RowSelectionModel.superclass.destroy.call(this);
+    }
+});
+
+Ext.grid.Column = Ext.extend(Ext.util.Observable, {
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    isColumn : true,
+
+    constructor : function(config){
+        Ext.apply(this, config);
+
+        if(Ext.isString(this.renderer)){
+            this.renderer = Ext.util.Format[this.renderer];
+        }else if(Ext.isObject(this.renderer)){
+            this.scope = this.renderer.scope;
+            this.renderer = this.renderer.fn;
+        }
+        if(!this.scope){
+            this.scope = this;
+        }
+
+        var ed = this.editor;
+        delete this.editor;
+        this.setEditor(ed);
+        this.addEvents(
+            
+            'click',
+            
+            'contextmenu',
+            
+            'dblclick',
+            
+            'mousedown'
+        );
+        Ext.grid.Column.superclass.constructor.call(this);
+    },
+
+    
+    processEvent : function(name, e, grid, rowIndex, colIndex){
+        return this.fireEvent(name, this, grid, rowIndex, e);
+    },
+
+    
+    destroy: function() {
+        if(this.setEditor){
+            this.setEditor(null);
+        }
+        this.purgeListeners();
+    },
+
+    
+    renderer : function(value){
+        return value;
+    },
+
+    
+    getEditor: function(rowIndex){
+        return this.editable !== false ? this.editor : null;
+    },
+
+    
+    setEditor : function(editor){
+        var ed = this.editor;
+        if(ed){
+            if(ed.gridEditor){
+                ed.gridEditor.destroy();
+                delete ed.gridEditor;
+            }else{
+                ed.destroy();
+            }
+        }
+        this.editor = null;
+        if(editor){
+            
+            if(!editor.isXType){
+                editor = Ext.create(editor, 'textfield');
+            }
+            this.editor = editor;
+        }
+    },
+
+    
+    getCellEditor: function(rowIndex){
+        var ed = this.getEditor(rowIndex);
+        if(ed){
+            if(!ed.startEdit){
+                if(!ed.gridEditor){
+                    ed.gridEditor = new Ext.grid.GridEditor(ed);
+                }
+                ed = ed.gridEditor;
+            }
+        }
+        return ed;
+    }
+});
+
+
+Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
+    
+    trueText: 'true',
+    
+    falseText: 'false',
+    
+    undefinedText: '&#160;',
+
+    constructor: function(cfg){
+        Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
+        var t = this.trueText, f = this.falseText, u = this.undefinedText;
+        this.renderer = function(v){
+            if(v === undefined){
+                return u;
+            }
+            if(!v || v === 'false'){
+                return f;
+            }
+            return t;
+        };
+    }
+});
+
+
+Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
+    
+    format : '0,000.00',
+    constructor: function(cfg){
+        Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
+        this.renderer = Ext.util.Format.numberRenderer(this.format);
+    }
+});
+
+
+Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
+    
+    format : 'm/d/Y',
+    constructor: function(cfg){
+        Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
+        this.renderer = Ext.util.Format.dateRenderer(this.format);
+    }
+});
+
+
+Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
+    
+    constructor: function(cfg){
+        Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
+        var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
+        this.renderer = function(value, p, r){
+            return tpl.apply(r.data);
+        };
+        this.tpl = tpl;
+    }
+});
+
+
+Ext.grid.ActionColumn = Ext.extend(Ext.grid.Column, {
+    
+    
+    
+    
+    
+    
+    
+    
+    header: '&#160;',
+
+    actionIdRe: /x-action-col-(\d+)/,
+    
+    
+    altText: '',
+
+    constructor: function(cfg) {
+        var me = this,
+            items = cfg.items || (me.items = [me]),
+            l = items.length,
+            i,
+            item;
+
+        Ext.grid.ActionColumn.superclass.constructor.call(me, cfg);
+
+
+
+        me.renderer = function(v, meta) {
+
+            v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
+
+            meta.css += ' x-action-col-cell';
+            for (i = 0; i < l; i++) {
+                item = items[i];
+                v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
+                    '" class="x-action-col-icon x-action-col-' + String(i) + ' ' + (item.iconCls || '') +
+                    ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||this.scope||this, arguments) : '') + '"' +
+                    ((item.tooltip) ? ' ext:qtip="' + item.tooltip + '"' : '') + ' />';
+            }
+            return v;
+        };
+    },
+
+    destroy: function() {
+        delete this.items;
+        delete this.renderer;
+        return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments);
+    },
+
+    
+    processEvent : function(name, e, grid, rowIndex, colIndex){
+        var m = e.getTarget().className.match(this.actionIdRe),
+            item, fn;
+        if (m && (item = this.items[parseInt(m[1], 10)])) {
+            if (name == 'click') {
+                (fn = item.handler || this.handler) && fn.call(item.scope||this.scope||this, grid, rowIndex, colIndex, item, e);
+            } else if ((name == 'mousedown') && (item.stopSelection !== false)) {
+                return false;
+            }
+        }
+        return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
+    }
+});
+
+
+Ext.grid.Column.types = {
+    gridcolumn : Ext.grid.Column,
+    booleancolumn: Ext.grid.BooleanColumn,
+    numbercolumn: Ext.grid.NumberColumn,
+    datecolumn: Ext.grid.DateColumn,
+    templatecolumn: Ext.grid.TemplateColumn,
+    actioncolumn: Ext.grid.ActionColumn
+};
+Ext.grid.RowNumberer = Ext.extend(Object, {
+    
+    header: "",
+    
+    width: 23,
+    
+    sortable: false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+        if(this.rowspan){
+            this.renderer = this.renderer.createDelegate(this);
+        }
+    },
+
+    
+    fixed:true,
+    hideable: false,
+    menuDisabled:true,
+    dataIndex: '',
+    id: 'numberer',
+    rowspan: undefined,
+
+    
+    renderer : function(v, p, record, rowIndex){
+        if(this.rowspan){
+            p.cellAttr = 'rowspan="'+this.rowspan+'"';
+        }
+        return rowIndex+1;
+    }
+});
+Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
+
+    
+    
+    header : '<div class="x-grid3-hd-checker">&#160;</div>',
+    
+    width : 20,
+    
+    sortable : false,
+
+    
+    menuDisabled : true,
+    fixed : true,
+    hideable: false,
+    dataIndex : '',
+    id : 'checker',
+    isColumn: true, 
+
+    constructor : function(){
+        Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
+        if(this.checkOnly){
+            this.handleMouseDown = Ext.emptyFn;
+        }
+    },
+
+    
+    initEvents : function(){
+        Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
+        this.grid.on('render', function(){
+            Ext.fly(this.grid.getView().innerHd).on('mousedown', this.onHdMouseDown, this);
+        }, this);
+    },
+
+    
+    processEvent : function(name, e, grid, rowIndex, colIndex){
+        if (name == 'mousedown') {
+            this.onMouseDown(e, e.getTarget());
+            return false;
+        } else {
+            return Ext.grid.Column.prototype.processEvent.apply(this, arguments);
+        }
+    },
+
+    
+    onMouseDown : function(e, t){
+        if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
+            e.stopEvent();
+            var row = e.getTarget('.x-grid3-row');
+            if(row){
+                var index = row.rowIndex;
+                if(this.isSelected(index)){
+                    this.deselectRow(index);
+                }else{
+                    this.selectRow(index, true);
+                    this.grid.getView().focusRow(index);
+                }
+            }
+        }
+    },
+
+    
+    onHdMouseDown : function(e, t) {
+        if(t.className == 'x-grid3-hd-checker'){
+            e.stopEvent();
+            var hd = Ext.fly(t.parentNode);
+            var isChecked = hd.hasClass('x-grid3-hd-checker-on');
+            if(isChecked){
+                hd.removeClass('x-grid3-hd-checker-on');
+                this.clearSelections();
+            }else{
+                hd.addClass('x-grid3-hd-checker-on');
+                this.selectAll();
+            }
+        }
+    },
+
+    
+    renderer : function(v, p, record){
+        return '<div class="x-grid3-row-checker">&#160;</div>';
+    },
+    
+    onEditorSelect: function(row, lastRow){
+        if(lastRow != row && !this.checkOnly){
+            this.selectRow(row); 
+        }
+    }
+});
+Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+
+	    this.selection = null;
+	
+	    this.addEvents(
+	        
+	        "beforecellselect",
+	        
+	        "cellselect",
+	        
+	        "selectionchange"
+	    );
+	
+	    Ext.grid.CellSelectionModel.superclass.constructor.call(this);
+    },
+
+    
+    initEvents : function(){
+        this.grid.on('cellmousedown', this.handleMouseDown, this);
+        this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);
+        this.grid.getView().on({
+            scope: this,
+            refresh: this.onViewChange,
+            rowupdated: this.onRowUpdated,
+            beforerowremoved: this.clearSelections,
+            beforerowsinserted: this.clearSelections
+        });
+        if(this.grid.isEditor){
+            this.grid.on('beforeedit', this.beforeEdit,  this);
+        }
+    },
+
+	
+    beforeEdit : function(e){
+        this.select(e.row, e.column, false, true, e.record);
+    },
+
+	
+    onRowUpdated : function(v, index, r){
+        if(this.selection && this.selection.record == r){
+            v.onCellSelect(index, this.selection.cell[1]);
+        }
+    },
+
+	
+    onViewChange : function(){
+        this.clearSelections(true);
+    },
+
+	
+    getSelectedCell : function(){
+        return this.selection ? this.selection.cell : null;
+    },
+
+    
+    clearSelections : function(preventNotify){
+        var s = this.selection;
+        if(s){
+            if(preventNotify !== true){
+                this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
+            }
+            this.selection = null;
+            this.fireEvent("selectionchange", this, null);
+        }
+    },
+
+    
+    hasSelection : function(){
+        return this.selection ? true : false;
+    },
+
+    
+    handleMouseDown : function(g, row, cell, e){
+        if(e.button !== 0 || this.isLocked()){
+            return;
+        }
+        this.select(row, cell);
+    },
+
+    
+    select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
+        if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
+            this.clearSelections();
+            r = r || this.grid.store.getAt(rowIndex);
+            this.selection = {
+                record : r,
+                cell : [rowIndex, colIndex]
+            };
+            if(!preventViewNotify){
+                var v = this.grid.getView();
+                v.onCellSelect(rowIndex, colIndex);
+                if(preventFocus !== true){
+                    v.focusCell(rowIndex, colIndex);
+                }
+            }
+            this.fireEvent("cellselect", this, rowIndex, colIndex);
+            this.fireEvent("selectionchange", this, this.selection);
+        }
+    },
+
+	
+    isSelectable : function(rowIndex, colIndex, cm){
+        return !cm.isHidden(colIndex);
+    },
+    
+    
+    onEditorKey: function(field, e){
+        if(e.getKey() == e.TAB){
+            this.handleKeyDown(e);
+        }
+    },
+
+    
+    handleKeyDown : function(e){
+        if(!e.isNavKeyPress()){
+            return;
+        }
+        
+        var k = e.getKey(),
+            g = this.grid,
+            s = this.selection,
+            sm = this,
+            walk = function(row, col, step){
+                return g.walkCells(
+                    row,
+                    col,
+                    step,
+                    g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
+                    sm
+                );
+            },
+            cell, newCell, r, c, ae;
+
+        switch(k){
+            case e.ESC:
+            case e.PAGE_UP:
+            case e.PAGE_DOWN:
+                
+                break;
+            default:
+                
+                e.stopEvent();
+                break;
+        }
+
+        if(!s){
+            cell = walk(0, 0, 1); 
+            if(cell){
+                this.select(cell[0], cell[1]);
+            }
+            return;
+        }
+
+        cell = s.cell;  
+        r = cell[0];    
+        c = cell[1];    
+        
+        switch(k){
+            case e.TAB:
+                if(e.shiftKey){
+                    newCell = walk(r, c - 1, -1);
+                }else{
+                    newCell = walk(r, c + 1, 1);
+                }
+                break;
+            case e.DOWN:
+                newCell = walk(r + 1, c, 1);
+                break;
+            case e.UP:
+                newCell = walk(r - 1, c, -1);
+                break;
+            case e.RIGHT:
+                newCell = walk(r, c + 1, 1);
+                break;
+            case e.LEFT:
+                newCell = walk(r, c - 1, -1);
+                break;
+            case e.ENTER:
+                if (g.isEditor && !g.editing) {
+                    g.startEditing(r, c);
+                    return;
+                }
+                break;
+        }
+
+        if(newCell){
+            
+            r = newCell[0];
+            c = newCell[1];
+
+            this.select(r, c); 
+
+            if(g.isEditor && g.editing){ 
+                ae = g.activeEditor;
+                if(ae && ae.field.triggerBlur){
+                    
+                    ae.field.triggerBlur();
+                }
+                g.startEditing(r, c);
+            }
+        }
+    },
+
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    }
+});
+Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
+    
+    clicksToEdit: 2,
+
+    
+    forceValidation: false,
+
+    
+    isEditor : true,
+    
+    detectEdit: false,
+
+    
+    autoEncode : false,
+
+    
+    
+    trackMouseOver: false, 
+
+    
+    initComponent : function(){
+        Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
+
+        if(!this.selModel){
+            
+            this.selModel = new Ext.grid.CellSelectionModel();
+        }
+
+        this.activeEditor = null;
+
+        this.addEvents(
+            
+            "beforeedit",
+            
+            "afteredit",
+            
+            "validateedit"
+        );
+    },
+
+    
+    initEvents : function(){
+        Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
+
+        this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
+        this.on('columnresize', this.stopEditing, this, [true]);
+
+        if(this.clicksToEdit == 1){
+            this.on("cellclick", this.onCellDblClick, this);
+        }else {
+            var view = this.getView();
+            if(this.clicksToEdit == 'auto' && view.mainBody){
+                view.mainBody.on('mousedown', this.onAutoEditClick, this);
+            }
+            this.on('celldblclick', this.onCellDblClick, this);
+        }
+    },
+
+    onResize : function(){
+        Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
+        var ae = this.activeEditor;
+        if(this.editing && ae){
+            ae.realign(true);
+        }
+    },
+
+    
+    onCellDblClick : function(g, row, col){
+        this.startEditing(row, col);
+    },
+
+    
+    onAutoEditClick : function(e, t){
+        if(e.button !== 0){
+            return;
+        }
+        var row = this.view.findRowIndex(t),
+            col = this.view.findCellIndex(t);
+        if(row !== false && col !== false){
+            this.stopEditing();
+            if(this.selModel.getSelectedCell){ 
+                var sc = this.selModel.getSelectedCell();
+                if(sc && sc[0] === row && sc[1] === col){
+                    this.startEditing(row, col);
+                }
+            }else{
+                if(this.selModel.isSelected(row)){
+                    this.startEditing(row, col);
+                }
+            }
+        }
+    },
+
+    
+    onEditComplete : function(ed, value, startValue){
+        this.editing = false;
+        this.lastActiveEditor = this.activeEditor;
+        this.activeEditor = null;
+
+        var r = ed.record,
+            field = this.colModel.getDataIndex(ed.col);
+        value = this.postEditValue(value, startValue, r, field);
+        if(this.forceValidation === true || String(value) !== String(startValue)){
+            var e = {
+                grid: this,
+                record: r,
+                field: field,
+                originalValue: startValue,
+                value: value,
+                row: ed.row,
+                column: ed.col,
+                cancel:false
+            };
+            if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
+                r.set(field, e.value);
+                delete e.cancel;
+                this.fireEvent("afteredit", e);
+            }
+        }
+        this.view.focusCell(ed.row, ed.col);
+    },
+
+    
+    startEditing : function(row, col){
+        this.stopEditing();
+        if(this.colModel.isCellEditable(col, row)){
+            this.view.ensureVisible(row, col, true);
+            var r = this.store.getAt(row),
+                field = this.colModel.getDataIndex(col),
+                e = {
+                    grid: this,
+                    record: r,
+                    field: field,
+                    value: r.data[field],
+                    row: row,
+                    column: col,
+                    cancel:false
+                };
+            if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
+                this.editing = true;
+                var ed = this.colModel.getCellEditor(col, row);
+                if(!ed){
+                    return;
+                }
+                if(!ed.rendered){
+                    ed.parentEl = this.view.getEditorParent(ed);
+                    ed.on({
+                        scope: this,
+                        render: {
+                            fn: function(c){
+                                c.field.focus(false, true);
+                            },
+                            single: true,
+                            scope: this
+                        },
+                        specialkey: function(field, e){
+                            this.getSelectionModel().onEditorKey(field, e);
+                        },
+                        complete: this.onEditComplete,
+                        canceledit: this.stopEditing.createDelegate(this, [true])
+                    });
+                }
+                Ext.apply(ed, {
+                    row     : row,
+                    col     : col,
+                    record  : r
+                });
+                this.lastEdit = {
+                    row: row,
+                    col: col
+                };
+                this.activeEditor = ed;
+                
+                
+                ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
+                var v = this.preEditValue(r, field);
+                ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
+
+                
+                (function(){
+                    delete ed.selectSameEditor;
+                }).defer(50);
+            }
+        }
+    },
+
+    
+    preEditValue : function(r, field){
+        var value = r.data[field];
+        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
+    },
+
+    
+    postEditValue : function(value, originalValue, r, field){
+        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
+    },
+
+    
+    stopEditing : function(cancel){
+        if(this.editing){
+            
+            var ae = this.lastActiveEditor = this.activeEditor;
+            if(ae){
+                ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
+                this.view.focusCell(ae.row, ae.col);
+            }
+            this.activeEditor = null;
+        }
+        this.editing = false;
+    }
+});
+Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
+
+Ext.grid.GridEditor = function(field, config){
+    Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
+    field.monitorTab = false;
+};
+
+Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
+    alignment: "tl-tl",
+    autoSize: "width",
+    hideEl : false,
+    cls: "x-small-editor x-grid-editor",
+    shim:false,
+    shadow:false
+});
+Ext.grid.PropertyRecord = Ext.data.Record.create([
+    {name:'name',type:'string'}, 'value'
+]);
+
+
+Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(grid, source){
+        this.grid = grid;
+        this.store = new Ext.data.Store({
+            recordType : Ext.grid.PropertyRecord
+        });
+        this.store.on('update', this.onUpdate,  this);
+        if(source){
+            this.setSource(source);
+        }
+        Ext.grid.PropertyStore.superclass.constructor.call(this);    
+    },
+    
+    
+    setSource : function(o){
+        this.source = o;
+        this.store.removeAll();
+        var data = [];
+        for(var k in o){
+            if(this.isEditableValue(o[k])){
+                data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
+            }
+        }
+        this.store.loadRecords({records: data}, {}, true);
+    },
+
+    
+    onUpdate : function(ds, record, type){
+        if(type == Ext.data.Record.EDIT){
+            var v = record.data.value;
+            var oldValue = record.modified.value;
+            if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
+                this.source[record.id] = v;
+                record.commit();
+                this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
+            }else{
+                record.reject();
+            }
+        }
+    },
+
+    
+    getProperty : function(row){
+       return this.store.getAt(row);
+    },
+
+    
+    isEditableValue: function(val){
+        return Ext.isPrimitive(val) || Ext.isDate(val);
+    },
+
+    
+    setValue : function(prop, value, create){
+        var r = this.getRec(prop);
+        if(r){
+            r.set('value', value);
+            this.source[prop] = value;
+        }else if(create){
+            
+            this.source[prop] = value;
+            r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
+            this.store.add(r);
+
+        }
+    },
+    
+    
+    remove : function(prop){
+        var r = this.getRec(prop);
+        if(r){
+            this.store.remove(r);
+            delete this.source[prop];
+        }
+    },
+    
+    
+    getRec : function(prop){
+        return this.store.getById(prop);
+    },
+
+    
+    getSource : function(){
+        return this.source;
+    }
+});
+
+
+Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
+    
+    nameText : 'Name',
+    valueText : 'Value',
+    dateFormat : 'm/j/Y',
+    trueText: 'true',
+    falseText: 'false',
+    
+    constructor : function(grid, store){
+        var g = Ext.grid,
+	        f = Ext.form;
+	        
+	    this.grid = grid;
+	    g.PropertyColumnModel.superclass.constructor.call(this, [
+	        {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
+	        {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
+	    ]);
+	    this.store = store;
+	
+	    var bfield = new f.Field({
+	        autoCreate: {tag: 'select', children: [
+	            {tag: 'option', value: 'true', html: this.trueText},
+	            {tag: 'option', value: 'false', html: this.falseText}
+	        ]},
+	        getValue : function(){
+	            return this.el.dom.value == 'true';
+	        }
+	    });
+	    this.editors = {
+	        'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
+	        'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
+	        'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
+	        'boolean' : new g.GridEditor(bfield, {
+	            autoSize: 'both'
+	        })
+	    };
+	    this.renderCellDelegate = this.renderCell.createDelegate(this);
+	    this.renderPropDelegate = this.renderProp.createDelegate(this);
+    },
+
+    
+    renderDate : function(dateVal){
+        return dateVal.dateFormat(this.dateFormat);
+    },
+
+    
+    renderBool : function(bVal){
+        return this[bVal ? 'trueText' : 'falseText'];
+    },
+
+    
+    isCellEditable : function(colIndex, rowIndex){
+        return colIndex == 1;
+    },
+
+    
+    getRenderer : function(col){
+        return col == 1 ?
+            this.renderCellDelegate : this.renderPropDelegate;
+    },
+
+    
+    renderProp : function(v){
+        return this.getPropertyName(v);
+    },
+
+    
+    renderCell : function(val, meta, rec){
+        var renderer = this.grid.customRenderers[rec.get('name')];
+        if(renderer){
+            return renderer.apply(this, arguments);
+        }
+        var rv = val;
+        if(Ext.isDate(val)){
+            rv = this.renderDate(val);
+        }else if(typeof val == 'boolean'){
+            rv = this.renderBool(val);
+        }
+        return Ext.util.Format.htmlEncode(rv);
+    },
+
+    
+    getPropertyName : function(name){
+        var pn = this.grid.propertyNames;
+        return pn && pn[name] ? pn[name] : name;
+    },
+
+    
+    getCellEditor : function(colIndex, rowIndex){
+        var p = this.store.getProperty(rowIndex),
+            n = p.data.name, 
+            val = p.data.value;
+        if(this.grid.customEditors[n]){
+            return this.grid.customEditors[n];
+        }
+        if(Ext.isDate(val)){
+            return this.editors.date;
+        }else if(typeof val == 'number'){
+            return this.editors.number;
+        }else if(typeof val == 'boolean'){
+            return this.editors['boolean'];
+        }else{
+            return this.editors.string;
+        }
+    },
+
+    
+    destroy : function(){
+        Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
+        this.destroyEditors(this.editors);
+        this.destroyEditors(this.grid.customEditors);
+    },
+    
+    destroyEditors: function(editors){
+        for(var ed in editors){
+            Ext.destroy(editors[ed]);
+        }
+    }
+});
+
+
+Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
+    
+    
+    
+    
+    
+
+    
+    enableColumnMove:false,
+    stripeRows:false,
+    trackMouseOver: false,
+    clicksToEdit:1,
+    enableHdMenu : false,
+    viewConfig : {
+        forceFit:true
+    },
+
+    
+    initComponent : function(){
+        this.customRenderers = this.customRenderers || {};
+        this.customEditors = this.customEditors || {};
+        this.lastEditRow = null;
+        var store = new Ext.grid.PropertyStore(this);
+        this.propStore = store;
+        var cm = new Ext.grid.PropertyColumnModel(this, store);
+        store.store.sort('name', 'ASC');
+        this.addEvents(
+            
+            'beforepropertychange',
+            
+            'propertychange'
+        );
+        this.cm = cm;
+        this.ds = store.store;
+        Ext.grid.PropertyGrid.superclass.initComponent.call(this);
+
+		this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
+            if(colIndex === 0){
+                this.startEditing.defer(200, this, [rowIndex, 1]);
+                return false;
+            }
+        }, this);
+    },
+
+    
+    onRender : function(){
+        Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
+
+        this.getGridEl().addClass('x-props-grid');
+    },
+
+    
+    afterRender: function(){
+        Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
+        if(this.source){
+            this.setSource(this.source);
+        }
+    },
+
+    
+    setSource : function(source){
+        this.propStore.setSource(source);
+    },
+
+    
+    getSource : function(){
+        return this.propStore.getSource();
+    },
+    
+    
+    setProperty : function(prop, value, create){
+        this.propStore.setValue(prop, value, create);    
+    },
+    
+    
+    removeProperty : function(prop){
+        this.propStore.remove(prop);
+    }
+
+    
+    
+    
+    
+});
+Ext.reg("propertygrid", Ext.grid.PropertyGrid);
+
+Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
+
+    
+    groupByText : 'Group By This Field',
+    
+    showGroupsText : 'Show in Groups',
+    
+    hideGroupedColumn : false,
+    
+    showGroupName : true,
+    
+    startCollapsed : false,
+    
+    enableGrouping : true,
+    
+    enableGroupingMenu : true,
+    
+    enableNoGroups : true,
+    
+    emptyGroupText : '(None)',
+    
+    ignoreAdd : false,
+    
+    groupTextTpl : '{text}',
+
+    
+    groupMode: 'value',
+
+    
+    
+    
+    cancelEditOnToggle: true,
+
+    
+    initTemplates : function(){
+        Ext.grid.GroupingView.superclass.initTemplates.call(this);
+        this.state = {};
+
+        var sm = this.grid.getSelectionModel();
+        sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
+                this.onBeforeRowSelect, this);
+
+        if(!this.startGroup){
+            this.startGroup = new Ext.XTemplate(
+                '<div id="{groupId}" class="x-grid-group {cls}">',
+                    '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
+                    '<div id="{groupId}-bd" class="x-grid-group-body">'
+            );
+        }
+        this.startGroup.compile();
+
+        if (!this.endGroup) {
+            this.endGroup = '</div></div>';
+        }
+    },
+
+    
+    findGroup : function(el){
+        return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
+    },
+
+    
+    getGroups : function(){
+        return this.hasRows() ? this.mainBody.dom.childNodes : [];
+    },
+
+    
+    onAdd : function(ds, records, index) {
+        if (this.canGroup() && !this.ignoreAdd) {
+            var ss = this.getScrollState();
+            this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
+            this.refresh();
+            this.restoreScroll(ss);
+            this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
+        } else if (!this.canGroup()) {
+            Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
+        }
+    },
+
+    
+    onRemove : function(ds, record, index, isUpdate){
+        Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
+        var g = document.getElementById(record._groupId);
+        if(g && g.childNodes[1].childNodes.length < 1){
+            Ext.removeNode(g);
+        }
+        this.applyEmptyText();
+    },
+
+    
+    refreshRow : function(record){
+        if(this.ds.getCount()==1){
+            this.refresh();
+        }else{
+            this.isUpdating = true;
+            Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
+            this.isUpdating = false;
+        }
+    },
+
+    
+    beforeMenuShow : function(){
+        var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
+        if((item = items.get('groupBy'))){
+            item.setDisabled(disabled);
+        }
+        if((item = items.get('showGroups'))){
+            item.setDisabled(disabled);
+            item.setChecked(this.canGroup(), true);
+        }
+    },
+
+    
+    renderUI : function(){
+        var markup = Ext.grid.GroupingView.superclass.renderUI.call(this);
+
+        if(this.enableGroupingMenu && this.hmenu){
+            this.hmenu.add('-',{
+                itemId:'groupBy',
+                text: this.groupByText,
+                handler: this.onGroupByClick,
+                scope: this,
+                iconCls:'x-group-by-icon'
+            });
+            if(this.enableNoGroups){
+                this.hmenu.add({
+                    itemId:'showGroups',
+                    text: this.showGroupsText,
+                    checked: true,
+                    checkHandler: this.onShowGroupsClick,
+                    scope: this
+                });
+            }
+            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
+        }
+        return markup;
+    },
+
+    processEvent: function(name, e){
+        Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
+        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
+        if(hd){
+            
+            var field = this.getGroupField(),
+                prefix = this.getPrefix(field),
+                groupValue = hd.id.substring(prefix.length),
+                emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
+
+            
+            groupValue = groupValue.substr(0, groupValue.length - 3);
+            
+            
+            if(groupValue || emptyRe.test(hd.id)){
+                this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
+            }
+            if(name == 'mousedown' && e.button == 0){
+                this.toggleGroup(hd.parentNode);
+            }
+        }
+
+    },
+
+    
+    onGroupByClick : function(){
+        var grid = this.grid;
+        this.enableGrouping = true;
+        grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
+        grid.fireEvent('groupchange', grid, grid.store.getGroupState());
+        this.beforeMenuShow(); 
+        this.refresh();
+    },
+
+    
+    onShowGroupsClick : function(mi, checked){
+        this.enableGrouping = checked;
+        if(checked){
+            this.onGroupByClick();
+        }else{
+            this.grid.store.clearGrouping();
+            this.grid.fireEvent('groupchange', this, null);
+        }
+    },
+
+    
+    toggleRowIndex : function(rowIndex, expanded){
+        if(!this.canGroup()){
+            return;
+        }
+        var row = this.getRow(rowIndex);
+        if(row){
+            this.toggleGroup(this.findGroup(row), expanded);
+        }
+    },
+
+    
+    toggleGroup : function(group, expanded){
+        var gel = Ext.get(group),
+            id = Ext.util.Format.htmlEncode(gel.id);
+ 
+        expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
+        if(this.state[id] !== expanded){
+            if (this.cancelEditOnToggle !== false) {
+                this.grid.stopEditing(true);
+            }
+            this.state[id] = expanded;
+            gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
+        }
+    },
+
+    
+    toggleAllGroups : function(expanded){
+        var groups = this.getGroups();
+        for(var i = 0, len = groups.length; i < len; i++){
+            this.toggleGroup(groups[i], expanded);
+        }
+    },
+
+    
+    expandAllGroups : function(){
+        this.toggleAllGroups(true);
+    },
+
+    
+    collapseAllGroups : function(){
+        this.toggleAllGroups(false);
+    },
+
+    
+    getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
+        var column = this.cm.config[colIndex],
+            g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v);
+        if(g === '' || g === '&#160;'){
+            g = column.emptyGroupText || this.emptyGroupText;
+        }
+        return g;
+    },
+
+    
+    getGroupField : function(){
+        return this.grid.store.getGroupState();
+    },
+
+    
+    afterRender : function(){
+        if(!this.ds || !this.cm){
+            return;
+        }
+        Ext.grid.GroupingView.superclass.afterRender.call(this);
+        if(this.grid.deferRowRender){
+            this.updateGroupWidths();
+        }
+    },
+    
+    afterRenderUI: function () {
+        Ext.grid.GroupingView.superclass.afterRenderUI.call(this);
+
+        if (this.enableGroupingMenu && this.hmenu) {
+            this.hmenu.add('-',{
+                itemId:'groupBy',
+                text: this.groupByText,
+                handler: this.onGroupByClick,
+                scope: this,
+                iconCls:'x-group-by-icon'
+            });
+            
+            if (this.enableNoGroups) {
+                this.hmenu.add({
+                    itemId:'showGroups',
+                    text: this.showGroupsText,
+                    checked: true,
+                    checkHandler: this.onShowGroupsClick,
+                    scope: this
+                });
+            }
+            
+            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
+        }
+    },
+
+    
+    renderRows : function(){
+        var groupField = this.getGroupField();
+        var eg = !!groupField;
+        
+        if(this.hideGroupedColumn) {
+            var colIndex = this.cm.findColumnIndex(groupField),
+                hasLastGroupField = Ext.isDefined(this.lastGroupField);
+            if(!eg && hasLastGroupField){
+                this.mainBody.update('');
+                this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
+                delete this.lastGroupField;
+            }else if (eg && !hasLastGroupField){
+                this.lastGroupField = groupField;
+                this.cm.setHidden(colIndex, true);
+            }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
+                this.mainBody.update('');
+                var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
+                this.cm.setHidden(oldIndex, false);
+                this.lastGroupField = groupField;
+                this.cm.setHidden(colIndex, true);
+            }
+        }
+        return Ext.grid.GroupingView.superclass.renderRows.apply(
+                    this, arguments);
+    },
+
+    
+    doRender : function(cs, rs, ds, startRow, colCount, stripe){
+        if(rs.length < 1){
+            return '';
+        }
+
+        if(!this.canGroup() || this.isUpdating){
+            return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
+        }
+
+        var groupField = this.getGroupField(),
+            colIndex = this.cm.findColumnIndex(groupField),
+            g,
+            gstyle = 'width:' + this.getTotalWidth() + ';',
+            cfg = this.cm.config[colIndex],
+            groupRenderer = cfg.groupRenderer || cfg.renderer,
+            prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
+            groups = [],
+            curGroup, i, len, gid;
+
+        for(i = 0, len = rs.length; i < len; i++){
+            var rowIndex = startRow + i,
+                r = rs[i],
+                gvalue = r.data[groupField];
+
+                g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
+            if(!curGroup || curGroup.group != g){
+                gid = this.constructId(gvalue, groupField, colIndex);
+                
+                
+                this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
+                curGroup = {
+                    group: g,
+                    gvalue: gvalue,
+                    text: prefix + g,
+                    groupId: gid,
+                    startRow: rowIndex,
+                    rs: [r],
+                    cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
+                    style: gstyle
+                };
+                groups.push(curGroup);
+            }else{
+                curGroup.rs.push(r);
+            }
+            r._groupId = gid;
+        }
+
+        var buf = [];
+        for(i = 0, len = groups.length; i < len; i++){
+            g = groups[i];
+            this.doGroupStart(buf, g, cs, ds, colCount);
+            buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
+                    this, cs, g.rs, ds, g.startRow, colCount, stripe);
+
+            this.doGroupEnd(buf, g, cs, ds, colCount);
+        }
+        return buf.join('');
+    },
+
+    
+    getGroupId : function(value){
+        var field = this.getGroupField();
+        return this.constructId(value, field, this.cm.findColumnIndex(field));
+    },
+
+    
+    constructId : function(value, field, idx){
+        var cfg = this.cm.config[idx],
+            groupRenderer = cfg.groupRenderer || cfg.renderer,
+            val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
+
+        return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
+    },
+
+    
+    canGroup  : function(){
+        return this.enableGrouping && !!this.getGroupField();
+    },
+
+    
+    getPrefix: function(field){
+        return this.grid.getGridEl().id + '-gp-' + field + '-';
+    },
+
+    
+    doGroupStart : function(buf, g, cs, ds, colCount){
+        buf[buf.length] = this.startGroup.apply(g);
+    },
+
+    
+    doGroupEnd : function(buf, g, cs, ds, colCount){
+        buf[buf.length] = this.endGroup;
+    },
+
+    
+    getRows : function(){
+        if(!this.canGroup()){
+            return Ext.grid.GroupingView.superclass.getRows.call(this);
+        }
+        var r = [],
+            gs = this.getGroups(),
+            g,
+            i = 0,
+            len = gs.length,
+            j,
+            jlen;
+        for(; i < len; ++i){
+            g = gs[i].childNodes[1];
+            if(g){
+                g = g.childNodes;
+                for(j = 0, jlen = g.length; j < jlen; ++j){
+                    r[r.length] = g[j];
+                }
+            }
+        }
+        return r;
+    },
+
+    
+    updateGroupWidths : function(){
+        if(!this.canGroup() || !this.hasRows()){
+            return;
+        }
+        var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
+        var gs = this.getGroups();
+        for(var i = 0, len = gs.length; i < len; i++){
+            gs[i].firstChild.style.width = tw;
+        }
+    },
+
+    
+    onColumnWidthUpdated : function(col, w, tw){
+        Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
+        this.updateGroupWidths();
+    },
+
+    
+    onAllColumnWidthsUpdated : function(ws, tw){
+        Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
+        this.updateGroupWidths();
+    },
+
+    
+    onColumnHiddenUpdated : function(col, hidden, tw){
+        Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
+        this.updateGroupWidths();
+    },
+
+    
+    onLayout : function(){
+        this.updateGroupWidths();
+    },
+
+    
+    onBeforeRowSelect : function(sm, rowIndex){
+        this.toggleRowIndex(rowIndex, true);
+    }
+});
+
+Ext.grid.GroupingView.GROUP_ID = 1000;
diff --git a/src/main/webapp/lib/ext-3.4.0/ext-all.js b/src/main/webapp/lib/ext-3.4.0/ext-all.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b0034a5954a38fc7de210d6b7d3ddc045b7bf3f
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/ext-all.js
@@ -0,0 +1,11 @@
+/*
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+(function(){var h=Ext.util,j=Ext.each,g=true,i=false;h.Observable=function(){var k=this,l=k.events;if(k.listeners){k.on(k.listeners);delete k.listeners}k.events=l||{}};h.Observable.prototype={filterOptRe:/^(?:scope|delay|buffer|single)$/,fireEvent:function(){var k=Array.prototype.slice.call(arguments,0),m=k[0].toLowerCase(),n=this,l=g,p=n.events[m],s,o,r;if(n.eventsSuspended===g){if(o=n.eventQueue){o.push(k)}}else{if(typeof p=="object"){if(p.bubble){if(p.fire.apply(p,k.slice(1))===i){return i}r=n.getBubbleTarget&&n.getBubbleTarget();if(r&&r.enableBubble){s=r.events[m];if(!s||typeof s!="object"||!s.bubble){r.enableBubble(m)}return r.fireEvent.apply(r,k)}}else{k.shift();l=p.fire.apply(p,k)}}}return l},addListener:function(k,m,l,r){var n=this,q,s,p;if(typeof k=="object"){r=k;for(q in r){s=r[q];if(!n.filterOptRe.test(q)){n.addListener(q,s.fn||s,s.scope||r.scope,s.fn?s:r)}}}else{k=k.toLowerCase();p=n.events[k]||g;if(typeof p=="boolean"){n.events[k]=p=new h.Event(n,k)}p.addListener(m,l,typeof r=="object"?r:{})}},removeListener:function(k,m,l){var n=this.events[k.toLowerCase()];if(typeof n=="object"){n.removeListener(m,l)}},purgeListeners:function(){var m=this.events,k,l;for(l in m){k=m[l];if(typeof k=="object"){k.clearListeners()}}},addEvents:function(n){var m=this;m.events=m.events||{};if(typeof n=="string"){var k=arguments,l=k.length;while(l--){m.events[k[l]]=m.events[k[l]]||g}}else{Ext.applyIf(m.events,n)}},hasListener:function(k){var l=this.events[k.toLowerCase()];return typeof l=="object"&&l.listeners.length>0},suspendEvents:function(k){this.eventsSuspended=g;if(k&&!this.eventQueue){this.eventQueue=[]}},resumeEvents:function(){var k=this,l=k.eventQueue||[];k.eventsSuspended=i;delete k.eventQueue;j(l,function(m){k.fireEvent.apply(k,m)})}};var d=h.Observable.prototype;d.on=d.addListener;d.un=d.removeListener;h.Observable.releaseCapture=function(k){k.fireEvent=d.fireEvent};function e(l,m,k){return function(){if(m.target==arguments[0]){l.apply(k,Array.prototype.slice.call(arguments,0))}}}function b(n,p,k,m){k.task=new h.DelayedTask();return function(){k.task.delay(p.buffer,n,m,Array.prototype.slice.call(arguments,0))}}function c(m,n,l,k){return function(){n.removeListener(l,k);return m.apply(k,arguments)}}function a(n,p,k,m){return function(){var l=new h.DelayedTask(),o=Array.prototype.slice.call(arguments,0);if(!k.tasks){k.tasks=[]}k.tasks.push(l);l.delay(p.delay||10,function(){k.tasks.remove(l);n.apply(m,o)},m)}}h.Event=function(l,k){this.name=k;this.obj=l;this.listeners=[]};h.Event.prototype={addListener:function(o,n,m){var p=this,k;n=n||p.obj;if(!p.isListening(o,n)){k=p.createListener(o,n,m);if(p.firing){p.listeners=p.listeners.slice(0)}p.listeners.push(k)}},createListener:function(p,n,q){q=q||{};n=n||this.obj;var k={fn:p,scope:n,options:q},m=p;if(q.target){m=e(m,q,n)}if(q.delay){m=a(m,q,k,n)}if(q.single){m=c(m,this,p,n)}if(q.buffer){m=b(m,q,k,n)}k.fireFn=m;return k},findListener:function(o,n){var p=this.listeners,m=p.length,k;n=n||this.obj;while(m--){k=p[m];if(k){if(k.fn==o&&k.scope==n){return m}}}return -1},isListening:function(l,k){return this.findListener(l,k)!=-1},removeListener:function(r,q){var p,m,n,s=this,o=i;if((p=s.findListener(r,q))!=-1){if(s.firing){s.listeners=s.listeners.slice(0)}m=s.listeners[p];if(m.task){m.task.cancel();delete m.task}n=m.tasks&&m.tasks.length;if(n){while(n--){m.tasks[n].cancel()}delete m.tasks}s.listeners.splice(p,1);o=g}return o},clearListeners:function(){var n=this,k=n.listeners,m=k.length;while(m--){n.removeListener(k[m].fn,k[m].scope)}},fire:function(){var q=this,p=q.listeners,k=p.length,o=0,m;if(k>0){q.firing=g;var n=Array.prototype.slice.call(arguments,0);for(;o<k;o++){m=p[o];if(m&&m.fireFn.apply(m.scope||q.obj||window,n)===i){return(q.firing=i)}}}q.firing=i;return g}}})();Ext.DomHelper=function(){var x=null,k=/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,m=/^table|tbody|tr|td$/i,d=/tag|children|cn|html$/i,t=/td|tr|tbody/i,o=/([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,v=/end/i,r,n="afterbegin",p="afterend",c="beforebegin",q="beforeend",a="<table>",i="</table>",b=a+"<tbody>",j="</tbody>"+i,l=b+"<tr>",w="</tr>"+j;function h(B,D,C,E,A,y){var z=r.insertHtml(E,Ext.getDom(B),u(D));return C?Ext.get(z,true):z}function u(D){var z="",y,C,B,E;if(typeof D=="string"){z=D}else{if(Ext.isArray(D)){for(var A=0;A<D.length;A++){if(D[A]){z+=u(D[A])}}}else{z+="<"+(D.tag=D.tag||"div");for(y in D){C=D[y];if(!d.test(y)){if(typeof C=="object"){z+=" "+y+'="';for(B in C){z+=B+":"+C[B]+";"}z+='"'}else{z+=" "+({cls:"class",htmlFor:"for"}[y]||y)+'="'+C+'"'}}}if(k.test(D.tag)){z+="/>"}else{z+=">";if((E=D.children||D.cn)){z+=u(E)}else{if(D.html){z+=D.html}}z+="</"+D.tag+">"}}}return z}function g(F,C,B,D){x.innerHTML=[C,B,D].join("");var y=-1,A=x,z;while(++y<F){A=A.firstChild}if(z=A.nextSibling){var E=document.createDocumentFragment();while(A){z=A.nextSibling;E.appendChild(A);A=z}A=E}return A}function e(y,z,B,A){var C,D;x=x||document.createElement("div");if(y=="td"&&(z==n||z==q)||!t.test(y)&&(z==c||z==p)){return}D=z==c?B:z==p?B.nextSibling:z==n?B.firstChild:null;if(z==c||z==p){B=B.parentNode}if(y=="td"||(y=="tr"&&(z==q||z==n))){C=g(4,l,A,w)}else{if((y=="tbody"&&(z==q||z==n))||(y=="tr"&&(z==c||z==p))){C=g(3,b,A,j)}else{C=g(2,a,A,i)}}B.insertBefore(C,D);return C}function s(A){var D=document.createElement("div"),y=document.createDocumentFragment(),z=0,B,C;D.innerHTML=A;C=D.childNodes;B=C.length;for(;z<B;z++){y.appendChild(C[z].cloneNode(true))}return y}r={markup:function(y){return u(y)},applyStyles:function(y,z){if(z){var A;y=Ext.fly(y);if(typeof z=="function"){z=z.call()}if(typeof z=="string"){o.lastIndex=0;while((A=o.exec(z))){y.setStyle(A[1],A[2])}}else{if(typeof z=="object"){y.setStyle(z)}}}},insertHtml:function(D,y,E){var B={},A,F,C,G,H,z;D=D.toLowerCase();B[c]=["BeforeBegin","previousSibling"];B[p]=["AfterEnd","nextSibling"];if(y.insertAdjacentHTML){if(m.test(y.tagName)&&(z=e(y.tagName.toLowerCase(),D,y,E))){return z}B[n]=["AfterBegin","firstChild"];B[q]=["BeforeEnd","lastChild"];if((A=B[D])){y.insertAdjacentHTML(A[0],E);return y[A[1]]}}else{F=y.ownerDocument.createRange();G="setStart"+(v.test(D)?"After":"Before");if(B[D]){F[G](y);if(!F.createContextualFragment){H=s(E)}else{H=F.createContextualFragment(E)}y.parentNode.insertBefore(H,D==c?y:y.nextSibling);return y[(D==c?"previous":"next")+"Sibling"]}else{C=(D==n?"first":"last")+"Child";if(y.firstChild){F[G](y[C]);if(!F.createContextualFragment){H=s(E)}else{H=F.createContextualFragment(E)}if(D==n){y.insertBefore(H,y.firstChild)}else{y.appendChild(H)}}else{y.innerHTML=E}return y[C]}}throw'Illegal insertion point -> "'+D+'"'},insertBefore:function(y,A,z){return h(y,A,z,c)},insertAfter:function(y,A,z){return h(y,A,z,p,"nextSibling")},insertFirst:function(y,A,z){return h(y,A,z,n,"firstChild")},append:function(y,A,z){return h(y,A,z,q,"",true)},overwrite:function(y,A,z){y=Ext.getDom(y);y.innerHTML=u(A);return z?Ext.get(y.firstChild):y.firstChild},createHtml:u};return r}();Ext.Template=function(h){var j=this,c=arguments,e=[],d;if(Ext.isArray(h)){h=h.join("")}else{if(c.length>1){for(var g=0,b=c.length;g<b;g++){d=c[g];if(typeof d=="object"){Ext.apply(j,d)}else{e.push(d)}}h=e.join("")}}j.html=h;if(j.compiled){j.compile()}};Ext.Template.prototype={re:/\{([\w\-]+)\}/g,applyTemplate:function(a){var b=this;return b.compiled?b.compiled(a):b.html.replace(b.re,function(c,d){return a[d]!==undefined?a[d]:""})},set:function(a,c){var b=this;b.html=a;b.compiled=null;return c?b.compile():b},compile:function(){var me=this,sep=Ext.isGecko?"+":",";function fn(m,name){name="values['"+name+"']";return"'"+sep+"("+name+" == undefined ? '' : "+name+")"+sep+"'"}eval("this.compiled = function(values){ return "+(Ext.isGecko?"'":"['")+me.html.replace(/\\/g,"\\\\").replace(/(\r\n|\n)/g,"\\n").replace(/'/g,"\\'").replace(this.re,fn)+(Ext.isGecko?"';};":"'].join('');};"));return me},insertFirst:function(b,a,c){return this.doInsert("afterBegin",b,a,c)},insertBefore:function(b,a,c){return this.doInsert("beforeBegin",b,a,c)},insertAfter:function(b,a,c){return this.doInsert("afterEnd",b,a,c)},append:function(b,a,c){return this.doInsert("beforeEnd",b,a,c)},doInsert:function(c,e,b,a){e=Ext.getDom(e);var d=Ext.DomHelper.insertHtml(c,e,this.applyTemplate(b));return a?Ext.get(d,true):d},overwrite:function(b,a,c){b=Ext.getDom(b);b.innerHTML=this.applyTemplate(a);return c?Ext.get(b.firstChild,true):b.firstChild}};Ext.Template.prototype.apply=Ext.Template.prototype.applyTemplate;Ext.Template.from=function(b,a){b=Ext.getDom(b);return new Ext.Template(b.value||b.innerHTML,a||"")};Ext.DomQuery=function(){var cache={},simpleCache={},valueCache={},nonSpace=/\S/,trimRe=/^\s+|\s+$/g,tplRe=/\{(\d+)\}/g,modeRe=/^(\s?[\/>+~]\s?|\s|$)/,tagTokenRe=/^(#)?([\w\-\*]+)/,nthRe=/(\d*)n\+?(\d*)/,nthRe2=/\D/,isIE=window.ActiveXObject?true:false,key=30803;eval("var batch = 30803;");function child(parent,index){var i=0,n=parent.firstChild;while(n){if(n.nodeType==1){if(++i==index){return n}}n=n.nextSibling}return null}function next(n){while((n=n.nextSibling)&&n.nodeType!=1){}return n}function prev(n){while((n=n.previousSibling)&&n.nodeType!=1){}return n}function children(parent){var n=parent.firstChild,nodeIndex=-1,nextNode;while(n){nextNode=n.nextSibling;if(n.nodeType==3&&!nonSpace.test(n.nodeValue)){parent.removeChild(n)}else{n.nodeIndex=++nodeIndex}n=nextNode}return this}function byClassName(nodeSet,cls){if(!cls){return nodeSet}var result=[],ri=-1;for(var i=0,ci;ci=nodeSet[i];i++){if((" "+ci.className+" ").indexOf(cls)!=-1){result[++ri]=ci}}return result}function attrValue(n,attr){if(!n.tagName&&typeof n.length!="undefined"){n=n[0]}if(!n){return null}if(attr=="for"){return n.htmlFor}if(attr=="class"||attr=="className"){return n.className}return n.getAttribute(attr)||n[attr]}function getNodes(ns,mode,tagName){var result=[],ri=-1,cs;if(!ns){return result}tagName=tagName||"*";if(typeof ns.getElementsByTagName!="undefined"){ns=[ns]}if(!mode){for(var i=0,ni;ni=ns[i];i++){cs=ni.getElementsByTagName(tagName);for(var j=0,ci;ci=cs[j];j++){result[++ri]=ci}}}else{if(mode=="/"||mode==">"){var utag=tagName.toUpperCase();for(var i=0,ni,cn;ni=ns[i];i++){cn=ni.childNodes;for(var j=0,cj;cj=cn[j];j++){if(cj.nodeName==utag||cj.nodeName==tagName||tagName=="*"){result[++ri]=cj}}}}else{if(mode=="+"){var utag=tagName.toUpperCase();for(var i=0,n;n=ns[i];i++){while((n=n.nextSibling)&&n.nodeType!=1){}if(n&&(n.nodeName==utag||n.nodeName==tagName||tagName=="*")){result[++ri]=n}}}else{if(mode=="~"){var utag=tagName.toUpperCase();for(var i=0,n;n=ns[i];i++){while((n=n.nextSibling)){if(n.nodeName==utag||n.nodeName==tagName||tagName=="*"){result[++ri]=n}}}}}}}return result}function concat(a,b){if(b.slice){return a.concat(b)}for(var i=0,l=b.length;i<l;i++){a[a.length]=b[i]}return a}function byTag(cs,tagName){if(cs.tagName||cs==document){cs=[cs]}if(!tagName){return cs}var result=[],ri=-1;tagName=tagName.toLowerCase();for(var i=0,ci;ci=cs[i];i++){if(ci.nodeType==1&&ci.tagName.toLowerCase()==tagName){result[++ri]=ci}}return result}function byId(cs,id){if(cs.tagName||cs==document){cs=[cs]}if(!id){return cs}var result=[],ri=-1;for(var i=0,ci;ci=cs[i];i++){if(ci&&ci.id==id){result[++ri]=ci;return result}}return result}function byAttribute(cs,attr,value,op,custom){var result=[],ri=-1,useGetStyle=custom=="{",fn=Ext.DomQuery.operators[op],a,xml,hasXml;for(var i=0,ci;ci=cs[i];i++){if(ci.nodeType!=1){continue}if(!hasXml){xml=Ext.DomQuery.isXml(ci);hasXml=true}if(!xml){if(useGetStyle){a=Ext.DomQuery.getStyle(ci,attr)}else{if(attr=="class"||attr=="className"){a=ci.className}else{if(attr=="for"){a=ci.htmlFor}else{if(attr=="href"){a=ci.getAttribute("href",2)}else{a=ci.getAttribute(attr)}}}}}else{a=ci.getAttribute(attr)}if((fn&&fn(a,value))||(!fn&&a)){result[++ri]=ci}}return result}function byPseudo(cs,name,value){return Ext.DomQuery.pseudos[name](cs,value)}function nodupIEXml(cs){var d=++key,r;cs[0].setAttribute("_nodup",d);r=[cs[0]];for(var i=1,len=cs.length;i<len;i++){var c=cs[i];if(!c.getAttribute("_nodup")!=d){c.setAttribute("_nodup",d);r[r.length]=c}}for(var i=0,len=cs.length;i<len;i++){cs[i].removeAttribute("_nodup")}return r}function nodup(cs){if(!cs){return[]}var len=cs.length,c,i,r=cs,cj,ri=-1;if(!len||typeof cs.nodeType!="undefined"||len==1){return cs}if(isIE&&typeof cs[0].selectSingleNode!="undefined"){return nodupIEXml(cs)}var d=++key;cs[0]._nodup=d;for(i=1;c=cs[i];i++){if(c._nodup!=d){c._nodup=d}else{r=[];for(var j=0;j<i;j++){r[++ri]=cs[j]}for(j=i+1;cj=cs[j];j++){if(cj._nodup!=d){cj._nodup=d;r[++ri]=cj}}return r}}return r}function quickDiffIEXml(c1,c2){var d=++key,r=[];for(var i=0,len=c1.length;i<len;i++){c1[i].setAttribute("_qdiff",d)}for(var i=0,len=c2.length;i<len;i++){if(c2[i].getAttribute("_qdiff")!=d){r[r.length]=c2[i]}}for(var i=0,len=c1.length;i<len;i++){c1[i].removeAttribute("_qdiff")}return r}function quickDiff(c1,c2){var len1=c1.length,d=++key,r=[];if(!len1){return c2}if(isIE&&typeof c1[0].selectSingleNode!="undefined"){return quickDiffIEXml(c1,c2)}for(var i=0;i<len1;i++){c1[i]._qdiff=d}for(var i=0,len=c2.length;i<len;i++){if(c2[i]._qdiff!=d){r[r.length]=c2[i]}}return r}function quickId(ns,mode,root,id){if(ns==root){var d=root.ownerDocument||root;return d.getElementById(id)}ns=getNodes(ns,mode,"*");return byId(ns,id)}return{getStyle:function(el,name){return Ext.fly(el).getStyle(name)},compile:function(path,type){type=type||"select";var fn=["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],mode,lastPath,matchers=Ext.DomQuery.matchers,matchersLn=matchers.length,modeMatch,lmode=path.match(modeRe);if(lmode&&lmode[1]){fn[fn.length]='mode="'+lmode[1].replace(trimRe,"")+'";';path=path.replace(lmode[1],"")}while(path.substr(0,1)=="/"){path=path.substr(1)}while(path&&lastPath!=path){lastPath=path;var tokenMatch=path.match(tagTokenRe);if(type=="select"){if(tokenMatch){if(tokenMatch[1]=="#"){fn[fn.length]='n = quickId(n, mode, root, "'+tokenMatch[2]+'");'}else{fn[fn.length]='n = getNodes(n, mode, "'+tokenMatch[2]+'");'}path=path.replace(tokenMatch[0],"")}else{if(path.substr(0,1)!="@"){fn[fn.length]='n = getNodes(n, mode, "*");'}}}else{if(tokenMatch){if(tokenMatch[1]=="#"){fn[fn.length]='n = byId(n, "'+tokenMatch[2]+'");'}else{fn[fn.length]='n = byTag(n, "'+tokenMatch[2]+'");'}path=path.replace(tokenMatch[0],"")}}while(!(modeMatch=path.match(modeRe))){var matched=false;for(var j=0;j<matchersLn;j++){var t=matchers[j];var m=path.match(t.re);if(m){fn[fn.length]=t.select.replace(tplRe,function(x,i){return m[i]});path=path.replace(m[0],"");matched=true;break}}if(!matched){throw'Error parsing selector, parsing failed at "'+path+'"'}}if(modeMatch[1]){fn[fn.length]='mode="'+modeMatch[1].replace(trimRe,"")+'";';path=path.replace(modeMatch[1],"")}}fn[fn.length]="return nodup(n);\n}";eval(fn.join(""));return f},jsSelect:function(path,root,type){root=root||document;if(typeof root=="string"){root=document.getElementById(root)}var paths=path.split(","),results=[];for(var i=0,len=paths.length;i<len;i++){var subPath=paths[i].replace(trimRe,"");if(!cache[subPath]){cache[subPath]=Ext.DomQuery.compile(subPath);if(!cache[subPath]){throw subPath+" is not a valid selector"}}var result=cache[subPath](root);if(result&&result!=document){results=results.concat(result)}}if(paths.length>1){return nodup(results)}return results},isXml:function(el){var docEl=(el?el.ownerDocument||el:0).documentElement;return docEl?docEl.nodeName!=="HTML":false},select:document.querySelectorAll?function(path,root,type){root=root||document;if(!Ext.DomQuery.isXml(root)){try{var cs=root.querySelectorAll(path);return Ext.toArray(cs)}catch(ex){}}return Ext.DomQuery.jsSelect.call(this,path,root,type)}:function(path,root,type){return Ext.DomQuery.jsSelect.call(this,path,root,type)},selectNode:function(path,root){return Ext.DomQuery.select(path,root)[0]},selectValue:function(path,root,defaultValue){path=path.replace(trimRe,"");if(!valueCache[path]){valueCache[path]=Ext.DomQuery.compile(path,"select")}var n=valueCache[path](root),v;n=n[0]?n[0]:n;if(typeof n.normalize=="function"){n.normalize()}v=(n&&n.firstChild?n.firstChild.nodeValue:null);return((v===null||v===undefined||v==="")?defaultValue:v)},selectNumber:function(path,root,defaultValue){var v=Ext.DomQuery.selectValue(path,root,defaultValue||0);return parseFloat(v)},is:function(el,ss){if(typeof el=="string"){el=document.getElementById(el)}var isArray=Ext.isArray(el),result=Ext.DomQuery.filter(isArray?el:[el],ss);return isArray?(result.length==el.length):(result.length>0)},filter:function(els,ss,nonMatches){ss=ss.replace(trimRe,"");if(!simpleCache[ss]){simpleCache[ss]=Ext.DomQuery.compile(ss,"simple")}var result=simpleCache[ss](els);return nonMatches?quickDiff(result,els):result},matchers:[{re:/^\.([\w\-]+)/,select:'n = byClassName(n, " {1} ");'},{re:/^\:([\w\-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,select:'n = byPseudo(n, "{1}", "{2}");'},{re:/^(?:([\[\{])(?:@)?([\w\-]+)\s?(?:(=|.=)\s?(["']?)(.*?)\4)?[\]\}])/,select:'n = byAttribute(n, "{2}", "{5}", "{3}", "{1}");'},{re:/^#([\w\-]+)/,select:'n = byId(n, "{1}");'},{re:/^@([\w\-]+)/,select:'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'}],operators:{"=":function(a,v){return a==v},"!=":function(a,v){return a!=v},"^=":function(a,v){return a&&a.substr(0,v.length)==v},"$=":function(a,v){return a&&a.substr(a.length-v.length)==v},"*=":function(a,v){return a&&a.indexOf(v)!==-1},"%=":function(a,v){return(a%v)==0},"|=":function(a,v){return a&&(a==v||a.substr(0,v.length+1)==v+"-")},"~=":function(a,v){return a&&(" "+a+" ").indexOf(" "+v+" ")!=-1}},pseudos:{"first-child":function(c){var r=[],ri=-1,n;for(var i=0,ci;ci=n=c[i];i++){while((n=n.previousSibling)&&n.nodeType!=1){}if(!n){r[++ri]=ci}}return r},"last-child":function(c){var r=[],ri=-1,n;for(var i=0,ci;ci=n=c[i];i++){while((n=n.nextSibling)&&n.nodeType!=1){}if(!n){r[++ri]=ci}}return r},"nth-child":function(c,a){var r=[],ri=-1,m=nthRe.exec(a=="even"&&"2n"||a=="odd"&&"2n+1"||!nthRe2.test(a)&&"n+"+a||a),f=(m[1]||1)-0,l=m[2]-0;for(var i=0,n;n=c[i];i++){var pn=n.parentNode;if(batch!=pn._batch){var j=0;for(var cn=pn.firstChild;cn;cn=cn.nextSibling){if(cn.nodeType==1){cn.nodeIndex=++j}}pn._batch=batch}if(f==1){if(l==0||n.nodeIndex==l){r[++ri]=n}}else{if((n.nodeIndex+l)%f==0){r[++ri]=n}}}return r},"only-child":function(c){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(!prev(ci)&&!next(ci)){r[++ri]=ci}}return r},empty:function(c){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var cns=ci.childNodes,j=0,cn,empty=true;while(cn=cns[j]){++j;if(cn.nodeType==1||cn.nodeType==3){empty=false;break}}if(empty){r[++ri]=ci}}return r},contains:function(c,v){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if((ci.textContent||ci.innerText||"").indexOf(v)!=-1){r[++ri]=ci}}return r},nodeValue:function(c,v){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(ci.firstChild&&ci.firstChild.nodeValue==v){r[++ri]=ci}}return r},checked:function(c){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(ci.checked==true){r[++ri]=ci}}return r},not:function(c,ss){return Ext.DomQuery.filter(c,ss,true)},any:function(c,selectors){var ss=selectors.split("|"),r=[],ri=-1,s;for(var i=0,ci;ci=c[i];i++){for(var j=0;s=ss[j];j++){if(Ext.DomQuery.is(ci,s)){r[++ri]=ci;break}}}return r},odd:function(c){return this["nth-child"](c,"odd")},even:function(c){return this["nth-child"](c,"even")},nth:function(c,a){return c[a-1]||[]},first:function(c){return c[0]||[]},last:function(c){return c[c.length-1]||[]},has:function(c,ss){var s=Ext.DomQuery.select,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(s(ss,ci).length>0){r[++ri]=ci}}return r},next:function(c,ss){var is=Ext.DomQuery.is,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var n=next(ci);if(n&&is(n,ss)){r[++ri]=ci}}return r},prev:function(c,ss){var is=Ext.DomQuery.is,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var n=prev(ci);if(n&&is(n,ss)){r[++ri]=ci}}return r}}}}();Ext.query=Ext.DomQuery.select;Ext.util.DelayedTask=function(d,c,a){var e=this,g,b=function(){clearInterval(g);g=null;d.apply(c,a||[])};e.delay=function(i,k,j,h){e.cancel();d=k||d;c=j||c;a=h||a;g=setInterval(b,i)};e.cancel=function(){if(g){clearInterval(g);g=null}}};(function(){var h=document;Ext.Element=function(l,m){var n=typeof l=="string"?h.getElementById(l):l,o;if(!n){return null}o=n.id;if(!m&&o&&Ext.elCache[o]){return Ext.elCache[o].el}this.dom=n;this.id=o||Ext.id(n)};var d=Ext.DomHelper,e=Ext.Element,a=Ext.elCache;e.prototype={set:function(q,m){var n=this.dom,l,p,m=(m!==false)&&!!n.setAttribute;for(l in q){if(q.hasOwnProperty(l)){p=q[l];if(l=="style"){d.applyStyles(n,p)}else{if(l=="cls"){n.className=p}else{if(m){n.setAttribute(l,p)}else{n[l]=p}}}}}return this},defaultUnit:"px",is:function(l){return Ext.DomQuery.is(this.dom,l)},focus:function(o,n){var l=this,n=n||l.dom;try{if(Number(o)){l.focus.defer(o,null,[null,n])}else{n.focus()}}catch(m){}return l},blur:function(){try{this.dom.blur()}catch(l){}return this},getValue:function(l){var m=this.dom.value;return l?parseInt(m,10):m},addListener:function(l,o,n,m){Ext.EventManager.on(this.dom,l,o,n||this,m);return this},removeListener:function(l,n,m){Ext.EventManager.removeListener(this.dom,l,n,m||this);return this},removeAllListeners:function(){Ext.EventManager.removeAll(this.dom);return this},purgeAllListeners:function(){Ext.EventManager.purgeElement(this,true);return this},addUnits:function(l){if(l===""||l=="auto"||l===undefined){l=l||""}else{if(!isNaN(l)||!i.test(l)){l=l+(this.defaultUnit||"px")}}return l},load:function(m,n,l){Ext.Ajax.request(Ext.apply({params:n,url:m.url||m,callback:l,el:this.dom,indicatorText:m.indicatorText||""},Ext.isObject(m)?m:{}));return this},isBorderBox:function(){return Ext.isBorderBox||Ext.isForcedBorderBox||g[(this.dom.tagName||"").toLowerCase()]},remove:function(){var l=this,m=l.dom;if(m){delete l.dom;Ext.removeNode(m)}},hover:function(m,l,o,n){var p=this;p.on("mouseenter",m,o||p.dom,n);p.on("mouseleave",l,o||p.dom,n);return p},contains:function(l){return !l?false:Ext.lib.Dom.isAncestor(this.dom,l.dom?l.dom:l)},getAttributeNS:function(m,l){return this.getAttribute(l,m)},getAttribute:(function(){var p=document.createElement("table"),o=false,m="getAttribute" in p,l=/undefined|unknown/;if(m){try{p.getAttribute("ext:qtip")}catch(n){o=true}return function(q,s){var r=this.dom,t;if(r.getAttributeNS){t=r.getAttributeNS(s,q)||null}if(t==null){if(s){if(o&&r.tagName.toUpperCase()=="TABLE"){try{t=r.getAttribute(s+":"+q)}catch(u){t=""}}else{t=r.getAttribute(s+":"+q)}}else{t=r.getAttribute(q)||r[q]}}return t||""}}else{return function(q,s){var r=this.om,u,t;if(s){t=r[s+":"+q];u=l.test(typeof t)?undefined:t}else{u=r[q]}return u||""}}p=null})(),update:function(l){if(this.dom){this.dom.innerHTML=l}return this}};var k=e.prototype;e.addMethods=function(l){Ext.apply(k,l)};k.on=k.addListener;k.un=k.removeListener;k.autoBoxAdjust=true;var i=/\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,c;e.get=function(m){var l,p,o;if(!m){return null}if(typeof m=="string"){if(!(p=h.getElementById(m))){return null}if(a[m]&&a[m].el){l=a[m].el;l.dom=p}else{l=e.addToCache(new e(p))}return l}else{if(m.tagName){if(!(o=m.id)){o=Ext.id(m)}if(a[o]&&a[o].el){l=a[o].el;l.dom=m}else{l=e.addToCache(new e(m))}return l}else{if(m instanceof e){if(m!=c){if(Ext.isIE&&(m.id==undefined||m.id=="")){m.dom=m.dom}else{m.dom=h.getElementById(m.id)||m.dom}}return m}else{if(m.isComposite){return m}else{if(Ext.isArray(m)){return e.select(m)}else{if(m==h){if(!c){var n=function(){};n.prototype=e.prototype;c=new n();c.dom=h}return c}}}}}}return null};e.addToCache=function(l,m){m=m||l.id;a[m]={el:l,data:{},events:{}};return l};e.data=function(m,l,n){m=e.get(m);if(!m){return null}var o=a[m.id].data;if(arguments.length==2){return o[l]}else{return(o[l]=n)}};function j(){if(!Ext.enableGarbageCollector){clearInterval(e.collectorThreadId)}else{var l,n,q,p;for(l in a){p=a[l];if(p.skipGC){continue}n=p.el;q=n.dom;if(!q||!q.parentNode||(!q.offsetParent&&!h.getElementById(l))){if(Ext.enableListenerCollection){Ext.EventManager.removeAll(q)}delete a[l]}}if(Ext.isIE){var m={};for(l in a){m[l]=a[l]}a=Ext.elCache=m}}}e.collectorThreadId=setInterval(j,30000);var b=function(){};b.prototype=e.prototype;e.Flyweight=function(l){this.dom=l};e.Flyweight.prototype=new b();e.Flyweight.prototype.isFlyweight=true;e._flyweights={};e.fly=function(n,l){var m=null;l=l||"_global";if(n=Ext.getDom(n)){(e._flyweights[l]=e._flyweights[l]||new e.Flyweight()).dom=n;m=e._flyweights[l]}return m};Ext.get=e.get;Ext.fly=e.fly;var g=Ext.isStrict?{select:1}:{input:1,select:1,textarea:1};if(Ext.isIE||Ext.isGecko){g.button=1}})();Ext.Element.addMethods(function(){var d="parentNode",b="nextSibling",c="previousSibling",e=Ext.DomQuery,a=Ext.get;return{findParent:function(m,l,h){var j=this.dom,g=document.body,k=0,i;if(Ext.isGecko&&Object.prototype.toString.call(j)=="[object XULElement]"){return null}l=l||50;if(isNaN(l)){i=Ext.getDom(l);l=Number.MAX_VALUE}while(j&&j.nodeType==1&&k<l&&j!=g&&j!=i){if(e.is(j,m)){return h?a(j):j}k++;j=j.parentNode}return null},findParentNode:function(j,i,g){var h=Ext.fly(this.dom.parentNode,"_internal");return h?h.findParent(j,i,g):null},up:function(h,g){return this.findParentNode(h,g,true)},select:function(g){return Ext.Element.select(g,this.dom)},query:function(g){return e.select(g,this.dom)},child:function(g,h){var i=e.selectNode(g,this.dom);return h?i:a(i)},down:function(g,h){var i=e.selectNode(" > "+g,this.dom);return h?i:a(i)},parent:function(g,h){return this.matchNode(d,d,g,h)},next:function(g,h){return this.matchNode(b,b,g,h)},prev:function(g,h){return this.matchNode(c,c,g,h)},first:function(g,h){return this.matchNode(b,"firstChild",g,h)},last:function(g,h){return this.matchNode(c,"lastChild",g,h)},matchNode:function(h,k,g,i){var j=this.dom[k];while(j){if(j.nodeType==1&&(!g||e.is(j,g))){return !i?a(j):j}j=j[h]}return null}}}());Ext.Element.addMethods(function(){var c=Ext.getDom,a=Ext.get,b=Ext.DomHelper;return{appendChild:function(d){return a(d).appendTo(this)},appendTo:function(d){c(d).appendChild(this.dom);return this},insertBefore:function(d){(d=c(d)).parentNode.insertBefore(this.dom,d);return this},insertAfter:function(d){(d=c(d)).parentNode.insertBefore(this.dom,d.nextSibling);return this},insertFirst:function(e,d){e=e||{};if(e.nodeType||e.dom||typeof e=="string"){e=c(e);this.dom.insertBefore(e,this.dom.firstChild);return !d?a(e):e}else{return this.createChild(e,this.dom.firstChild,d)}},replace:function(d){d=a(d);this.insertBefore(d);d.remove();return this},replaceWith:function(d){var e=this;if(d.nodeType||d.dom||typeof d=="string"){d=c(d);e.dom.parentNode.insertBefore(d,e.dom)}else{d=b.insertBefore(e.dom,d)}delete Ext.elCache[e.id];Ext.removeNode(e.dom);e.id=Ext.id(e.dom=d);Ext.Element.addToCache(e.isFlyweight?new Ext.Element(e.dom):e);return e},createChild:function(e,d,g){e=e||{tag:"div"};return d?b.insertBefore(d,e,g!==true):b[!this.dom.firstChild?"overwrite":"append"](this.dom,e,g!==true)},wrap:function(d,e){var g=b.insertBefore(this.dom,d||{tag:"div"},!e);g.dom?g.dom.appendChild(this.dom):g.appendChild(this.dom);return g},insertHtml:function(e,g,d){var h=b.insertHtml(e,this.dom,g);return d?Ext.get(h):h}}}());Ext.Element.addMethods(function(){var A=Ext.supports,h={},x=/(-[a-z])/gi,s=document.defaultView,D=/alpha\(opacity=(.*)\)/i,l=/^\s+|\s+$/g,B=Ext.Element,u=/\s+/,b=/\w/g,d="padding",c="margin",y="border",t="-left",q="-right",w="-top",o="-bottom",j="-width",r=Math,z="hidden",e="isClipped",k="overflow",n="overflow-x",m="overflow-y",C="originalClip",i={l:y+t+j,r:y+q+j,t:y+w+j,b:y+o+j},g={l:d+t,r:d+q,t:d+w,b:d+o},a={l:c+t,r:c+q,t:c+w,b:c+o},E=Ext.Element.data;function p(F,G){return G.charAt(1).toUpperCase()}function v(F){return h[F]||(h[F]=F=="float"?(A.cssFloat?"cssFloat":"styleFloat"):F.replace(x,p))}return{adjustWidth:function(F){var G=this;var H=(typeof F=="number");if(H&&G.autoBoxAdjust&&!G.isBorderBox()){F-=(G.getBorderWidth("lr")+G.getPadding("lr"))}return(H&&F<0)?0:F},adjustHeight:function(F){var G=this;var H=(typeof F=="number");if(H&&G.autoBoxAdjust&&!G.isBorderBox()){F-=(G.getBorderWidth("tb")+G.getPadding("tb"))}return(H&&F<0)?0:F},addClass:function(J){var K=this,I,F,H,G=[];if(!Ext.isArray(J)){if(typeof J=="string"&&!this.hasClass(J)){K.dom.className+=" "+J}}else{for(I=0,F=J.length;I<F;I++){H=J[I];if(typeof H=="string"&&(" "+K.dom.className+" ").indexOf(" "+H+" ")==-1){G.push(H)}}if(G.length){K.dom.className+=" "+G.join(" ")}}return K},removeClass:function(K){var L=this,J,G,F,I,H;if(!Ext.isArray(K)){K=[K]}if(L.dom&&L.dom.className){H=L.dom.className.replace(l,"").split(u);for(J=0,F=K.length;J<F;J++){I=K[J];if(typeof I=="string"){I=I.replace(l,"");G=H.indexOf(I);if(G!=-1){H.splice(G,1)}}}L.dom.className=H.join(" ")}return L},radioClass:function(I){var J=this.dom.parentNode.childNodes,G,H,F;I=Ext.isArray(I)?I:[I];for(H=0,F=J.length;H<F;H++){G=J[H];if(G&&G.nodeType==1){Ext.fly(G,"_internal").removeClass(I)}}return this.addClass(I)},toggleClass:function(F){return this.hasClass(F)?this.removeClass(F):this.addClass(F)},hasClass:function(F){return F&&(" "+this.dom.className+" ").indexOf(" "+F+" ")!=-1},replaceClass:function(G,F){return this.removeClass(G).addClass(F)},isStyle:function(F,G){return this.getStyle(F)==G},getStyle:function(){return s&&s.getComputedStyle?function(K){var I=this.dom,F,H,G,J;if(I==document){return null}K=v(K);G=(F=I.style[K])?F:(H=s.getComputedStyle(I,""))?H[K]:null;if(K=="marginRight"&&G!="0px"&&!A.correctRightMargin){J=I.style.display;I.style.display="inline-block";G=s.getComputedStyle(I,"").marginRight;I.style.display=J}if(K=="backgroundColor"&&G=="rgba(0, 0, 0, 0)"&&!A.correctTransparentColor){G="transparent"}return G}:function(J){var H=this.dom,F,G;if(H==document){return null}if(J=="opacity"){if(H.style.filter.match){if(F=H.style.filter.match(D)){var I=parseFloat(F[1]);if(!isNaN(I)){return I?I/100:0}}}return 1}J=v(J);return H.style[J]||((G=H.currentStyle)?G[J]:null)}}(),getColor:function(F,G,K){var I=this.getStyle(F),H=(typeof K!="undefined")?K:"#",J;if(!I||(/transparent|inherit/.test(I))){return G}if(/^r/.test(I)){Ext.each(I.slice(4,I.length-1).split(","),function(L){J=parseInt(L,10);H+=(J<16?"0":"")+J.toString(16)})}else{I=I.replace("#","");H+=I.length==3?I.replace(/^(\w)(\w)(\w)$/,"$1$1$2$2$3$3"):I}return(H.length>5?H.toLowerCase():G)},setStyle:function(I,H){var F,G;if(typeof I!="object"){F={};F[I]=H;I=F}for(G in I){H=I[G];G=="opacity"?this.setOpacity(H):this.dom.style[v(G)]=H}return this},setOpacity:function(G,F){var J=this,H=J.dom.style;if(!F||!J.anim){if(Ext.isIE){var I=G<1?"alpha(opacity="+G*100+")":"",K=H.filter.replace(D,"").replace(l,"");H.zoom=1;H.filter=K+(K.length>0?" ":"")+I}else{H.opacity=G}}else{J.anim({opacity:{to:G}},J.preanim(arguments,1),null,0.35,"easeIn")}return J},clearOpacity:function(){var F=this.dom.style;if(Ext.isIE){if(!Ext.isEmpty(F.filter)){F.filter=F.filter.replace(D,"").replace(l,"")}}else{F.opacity=F["-moz-opacity"]=F["-khtml-opacity"]=""}return this},getHeight:function(H){var G=this,J=G.dom,I=Ext.isIE&&G.isStyle("display","none"),F=r.max(J.offsetHeight,I?0:J.clientHeight)||0;F=!H?F:F-G.getBorderWidth("tb")-G.getPadding("tb");return F<0?0:F},getWidth:function(G){var H=this,J=H.dom,I=Ext.isIE&&H.isStyle("display","none"),F=r.max(J.offsetWidth,I?0:J.clientWidth)||0;F=!G?F:F-H.getBorderWidth("lr")-H.getPadding("lr");return F<0?0:F},setWidth:function(G,F){var H=this;G=H.adjustWidth(G);!F||!H.anim?H.dom.style.width=H.addUnits(G):H.anim({width:{to:G}},H.preanim(arguments,1));return H},setHeight:function(F,G){var H=this;F=H.adjustHeight(F);!G||!H.anim?H.dom.style.height=H.addUnits(F):H.anim({height:{to:F}},H.preanim(arguments,1));return H},getBorderWidth:function(F){return this.addStyles(F,i)},getPadding:function(F){return this.addStyles(F,g)},clip:function(){var F=this,G=F.dom;if(!E(G,e)){E(G,e,true);E(G,C,{o:F.getStyle(k),x:F.getStyle(n),y:F.getStyle(m)});F.setStyle(k,z);F.setStyle(n,z);F.setStyle(m,z)}return F},unclip:function(){var F=this,H=F.dom;if(E(H,e)){E(H,e,false);var G=E(H,C);if(G.o){F.setStyle(k,G.o)}if(G.x){F.setStyle(n,G.x)}if(G.y){F.setStyle(m,G.y)}}return F},addStyles:function(M,L){var J=0,K=M.match(b),I,H,G,F=K.length;for(G=0;G<F;G++){I=K[G];H=I&&parseInt(this.getStyle(L[I]),10);if(H){J+=r.abs(H)}}return J},margins:a}}());(function(){var a=Ext.lib.Dom,b="left",g="right",d="top",i="bottom",h="position",c="static",e="relative",j="auto",k="z-index";Ext.Element.addMethods({getX:function(){return a.getX(this.dom)},getY:function(){return a.getY(this.dom)},getXY:function(){return a.getXY(this.dom)},getOffsetsTo:function(l){var n=this.getXY(),m=Ext.fly(l,"_internal").getXY();return[n[0]-m[0],n[1]-m[1]]},setX:function(l,m){return this.setXY([l,this.getY()],this.animTest(arguments,m,1))},setY:function(m,l){return this.setXY([this.getX(),m],this.animTest(arguments,l,1))},setLeft:function(l){this.setStyle(b,this.addUnits(l));return this},setTop:function(l){this.setStyle(d,this.addUnits(l));return this},setRight:function(l){this.setStyle(g,this.addUnits(l));return this},setBottom:function(l){this.setStyle(i,this.addUnits(l));return this},setXY:function(n,l){var m=this;if(!l||!m.anim){a.setXY(m.dom,n)}else{m.anim({points:{to:n}},m.preanim(arguments,1),"motion")}return m},setLocation:function(l,n,m){return this.setXY([l,n],this.animTest(arguments,m,2))},moveTo:function(l,n,m){return this.setXY([l,n],this.animTest(arguments,m,2))},getLeft:function(l){return !l?this.getX():parseInt(this.getStyle(b),10)||0},getRight:function(l){var m=this;return !l?m.getX()+m.getWidth():(m.getLeft(true)+m.getWidth())||0},getTop:function(l){return !l?this.getY():parseInt(this.getStyle(d),10)||0},getBottom:function(l){var m=this;return !l?m.getY()+m.getHeight():(m.getTop(true)+m.getHeight())||0},position:function(p,o,l,n){var m=this;if(!p&&m.isStyle(h,c)){m.setStyle(h,e)}else{if(p){m.setStyle(h,p)}}if(o){m.setStyle(k,o)}if(l||n){m.setXY([l||false,n||false])}},clearPositioning:function(l){l=l||"";this.setStyle({left:l,right:l,top:l,bottom:l,"z-index":"",position:c});return this},getPositioning:function(){var m=this.getStyle(b);var n=this.getStyle(d);return{position:this.getStyle(h),left:m,right:m?"":this.getStyle(g),top:n,bottom:n?"":this.getStyle(i),"z-index":this.getStyle(k)}},setPositioning:function(l){var n=this,m=n.dom.style;n.setStyle(l);if(l.right==j){m.right=""}if(l.bottom==j){m.bottom=""}return n},translatePoints:function(m,u){u=isNaN(m[1])?u:m[1];m=isNaN(m[0])?m:m[0];var q=this,r=q.isStyle(h,e),s=q.getXY(),n=parseInt(q.getStyle(b),10),p=parseInt(q.getStyle(d),10);n=!isNaN(n)?n:(r?0:q.dom.offsetLeft);p=!isNaN(p)?p:(r?0:q.dom.offsetTop);return{left:(m-s[0]+n),top:(u-s[1]+p)}},animTest:function(m,l,n){return !!l&&this.preanim?this.preanim(m,n):false}})})();Ext.Element.addMethods({isScrollable:function(){var a=this.dom;return a.scrollHeight>a.clientHeight||a.scrollWidth>a.clientWidth},scrollTo:function(a,b){this.dom["scroll"+(/top/i.test(a)?"Top":"Left")]=b;return this},getScroll:function(){var i=this.dom,h=document,a=h.body,c=h.documentElement,b,g,e;if(i==h||i==a){if(Ext.isIE&&Ext.isStrict){b=c.scrollLeft;g=c.scrollTop}else{b=window.pageXOffset;g=window.pageYOffset}e={left:b||(a?a.scrollLeft:0),top:g||(a?a.scrollTop:0)}}else{e={left:i.scrollLeft,top:i.scrollTop}}return e}});Ext.Element.VISIBILITY=1;Ext.Element.DISPLAY=2;Ext.Element.OFFSETS=3;Ext.Element.ASCLASS=4;Ext.Element.visibilityCls="x-hide-nosize";Ext.Element.addMethods(function(){var e=Ext.Element,p="opacity",j="visibility",g="display",d="hidden",n="offsets",k="asclass",m="none",a="nosize",b="originalDisplay",c="visibilityMode",h="isVisible",i=e.data,l=function(r){var q=i(r,b);if(q===undefined){i(r,b,q="")}return q},o=function(r){var q=i(r,c);if(q===undefined){i(r,c,q=1)}return q};return{originalDisplay:"",visibilityMode:1,setVisibilityMode:function(q){i(this.dom,c,q);return this},animate:function(r,t,s,u,q){this.anim(r,{duration:t,callback:s,easing:u},q);return this},anim:function(t,u,r,w,s,q){r=r||"run";u=u||{};var v=this,x=Ext.lib.Anim[r](v.dom,t,(u.duration||w)||0.35,(u.easing||s)||"easeOut",function(){if(q){q.call(v)}if(u.callback){u.callback.call(u.scope||v,v,u)}},v);u.anim=x;return x},preanim:function(q,r){return !q[r]?false:(typeof q[r]=="object"?q[r]:{duration:q[r+1],callback:q[r+2],easing:q[r+3]})},isVisible:function(){var q=this,s=q.dom,r=i(s,h);if(typeof r=="boolean"){return r}r=!q.isStyle(j,d)&&!q.isStyle(g,m)&&!((o(s)==e.ASCLASS)&&q.hasClass(q.visibilityCls||e.visibilityCls));i(s,h,r);return r},setVisible:function(t,q){var w=this,r,y,x,v,u=w.dom,s=o(u);if(typeof q=="string"){switch(q){case g:s=e.DISPLAY;break;case j:s=e.VISIBILITY;break;case n:s=e.OFFSETS;break;case a:case k:s=e.ASCLASS;break}w.setVisibilityMode(s);q=false}if(!q||!w.anim){if(s==e.ASCLASS){w[t?"removeClass":"addClass"](w.visibilityCls||e.visibilityCls)}else{if(s==e.DISPLAY){return w.setDisplayed(t)}else{if(s==e.OFFSETS){if(!t){w.hideModeStyles={position:w.getStyle("position"),top:w.getStyle("top"),left:w.getStyle("left")};w.applyStyles({position:"absolute",top:"-10000px",left:"-10000px"})}else{w.applyStyles(w.hideModeStyles||{position:"",top:"",left:""});delete w.hideModeStyles}}else{w.fixDisplay();u.style.visibility=t?"visible":d}}}}else{if(t){w.setOpacity(0.01);w.setVisible(true)}w.anim({opacity:{to:(t?1:0)}},w.preanim(arguments,1),null,0.35,"easeIn",function(){t||w.setVisible(false).setOpacity(1)})}i(u,h,t);return w},hasMetrics:function(){var q=this.dom;return this.isVisible()||(o(q)==e.VISIBILITY)},toggle:function(q){var r=this;r.setVisible(!r.isVisible(),r.preanim(arguments,0));return r},setDisplayed:function(q){if(typeof q=="boolean"){q=q?l(this.dom):m}this.setStyle(g,q);return this},fixDisplay:function(){var q=this;if(q.isStyle(g,m)){q.setStyle(j,d);q.setStyle(g,l(this.dom));if(q.isStyle(g,m)){q.setStyle(g,"block")}}},hide:function(q){if(typeof q=="string"){this.setVisible(false,q);return this}this.setVisible(false,this.preanim(arguments,0));return this},show:function(q){if(typeof q=="string"){this.setVisible(true,q);return this}this.setVisible(true,this.preanim(arguments,0));return this}}}());(function(){var y=null,A=undefined,k=true,t=false,j="setX",h="setY",a="setXY",n="left",l="bottom",s="top",m="right",q="height",g="width",i="points",w="hidden",z="absolute",u="visible",e="motion",o="position",r="easeOut",d=new Ext.Element.Flyweight(),v={},x=function(B){return B||{}},p=function(B){d.dom=B;d.id=Ext.id(B);return d},c=function(B){if(!v[B]){v[B]=[]}return v[B]},b=function(C,B){v[C]=B};Ext.enableFx=k;Ext.Fx={switchStatements:function(C,D,B){return D.apply(this,B[C])},slideIn:function(H,E){E=x(E);var J=this,G=J.dom,M=G.style,O,B,L,D,C,M,I,N,K,F;H=H||"t";J.queueFx(E,function(){O=p(G).getXY();p(G).fixDisplay();B=p(G).getFxRestore();L={x:O[0],y:O[1],0:O[0],1:O[1],width:G.offsetWidth,height:G.offsetHeight};L.right=L.x+L.width;L.bottom=L.y+L.height;p(G).setWidth(L.width).setHeight(L.height);D=p(G).fxWrap(B.pos,E,w);M.visibility=u;M.position=z;function P(){p(G).fxUnwrap(D,B.pos,E);M.width=B.width;M.height=B.height;p(G).afterFx(E)}N={to:[L.x,L.y]};K={to:L.width};F={to:L.height};function Q(U,R,V,S,X,Z,ac,ab,aa,W,T){var Y={};p(U).setWidth(V).setHeight(S);if(p(U)[X]){p(U)[X](Z)}R[ac]=R[ab]="0";if(aa){Y.width=aa}if(W){Y.height=W}if(T){Y.points=T}return Y}I=p(G).switchStatements(H.toLowerCase(),Q,{t:[D,M,L.width,0,y,y,n,l,y,F,y],l:[D,M,0,L.height,y,y,m,s,K,y,y],r:[D,M,L.width,L.height,j,L.right,n,s,y,y,N],b:[D,M,L.width,L.height,h,L.bottom,n,s,y,F,N],tl:[D,M,0,0,y,y,m,l,K,F,N],bl:[D,M,0,0,h,L.y+L.height,m,s,K,F,N],br:[D,M,0,0,a,[L.right,L.bottom],n,s,K,F,N],tr:[D,M,0,0,j,L.x+L.width,n,l,K,F,N]});M.visibility=u;p(D).show();arguments.callee.anim=p(D).fxanim(I,E,e,0.5,r,P)});return J},slideOut:function(F,D){D=x(D);var H=this,E=H.dom,K=E.style,L=H.getXY(),C,B,I,J,G={to:0};F=F||"t";H.queueFx(D,function(){B=p(E).getFxRestore();I={x:L[0],y:L[1],0:L[0],1:L[1],width:E.offsetWidth,height:E.offsetHeight};I.right=I.x+I.width;I.bottom=I.y+I.height;p(E).setWidth(I.width).setHeight(I.height);C=p(E).fxWrap(B.pos,D,u);K.visibility=u;K.position=z;p(C).setWidth(I.width).setHeight(I.height);function M(){D.useDisplay?p(E).setDisplayed(t):p(E).hide();p(E).fxUnwrap(C,B.pos,D);K.width=B.width;K.height=B.height;p(E).afterFx(D)}function N(O,W,U,X,S,V,R,T,Q){var P={};O[W]=O[U]="0";P[X]=S;if(V){P[V]=R}if(T){P[T]=Q}return P}J=p(E).switchStatements(F.toLowerCase(),N,{t:[K,n,l,q,G],l:[K,m,s,g,G],r:[K,n,s,g,G,i,{to:[I.right,I.y]}],b:[K,n,s,q,G,i,{to:[I.x,I.bottom]}],tl:[K,m,l,g,G,q,G],bl:[K,m,s,g,G,q,G,i,{to:[I.x,I.bottom]}],br:[K,n,s,g,G,q,G,i,{to:[I.x+I.width,I.bottom]}],tr:[K,n,l,g,G,q,G,i,{to:[I.right,I.y]}]});arguments.callee.anim=p(C).fxanim(J,D,e,0.5,r,M)});return H},puff:function(H){H=x(H);var F=this,G=F.dom,C=G.style,D,B,E;F.queueFx(H,function(){D=p(G).getWidth();B=p(G).getHeight();p(G).clearOpacity();p(G).show();E=p(G).getFxRestore();function I(){H.useDisplay?p(G).setDisplayed(t):p(G).hide();p(G).clearOpacity();p(G).setPositioning(E.pos);C.width=E.width;C.height=E.height;C.fontSize="";p(G).afterFx(H)}arguments.callee.anim=p(G).fxanim({width:{to:p(G).adjustWidth(D*2)},height:{to:p(G).adjustHeight(B*2)},points:{by:[-D*0.5,-B*0.5]},opacity:{to:0},fontSize:{to:200,unit:"%"}},H,e,0.5,r,I)});return F},switchOff:function(F){F=x(F);var D=this,E=D.dom,B=E.style,C;D.queueFx(F,function(){p(E).clearOpacity();p(E).clip();C=p(E).getFxRestore();function G(){F.useDisplay?p(E).setDisplayed(t):p(E).hide();p(E).clearOpacity();p(E).setPositioning(C.pos);B.width=C.width;B.height=C.height;p(E).afterFx(F)}p(E).fxanim({opacity:{to:0.3}},y,y,0.1,y,function(){p(E).clearOpacity();(function(){p(E).fxanim({height:{to:1},points:{by:[0,p(E).getHeight()*0.5]}},F,e,0.3,"easeIn",G)}).defer(100)})});return D},highlight:function(D,H){H=x(H);var F=this,G=F.dom,B=H.attr||"backgroundColor",C={},E;F.queueFx(H,function(){p(G).clearOpacity();p(G).show();function I(){G.style[B]=E;p(G).afterFx(H)}E=G.style[B];C[B]={from:D||"ffff9c",to:H.endColor||p(G).getColor(B)||"ffffff"};arguments.callee.anim=p(G).fxanim(C,H,"color",1,"easeIn",I)});return F},frame:function(B,E,H){H=x(H);var D=this,G=D.dom,C,F;D.queueFx(H,function(){B=B||"#C3DAF9";if(B.length==6){B="#"+B}E=E||1;p(G).show();var L=p(G).getXY(),J={x:L[0],y:L[1],0:L[0],1:L[1],width:G.offsetWidth,height:G.offsetHeight},I=function(){C=p(document.body||document.documentElement).createChild({style:{position:z,"z-index":35000,border:"0px solid "+B}});return C.queueFx({},K)};arguments.callee.anim={isAnimated:true,stop:function(){E=0;C.stopFx()}};function K(){var M=Ext.isBorderBox?2:1;F=C.anim({top:{from:J.y,to:J.y-20},left:{from:J.x,to:J.x-20},borderWidth:{from:0,to:10},opacity:{from:1,to:0},height:{from:J.height,to:J.height+20*M},width:{from:J.width,to:J.width+20*M}},{duration:H.duration||1,callback:function(){C.remove();--E>0?I():p(G).afterFx(H)}});arguments.callee.anim={isAnimated:true,stop:function(){F.stop()}}}I()});return D},pause:function(D){var C=this.dom,B;this.queueFx({},function(){B=setTimeout(function(){p(C).afterFx({})},D*1000);arguments.callee.anim={isAnimated:true,stop:function(){clearTimeout(B);p(C).afterFx({})}}});return this},fadeIn:function(D){D=x(D);var B=this,C=B.dom,E=D.endOpacity||1;B.queueFx(D,function(){p(C).setOpacity(0);p(C).fixDisplay();C.style.visibility=u;arguments.callee.anim=p(C).fxanim({opacity:{to:E}},D,y,0.5,r,function(){if(E==1){p(C).clearOpacity()}p(C).afterFx(D)})});return B},fadeOut:function(E){E=x(E);var C=this,D=C.dom,B=D.style,F=E.endOpacity||0;C.queueFx(E,function(){arguments.callee.anim=p(D).fxanim({opacity:{to:F}},E,y,0.5,r,function(){if(F==0){Ext.Element.data(D,"visibilityMode")==Ext.Element.DISPLAY||E.useDisplay?B.display="none":B.visibility=w;p(D).clearOpacity()}p(D).afterFx(E)})});return C},scale:function(B,C,D){this.shift(Ext.apply({},D,{width:B,height:C}));return this},shift:function(D){D=x(D);var C=this.dom,B={};this.queueFx(D,function(){for(var E in D){if(D[E]!=A){B[E]={to:D[E]}}}B.width?B.width.to=p(C).adjustWidth(D.width):B;B.height?B.height.to=p(C).adjustWidth(D.height):B;if(B.x||B.y||B.xy){B.points=B.xy||{to:[B.x?B.x.to:p(C).getX(),B.y?B.y.to:p(C).getY()]}}arguments.callee.anim=p(C).fxanim(B,D,e,0.35,r,function(){p(C).afterFx(D)})});return this},ghost:function(E,C){C=x(C);var G=this,D=G.dom,J=D.style,H={opacity:{to:0},points:{}},K=H.points,B,I,F;E=E||"b";G.queueFx(C,function(){B=p(D).getFxRestore();I=p(D).getWidth();F=p(D).getHeight();function L(){C.useDisplay?p(D).setDisplayed(t):p(D).hide();p(D).clearOpacity();p(D).setPositioning(B.pos);J.width=B.width;J.height=B.height;p(D).afterFx(C)}K.by=p(D).switchStatements(E.toLowerCase(),function(N,M){return[N,M]},{t:[0,-F],l:[-I,0],r:[I,0],b:[0,F],tl:[-I,-F],bl:[-I,F],br:[I,F],tr:[I,-F]});arguments.callee.anim=p(D).fxanim(H,C,e,0.5,r,L)});return G},syncFx:function(){var B=this;B.fxDefaults=Ext.apply(B.fxDefaults||{},{block:t,concurrent:k,stopFx:t});return B},sequenceFx:function(){var B=this;B.fxDefaults=Ext.apply(B.fxDefaults||{},{block:t,concurrent:t,stopFx:t});return B},nextFx:function(){var B=c(this.dom.id)[0];if(B){B.call(this)}},hasActiveFx:function(){return c(this.dom.id)[0]},stopFx:function(B){var C=this,E=C.dom.id;if(C.hasActiveFx()){var D=c(E)[0];if(D&&D.anim){if(D.anim.isAnimated){b(E,[D]);D.anim.stop(B!==undefined?B:k)}else{b(E,[])}}}return C},beforeFx:function(B){if(this.hasActiveFx()&&!B.concurrent){if(B.stopFx){this.stopFx();return k}return t}return k},hasFxBlock:function(){var B=c(this.dom.id);return B&&B[0]&&B[0].block},queueFx:function(E,B){var C=p(this.dom);if(!C.hasFxBlock()){Ext.applyIf(E,C.fxDefaults);if(!E.concurrent){var D=C.beforeFx(E);B.block=E.block;c(C.dom.id).push(B);if(D){C.nextFx()}}else{B.call(C)}}return C},fxWrap:function(H,F,D){var E=this.dom,C,B;if(!F.wrap||!(C=Ext.getDom(F.wrap))){if(F.fixPosition){B=p(E).getXY()}var G=document.createElement("div");G.style.visibility=D;C=E.parentNode.insertBefore(G,E);p(C).setPositioning(H);if(p(C).isStyle(o,"static")){p(C).position("relative")}p(E).clearPositioning("auto");p(C).clip();C.appendChild(E);if(B){p(C).setXY(B)}}return C},fxUnwrap:function(C,F,E){var D=this.dom;p(D).clearPositioning();p(D).setPositioning(F);if(!E.wrap){var B=p(C).dom.parentNode;B.insertBefore(D,C);p(C).remove()}},getFxRestore:function(){var B=this.dom.style;return{pos:this.getPositioning(),width:B.width,height:B.height}},afterFx:function(C){var B=this.dom,D=B.id;if(C.afterStyle){p(B).setStyle(C.afterStyle)}if(C.afterCls){p(B).addClass(C.afterCls)}if(C.remove==k){p(B).remove()}if(C.callback){C.callback.call(C.scope,p(B))}if(!C.concurrent){c(D).shift();p(B).nextFx()}},fxanim:function(E,F,C,G,D,B){C=C||"run";F=F||{};var H=Ext.lib.Anim[C](this.dom,E,(F.duration||G)||0.35,(F.easing||D)||r,B,this);F.anim=H;return H}};Ext.Fx.resize=Ext.Fx.scale;Ext.Element.addMethods(Ext.Fx)})();Ext.CompositeElementLite=function(b,a){this.elements=[];this.add(b,a);this.el=new Ext.Element.Flyweight()};Ext.CompositeElementLite.prototype={isComposite:true,getElement:function(a){var b=this.el;b.dom=a;b.id=a.id;return b},transformElement:function(a){return Ext.getDom(a)},getCount:function(){return this.elements.length},add:function(d,b){var e=this,g=e.elements;if(!d){return this}if(typeof d=="string"){d=Ext.Element.selectorFunction(d,b)}else{if(d.isComposite){d=d.elements}else{if(!Ext.isIterable(d)){d=[d]}}}for(var c=0,a=d.length;c<a;++c){g.push(e.transformElement(d[c]))}return e},invoke:function(g,b){var h=this,d=h.elements,a=d.length,j,c;for(c=0;c<a;c++){j=d[c];if(j){Ext.Element.prototype[g].apply(h.getElement(j),b)}}return h},item:function(b){var d=this,c=d.elements[b],a=null;if(c){a=d.getElement(c)}return a},addListener:function(b,j,h,g){var d=this.elements,a=d.length,c,k;for(c=0;c<a;c++){k=d[c];if(k){Ext.EventManager.on(k,b,j,h||k,g)}}return this},each:function(g,d){var h=this,c=h.elements,a=c.length,b,j;for(b=0;b<a;b++){j=c[b];if(j){j=this.getElement(j);if(g.call(d||j,j,h,b)===false){break}}}return h},fill:function(a){var b=this;b.elements=[];b.add(a);return b},filter:function(a){var b=[],d=this,c=Ext.isFunction(a)?a:function(e){return e.is(a)};d.each(function(h,e,g){if(c(h,g)!==false){b[b.length]=d.transformElement(h)}});d.elements=b;return d},indexOf:function(a){return this.elements.indexOf(this.transformElement(a))},replaceElement:function(e,c,a){var b=!isNaN(e)?e:this.indexOf(e),g;if(b>-1){c=Ext.getDom(c);if(a){g=this.elements[b];g.parentNode.insertBefore(c,g);Ext.removeNode(g)}this.elements.splice(b,1,c)}return this},clear:function(){this.elements=[]}};Ext.CompositeElementLite.prototype.on=Ext.CompositeElementLite.prototype.addListener;Ext.CompositeElementLite.importElementMethods=function(){var c,b=Ext.Element.prototype,a=Ext.CompositeElementLite.prototype;for(c in b){if(typeof b[c]=="function"){(function(d){a[d]=a[d]||function(){return this.invoke(d,arguments)}}).call(a,c)}}};Ext.CompositeElementLite.importElementMethods();if(Ext.DomQuery){Ext.Element.selectorFunction=Ext.DomQuery.select}Ext.Element.select=function(a,b){var c;if(typeof a=="string"){c=Ext.Element.selectorFunction(a,b)}else{if(a.length!==undefined){c=a}else{throw"Invalid selector"}}return new Ext.CompositeElementLite(c)};Ext.select=Ext.Element.select;(function(){var b="beforerequest",e="requestcomplete",d="requestexception",h=undefined,c="load",i="POST",a="GET",g=window;Ext.data.Connection=function(j){Ext.apply(this,j);this.addEvents(b,e,d);Ext.data.Connection.superclass.constructor.call(this)};Ext.extend(Ext.data.Connection,Ext.util.Observable,{timeout:30000,autoAbort:false,disableCaching:true,disableCachingParam:"_dc",request:function(n){var s=this;if(s.fireEvent(b,s,n)){if(n.el){if(!Ext.isEmpty(n.indicatorText)){s.indicatorText='<div class="loading-indicator">'+n.indicatorText+"</div>"}if(s.indicatorText){Ext.getDom(n.el).innerHTML=s.indicatorText}n.success=(Ext.isFunction(n.success)?n.success:function(){}).createInterceptor(function(o){Ext.getDom(n.el).innerHTML=o.responseText})}var l=n.params,k=n.url||s.url,j,q={success:s.handleResponse,failure:s.handleFailure,scope:s,argument:{options:n},timeout:Ext.num(n.timeout,s.timeout)},m,t;if(Ext.isFunction(l)){l=l.call(n.scope||g,n)}l=Ext.urlEncode(s.extraParams,Ext.isObject(l)?Ext.urlEncode(l):l);if(Ext.isFunction(k)){k=k.call(n.scope||g,n)}if((m=Ext.getDom(n.form))){k=k||m.action;if(n.isUpload||(/multipart\/form-data/i.test(m.getAttribute("enctype")))){return s.doFormUpload.call(s,n,l,k)}t=Ext.lib.Ajax.serializeForm(m);l=l?(l+"&"+t):t}j=n.method||s.method||((l||n.xmlData||n.jsonData)?i:a);if(j===a&&(s.disableCaching&&n.disableCaching!==false)||n.disableCaching===true){var r=n.disableCachingParam||s.disableCachingParam;k=Ext.urlAppend(k,r+"="+(new Date().getTime()))}n.headers=Ext.applyIf(n.headers||{},s.defaultHeaders||{});if(n.autoAbort===true||s.autoAbort){s.abort()}if((j==a||n.xmlData||n.jsonData)&&l){k=Ext.urlAppend(k,l);l=""}return(s.transId=Ext.lib.Ajax.request(j,k,q,l,n))}else{return n.callback?n.callback.apply(n.scope,[n,h,h]):null}},isLoading:function(j){return j?Ext.lib.Ajax.isCallInProgress(j):!!this.transId},abort:function(j){if(j||this.isLoading()){Ext.lib.Ajax.abort(j||this.transId)}},handleResponse:function(j){this.transId=false;var k=j.argument.options;j.argument=k?k.argument:null;this.fireEvent(e,this,j,k);if(k.success){k.success.call(k.scope,j,k)}if(k.callback){k.callback.call(k.scope,k,true,j)}},handleFailure:function(j,l){this.transId=false;var k=j.argument.options;j.argument=k?k.argument:null;this.fireEvent(d,this,j,k,l);if(k.failure){k.failure.call(k.scope,j,k)}if(k.callback){k.callback.call(k.scope,k,false,j)}},doFormUpload:function(q,j,k){var l=Ext.id(),v=document,r=v.createElement("iframe"),m=Ext.getDom(q.form),u=[],t,p="multipart/form-data",n={target:m.target,method:m.method,encoding:m.encoding,enctype:m.enctype,action:m.action};Ext.fly(r).set({id:l,name:l,cls:"x-hidden",src:Ext.SSL_SECURE_URL});v.body.appendChild(r);if(Ext.isIE){document.frames[l].name=l}Ext.fly(m).set({target:l,method:i,enctype:p,encoding:p,action:k||n.action});Ext.iterate(Ext.urlDecode(j,false),function(w,o){t=v.createElement("input");Ext.fly(t).set({type:"hidden",value:o,name:w});m.appendChild(t);u.push(t)});function s(){var x=this,w={responseText:"",responseXML:null,argument:q.argument},A,z;try{A=r.contentWindow.document||r.contentDocument||g.frames[l].document;if(A){if(A.body){if(/textarea/i.test((z=A.body.firstChild||{}).tagName)){w.responseText=z.value}else{w.responseText=A.body.innerHTML}}w.responseXML=A.XMLDocument||A}}catch(y){}Ext.EventManager.removeListener(r,c,s,x);x.fireEvent(e,x,w,q);function o(D,C,B){if(Ext.isFunction(D)){D.apply(C,B)}}o(q.success,q.scope,[w,q]);o(q.callback,q.scope,[q,true,w]);if(!x.debugUploads){setTimeout(function(){Ext.removeNode(r)},100)}}Ext.EventManager.on(r,c,s,this);m.submit();Ext.fly(m).set(n);Ext.each(u,function(o){Ext.removeNode(o)})}})})();Ext.Ajax=new Ext.data.Connection({autoAbort:false,serializeForm:function(a){return Ext.lib.Ajax.serializeForm(a)}});Ext.util.JSON=new (function(){var useHasOwn=!!{}.hasOwnProperty,isNative=function(){var useNative=null;return function(){if(useNative===null){useNative=Ext.USE_NATIVE_JSON&&window.JSON&&JSON.toString()=="[object JSON]"}return useNative}}(),pad=function(n){return n<10?"0"+n:n},doDecode=function(json){return json?eval("("+json+")"):""},doEncode=function(o){if(!Ext.isDefined(o)||o===null){return"null"}else{if(Ext.isArray(o)){return encodeArray(o)}else{if(Ext.isDate(o)){return Ext.util.JSON.encodeDate(o)}else{if(Ext.isString(o)){return encodeString(o)}else{if(typeof o=="number"){return isFinite(o)?String(o):"null"}else{if(Ext.isBoolean(o)){return String(o)}else{var a=["{"],b,i,v;for(i in o){if(!o.getElementsByTagName){if(!useHasOwn||o.hasOwnProperty(i)){v=o[i];switch(typeof v){case"undefined":case"function":case"unknown":break;default:if(b){a.push(",")}a.push(doEncode(i),":",v===null?"null":doEncode(v));b=true}}}}a.push("}");return a.join("")}}}}}}},m={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},encodeString=function(s){if(/["\\\x00-\x1f]/.test(s)){return'"'+s.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c}c=b.charCodeAt();return"\\u00"+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"'}return'"'+s+'"'},encodeArray=function(o){var a=["["],b,i,l=o.length,v;for(i=0;i<l;i+=1){v=o[i];switch(typeof v){case"undefined":case"function":case"unknown":break;default:if(b){a.push(",")}a.push(v===null?"null":Ext.util.JSON.encode(v));b=true}}a.push("]");return a.join("")};this.encodeDate=function(o){return'"'+o.getFullYear()+"-"+pad(o.getMonth()+1)+"-"+pad(o.getDate())+"T"+pad(o.getHours())+":"+pad(o.getMinutes())+":"+pad(o.getSeconds())+'"'};this.encode=function(){var ec;return function(o){if(!ec){ec=isNative()?JSON.stringify:doEncode}return ec(o)}}();this.decode=function(){var dc;return function(json){if(!dc){dc=isNative()?JSON.parse:doDecode}return dc(json)}}()})();Ext.encode=Ext.util.JSON.encode;Ext.decode=Ext.util.JSON.decode;Ext.EventManager=function(){var z,p,j=false,l=Ext.isGecko||Ext.isWebKit||Ext.isSafari,o=Ext.lib.Event,q=Ext.lib.Dom,c=document,A=window,r="DOMContentLoaded",t="complete",g=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,u=[];function n(E){var H=false,D=0,C=u.length,F=false,G;if(E){if(E.getElementById||E.navigator){for(;D<C;++D){G=u[D];if(G.el===E){H=G.id;break}}if(!H){H=Ext.id(E);u.push({id:H,el:E});F=true}}else{H=Ext.id(E)}if(!Ext.elCache[H]){Ext.Element.addToCache(new Ext.Element(E),H);if(F){Ext.elCache[H].skipGC=true}}}return H}function m(E,G,J,F,D,L){E=Ext.getDom(E);var C=n(E),K=Ext.elCache[C].events,H;H=o.on(E,G,D);K[G]=K[G]||[];K[G].push([J,D,L,H,F]);if(E.addEventListener&&G=="mousewheel"){var I=["DOMMouseScroll",D,false];E.addEventListener.apply(E,I);Ext.EventManager.addListener(A,"unload",function(){E.removeEventListener.apply(E,I)})}if(E==c&&G=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.addListener(D)}}function d(){if(window!=top){return false}try{c.documentElement.doScroll("left")}catch(C){return false}b();return true}function B(C){if(Ext.isIE&&d()){return true}if(c.readyState==t){b();return true}j||(p=setTimeout(arguments.callee,2));return false}var k;function i(C){k||(k=Ext.query("style, link[rel=stylesheet]"));if(k.length==c.styleSheets.length){b();return true}j||(p=setTimeout(arguments.callee,2));return false}function y(C){c.removeEventListener(r,arguments.callee,false);i()}function b(C){if(!j){j=true;if(p){clearTimeout(p)}if(l){c.removeEventListener(r,b,false)}if(Ext.isIE&&B.bindIE){c.detachEvent("onreadystatechange",B)}o.un(A,"load",arguments.callee)}if(z&&!Ext.isReady){Ext.isReady=true;z.fire();z.listeners=[]}}function a(){z||(z=new Ext.util.Event());if(l){c.addEventListener(r,b,false)}if(Ext.isIE){if(!B()){B.bindIE=true;c.attachEvent("onreadystatechange",B)}}else{if(Ext.isOpera){(c.readyState==t&&i())||c.addEventListener(r,y,false)}else{if(Ext.isWebKit){B()}}}o.on(A,"load",b)}function x(C,D){return function(){var E=Ext.toArray(arguments);if(D.target==Ext.EventObject.setEvent(E[0]).target){C.apply(this,E)}}}function w(D,E,C){return function(F){C.delay(E.buffer,D,null,[new Ext.EventObjectImpl(F)])}}function s(G,F,C,E,D){return function(H){Ext.EventManager.removeListener(F,C,E,D);G(H)}}function e(D,E,C){return function(G){var F=new Ext.util.DelayedTask(D);if(!C.tasks){C.tasks=[]}C.tasks.push(F);F.delay(E.delay||10,D,null,[new Ext.EventObjectImpl(G)])}}function h(H,G,C,J,K){var D=(!C||typeof C=="boolean")?{}:C,E=Ext.getDom(H),F;J=J||D.fn;K=K||D.scope;if(!E){throw'Error listening for "'+G+'". Element "'+H+"\" doesn't exist."}function I(M){if(!Ext){return}M=Ext.EventObject.setEvent(M);var L;if(D.delegate){if(!(L=M.getTarget(D.delegate,E))){return}}else{L=M.target}if(D.stopEvent){M.stopEvent()}if(D.preventDefault){M.preventDefault()}if(D.stopPropagation){M.stopPropagation()}if(D.normalized===false){M=M.browserEvent}J.call(K||E,M,L,D)}if(D.target){I=x(I,D)}if(D.delay){I=e(I,D,J)}if(D.single){I=s(I,E,G,J,K)}if(D.buffer){F=new Ext.util.DelayedTask(I);I=w(I,D,F)}m(E,G,J,F,I,K);return I}var v={addListener:function(E,C,G,F,D){if(typeof C=="object"){var J=C,H,I;for(H in J){I=J[H];if(!g.test(H)){if(Ext.isFunction(I)){h(E,H,J,I,J.scope)}else{h(E,H,I)}}}}else{h(E,C,D,G,F)}},removeListener:function(E,I,M,N){E=Ext.getDom(E);var C=n(E),K=E&&(Ext.elCache[C].events)[I]||[],D,H,F,G,J,L;for(H=0,J=K.length;H<J;H++){if(Ext.isArray(L=K[H])&&L[0]==M&&(!N||L[2]==N)){if(L[4]){L[4].cancel()}G=M.tasks&&M.tasks.length;if(G){while(G--){M.tasks[G].cancel()}delete M.tasks}D=L[1];o.un(E,I,o.extAdapter?L[3]:D);if(D&&E.addEventListener&&I=="mousewheel"){E.removeEventListener("DOMMouseScroll",D,false)}if(D&&E==c&&I=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.removeListener(D)}K.splice(H,1);if(K.length===0){delete Ext.elCache[C].events[I]}for(G in Ext.elCache[C].events){return false}Ext.elCache[C].events={};return false}}},removeAll:function(E){E=Ext.getDom(E);var D=n(E),J=Ext.elCache[D]||{},M=J.events||{},I,H,K,F,L,G,C;for(F in M){if(M.hasOwnProperty(F)){I=M[F];for(H=0,K=I.length;H<K;H++){L=I[H];if(L[4]){L[4].cancel()}if(L[0].tasks&&(G=L[0].tasks.length)){while(G--){L[0].tasks[G].cancel()}delete L.tasks}C=L[1];o.un(E,F,o.extAdapter?L[3]:C);if(E.addEventListener&&C&&F=="mousewheel"){E.removeEventListener("DOMMouseScroll",C,false)}if(C&&E==c&&F=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.removeListener(C)}}}}if(Ext.elCache[D]){Ext.elCache[D].events={}}},getListeners:function(F,C){F=Ext.getDom(F);var H=n(F),D=Ext.elCache[H]||{},G=D.events||{},E=[];if(G&&G[C]){return G[C]}else{return null}},purgeElement:function(E,C,G){E=Ext.getDom(E);var D=n(E),J=Ext.elCache[D]||{},K=J.events||{},F,I,H;if(G){if(K&&K.hasOwnProperty(G)){I=K[G];for(F=0,H=I.length;F<H;F++){Ext.EventManager.removeListener(E,G,I[F][0])}}}else{Ext.EventManager.removeAll(E)}if(C&&E&&E.childNodes){for(F=0,H=E.childNodes.length;F<H;F++){Ext.EventManager.purgeElement(E.childNodes[F],C,G)}}},_unload:function(){var C;for(C in Ext.elCache){Ext.EventManager.removeAll(C)}delete Ext.elCache;delete Ext.Element._flyweights;var G,D,F,E=Ext.lib.Ajax;(typeof E.conn=="object")?D=E.conn:D={};for(F in D){G=D[F];if(G){E.abort({conn:G,tId:F})}}},onDocumentReady:function(E,D,C){if(Ext.isReady){z||(z=new Ext.util.Event());z.addListener(E,D,C);z.fire();z.listeners=[]}else{if(!z){a()}C=C||{};C.delay=C.delay||1;z.addListener(E,D,C)}},fireDocReady:b};v.on=v.addListener;v.un=v.removeListener;v.stoppedMouseDownEvent=new Ext.util.Event();return v}();Ext.onReady=Ext.EventManager.onDocumentReady;(function(){var a=function(){var c=document.body||document.getElementsByTagName("body")[0];if(!c){return false}var b=[" ",Ext.isIE?"ext-ie "+(Ext.isIE6?"ext-ie6":(Ext.isIE7?"ext-ie7":(Ext.isIE8?"ext-ie8":"ext-ie9"))):Ext.isGecko?"ext-gecko "+(Ext.isGecko2?"ext-gecko2":"ext-gecko3"):Ext.isOpera?"ext-opera":Ext.isWebKit?"ext-webkit":""];if(Ext.isSafari){b.push("ext-safari "+(Ext.isSafari2?"ext-safari2":(Ext.isSafari3?"ext-safari3":"ext-safari4")))}else{if(Ext.isChrome){b.push("ext-chrome")}}if(Ext.isMac){b.push("ext-mac")}if(Ext.isLinux){b.push("ext-linux")}if(Ext.isStrict||Ext.isBorderBox){var d=c.parentNode;if(d){if(!Ext.isStrict){Ext.fly(d,"_internal").addClass("x-quirks");if(Ext.isIE&&!Ext.isStrict){Ext.isIEQuirks=true}}Ext.fly(d,"_internal").addClass(((Ext.isStrict&&Ext.isIE)||(!Ext.enableForcedBoxModel&&!Ext.isIE))?" ext-strict":" ext-border-box")}}if(Ext.enableForcedBoxModel&&!Ext.isIE){Ext.isForcedBorderBox=true;b.push("ext-forced-border-box")}Ext.fly(c,"_internal").addClass(b);return true};if(!a()){Ext.onReady(a)}})();(function(){var b=Ext.apply(Ext.supports,{correctRightMargin:true,correctTransparentColor:true,cssFloat:true});var a=function(){var g=document.createElement("div"),e=document,c,d;g.innerHTML='<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';e.body.appendChild(g);d=g.lastChild;if((c=e.defaultView)){if(c.getComputedStyle(g.firstChild.firstChild,null).marginRight!="0px"){b.correctRightMargin=false}if(c.getComputedStyle(d,null).backgroundColor!="transparent"){b.correctTransparentColor=false}}b.cssFloat=!!d.style.cssFloat;e.body.removeChild(g)};if(Ext.isReady){a()}else{Ext.onReady(a)}})();Ext.EventObject=function(){var b=Ext.lib.Event,c=/(dbl)?click/,a={3:13,63234:37,63235:39,63232:38,63233:40,63276:33,63277:34,63272:46,63273:36,63275:35},d=Ext.isIE?{1:0,4:1,2:2}:{0:0,1:1,2:2};Ext.EventObjectImpl=function(g){if(g){this.setEvent(g.browserEvent||g)}};Ext.EventObjectImpl.prototype={setEvent:function(h){var g=this;if(h==g||(h&&h.browserEvent)){return h}g.browserEvent=h;if(h){g.button=h.button?d[h.button]:(h.which?h.which-1:-1);if(c.test(h.type)&&g.button==-1){g.button=0}g.type=h.type;g.shiftKey=h.shiftKey;g.ctrlKey=h.ctrlKey||h.metaKey||false;g.altKey=h.altKey;g.keyCode=h.keyCode;g.charCode=h.charCode;g.target=b.getTarget(h);g.xy=b.getXY(h)}else{g.button=-1;g.shiftKey=false;g.ctrlKey=false;g.altKey=false;g.keyCode=0;g.charCode=0;g.target=null;g.xy=[0,0]}return g},stopEvent:function(){var e=this;if(e.browserEvent){if(e.browserEvent.type=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.fire(e)}b.stopEvent(e.browserEvent)}},preventDefault:function(){if(this.browserEvent){b.preventDefault(this.browserEvent)}},stopPropagation:function(){var e=this;if(e.browserEvent){if(e.browserEvent.type=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.fire(e)}b.stopPropagation(e.browserEvent)}},getCharCode:function(){return this.charCode||this.keyCode},getKey:function(){return this.normalizeKey(this.keyCode||this.charCode)},normalizeKey:function(e){return Ext.isSafari?(a[e]||e):e},getPageX:function(){return this.xy[0]},getPageY:function(){return this.xy[1]},getXY:function(){return this.xy},getTarget:function(g,h,e){return g?Ext.fly(this.target).findParent(g,h,e):(e?Ext.get(this.target):this.target)},getRelatedTarget:function(){return this.browserEvent?b.getRelatedTarget(this.browserEvent):null},getWheelDelta:function(){var g=this.browserEvent;var h=0;if(g.wheelDelta){h=g.wheelDelta/120}else{if(g.detail){h=-g.detail/3}}return h},within:function(h,i,e){if(h){var g=this[i?"getRelatedTarget":"getTarget"]();return g&&((e?(g==Ext.getDom(h)):false)||Ext.fly(h).contains(g))}return false}};return new Ext.EventObjectImpl()}();Ext.Loader=Ext.apply({},{load:function(j,i,k,c){var k=k||this,g=document.getElementsByTagName("head")[0],b=document.createDocumentFragment(),a=j.length,h=0,e=this;var l=function(m){g.appendChild(e.buildScriptTag(j[m],d))};var d=function(){h++;if(a==h&&typeof i=="function"){i.call(k)}else{if(c===true){l(h)}}};if(c===true){l.call(this,0)}else{Ext.each(j,function(n,m){b.appendChild(this.buildScriptTag(n,d))},this);g.appendChild(b)}},buildScriptTag:function(b,c){var a=document.createElement("script");a.type="text/javascript";a.src=b;if(a.readyState){a.onreadystatechange=function(){if(a.readyState=="loaded"||a.readyState=="complete"){a.onreadystatechange=null;c()}}}else{a.onload=c}return a}});Ext.ns("Ext.grid","Ext.list","Ext.dd","Ext.tree","Ext.form","Ext.menu","Ext.state","Ext.layout.boxOverflow","Ext.app","Ext.ux","Ext.chart","Ext.direct","Ext.slider");Ext.apply(Ext,function(){var c=Ext,a=0,b=null;return{emptyFn:function(){},BLANK_IMAGE_URL:Ext.isIE6||Ext.isIE7||Ext.isAir?"http://www.extjs.com/s.gif":"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",extendX:function(d,e){return Ext.extend(d,e(d.prototype))},getDoc:function(){return Ext.get(document)},num:function(e,d){e=Number(Ext.isEmpty(e)||Ext.isArray(e)||typeof e=="boolean"||(typeof e=="string"&&e.trim().length==0)?NaN:e);return isNaN(e)?d:e},value:function(g,d,e){return Ext.isEmpty(g,e)?d:g},escapeRe:function(d){return d.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1")},sequence:function(h,d,g,e){h[d]=h[d].createSequence(g,e)},addBehaviors:function(i){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(i)})}else{var e={},h,d,g;for(d in i){if((h=d.split("@"))[1]){g=h[0];if(!e[g]){e[g]=Ext.select(g)}e[g].on(h[1],i[d])}}e=null}},getScrollBarWidth:function(g){if(!Ext.isReady){return 0}if(g===true||b===null){var i=Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),h=i.child("div",true);var e=h.offsetWidth;i.setStyle("overflow",(Ext.isWebKit||Ext.isGecko)?"auto":"scroll");var d=h.offsetWidth;i.remove();b=e-d+2}return b},combine:function(){var g=arguments,e=g.length,j=[];for(var h=0;h<e;h++){var d=g[h];if(Ext.isArray(d)){j=j.concat(d)}else{if(d.length!==undefined&&!d.substr){j=j.concat(Array.prototype.slice.call(d,0))}else{j.push(d)}}}return j},copyTo:function(d,e,g){if(typeof g=="string"){g=g.split(/[,;\s]/)}Ext.each(g,function(h){if(e.hasOwnProperty(h)){d[h]=e[h]}},this);return d},destroy:function(){Ext.each(arguments,function(d){if(d){if(Ext.isArray(d)){this.destroy.apply(this,d)}else{if(typeof d.destroy=="function"){d.destroy()}else{if(d.dom){d.remove()}}}}},this)},destroyMembers:function(l,j,g,h){for(var k=1,e=arguments,d=e.length;k<d;k++){Ext.destroy(l[e[k]]);delete l[e[k]]}},clean:function(d){var e=[];Ext.each(d,function(g){if(!!g){e.push(g)}});return e},unique:function(d){var e=[],g={};Ext.each(d,function(h){if(!g[h]){e.push(h)}g[h]=true});return e},flatten:function(d){var g=[];function e(h){Ext.each(h,function(i){if(Ext.isArray(i)){e(i)}else{g.push(i)}});return g}return e(d)},min:function(d,e){var g=d[0];e=e||function(i,h){return i<h?-1:1};Ext.each(d,function(h){g=e(g,h)==-1?g:h});return g},max:function(d,e){var g=d[0];e=e||function(i,h){return i>h?1:-1};Ext.each(d,function(h){g=e(g,h)==1?g:h});return g},mean:function(d){return d.length>0?Ext.sum(d)/d.length:undefined},sum:function(d){var e=0;Ext.each(d,function(g){e+=g});return e},partition:function(d,e){var g=[[],[]];Ext.each(d,function(j,k,h){g[(e&&e(j,k,h))||(!e&&j)?0:1].push(j)});return g},invoke:function(d,e){var h=[],g=Array.prototype.slice.call(arguments,2);Ext.each(d,function(j,k){if(j&&typeof j[e]=="function"){h.push(j[e].apply(j,g))}else{h.push(undefined)}});return h},pluck:function(d,g){var e=[];Ext.each(d,function(h){e.push(h[g])});return e},zip:function(){var n=Ext.partition(arguments,function(i){return typeof i!="function"}),k=n[0],m=n[1][0],d=Ext.max(Ext.pluck(k,"length")),h=[];for(var l=0;l<d;l++){h[l]=[];if(m){h[l]=m.apply(m,Ext.pluck(k,l))}else{for(var g=0,e=k.length;g<e;g++){h[l].push(k[g][l])}}}return h},getCmp:function(d){return Ext.ComponentMgr.get(d)},useShims:c.isIE6||(c.isMac&&c.isGecko2),type:function(e){if(e===undefined||e===null){return false}if(e.htmlElement){return"element"}var d=typeof e;if(d=="object"&&e.nodeName){switch(e.nodeType){case 1:return"element";case 3:return(/\S/).test(e.nodeValue)?"textnode":"whitespace"}}if(d=="object"||d=="function"){switch(e.constructor){case Array:return"array";case RegExp:return"regexp";case Date:return"date"}if(typeof e.length=="number"&&typeof e.item=="function"){return"nodelist"}}return d},intercept:function(h,d,g,e){h[d]=h[d].createInterceptor(g,e)},callback:function(d,h,g,e){if(typeof d=="function"){if(e){d.defer(e,h,g||[])}else{d.apply(h,g||[])}}}}}());Ext.apply(Function.prototype,{createSequence:function(b,a){var c=this;return(typeof b!="function")?this:function(){var d=c.apply(this||window,arguments);b.apply(a||this||window,arguments);return d}}});Ext.applyIf(String,{escape:function(a){return a.replace(/('|\\)/g,"\\$1")},leftPad:function(d,b,c){var a=String(d);if(!c){c=" "}while(a.length<b){a=c+a}return a}});String.prototype.toggle=function(b,a){return this==b?a:b};String.prototype.trim=function(){var a=/^\s+|\s+$/g;return function(){return this.replace(a,"")}}();Date.prototype.getElapsed=function(a){return Math.abs((a||new Date()).getTime()-this.getTime())};Ext.applyIf(Number.prototype,{constrain:function(b,a){return Math.min(Math.max(this,b),a)}});Ext.lib.Dom.getRegion=function(a){return Ext.lib.Region.getRegion(a)};Ext.lib.Region=function(d,g,a,c){var e=this;e.top=d;e[1]=d;e.right=g;e.bottom=a;e.left=c;e[0]=c};Ext.lib.Region.prototype={contains:function(b){var a=this;return(b.left>=a.left&&b.right<=a.right&&b.top>=a.top&&b.bottom<=a.bottom)},getArea:function(){var a=this;return((a.bottom-a.top)*(a.right-a.left))},intersect:function(h){var g=this,d=Math.max(g.top,h.top),e=Math.min(g.right,h.right),a=Math.min(g.bottom,h.bottom),c=Math.max(g.left,h.left);if(a>=d&&e>=c){return new Ext.lib.Region(d,e,a,c)}},union:function(h){var g=this,d=Math.min(g.top,h.top),e=Math.max(g.right,h.right),a=Math.max(g.bottom,h.bottom),c=Math.min(g.left,h.left);return new Ext.lib.Region(d,e,a,c)},constrainTo:function(b){var a=this;a.top=a.top.constrain(b.top,b.bottom);a.bottom=a.bottom.constrain(b.top,b.bottom);a.left=a.left.constrain(b.left,b.right);a.right=a.right.constrain(b.left,b.right);return a},adjust:function(d,c,a,g){var e=this;e.top+=d;e.left+=c;e.right+=g;e.bottom+=a;return e}};Ext.lib.Region.getRegion=function(e){var h=Ext.lib.Dom.getXY(e),d=h[1],g=h[0]+e.offsetWidth,a=h[1]+e.offsetHeight,c=h[0];return new Ext.lib.Region(d,g,a,c)};Ext.lib.Point=function(a,c){if(Ext.isArray(a)){c=a[1];a=a[0]}var b=this;b.x=b.right=b.left=b[0]=a;b.y=b.top=b.bottom=b[1]=c};Ext.lib.Point.prototype=new Ext.lib.Region();Ext.apply(Ext.DomHelper,function(){var e,a="afterbegin",h="afterend",i="beforebegin",d="beforeend",b=/tag|children|cn|html$/i;function g(m,p,n,q,l,j){m=Ext.getDom(m);var k;if(e.useDom){k=c(p,null);if(j){m.appendChild(k)}else{(l=="firstChild"?m:m.parentNode).insertBefore(k,m[l]||m)}}else{k=Ext.DomHelper.insertHtml(q,m,Ext.DomHelper.createHtml(p))}return n?Ext.get(k,true):k}function c(j,r){var k,u=document,p,s,m,t;if(Ext.isArray(j)){k=u.createDocumentFragment();for(var q=0,n=j.length;q<n;q++){c(j[q],k)}}else{if(typeof j=="string"){k=u.createTextNode(j)}else{k=u.createElement(j.tag||"div");p=!!k.setAttribute;for(var s in j){if(!b.test(s)){m=j[s];if(s=="cls"){k.className=m}else{if(p){k.setAttribute(s,m)}else{k[s]=m}}}}Ext.DomHelper.applyStyles(k,j.style);if((t=j.children||j.cn)){c(t,k)}else{if(j.html){k.innerHTML=j.html}}}}if(r){r.appendChild(k)}return k}e={createTemplate:function(k){var j=Ext.DomHelper.createHtml(k);return new Ext.Template(j)},useDom:false,insertBefore:function(j,l,k){return g(j,l,k,i)},insertAfter:function(j,l,k){return g(j,l,k,h,"nextSibling")},insertFirst:function(j,l,k){return g(j,l,k,a,"firstChild")},append:function(j,l,k){return g(j,l,k,d,"",true)},createDom:c};return e}());Ext.apply(Ext.Template.prototype,{disableFormats:false,re:/\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,argsRe:/^\s*['"](.*)["']\s*$/,compileARe:/\\/g,compileBRe:/(\r\n|\n)/g,compileCRe:/'/g,applyTemplate:function(b){var g=this,a=g.disableFormats!==true,e=Ext.util.Format,c=g;if(g.compiled){return g.compiled(b)}function d(j,l,p,k){if(p&&a){if(p.substr(0,5)=="this."){return c.call(p.substr(5),b[l],b)}else{if(k){var o=g.argsRe;k=k.split(",");for(var n=0,h=k.length;n<h;n++){k[n]=k[n].replace(o,"$1")}k=[b[l]].concat(k)}else{k=[b[l]]}return e[p].apply(e,k)}}else{return b[l]!==undefined?b[l]:""}}return g.html.replace(g.re,d)},compile:function(){var me=this,fm=Ext.util.Format,useF=me.disableFormats!==true,sep=Ext.isGecko?"+":",",body;function fn(m,name,format,args){if(format&&useF){args=args?","+args:"";if(format.substr(0,5)!="this."){format="fm."+format+"("}else{format='this.call("'+format.substr(5)+'", ';args=", values"}}else{args="";format="(values['"+name+"'] == undefined ? '' : "}return"'"+sep+format+"values['"+name+"']"+args+")"+sep+"'"}if(Ext.isGecko){body="this.compiled = function(values){ return '"+me.html.replace(me.compileARe,"\\\\").replace(me.compileBRe,"\\n").replace(me.compileCRe,"\\'").replace(me.re,fn)+"';};"}else{body=["this.compiled = function(values){ return ['"];body.push(me.html.replace(me.compileARe,"\\\\").replace(me.compileBRe,"\\n").replace(me.compileCRe,"\\'").replace(me.re,fn));body.push("'].join('');};");body=body.join("")}eval(body);return me},call:function(c,b,a){return this[c](b,a)}});Ext.Template.prototype.apply=Ext.Template.prototype.applyTemplate;Ext.util.Functions={createInterceptor:function(c,b,a){var d=c;if(!Ext.isFunction(b)){return c}else{return function(){var g=this,e=arguments;b.target=g;b.method=c;return(b.apply(a||g||window,e)!==false)?c.apply(g||window,e):null}}},createDelegate:function(c,d,b,a){if(!Ext.isFunction(c)){return c}return function(){var g=b||arguments;if(a===true){g=Array.prototype.slice.call(arguments,0);g=g.concat(b)}else{if(Ext.isNumber(a)){g=Array.prototype.slice.call(arguments,0);var e=[a,0].concat(b);Array.prototype.splice.apply(g,e)}}return c.apply(d||window,g)}},defer:function(d,c,e,b,a){d=Ext.util.Functions.createDelegate(d,e,b,a);if(c>0){return setTimeout(d,c)}d();return 0},createSequence:function(c,b,a){if(!Ext.isFunction(b)){return c}else{return function(){var d=c.apply(this||window,arguments);b.apply(a||this||window,arguments);return d}}}};Ext.defer=Ext.util.Functions.defer;Ext.createInterceptor=Ext.util.Functions.createInterceptor;Ext.createSequence=Ext.util.Functions.createSequence;Ext.createDelegate=Ext.util.Functions.createDelegate;Ext.apply(Ext.util.Observable.prototype,function(){function a(j){var i=(this.methodEvents=this.methodEvents||{})[j],d,c,g,h=this;if(!i){this.methodEvents[j]=i={};i.originalFn=this[j];i.methodName=j;i.before=[];i.after=[];var b=function(l,k,e){if((c=l.apply(k||h,e))!==undefined){if(typeof c=="object"){if(c.returnValue!==undefined){d=c.returnValue}else{d=c}g=!!c.cancel}else{if(c===false){g=true}else{d=c}}}};this[j]=function(){var l=Array.prototype.slice.call(arguments,0),k;d=c=undefined;g=false;for(var m=0,e=i.before.length;m<e;m++){k=i.before[m];b(k.fn,k.scope,l);if(g){return d}}if((c=i.originalFn.apply(h,l))!==undefined){d=c}for(var m=0,e=i.after.length;m<e;m++){k=i.after[m];b(k.fn,k.scope,l);if(g){return d}}return d}}return i}return{beforeMethod:function(d,c,b){a.call(this,d).before.push({fn:c,scope:b})},afterMethod:function(d,c,b){a.call(this,d).after.push({fn:c,scope:b})},removeMethodListener:function(j,g,d){var h=this.getMethodEvent(j);for(var c=0,b=h.before.length;c<b;c++){if(h.before[c].fn==g&&h.before[c].scope==d){h.before.splice(c,1);return}}for(var c=0,b=h.after.length;c<b;c++){if(h.after[c].fn==g&&h.after[c].scope==d){h.after.splice(c,1);return}}},relayEvents:function(j,e){var h=this;function g(i){return function(){return h.fireEvent.apply(h,[i].concat(Array.prototype.slice.call(arguments,0)))}}for(var d=0,b=e.length;d<b;d++){var c=e[d];h.events[c]=h.events[c]||true;j.on(c,g(c),h)}},enableBubble:function(e){var g=this;if(!Ext.isEmpty(e)){e=Ext.isArray(e)?e:Array.prototype.slice.call(arguments,0);for(var d=0,b=e.length;d<b;d++){var c=e[d];c=c.toLowerCase();var h=g.events[c]||true;if(typeof h=="boolean"){h=new Ext.util.Event(g,c);g.events[c]=h}h.bubble=true}}}}}());Ext.util.Observable.capture=function(c,b,a){c.fireEvent=c.fireEvent.createInterceptor(b,a)};Ext.util.Observable.observeClass=function(b,a){if(b){if(!b.fireEvent){Ext.apply(b,new Ext.util.Observable());Ext.util.Observable.capture(b.prototype,b.fireEvent,b)}if(typeof a=="object"){b.on(a)}return b}};Ext.apply(Ext.EventManager,function(){var d,k,g,b,a=Ext.lib.Dom,j=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,c=Ext.EventManager._unload,i=0,h=0,e=Ext.isWebKit?Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1])>=525:!((Ext.isGecko&&!Ext.isWindows)||Ext.isOpera);return{_unload:function(){Ext.EventManager.un(window,"resize",this.fireWindowResize,this);c.call(Ext.EventManager)},doResizeEvent:function(){var m=a.getViewHeight(),l=a.getViewWidth();if(h!=m||i!=l){d.fire(i=l,h=m)}},onWindowResize:function(n,m,l){if(!d){d=new Ext.util.Event();k=new Ext.util.DelayedTask(this.doResizeEvent);Ext.EventManager.on(window,"resize",this.fireWindowResize,this)}d.addListener(n,m,l)},fireWindowResize:function(){if(d){k.delay(100)}},onTextResize:function(o,n,l){if(!g){g=new Ext.util.Event();var m=new Ext.Element(document.createElement("div"));m.dom.className="x-text-resize";m.dom.innerHTML="X";m.appendTo(document.body);b=m.dom.offsetHeight;setInterval(function(){if(m.dom.offsetHeight!=b){g.fire(b,b=m.dom.offsetHeight)}},this.textResizeInterval)}g.addListener(o,n,l)},removeResizeListener:function(m,l){if(d){d.removeListener(m,l)}},fireResize:function(){if(d){d.fire(a.getViewWidth(),a.getViewHeight())}},textResizeInterval:50,ieDeferSrc:false,getKeyEvent:function(){return e?"keydown":"keypress"},useKeydown:e}}());Ext.EventManager.on=Ext.EventManager.addListener;Ext.apply(Ext.EventObjectImpl.prototype,{BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,RETURN:13,SHIFT:16,CTRL:17,CONTROL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGEUP:33,PAGE_DOWN:34,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,isNavKeyPress:function(){var b=this,a=this.normalizeKey(b.keyCode);return(a>=33&&a<=40)||a==b.RETURN||a==b.TAB||a==b.ESC},isSpecialKey:function(){var a=this.normalizeKey(this.keyCode);return(this.type=="keypress"&&this.ctrlKey)||this.isNavKeyPress()||(a==this.BACKSPACE)||(a>=16&&a<=20)||(a>=44&&a<=46)},getPoint:function(){return new Ext.lib.Point(this.xy[0],this.xy[1])},hasModifier:function(){return((this.ctrlKey||this.altKey)||this.shiftKey)}});Ext.Element.addMethods({swallowEvent:function(a,b){var d=this;function c(g){g.stopPropagation();if(b){g.preventDefault()}}if(Ext.isArray(a)){Ext.each(a,function(g){d.on(g,c)});return d}d.on(a,c);return d},relayEvent:function(a,b){this.on(a,function(c){b.fireEvent(a,c)})},clean:function(b){var d=this,e=d.dom,g=e.firstChild,c=-1;if(Ext.Element.data(e,"isCleaned")&&b!==true){return d}while(g){var a=g.nextSibling;if(g.nodeType==3&&!(/\S/.test(g.nodeValue))){e.removeChild(g)}else{g.nodeIndex=++c}g=a}Ext.Element.data(e,"isCleaned",true);return d},load:function(){var a=this.getUpdater();a.update.apply(a,arguments);return this},getUpdater:function(){return this.updateManager||(this.updateManager=new Ext.Updater(this))},update:function(html,loadScripts,callback){if(!this.dom){return this}html=html||"";if(loadScripts!==true){this.dom.innerHTML=html;if(typeof callback=="function"){callback()}return this}var id=Ext.id(),dom=this.dom;html+='<span id="'+id+'"></span>';Ext.lib.Event.onAvailable(id,function(){var DOC=document,hd=DOC.getElementsByTagName("head")[0],re=/(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,srcRe=/\ssrc=([\'\"])(.*?)\1/i,typeRe=/\stype=([\'\"])(.*?)\1/i,match,attrs,srcMatch,typeMatch,el,s;while((match=re.exec(html))){attrs=match[1];srcMatch=attrs?attrs.match(srcRe):false;if(srcMatch&&srcMatch[2]){s=DOC.createElement("script");s.src=srcMatch[2];typeMatch=attrs.match(typeRe);if(typeMatch&&typeMatch[2]){s.type=typeMatch[2]}hd.appendChild(s)}else{if(match[2]&&match[2].length>0){if(window.execScript){window.execScript(match[2])}else{window.eval(match[2])}}}}el=DOC.getElementById(id);if(el){Ext.removeNode(el)}if(typeof callback=="function"){callback()}});dom.innerHTML=html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,"");return this},removeAllListeners:function(){this.removeAnchor();Ext.EventManager.removeAll(this.dom);return this},createProxy:function(a,e,d){a=(typeof a=="object")?a:{tag:"div",cls:a};var c=this,b=e?Ext.DomHelper.append(e,a,true):Ext.DomHelper.insertBefore(c.dom,a,true);if(d&&c.setBox&&c.getBox){b.setBox(c.getBox())}return b}});Ext.Element.prototype.getUpdateManager=Ext.Element.prototype.getUpdater;Ext.Element.addMethods({getAnchorXY:function(e,l,q){e=(e||"tl").toLowerCase();q=q||{};var k=this,b=k.dom==document.body||k.dom==document,n=q.width||b?Ext.lib.Dom.getViewWidth():k.getWidth(),i=q.height||b?Ext.lib.Dom.getViewHeight():k.getHeight(),p,a=Math.round,c=k.getXY(),m=k.getScroll(),j=b?m.left:!l?c[0]:0,g=b?m.top:!l?c[1]:0,d={c:[a(n*0.5),a(i*0.5)],t:[a(n*0.5),0],l:[0,a(i*0.5)],r:[n,a(i*0.5)],b:[a(n*0.5),i],tl:[0,0],bl:[0,i],br:[n,i],tr:[n,0]};p=d[e];return[p[0]+j,p[1]+g]},anchorTo:function(b,h,c,a,k,l){var i=this,e=i.dom,j=!Ext.isEmpty(k),d=function(){Ext.fly(e).alignTo(b,h,c,a);Ext.callback(l,Ext.fly(e))},g=this.getAnchor();this.removeAnchor();Ext.apply(g,{fn:d,scroll:j});Ext.EventManager.onWindowResize(d,null);if(j){Ext.EventManager.on(window,"scroll",d,null,{buffer:!isNaN(k)?k:50})}d.call(i);return i},removeAnchor:function(){var b=this,a=this.getAnchor();if(a&&a.fn){Ext.EventManager.removeResizeListener(a.fn);if(a.scroll){Ext.EventManager.un(window,"scroll",a.fn)}delete a.fn}return b},getAnchor:function(){var b=Ext.Element.data,c=this.dom;if(!c){return}var a=b(c,"_anchor");if(!a){a=b(c,"_anchor",{})}return a},getAlignToXY:function(g,A,B){g=Ext.get(g);if(!g||!g.dom){throw"Element.alignToXY with an element that doesn't exist"}B=B||[0,0];A=(!A||A=="?"?"tl-bl?":(!(/-/).test(A)&&A!==""?"tl-"+A:A||"tl-bl")).toLowerCase();var K=this,H=K.dom,M,L,n,l,s,F,v,t=Ext.lib.Dom.getViewWidth()-10,G=Ext.lib.Dom.getViewHeight()-10,b,i,j,k,u,z,N=document,J=N.documentElement,q=N.body,E=(J.scrollLeft||q.scrollLeft||0)+5,D=(J.scrollTop||q.scrollTop||0)+5,I=false,e="",a="",C=A.match(/^([a-z]+)-([a-z]+)(\?)?$/);if(!C){throw"Element.alignTo with an invalid alignment "+A}e=C[1];a=C[2];I=!!C[3];M=K.getAnchorXY(e,true);L=g.getAnchorXY(a,false);n=L[0]-M[0]+B[0];l=L[1]-M[1]+B[1];if(I){s=K.getWidth();F=K.getHeight();v=g.getRegion();b=e.charAt(0);i=e.charAt(e.length-1);j=a.charAt(0);k=a.charAt(a.length-1);u=((b=="t"&&j=="b")||(b=="b"&&j=="t"));z=((i=="r"&&k=="l")||(i=="l"&&k=="r"));if(n+s>t+E){n=z?v.left-s:t+E-s}if(n<E){n=z?v.right:E}if(l+F>G+D){l=u?v.top-F:G+D-F}if(l<D){l=u?v.bottom:D}}return[n,l]},alignTo:function(c,a,e,b){var d=this;return d.setXY(d.getAlignToXY(c,a,e),d.preanim&&!!b?d.preanim(arguments,3):false)},adjustForConstraints:function(c,a,b){return this.getConstrainToXY(a||document,false,b,c)||c},getConstrainToXY:function(b,a,c,e){var d={top:0,left:0,bottom:0,right:0};return function(i,A,l,n){i=Ext.get(i);l=l?Ext.applyIf(l,d):d;var z,D,v=0,u=0;if(i.dom==document.body||i.dom==document){z=Ext.lib.Dom.getViewWidth();D=Ext.lib.Dom.getViewHeight()}else{z=i.dom.clientWidth;D=i.dom.clientHeight;if(!A){var t=i.getXY();v=t[0];u=t[1]}}var r=i.getScroll();v+=l.left+r.left;u+=l.top+r.top;z-=l.right;D-=l.bottom;var B=v+z,g=u+D,j=n||(!A?this.getXY():[this.getLeft(true),this.getTop(true)]),p=j[0],o=j[1],k=this.getConstrainOffset(),q=this.dom.offsetWidth+k,C=this.dom.offsetHeight+k;var m=false;if((p+q)>B){p=B-q;m=true}if((o+C)>g){o=g-C;m=true}if(p<v){p=v;m=true}if(o<u){o=u;m=true}return m?[p,o]:false}}(),getConstrainOffset:function(){return 0},getCenterXY:function(){return this.getAlignToXY(document,"c-c")},center:function(a){return this.alignTo(a||document,"c-c")}});Ext.Element.addMethods({select:function(a,b){return Ext.Element.select(a,b,this.dom)}});Ext.apply(Ext.Element.prototype,function(){var c=Ext.getDom,a=Ext.get,b=Ext.DomHelper;return{insertSibling:function(i,g,h){var j=this,e,d=(g||"before").toLowerCase()=="after",k;if(Ext.isArray(i)){k=j;Ext.each(i,function(l){e=Ext.fly(k,"_internal").insertSibling(l,g,h);if(d){k=e}});return e}i=i||{};if(i.nodeType||i.dom){e=j.dom.parentNode.insertBefore(c(i),d?j.dom.nextSibling:j.dom);if(!h){e=a(e)}}else{if(d&&!j.dom.nextSibling){e=b.append(j.dom.parentNode,i,!h)}else{e=b[d?"insertAfter":"insertBefore"](j.dom,i,!h)}}return e}}}());Ext.Element.boxMarkup='<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';Ext.Element.addMethods(function(){var a="_internal",b=/(\d+\.?\d+)px/;return{applyStyles:function(c){Ext.DomHelper.applyStyles(this.dom,c);return this},getStyles:function(){var c={};Ext.each(arguments,function(d){c[d]=this.getStyle(d)},this);return c},setOverflow:function(c){var d=this.dom;if(c=="auto"&&Ext.isMac&&Ext.isGecko2){d.style.overflow="hidden";(function(){d.style.overflow="auto"}).defer(1)}else{d.style.overflow=c}},boxWrap:function(c){c=c||"x-box";var d=Ext.get(this.insertHtml("beforeBegin","<div class='"+c+"'>"+String.format(Ext.Element.boxMarkup,c)+"</div>"));Ext.DomQuery.selectNode("."+c+"-mc",d.dom).appendChild(this.dom);return d},setSize:function(e,c,d){var g=this;if(typeof e=="object"){c=e.height;e=e.width}e=g.adjustWidth(e);c=g.adjustHeight(c);if(!d||!g.anim){g.dom.style.width=g.addUnits(e);g.dom.style.height=g.addUnits(c)}else{g.anim({width:{to:e},height:{to:c}},g.preanim(arguments,2))}return g},getComputedHeight:function(){var d=this,c=Math.max(d.dom.offsetHeight,d.dom.clientHeight);if(!c){c=parseFloat(d.getStyle("height"))||0;if(!d.isBorderBox()){c+=d.getFrameWidth("tb")}}return c},getComputedWidth:function(){var c=Math.max(this.dom.offsetWidth,this.dom.clientWidth);if(!c){c=parseFloat(this.getStyle("width"))||0;if(!this.isBorderBox()){c+=this.getFrameWidth("lr")}}return c},getFrameWidth:function(d,c){return c&&this.isBorderBox()?0:(this.getPadding(d)+this.getBorderWidth(d))},addClassOnOver:function(c){this.hover(function(){Ext.fly(this,a).addClass(c)},function(){Ext.fly(this,a).removeClass(c)});return this},addClassOnFocus:function(c){this.on("focus",function(){Ext.fly(this,a).addClass(c)},this.dom);this.on("blur",function(){Ext.fly(this,a).removeClass(c)},this.dom);return this},addClassOnClick:function(c){var d=this.dom;this.on("mousedown",function(){Ext.fly(d,a).addClass(c);var g=Ext.getDoc(),e=function(){Ext.fly(d,a).removeClass(c);g.removeListener("mouseup",e)};g.on("mouseup",e)});return this},getViewSize:function(){var g=document,h=this.dom,c=(h==g||h==g.body);if(c){var e=Ext.lib.Dom;return{width:e.getViewWidth(),height:e.getViewHeight()}}else{return{width:h.clientWidth,height:h.clientHeight}}},getStyleSize:function(){var j=this,c,i,l=document,m=this.dom,e=(m==l||m==l.body),g=m.style;if(e){var k=Ext.lib.Dom;return{width:k.getViewWidth(),height:k.getViewHeight()}}if(g.width&&g.width!="auto"){c=parseFloat(g.width);if(j.isBorderBox()){c-=j.getFrameWidth("lr")}}if(g.height&&g.height!="auto"){i=parseFloat(g.height);if(j.isBorderBox()){i-=j.getFrameWidth("tb")}}return{width:c||j.getWidth(true),height:i||j.getHeight(true)}},getSize:function(c){return{width:this.getWidth(c),height:this.getHeight(c)}},repaint:function(){var c=this.dom;this.addClass("x-repaint");setTimeout(function(){Ext.fly(c).removeClass("x-repaint")},1);return this},unselectable:function(){this.dom.unselectable="on";return this.swallowEvent("selectstart",true).applyStyles("-moz-user-select:none;-khtml-user-select:none;").addClass("x-unselectable")},getMargins:function(d){var e=this,c,g={t:"top",l:"left",r:"right",b:"bottom"},h={};if(!d){for(c in e.margins){h[g[c]]=parseFloat(e.getStyle(e.margins[c]))||0}return h}else{return e.addStyles.call(e,d,e.margins)}}}}());Ext.Element.addMethods({setBox:function(e,g,b){var d=this,a=e.width,c=e.height;if((g&&!d.autoBoxAdjust)&&!d.isBorderBox()){a-=(d.getBorderWidth("lr")+d.getPadding("lr"));c-=(d.getBorderWidth("tb")+d.getPadding("tb"))}d.setBounds(e.x,e.y,a,c,d.animTest.call(d,arguments,b,2));return d},getBox:function(j,p){var m=this,v,e,o,d=m.getBorderWidth,q=m.getPadding,g,a,u,n;if(!p){v=m.getXY()}else{e=parseInt(m.getStyle("left"),10)||0;o=parseInt(m.getStyle("top"),10)||0;v=[e,o]}var c=m.dom,s=c.offsetWidth,i=c.offsetHeight,k;if(!j){k={x:v[0],y:v[1],0:v[0],1:v[1],width:s,height:i}}else{g=d.call(m,"l")+q.call(m,"l");a=d.call(m,"r")+q.call(m,"r");u=d.call(m,"t")+q.call(m,"t");n=d.call(m,"b")+q.call(m,"b");k={x:v[0]+g,y:v[1]+u,0:v[0]+g,1:v[1]+u,width:s-(g+a),height:i-(u+n)}}k.right=k.x+k.width;k.bottom=k.y+k.height;return k},move:function(j,b,c){var g=this,m=g.getXY(),k=m[0],i=m[1],d=[k-b,i],l=[k+b,i],h=[k,i-b],a=[k,i+b],e={l:d,left:d,r:l,right:l,t:h,top:h,up:h,b:a,bottom:a,down:a};j=j.toLowerCase();g.moveTo(e[j][0],e[j][1],g.animTest.call(g,arguments,c,2))},setLeftTop:function(d,c){var b=this,a=b.dom.style;a.left=b.addUnits(d);a.top=b.addUnits(c);return b},getRegion:function(){return Ext.lib.Dom.getRegion(this.dom)},setBounds:function(b,g,d,a,c){var e=this;if(!c||!e.anim){e.setSize(d,a);e.setLocation(b,g)}else{e.anim({points:{to:[b,g]},width:{to:e.adjustWidth(d)},height:{to:e.adjustHeight(a)}},e.preanim(arguments,4),"motion")}return e},setRegion:function(b,a){return this.setBounds(b.left,b.top,b.right-b.left,b.bottom-b.top,this.animTest.call(this,arguments,a,1))}});Ext.Element.addMethods({scrollTo:function(b,d,a){var e=/top/i.test(b),c=this,g=c.dom,h;if(!a||!c.anim){h="scroll"+(e?"Top":"Left");g[h]=d}else{h="scroll"+(e?"Left":"Top");c.anim({scroll:{to:e?[g[h],d]:[d,g[h]]}},c.preanim(arguments,2),"scroll")}return c},scrollIntoView:function(e,i){var p=Ext.getDom(e)||Ext.getBody().dom,h=this.dom,g=this.getOffsetsTo(p),k=g[0]+p.scrollLeft,u=g[1]+p.scrollTop,q=u+h.offsetHeight,d=k+h.offsetWidth,a=p.clientHeight,m=parseInt(p.scrollTop,10),s=parseInt(p.scrollLeft,10),j=m+a,n=s+p.clientWidth;if(h.offsetHeight>a||u<m){p.scrollTop=u}else{if(q>j){p.scrollTop=q-a}}p.scrollTop=p.scrollTop;if(i!==false){if(h.offsetWidth>p.clientWidth||k<s){p.scrollLeft=k}else{if(d>n){p.scrollLeft=d-p.clientWidth}}p.scrollLeft=p.scrollLeft}return this},scrollChildIntoView:function(b,a){Ext.fly(b,"_scrollChildIntoView").scrollIntoView(this,a)},scroll:function(m,b,d){if(!this.isScrollable()){return false}var e=this.dom,g=e.scrollLeft,p=e.scrollTop,n=e.scrollWidth,k=e.scrollHeight,i=e.clientWidth,a=e.clientHeight,c=false,o,j={l:Math.min(g+b,n-i),r:o=Math.max(g-b,0),t:Math.max(p-b,0),b:Math.min(p+b,k-a)};j.d=j.b;j.u=j.t;m=m.substr(0,1);if((o=j[m])>-1){c=true;this.scrollTo(m=="l"||m=="r"?"left":"top",o,this.preanim(arguments,2))}return c}});Ext.Element.addMethods(function(){var d="visibility",b="display",a="hidden",h="none",c="x-masked",g="x-masked-relative",e=Ext.Element.data;return{isVisible:function(i){var j=!this.isStyle(d,a)&&!this.isStyle(b,h),k=this.dom.parentNode;if(i!==true||!j){return j}while(k&&!(/^body/i.test(k.tagName))){if(!Ext.fly(k,"_isVisible").isVisible()){return false}k=k.parentNode}return true},isDisplayed:function(){return !this.isStyle(b,h)},enableDisplayMode:function(i){this.setVisibilityMode(Ext.Element.DISPLAY);if(!Ext.isEmpty(i)){e(this.dom,"originalDisplay",i)}return this},mask:function(j,n){var p=this,l=p.dom,o=Ext.DomHelper,m="ext-el-mask-msg",i,q;if(!/^body/i.test(l.tagName)&&p.getStyle("position")=="static"){p.addClass(g)}if(i=e(l,"maskMsg")){i.remove()}if(i=e(l,"mask")){i.remove()}q=o.append(l,{cls:"ext-el-mask"},true);e(l,"mask",q);p.addClass(c);q.setDisplayed(true);if(typeof j=="string"){var k=o.append(l,{cls:m,cn:{tag:"div"}},true);e(l,"maskMsg",k);k.dom.className=n?m+" "+n:m;k.dom.firstChild.innerHTML=j;k.setDisplayed(true);k.center(p)}if(Ext.isIE&&!(Ext.isIE7&&Ext.isStrict)&&p.getStyle("height")=="auto"){q.setSize(undefined,p.getHeight())}return q},unmask:function(){var k=this,l=k.dom,i=e(l,"mask"),j=e(l,"maskMsg");if(i){if(j){j.remove();e(l,"maskMsg",undefined)}i.remove();e(l,"mask",undefined);k.removeClass([c,g])}},isMasked:function(){var i=e(this.dom,"mask");return i&&i.isVisible()},createShim:function(){var i=document.createElement("iframe"),j;i.frameBorder="0";i.className="ext-shim";i.src=Ext.SSL_SECURE_URL;j=Ext.get(this.dom.parentNode.insertBefore(i,this.dom));j.autoBoxAdjust=false;return j}}}());Ext.Element.addMethods({addKeyListener:function(b,d,c){var a;if(typeof b!="object"||Ext.isArray(b)){a={key:b,fn:d,scope:c}}else{a={key:b.key,shift:b.shift,ctrl:b.ctrl,alt:b.alt,fn:d,scope:c}}return new Ext.KeyMap(this,a)},addKeyMap:function(a){return new Ext.KeyMap(this,a)}});Ext.CompositeElementLite.importElementMethods();Ext.apply(Ext.CompositeElementLite.prototype,{addElements:function(c,a){if(!c){return this}if(typeof c=="string"){c=Ext.Element.selectorFunction(c,a)}var b=this.elements;Ext.each(c,function(d){b.push(Ext.get(d))});return this},first:function(){return this.item(0)},last:function(){return this.item(this.getCount()-1)},contains:function(a){return this.indexOf(a)!=-1},removeElement:function(d,e){var c=this,a=this.elements,b;Ext.each(d,function(g){if((b=(a[g]||a[g=c.indexOf(g)]))){if(e){if(b.dom){b.remove()}else{Ext.removeNode(b)}}a.splice(g,1)}});return this}});Ext.CompositeElement=Ext.extend(Ext.CompositeElementLite,{constructor:function(b,a){this.elements=[];this.add(b,a)},getElement:function(a){return a},transformElement:function(a){return Ext.get(a)}});Ext.Element.select=function(a,d,b){var c;if(typeof a=="string"){c=Ext.Element.selectorFunction(a,b)}else{if(a.length!==undefined){c=a}else{throw"Invalid selector"}}return(d===true)?new Ext.CompositeElement(c):new Ext.CompositeElementLite(c)};Ext.select=Ext.Element.select;Ext.UpdateManager=Ext.Updater=Ext.extend(Ext.util.Observable,function(){var b="beforeupdate",d="update",c="failure";function a(h){var i=this;i.transaction=null;if(h.argument.form&&h.argument.reset){try{h.argument.form.reset()}catch(j){}}if(i.loadScripts){i.renderer.render(i.el,h,i,g.createDelegate(i,[h]))}else{i.renderer.render(i.el,h,i);g.call(i,h)}}function g(h,i,j){this.fireEvent(i||d,this.el,h);if(Ext.isFunction(h.argument.callback)){h.argument.callback.call(h.argument.scope,this.el,Ext.isEmpty(j)?true:false,h,h.argument.options)}}function e(h){g.call(this,h,c,!!(this.transaction=null))}return{constructor:function(i,h){var j=this;i=Ext.get(i);if(!h&&i.updateManager){return i.updateManager}j.el=i;j.defaultUrl=null;j.addEvents(b,d,c);Ext.apply(j,Ext.Updater.defaults);j.transaction=null;j.refreshDelegate=j.refresh.createDelegate(j);j.updateDelegate=j.update.createDelegate(j);j.formUpdateDelegate=(j.formUpdate||function(){}).createDelegate(j);j.renderer=j.renderer||j.getDefaultRenderer();Ext.Updater.superclass.constructor.call(j)},setRenderer:function(h){this.renderer=h},getRenderer:function(){return this.renderer},getDefaultRenderer:function(){return new Ext.Updater.BasicRenderer()},setDefaultUrl:function(h){this.defaultUrl=h},getEl:function(){return this.el},update:function(i,n,p,l){var k=this,h,j;if(k.fireEvent(b,k.el,i,n)!==false){if(Ext.isObject(i)){h=i;i=h.url;n=n||h.params;p=p||h.callback;l=l||h.discardUrl;j=h.scope;if(!Ext.isEmpty(h.nocache)){k.disableCaching=h.nocache}if(!Ext.isEmpty(h.text)){k.indicatorText='<div class="loading-indicator">'+h.text+"</div>"}if(!Ext.isEmpty(h.scripts)){k.loadScripts=h.scripts}if(!Ext.isEmpty(h.timeout)){k.timeout=h.timeout}}k.showLoading();if(!l){k.defaultUrl=i}if(Ext.isFunction(i)){i=i.call(k)}var m=Ext.apply({},{url:i,params:(Ext.isFunction(n)&&j)?n.createDelegate(j):n,success:a,failure:e,scope:k,callback:undefined,timeout:(k.timeout*1000),disableCaching:k.disableCaching,argument:{options:h,url:i,form:null,callback:p,scope:j||window,params:n}},h);k.transaction=Ext.Ajax.request(m)}},formUpdate:function(k,h,j,l){var i=this;if(i.fireEvent(b,i.el,k,h)!==false){if(Ext.isFunction(h)){h=h.call(i)}k=Ext.getDom(k);i.transaction=Ext.Ajax.request({form:k,url:h,success:a,failure:e,scope:i,timeout:(i.timeout*1000),argument:{url:h,form:k,callback:l,reset:j}});i.showLoading.defer(1,i)}},startAutoRefresh:function(i,j,l,m,h){var k=this;if(h){k.update(j||k.defaultUrl,l,m,true)}if(k.autoRefreshProcId){clearInterval(k.autoRefreshProcId)}k.autoRefreshProcId=setInterval(k.update.createDelegate(k,[j||k.defaultUrl,l,m,true]),i*1000)},stopAutoRefresh:function(){if(this.autoRefreshProcId){clearInterval(this.autoRefreshProcId);delete this.autoRefreshProcId}},isAutoRefreshing:function(){return !!this.autoRefreshProcId},showLoading:function(){if(this.showLoadIndicator){this.el.dom.innerHTML=this.indicatorText}},abort:function(){if(this.transaction){Ext.Ajax.abort(this.transaction)}},isUpdating:function(){return this.transaction?Ext.Ajax.isLoading(this.transaction):false},refresh:function(h){if(this.defaultUrl){this.update(this.defaultUrl,null,h,true)}}}}());Ext.Updater.defaults={timeout:30,disableCaching:false,showLoadIndicator:true,indicatorText:'<div class="loading-indicator">Loading...</div>',loadScripts:false,sslBlankUrl:Ext.SSL_SECURE_URL};Ext.Updater.updateElement=function(d,c,e,b){var a=Ext.get(d).getUpdater();Ext.apply(a,b);a.update(c,e,b?b.callback:null)};Ext.Updater.BasicRenderer=function(){};Ext.Updater.BasicRenderer.prototype={render:function(c,a,b,d){c.update(a.responseText,b.loadScripts,d)}};(function(){Date.useStrict=false;function b(d){var c=Array.prototype.slice.call(arguments,1);return d.replace(/\{(\d+)\}/g,function(e,g){return c[g]})}Date.formatCodeToRegex=function(d,c){var e=Date.parseCodes[d];if(e){e=typeof e=="function"?e():e;Date.parseCodes[d]=e}return e?Ext.applyIf({c:e.c?b(e.c,c||"{0}"):e.c},e):{g:0,c:null,s:Ext.escapeRe(d)}};var a=Date.formatCodeToRegex;Ext.apply(Date,{parseFunctions:{"M$":function(d,c){var e=new RegExp("\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/");var g=(d||"").match(e);return g?new Date(((g[1]||"")+g[2])*1):null}},parseRegexes:[],formatFunctions:{"M$":function(){return"\\/Date("+this.getTime()+")\\/"}},y2kYear:50,MILLI:"ms",SECOND:"s",MINUTE:"mi",HOUR:"h",DAY:"d",MONTH:"mo",YEAR:"y",defaults:{},dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNumbers:{Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11},getShortMonthName:function(c){return Date.monthNames[c].substring(0,3)},getShortDayName:function(c){return Date.dayNames[c].substring(0,3)},getMonthNumber:function(c){return Date.monthNumbers[c.substring(0,1).toUpperCase()+c.substring(1,3).toLowerCase()]},formatContainsHourInfo:(function(){var d=/(\\.)/g,c=/([gGhHisucUOPZ]|M\$)/;return function(e){return c.test(e.replace(d,""))}})(),formatCodes:{d:"String.leftPad(this.getDate(), 2, '0')",D:"Date.getShortDayName(this.getDay())",j:"this.getDate()",l:"Date.dayNames[this.getDay()]",N:"(this.getDay() ? this.getDay() : 7)",S:"this.getSuffix()",w:"this.getDay()",z:"this.getDayOfYear()",W:"String.leftPad(this.getWeekOfYear(), 2, '0')",F:"Date.monthNames[this.getMonth()]",m:"String.leftPad(this.getMonth() + 1, 2, '0')",M:"Date.getShortMonthName(this.getMonth())",n:"(this.getMonth() + 1)",t:"this.getDaysInMonth()",L:"(this.isLeapYear() ? 1 : 0)",o:"(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",Y:"String.leftPad(this.getFullYear(), 4, '0')",y:"('' + this.getFullYear()).substring(2, 4)",a:"(this.getHours() < 12 ? 'am' : 'pm')",A:"(this.getHours() < 12 ? 'AM' : 'PM')",g:"((this.getHours() % 12) ? this.getHours() % 12 : 12)",G:"this.getHours()",h:"String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",H:"String.leftPad(this.getHours(), 2, '0')",i:"String.leftPad(this.getMinutes(), 2, '0')",s:"String.leftPad(this.getSeconds(), 2, '0')",u:"String.leftPad(this.getMilliseconds(), 3, '0')",O:"this.getGMTOffset()",P:"this.getGMTOffset(true)",T:"this.getTimezone()",Z:"(this.getTimezoneOffset() * -60)",c:function(){for(var k="Y-m-dTH:i:sP",h=[],g=0,d=k.length;g<d;++g){var j=k.charAt(g);h.push(j=="T"?"'T'":Date.getFormatCode(j))}return h.join(" + ")},U:"Math.round(this.getTime() / 1000)"},isValid:function(o,c,n,k,g,j,e){k=k||0;g=g||0;j=j||0;e=e||0;var l=new Date(o<100?100:o,c-1,n,k,g,j,e).add(Date.YEAR,o<100?o-100:0);return o==l.getFullYear()&&c==l.getMonth()+1&&n==l.getDate()&&k==l.getHours()&&g==l.getMinutes()&&j==l.getSeconds()&&e==l.getMilliseconds()},parseDate:function(d,g,c){var e=Date.parseFunctions;if(e[g]==null){Date.createParser(g)}return e[g](d,Ext.isDefined(c)?c:Date.useStrict)},getFormatCode:function(d){var c=Date.formatCodes[d];if(c){c=typeof c=="function"?c():c;Date.formatCodes[d]=c}return c||("'"+String.escape(d)+"'")},createFormat:function(h){var g=[],c=false,e="";for(var d=0;d<h.length;++d){e=h.charAt(d);if(!c&&e=="\\"){c=true}else{if(c){c=false;g.push("'"+String.escape(e)+"'")}else{g.push(Date.getFormatCode(e))}}}Date.formatFunctions[h]=new Function("return "+g.join("+"))},createParser:function(){var c=["var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,","def = Date.defaults,","results = String(input).match(Date.parseRegexes[{0}]);","if(results){","{1}","if(u != null){","v = new Date(u * 1000);","}else{","dt = (new Date()).clearTime();","y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));","m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));","d = Ext.num(d, Ext.num(def.d, dt.getDate()));","h  = Ext.num(h, Ext.num(def.h, dt.getHours()));","i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));","s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));","ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));","if(z >= 0 && y >= 0){","v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);","v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);","}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){","v = null;","}else{","v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);","}","}","}","if(v){","if(zz != null){","v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);","}else if(o){","v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));","}","}","return v;"].join("\n");return function(m){var e=Date.parseRegexes.length,o=1,g=[],l=[],k=false,d="",j=0,h,n;for(;j<m.length;++j){d=m.charAt(j);if(!k&&d=="\\"){k=true}else{if(k){k=false;l.push(String.escape(d))}else{h=a(d,o);o+=h.g;l.push(h.s);if(h.g&&h.c){if(h.calcLast){n=h.c}else{g.push(h.c)}}}}}if(n){g.push(n)}Date.parseRegexes[e]=new RegExp("^"+l.join("")+"$","i");Date.parseFunctions[m]=new Function("input","strict",b(c,e,g.join("")))}}(),parseCodes:{d:{g:1,c:"d = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},j:{g:1,c:"d = parseInt(results[{0}], 10);\n",s:"(\\d{1,2})"},D:function(){for(var c=[],d=0;d<7;c.push(Date.getShortDayName(d)),++d){}return{g:0,c:null,s:"(?:"+c.join("|")+")"}},l:function(){return{g:0,c:null,s:"(?:"+Date.dayNames.join("|")+")"}},N:{g:0,c:null,s:"[1-7]"},S:{g:0,c:null,s:"(?:st|nd|rd|th)"},w:{g:0,c:null,s:"[0-6]"},z:{g:1,c:"z = parseInt(results[{0}], 10);\n",s:"(\\d{1,3})"},W:{g:0,c:null,s:"(?:\\d{2})"},F:function(){return{g:1,c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n",s:"("+Date.monthNames.join("|")+")"}},M:function(){for(var c=[],d=0;d<12;c.push(Date.getShortMonthName(d)),++d){}return Ext.applyIf({s:"("+c.join("|")+")"},a("F"))},m:{g:1,c:"m = parseInt(results[{0}], 10) - 1;\n",s:"(\\d{2})"},n:{g:1,c:"m = parseInt(results[{0}], 10) - 1;\n",s:"(\\d{1,2})"},t:{g:0,c:null,s:"(?:\\d{2})"},L:{g:0,c:null,s:"(?:1|0)"},o:function(){return a("Y")},Y:{g:1,c:"y = parseInt(results[{0}], 10);\n",s:"(\\d{4})"},y:{g:1,c:"var ty = parseInt(results[{0}], 10);\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"},a:function(){return a("A")},A:{calcLast:true,g:1,c:"if (/(am)/i.test(results[{0}])) {\nif (!h || h == 12) { h = 0; }\n} else { if (!h || h < 12) { h = (h || 0) + 12; }}",s:"(AM|PM|am|pm)"},g:function(){return a("G")},G:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{1,2})"},h:function(){return a("H")},H:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},i:{g:1,c:"i = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},s:{g:1,c:"s = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},u:{g:1,c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",s:"(\\d+)"},O:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),","mn = o.substring(3,5) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+-]\\d{4})"},P:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),","mn = o.substring(4,6) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+-]\\d{2}:\\d{2})"},T:{g:0,c:null,s:"[A-Z]{1,4}"},Z:{g:1,c:"zz = results[{0}] * 1;\nzz = (-43200 <= zz && zz <= 50400)? zz : null;\n",s:"([+-]?\\d{1,5})"},c:function(){var e=[],c=[a("Y",1),a("m",2),a("d",3),a("h",4),a("i",5),a("s",6),{c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"},{c:["if(results[8]) {","if(results[8] == 'Z'){","zz = 0;","}else if (results[8].indexOf(':') > -1){",a("P",8).c,"}else{",a("O",8).c,"}","}"].join("\n")}];for(var g=0,d=c.length;g<d;++g){e.push(c[g].c)}return{g:1,c:e.join(""),s:[c[0].s,"(?:","-",c[1].s,"(?:","-",c[2].s,"(?:","(?:T| )?",c[3].s,":",c[4].s,"(?::",c[5].s,")?","(?:(?:\\.|,)(\\d+))?","(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?",")?",")?",")?"].join("")}},U:{g:1,c:"u = parseInt(results[{0}], 10);\n",s:"(-?\\d+)"}}})}());Ext.apply(Date.prototype,{dateFormat:function(a){if(Date.formatFunctions[a]==null){Date.createFormat(a)}return Date.formatFunctions[a].call(this)},getTimezone:function(){return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/,"$1$2").replace(/[^A-Z]/g,"")},getGMTOffset:function(a){return(this.getTimezoneOffset()>0?"-":"+")+String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset())/60),2,"0")+(a?":":"")+String.leftPad(Math.abs(this.getTimezoneOffset()%60),2,"0")},getDayOfYear:function(){var b=0,e=this.clone(),a=this.getMonth(),c;for(c=0,e.setDate(1),e.setMonth(0);c<a;e.setMonth(++c)){b+=e.getDaysInMonth()}return b+this.getDate()-1},getWeekOfYear:function(){var a=86400000,b=7*a;return function(){var d=Date.UTC(this.getFullYear(),this.getMonth(),this.getDate()+3)/a,c=Math.floor(d/7),e=new Date(c*b).getUTCFullYear();return c-Math.floor(Date.UTC(e,0,7)/b)+1}}(),isLeapYear:function(){var a=this.getFullYear();return !!((a&3)==0&&(a%100||(a%400==0&&a)))},getFirstDayOfMonth:function(){var a=(this.getDay()-(this.getDate()-1))%7;return(a<0)?(a+7):a},getLastDayOfMonth:function(){return this.getLastDateOfMonth().getDay()},getFirstDateOfMonth:function(){return new Date(this.getFullYear(),this.getMonth(),1)},getLastDateOfMonth:function(){return new Date(this.getFullYear(),this.getMonth(),this.getDaysInMonth())},getDaysInMonth:function(){var a=[31,28,31,30,31,30,31,31,30,31,30,31];return function(){var b=this.getMonth();return b==1&&this.isLeapYear()?29:a[b]}}(),getSuffix:function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th"}},clone:function(){return new Date(this.getTime())},isDST:function(){return new Date(this.getFullYear(),0,1).getTimezoneOffset()!=this.getTimezoneOffset()},clearTime:function(g){if(g){return this.clone().clearTime()}var b=this.getDate();this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);if(this.getDate()!=b){for(var a=1,e=this.add(Date.HOUR,a);e.getDate()!=b;a++,e=this.add(Date.HOUR,a)){}this.setDate(b);this.setHours(e.getHours())}return this},add:function(b,c){var e=this.clone();if(!b||c===0){return e}switch(b.toLowerCase()){case Date.MILLI:e.setMilliseconds(this.getMilliseconds()+c);break;case Date.SECOND:e.setSeconds(this.getSeconds()+c);break;case Date.MINUTE:e.setMinutes(this.getMinutes()+c);break;case Date.HOUR:e.setHours(this.getHours()+c);break;case Date.DAY:e.setDate(this.getDate()+c);break;case Date.MONTH:var a=this.getDate();if(a>28){a=Math.min(a,this.getFirstDateOfMonth().add("mo",c).getLastDateOfMonth().getDate())}e.setDate(a);e.setMonth(this.getMonth()+c);break;case Date.YEAR:e.setFullYear(this.getFullYear()+c);break}return e},between:function(c,a){var b=this.getTime();return c.getTime()<=b&&b<=a.getTime()}});Date.prototype.format=Date.prototype.dateFormat;if(Ext.isSafari&&(navigator.userAgent.match(/WebKit\/(\d+)/)[1]||NaN)<420){Ext.apply(Date.prototype,{_xMonth:Date.prototype.setMonth,_xDate:Date.prototype.setDate,setMonth:function(a){if(a<=-1){var d=Math.ceil(-a),c=Math.ceil(d/12),b=(d%12)?12-d%12:0;this.setFullYear(this.getFullYear()-c);return this._xMonth(b)}else{return this._xMonth(a)}},setDate:function(a){return this.setTime(this.getTime()-(this.getDate()-a)*86400000)}})}Ext.util.MixedCollection=function(b,a){this.items=[];this.map={};this.keys=[];this.length=0;this.addEvents("clear","add","replace","remove","sort");this.allowFunctions=b===true;if(a){this.getKey=a}Ext.util.MixedCollection.superclass.constructor.call(this)};Ext.extend(Ext.util.MixedCollection,Ext.util.Observable,{allowFunctions:false,add:function(b,c){if(arguments.length==1){c=arguments[0];b=this.getKey(c)}if(typeof b!="undefined"&&b!==null){var a=this.map[b];if(typeof a!="undefined"){return this.replace(b,c)}this.map[b]=c}this.length++;this.items.push(c);this.keys.push(b);this.fireEvent("add",this.length-1,c,b);return c},getKey:function(a){return a.id},replace:function(c,d){if(arguments.length==1){d=arguments[0];c=this.getKey(d)}var a=this.map[c];if(typeof c=="undefined"||c===null||typeof a=="undefined"){return this.add(c,d)}var b=this.indexOfKey(c);this.items[b]=d;this.map[c]=d;this.fireEvent("replace",c,a,d);return d},addAll:function(e){if(arguments.length>1||Ext.isArray(e)){var b=arguments.length>1?arguments:e;for(var d=0,a=b.length;d<a;d++){this.add(b[d])}}else{for(var c in e){if(this.allowFunctions||typeof e[c]!="function"){this.add(c,e[c])}}}},each:function(e,d){var b=[].concat(this.items);for(var c=0,a=b.length;c<a;c++){if(e.call(d||b[c],b[c],c,a)===false){break}}},eachKey:function(d,c){for(var b=0,a=this.keys.length;b<a;b++){d.call(c||window,this.keys[b],this.items[b],b,a)}},find:function(d,c){for(var b=0,a=this.items.length;b<a;b++){if(d.call(c||window,this.items[b],this.keys[b])){return this.items[b]}}return null},insert:function(a,b,c){if(arguments.length==2){c=arguments[1];b=this.getKey(c)}if(this.containsKey(b)){this.suspendEvents();this.removeKey(b);this.resumeEvents()}if(a>=this.length){return this.add(b,c)}this.length++;this.items.splice(a,0,c);if(typeof b!="undefined"&&b!==null){this.map[b]=c}this.keys.splice(a,0,b);this.fireEvent("add",a,c,b);return c},remove:function(a){return this.removeAt(this.indexOf(a))},removeAt:function(a){if(a<this.length&&a>=0){this.length--;var c=this.items[a];this.items.splice(a,1);var b=this.keys[a];if(typeof b!="undefined"){delete this.map[b]}this.keys.splice(a,1);this.fireEvent("remove",c,b);return c}return false},removeKey:function(a){return this.removeAt(this.indexOfKey(a))},getCount:function(){return this.length},indexOf:function(a){return this.items.indexOf(a)},indexOfKey:function(a){return this.keys.indexOf(a)},item:function(b){var a=this.map[b],c=a!==undefined?a:(typeof b=="number")?this.items[b]:undefined;return typeof c!="function"||this.allowFunctions?c:null},itemAt:function(a){return this.items[a]},key:function(a){return this.map[a]},contains:function(a){return this.indexOf(a)!=-1},containsKey:function(a){return typeof this.map[a]!="undefined"},clear:function(){this.length=0;this.items=[];this.keys=[];this.map={};this.fireEvent("clear")},first:function(){return this.items[0]},last:function(){return this.items[this.length-1]},_sort:function(k,a,j){var d,e,b=String(a).toUpperCase()=="DESC"?-1:1,h=[],l=this.keys,g=this.items;j=j||function(i,c){return i-c};for(d=0,e=g.length;d<e;d++){h[h.length]={key:l[d],value:g[d],index:d}}h.sort(function(i,c){var m=j(i[k],c[k])*b;if(m===0){m=(i.index<c.index?-1:1)}return m});for(d=0,e=h.length;d<e;d++){g[d]=h[d].value;l[d]=h[d].key}this.fireEvent("sort",this)},sort:function(a,b){this._sort("value",a,b)},reorder:function(d){this.suspendEvents();var b=this.items,c=0,g=b.length,a=[],e=[],h;for(h in d){a[d[h]]=b[h]}for(c=0;c<g;c++){if(d[c]==undefined){e.push(b[c])}}for(c=0;c<g;c++){if(a[c]==undefined){a[c]=e.shift()}}this.clear();this.addAll(a);this.resumeEvents();this.fireEvent("sort",this)},keySort:function(a,b){this._sort("key",a,b||function(d,c){var g=String(d).toUpperCase(),e=String(c).toUpperCase();return g>e?1:(g<e?-1:0)})},getRange:function(e,a){var b=this.items;if(b.length<1){return[]}e=e||0;a=Math.min(typeof a=="undefined"?this.length-1:a,this.length-1);var c,d=[];if(e<=a){for(c=e;c<=a;c++){d[d.length]=b[c]}}else{for(c=e;c>=a;c--){d[d.length]=b[c]}}return d},filter:function(c,b,d,a){if(Ext.isEmpty(b,false)){return this.clone()}b=this.createValueMatcher(b,d,a);return this.filterBy(function(e){return e&&b.test(e[c])})},filterBy:function(g,e){var h=new Ext.util.MixedCollection();h.getKey=this.getKey;var b=this.keys,d=this.items;for(var c=0,a=d.length;c<a;c++){if(g.call(e||this,d[c],b[c])){h.add(b[c],d[c])}}return h},findIndex:function(c,b,e,d,a){if(Ext.isEmpty(b,false)){return -1}b=this.createValueMatcher(b,d,a);return this.findIndexBy(function(g){return g&&b.test(g[c])},null,e)},findIndexBy:function(g,e,h){var b=this.keys,d=this.items;for(var c=(h||0),a=d.length;c<a;c++){if(g.call(e||this,d[c],b[c])){return c}}return -1},createValueMatcher:function(c,e,a,b){if(!c.exec){var d=Ext.escapeRe;c=String(c);if(e===true){c=d(c)}else{c="^"+d(c);if(b===true){c+="$"}}c=new RegExp(c,a?"":"i")}return c},clone:function(){var e=new Ext.util.MixedCollection();var b=this.keys,d=this.items;for(var c=0,a=d.length;c<a;c++){e.add(b[c],d[c])}e.getKey=this.getKey;return e}});Ext.util.MixedCollection.prototype.get=Ext.util.MixedCollection.prototype.item;Ext.AbstractManager=Ext.extend(Object,{typeName:"type",constructor:function(a){Ext.apply(this,a||{});this.all=new Ext.util.MixedCollection();this.types={}},get:function(a){return this.all.get(a)},register:function(a){this.all.add(a)},unregister:function(a){this.all.remove(a)},registerType:function(b,a){this.types[b]=a;a[this.typeName]=b},isRegistered:function(a){return this.types[a]!==undefined},create:function(a,d){var b=a[this.typeName]||a.type||d,c=this.types[b];if(c==undefined){throw new Error(String.format("The '{0}' type has not been registered with this manager",b))}return new c(a)},onAvailable:function(d,c,b){var a=this.all;a.on("add",function(e,g){if(g.id==d){c.call(b||g,g);a.un("add",c,b)}})}});Ext.util.Format=function(){var trimRe=/^\s+|\s+$/g,stripTagsRE=/<\/?[^>]+>/gi,stripScriptsRe=/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,nl2brRe=/\r?\n/g;return{ellipsis:function(value,len,word){if(value&&value.length>len){if(word){var vs=value.substr(0,len-2),index=Math.max(vs.lastIndexOf(" "),vs.lastIndexOf("."),vs.lastIndexOf("!"),vs.lastIndexOf("?"));if(index==-1||index<(len-15)){return value.substr(0,len-3)+"..."}else{return vs.substr(0,index)+"..."}}else{return value.substr(0,len-3)+"..."}}return value},undef:function(value){return value!==undefined?value:""},defaultValue:function(value,defaultValue){return value!==undefined&&value!==""?value:defaultValue},htmlEncode:function(value){return !value?value:String(value).replace(/&/g,"&amp;").replace(/>/g,"&gt;").replace(/</g,"&lt;").replace(/"/g,"&quot;")},htmlDecode:function(value){return !value?value:String(value).replace(/&gt;/g,">").replace(/&lt;/g,"<").replace(/&quot;/g,'"').replace(/&amp;/g,"&")},trim:function(value){return String(value).replace(trimRe,"")},substr:function(value,start,length){return String(value).substr(start,length)},lowercase:function(value){return String(value).toLowerCase()},uppercase:function(value){return String(value).toUpperCase()},capitalize:function(value){return !value?value:value.charAt(0).toUpperCase()+value.substr(1).toLowerCase()},call:function(value,fn){if(arguments.length>2){var args=Array.prototype.slice.call(arguments,2);args.unshift(value);return eval(fn).apply(window,args)}else{return eval(fn).call(window,value)}},usMoney:function(v){v=(Math.round((v-0)*100))/100;v=(v==Math.floor(v))?v+".00":((v*10==Math.floor(v*10))?v+"0":v);v=String(v);var ps=v.split("."),whole=ps[0],sub=ps[1]?"."+ps[1]:".00",r=/(\d+)(\d{3})/;while(r.test(whole)){whole=whole.replace(r,"$1,$2")}v=whole+sub;if(v.charAt(0)=="-"){return"-$"+v.substr(1)}return"$"+v},date:function(v,format){if(!v){return""}if(!Ext.isDate(v)){v=new Date(Date.parse(v))}return v.dateFormat(format||"m/d/Y")},dateRenderer:function(format){return function(v){return Ext.util.Format.date(v,format)}},stripTags:function(v){return !v?v:String(v).replace(stripTagsRE,"")},stripScripts:function(v){return !v?v:String(v).replace(stripScriptsRe,"")},fileSize:function(size){if(size<1024){return size+" bytes"}else{if(size<1048576){return(Math.round(((size*10)/1024))/10)+" KB"}else{return(Math.round(((size*10)/1048576))/10)+" MB"}}},math:function(){var fns={};return function(v,a){if(!fns[a]){fns[a]=new Function("v","return v "+a+";")}return fns[a](v)}}(),round:function(value,precision){var result=Number(value);if(typeof precision=="number"){precision=Math.pow(10,precision);result=Math.round(value*precision)/precision}return result},number:function(v,format){if(!format){return v}v=Ext.num(v,NaN);if(isNaN(v)){return""}var comma=",",dec=".",i18n=false,neg=v<0;v=Math.abs(v);if(format.substr(format.length-2)=="/i"){format=format.substr(0,format.length-2);i18n=true;comma=".";dec=","}var hasComma=format.indexOf(comma)!=-1,psplit=(i18n?format.replace(/[^\d\,]/g,""):format.replace(/[^\d\.]/g,"")).split(dec);if(1<psplit.length){v=v.toFixed(psplit[1].length)}else{if(2<psplit.length){throw ("NumberFormatException: invalid format, formats should have no more than 1 period: "+format)}else{v=v.toFixed(0)}}var fnum=v.toString();psplit=fnum.split(".");if(hasComma){var cnum=psplit[0],parr=[],j=cnum.length,m=Math.floor(j/3),n=cnum.length%3||3,i;for(i=0;i<j;i+=n){if(i!=0){n=3}parr[parr.length]=cnum.substr(i,n);m-=1}fnum=parr.join(comma);if(psplit[1]){fnum+=dec+psplit[1]}}else{if(psplit[1]){fnum=psplit[0]+dec+psplit[1]}}return(neg?"-":"")+format.replace(/[\d,?\.?]+/,fnum)},numberRenderer:function(format){return function(v){return Ext.util.Format.number(v,format)}},plural:function(v,s,p){return v+" "+(v==1?s:(p?p:s+"s"))},nl2br:function(v){return Ext.isEmpty(v)?"":v.replace(nl2brRe,"<br/>")}}}();Ext.XTemplate=function(){Ext.XTemplate.superclass.constructor.apply(this,arguments);var y=this,j=y.html,q=/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,d=/^<tpl\b[^>]*?for="(.*?)"/,v=/^<tpl\b[^>]*?if="(.*?)"/,x=/^<tpl\b[^>]*?exec="(.*?)"/,r,p=0,k=[],o="values",w="parent",l="xindex",n="xcount",e="return ",c="with(values){ ";j=["<tpl>",j,"</tpl>"].join("");while((r=j.match(q))){var b=r[0].match(d),a=r[0].match(v),A=r[0].match(x),g=null,h=null,t=null,z=b&&b[1]?b[1]:"";if(a){g=a&&a[1]?a[1]:null;if(g){h=new Function(o,w,l,n,c+e+(Ext.util.Format.htmlDecode(g))+"; }")}}if(A){g=A&&A[1]?A[1]:null;if(g){t=new Function(o,w,l,n,c+(Ext.util.Format.htmlDecode(g))+"; }")}}if(z){switch(z){case".":z=new Function(o,w,c+e+o+"; }");break;case"..":z=new Function(o,w,c+e+w+"; }");break;default:z=new Function(o,w,c+e+z+"; }")}}k.push({id:p,target:z,exec:t,test:h,body:r[1]||""});j=j.replace(r[0],"{xtpl"+p+"}");++p}for(var u=k.length-1;u>=0;--u){y.compileTpl(k[u])}y.master=k[k.length-1];y.tpls=k};Ext.extend(Ext.XTemplate,Ext.Template,{re:/\{([\w\-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,codeRe:/\{\[((?:\\\]|.|\n)*?)\]\}/g,applySubTemplate:function(a,k,j,d,c){var h=this,g,m=h.tpls[a],l,b=[];if((m.test&&!m.test.call(h,k,j,d,c))||(m.exec&&m.exec.call(h,k,j,d,c))){return""}l=m.target?m.target.call(h,k,j):k;g=l.length;j=m.target?k:j;if(m.target&&Ext.isArray(l)){for(var e=0,g=l.length;e<g;e++){b[b.length]=m.compiled.call(h,l[e],j,e+1,g)}return b.join("")}return m.compiled.call(h,l,j,d,c)},compileTpl:function(tpl){var fm=Ext.util.Format,useF=this.disableFormats!==true,sep=Ext.isGecko?"+":",",body;function fn(m,name,format,args,math){if(name.substr(0,4)=="xtpl"){return"'"+sep+"this.applySubTemplate("+name.substr(4)+", values, parent, xindex, xcount)"+sep+"'"}var v;if(name==="."){v="values"}else{if(name==="#"){v="xindex"}else{if(name.indexOf(".")!=-1){v=name}else{v="values['"+name+"']"}}}if(math){v="("+v+math+")"}if(format&&useF){args=args?","+args:"";if(format.substr(0,5)!="this."){format="fm."+format+"("}else{format='this.call("'+format.substr(5)+'", ';args=", values"}}else{args="";format="("+v+" === undefined ? '' : "}return"'"+sep+format+v+args+")"+sep+"'"}function codeFn(m,code){return"'"+sep+"("+code.replace(/\\'/g,"'")+")"+sep+"'"}if(Ext.isGecko){body="tpl.compiled = function(values, parent, xindex, xcount){ return '"+tpl.body.replace(/(\r\n|\n)/g,"\\n").replace(/'/g,"\\'").replace(this.re,fn).replace(this.codeRe,codeFn)+"';};"}else{body=["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];body.push(tpl.body.replace(/(\r\n|\n)/g,"\\n").replace(/'/g,"\\'").replace(this.re,fn).replace(this.codeRe,codeFn));body.push("'].join('');};");body=body.join("")}eval(body);return this},applyTemplate:function(a){return this.master.compiled.call(this,a,{},1,1)},compile:function(){return this}});Ext.XTemplate.prototype.apply=Ext.XTemplate.prototype.applyTemplate;Ext.XTemplate.from=function(a){a=Ext.getDom(a);return new Ext.XTemplate(a.value||a.innerHTML)};Ext.util.CSS=function(){var d=null;var c=document;var b=/(-[a-z])/gi;var a=function(e,g){return g.charAt(1).toUpperCase()};return{createStyleSheet:function(i,l){var h;var g=c.getElementsByTagName("head")[0];var k=c.createElement("style");k.setAttribute("type","text/css");if(l){k.setAttribute("id",l)}if(Ext.isIE){g.appendChild(k);h=k.styleSheet;h.cssText=i}else{try{k.appendChild(c.createTextNode(i))}catch(j){k.cssText=i}g.appendChild(k);h=k.styleSheet?k.styleSheet:(k.sheet||c.styleSheets[c.styleSheets.length-1])}this.cacheStyleSheet(h);return h},removeStyleSheet:function(g){var e=c.getElementById(g);if(e){e.parentNode.removeChild(e)}},swapStyleSheet:function(h,e){this.removeStyleSheet(h);var g=c.createElement("link");g.setAttribute("rel","stylesheet");g.setAttribute("type","text/css");g.setAttribute("id",h);g.setAttribute("href",e);c.getElementsByTagName("head")[0].appendChild(g)},refreshCache:function(){return this.getRules(true)},cacheStyleSheet:function(h){if(!d){d={}}try{var k=h.cssRules||h.rules;for(var g=k.length-1;g>=0;--g){d[k[g].selectorText.toLowerCase()]=k[g]}}catch(i){}},getRules:function(h){if(d===null||h){d={};var k=c.styleSheets;for(var j=0,g=k.length;j<g;j++){try{this.cacheStyleSheet(k[j])}catch(l){}}}return d},getRule:function(e,h){var g=this.getRules(h);if(!Ext.isArray(e)){return g[e.toLowerCase()]}for(var j=0;j<e.length;j++){if(g[e[j]]){return g[e[j].toLowerCase()]}}return null},updateRule:function(e,j,h){if(!Ext.isArray(e)){var k=this.getRule(e);if(k){k.style[j.replace(b,a)]=h;return true}}else{for(var g=0;g<e.length;g++){if(this.updateRule(e[g],j,h)){return true}}}return false}}}();Ext.util.ClickRepeater=Ext.extend(Ext.util.Observable,{constructor:function(b,a){this.el=Ext.get(b);this.el.unselectable();Ext.apply(this,a);this.addEvents("mousedown","click","mouseup");if(!this.disabled){this.disabled=true;this.enable()}if(this.handler){this.on("click",this.handler,this.scope||this)}Ext.util.ClickRepeater.superclass.constructor.call(this)},interval:20,delay:250,preventDefault:true,stopDefault:false,timer:0,enable:function(){if(this.disabled){this.el.on("mousedown",this.handleMouseDown,this);if(Ext.isIE){this.el.on("dblclick",this.handleDblClick,this)}if(this.preventDefault||this.stopDefault){this.el.on("click",this.eventOptions,this)}}this.disabled=false},disable:function(a){if(a||!this.disabled){clearTimeout(this.timer);if(this.pressClass){this.el.removeClass(this.pressClass)}Ext.getDoc().un("mouseup",this.handleMouseUp,this);this.el.removeAllListeners()}this.disabled=true},setDisabled:function(a){this[a?"disable":"enable"]()},eventOptions:function(a){if(this.preventDefault){a.preventDefault()}if(this.stopDefault){a.stopEvent()}},destroy:function(){this.disable(true);Ext.destroy(this.el);this.purgeListeners()},handleDblClick:function(a){clearTimeout(this.timer);this.el.blur();this.fireEvent("mousedown",this,a);this.fireEvent("click",this,a)},handleMouseDown:function(a){clearTimeout(this.timer);this.el.blur();if(this.pressClass){this.el.addClass(this.pressClass)}this.mousedownTime=new Date();Ext.getDoc().on("mouseup",this.handleMouseUp,this);this.el.on("mouseout",this.handleMouseOut,this);this.fireEvent("mousedown",this,a);this.fireEvent("click",this,a);if(this.accelerate){this.delay=400}this.timer=this.click.defer(this.delay||this.interval,this,[a])},click:function(a){this.fireEvent("click",this,a);this.timer=this.click.defer(this.accelerate?this.easeOutExpo(this.mousedownTime.getElapsed(),400,-390,12000):this.interval,this,[a])},easeOutExpo:function(e,a,h,g){return(e==g)?a+h:h*(-Math.pow(2,-10*e/g)+1)+a},handleMouseOut:function(){clearTimeout(this.timer);if(this.pressClass){this.el.removeClass(this.pressClass)}this.el.on("mouseover",this.handleMouseReturn,this)},handleMouseReturn:function(){this.el.un("mouseover",this.handleMouseReturn,this);if(this.pressClass){this.el.addClass(this.pressClass)}this.click()},handleMouseUp:function(a){clearTimeout(this.timer);this.el.un("mouseover",this.handleMouseReturn,this);this.el.un("mouseout",this.handleMouseOut,this);Ext.getDoc().un("mouseup",this.handleMouseUp,this);this.el.removeClass(this.pressClass);this.fireEvent("mouseup",this,a)}});Ext.KeyNav=function(b,a){this.el=Ext.get(b);Ext.apply(this,a);if(!this.disabled){this.disabled=true;this.enable()}};Ext.KeyNav.prototype={disabled:false,defaultEventAction:"stopEvent",forceKeyDown:false,relay:function(c){var a=c.getKey(),b=this.keyToHandler[a];if(b&&this[b]){if(this.doRelay(c,this[b],b)!==true){c[this.defaultEventAction]()}}},doRelay:function(c,b,a){return b.call(this.scope||this,c,a)},enter:false,left:false,right:false,up:false,down:false,tab:false,esc:false,pageUp:false,pageDown:false,del:false,home:false,end:false,space:false,keyToHandler:{37:"left",39:"right",38:"up",40:"down",33:"pageUp",34:"pageDown",46:"del",36:"home",35:"end",13:"enter",27:"esc",9:"tab",32:"space"},stopKeyUp:function(b){var a=b.getKey();if(a>=37&&a<=40){b.stopEvent()}},destroy:function(){this.disable()},enable:function(){if(this.disabled){if(Ext.isSafari2){this.el.on("keyup",this.stopKeyUp,this)}this.el.on(this.isKeydown()?"keydown":"keypress",this.relay,this);this.disabled=false}},disable:function(){if(!this.disabled){if(Ext.isSafari2){this.el.un("keyup",this.stopKeyUp,this)}this.el.un(this.isKeydown()?"keydown":"keypress",this.relay,this);this.disabled=true}},setDisabled:function(a){this[a?"disable":"enable"]()},isKeydown:function(){return this.forceKeyDown||Ext.EventManager.useKeydown}};Ext.KeyMap=function(c,b,a){this.el=Ext.get(c);this.eventName=a||"keydown";this.bindings=[];if(b){this.addBinding(b)}this.enable()};Ext.KeyMap.prototype={stopEvent:false,addBinding:function(b){if(Ext.isArray(b)){Ext.each(b,function(j){this.addBinding(j)},this);return}var k=b.key,g=b.fn||b.handler,l=b.scope;if(b.stopEvent){this.stopEvent=b.stopEvent}if(typeof k=="string"){var h=[];var e=k.toUpperCase();for(var c=0,d=e.length;c<d;c++){h.push(e.charCodeAt(c))}k=h}var a=Ext.isArray(k);var i=function(o){if(this.checkModifiers(b,o)){var m=o.getKey();if(a){for(var n=0,j=k.length;n<j;n++){if(k[n]==m){if(this.stopEvent){o.stopEvent()}g.call(l||window,m,o);return}}}else{if(m==k){if(this.stopEvent){o.stopEvent()}g.call(l||window,m,o)}}}};this.bindings.push(i)},checkModifiers:function(b,h){var j,d,g=["shift","ctrl","alt"];for(var c=0,a=g.length;c<a;++c){d=g[c];j=b[d];if(!(j===undefined||(j===h[d+"Key"]))){return false}}return true},on:function(b,d,c){var h,a,e,g;if(typeof b=="object"&&!Ext.isArray(b)){h=b.key;a=b.shift;e=b.ctrl;g=b.alt}else{h=b}this.addBinding({key:h,shift:a,ctrl:e,alt:g,fn:d,scope:c})},handleKeyDown:function(g){if(this.enabled){var c=this.bindings;for(var d=0,a=c.length;d<a;d++){c[d].call(this,g)}}},isEnabled:function(){return this.enabled},enable:function(){if(!this.enabled){this.el.on(this.eventName,this.handleKeyDown,this);this.enabled=true}},disable:function(){if(this.enabled){this.el.removeListener(this.eventName,this.handleKeyDown,this);this.enabled=false}},setDisabled:function(a){this[a?"disable":"enable"]()}};Ext.util.TextMetrics=function(){var a;return{measure:function(b,c,d){if(!a){a=Ext.util.TextMetrics.Instance(b,d)}a.bind(b);a.setFixedWidth(d||"auto");return a.getSize(c)},createInstance:function(b,c){return Ext.util.TextMetrics.Instance(b,c)}}}();Ext.util.TextMetrics.Instance=function(b,d){var c=new Ext.Element(document.createElement("div"));document.body.appendChild(c.dom);c.position("absolute");c.setLeftTop(-1000,-1000);c.hide();if(d){c.setWidth(d)}var a={getSize:function(g){c.update(g);var e=c.getSize();c.update("");return e},bind:function(e){c.setStyle(Ext.fly(e).getStyles("font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"))},setFixedWidth:function(e){c.setWidth(e)},getWidth:function(e){c.dom.style.width="auto";return this.getSize(e).width},getHeight:function(e){return this.getSize(e).height}};a.bind(b);return a};Ext.Element.addMethods({getTextWidth:function(c,b,a){return(Ext.util.TextMetrics.measure(this.dom,Ext.value(c,this.dom.innerHTML,true)).width).constrain(b||0,a||1000000)}});Ext.util.Cookies={set:function(c,e){var a=arguments;var i=arguments.length;var b=(i>2)?a[2]:null;var h=(i>3)?a[3]:"/";var d=(i>4)?a[4]:null;var g=(i>5)?a[5]:false;document.cookie=c+"="+escape(e)+((b===null)?"":("; expires="+b.toGMTString()))+((h===null)?"":("; path="+h))+((d===null)?"":("; domain="+d))+((g===true)?"; secure":"")},get:function(d){var b=d+"=";var g=b.length;var a=document.cookie.length;var e=0;var c=0;while(e<a){c=e+g;if(document.cookie.substring(e,c)==b){return Ext.util.Cookies.getCookieVal(c)}e=document.cookie.indexOf(" ",e)+1;if(e===0){break}}return null},clear:function(a){if(Ext.util.Cookies.get(a)){document.cookie=a+"=; expires=Thu, 01-Jan-70 00:00:01 GMT"}},getCookieVal:function(b){var a=document.cookie.indexOf(";",b);if(a==-1){a=document.cookie.length}return unescape(document.cookie.substring(b,a))}};Ext.handleError=function(a){throw a};Ext.Error=function(a){this.message=(this.lang[a])?this.lang[a]:a};Ext.Error.prototype=new Error();Ext.apply(Ext.Error.prototype,{lang:{},name:"Ext.Error",getName:function(){return this.name},getMessage:function(){return this.message},toJson:function(){return Ext.encode(this)}});Ext.ComponentMgr=function(){var c=new Ext.util.MixedCollection();var b={};var a={};return{register:function(d){c.add(d)},unregister:function(d){c.remove(d)},get:function(d){return c.get(d)},onAvailable:function(g,e,d){c.on("add",function(h,i){if(i.id==g){e.call(d||i,i);c.un("add",e,d)}})},all:c,types:b,ptypes:a,isRegistered:function(d){return b[d]!==undefined},isPluginRegistered:function(d){return a[d]!==undefined},registerType:function(e,d){b[e]=d;d.xtype=e},create:function(d,e){return d.render?d:new b[d.xtype||e](d)},registerPlugin:function(e,d){a[e]=d;d.ptype=e},createPlugin:function(e,g){var d=a[e.ptype||g];if(d.init){return d}else{return new d(e)}}}}();Ext.reg=Ext.ComponentMgr.registerType;Ext.preg=Ext.ComponentMgr.registerPlugin;Ext.create=Ext.ComponentMgr.create;Ext.Component=function(b){b=b||{};if(b.initialConfig){if(b.isAction){this.baseAction=b}b=b.initialConfig}else{if(b.tagName||b.dom||Ext.isString(b)){b={applyTo:b,id:b.id||b}}}this.initialConfig=b;Ext.apply(this,b);this.addEvents("added","disable","enable","beforeshow","show","beforehide","hide","removed","beforerender","render","afterrender","beforedestroy","destroy","beforestaterestore","staterestore","beforestatesave","statesave");this.getId();Ext.ComponentMgr.register(this);Ext.Component.superclass.constructor.call(this);if(this.baseAction){this.baseAction.addComponent(this)}this.initComponent();if(this.plugins){if(Ext.isArray(this.plugins)){for(var c=0,a=this.plugins.length;c<a;c++){this.plugins[c]=this.initPlugin(this.plugins[c])}}else{this.plugins=this.initPlugin(this.plugins)}}if(this.stateful!==false){this.initState()}if(this.applyTo){this.applyToMarkup(this.applyTo);delete this.applyTo}else{if(this.renderTo){this.render(this.renderTo);delete this.renderTo}}};Ext.Component.AUTO_ID=1000;Ext.extend(Ext.Component,Ext.util.Observable,{disabled:false,hidden:false,autoEl:"div",disabledClass:"x-item-disabled",allowDomMove:true,autoShow:false,hideMode:"display",hideParent:false,rendered:false,tplWriteMode:"overwrite",bubbleEvents:[],ctype:"Ext.Component",actionMode:"el",getActionEl:function(){return this[this.actionMode]},initPlugin:function(a){if(a.ptype&&!Ext.isFunction(a.init)){a=Ext.ComponentMgr.createPlugin(a)}else{if(Ext.isString(a)){a=Ext.ComponentMgr.createPlugin({ptype:a})}}a.init(this);return a},initComponent:function(){if(this.listeners){this.on(this.listeners);delete this.listeners}this.enableBubble(this.bubbleEvents)},render:function(b,a){if(!this.rendered&&this.fireEvent("beforerender",this)!==false){if(!b&&this.el){this.el=Ext.get(this.el);b=this.el.dom.parentNode;this.allowDomMove=false}this.container=Ext.get(b);if(this.ctCls){this.container.addClass(this.ctCls)}this.rendered=true;if(a!==undefined){if(Ext.isNumber(a)){a=this.container.dom.childNodes[a]}else{a=Ext.getDom(a)}}this.onRender(this.container,a||null);if(this.autoShow){this.el.removeClass(["x-hidden","x-hide-"+this.hideMode])}if(this.cls){this.el.addClass(this.cls);delete this.cls}if(this.style){this.el.applyStyles(this.style);delete this.style}if(this.overCls){this.el.addClassOnOver(this.overCls)}this.fireEvent("render",this);var c=this.getContentTarget();if(this.html){c.update(Ext.DomHelper.markup(this.html));delete this.html}if(this.contentEl){var d=Ext.getDom(this.contentEl);Ext.fly(d).removeClass(["x-hidden","x-hide-display"]);c.appendChild(d)}if(this.tpl){if(!this.tpl.compile){this.tpl=new Ext.XTemplate(this.tpl)}if(this.data){this.tpl[this.tplWriteMode](c,this.data);delete this.data}}this.afterRender(this.container);if(this.hidden){this.doHide()}if(this.disabled){this.disable(true)}if(this.stateful!==false){this.initStateEvents()}this.fireEvent("afterrender",this)}return this},update:function(b,d,a){var c=this.getContentTarget();if(this.tpl&&typeof b!=="string"){this.tpl[this.tplWriteMode](c,b||{})}else{var e=Ext.isObject(b)?Ext.DomHelper.markup(b):b;c.update(e,d,a)}},onAdded:function(a,b){this.ownerCt=a;this.initRef();this.fireEvent("added",this,a,b)},onRemoved:function(){this.removeRef();this.fireEvent("removed",this,this.ownerCt);delete this.ownerCt},initRef:function(){if(this.ref&&!this.refOwner){var d=this.ref.split("/"),c=d.length,b=0,a=this;while(a&&b<c){a=a.ownerCt;++b}if(a){a[this.refName=d[--b]]=this;this.refOwner=a}}},removeRef:function(){if(this.refOwner&&this.refName){delete this.refOwner[this.refName];delete this.refOwner}},initState:function(){if(Ext.state.Manager){var b=this.getStateId();if(b){var a=Ext.state.Manager.get(b);if(a){if(this.fireEvent("beforestaterestore",this,a)!==false){this.applyState(Ext.apply({},a));this.fireEvent("staterestore",this,a)}}}}},getStateId:function(){return this.stateId||((/^(ext-comp-|ext-gen)/).test(String(this.id))?null:this.id)},initStateEvents:function(){if(this.stateEvents){for(var a=0,b;b=this.stateEvents[a];a++){this.on(b,this.saveState,this,{delay:100})}}},applyState:function(a){if(a){Ext.apply(this,a)}},getState:function(){return null},saveState:function(){if(Ext.state.Manager&&this.stateful!==false){var b=this.getStateId();if(b){var a=this.getState();if(this.fireEvent("beforestatesave",this,a)!==false){Ext.state.Manager.set(b,a);this.fireEvent("statesave",this,a)}}}},applyToMarkup:function(a){this.allowDomMove=false;this.el=Ext.get(a);this.render(this.el.dom.parentNode)},addClass:function(a){if(this.el){this.el.addClass(a)}else{this.cls=this.cls?this.cls+" "+a:a}return this},removeClass:function(a){if(this.el){this.el.removeClass(a)}else{if(this.cls){this.cls=this.cls.split(" ").remove(a).join(" ")}}return this},onRender:function(b,a){if(!this.el&&this.autoEl){if(Ext.isString(this.autoEl)){this.el=document.createElement(this.autoEl)}else{var c=document.createElement("div");Ext.DomHelper.overwrite(c,this.autoEl);this.el=c.firstChild}if(!this.el.id){this.el.id=this.getId()}}if(this.el){this.el=Ext.get(this.el);if(this.allowDomMove!==false){b.dom.insertBefore(this.el.dom,a);if(c){Ext.removeNode(c);c=null}}}},getAutoCreate:function(){var a=Ext.isObject(this.autoCreate)?this.autoCreate:Ext.apply({},this.defaultAutoCreate);if(this.id&&!a.id){a.id=this.id}return a},afterRender:Ext.emptyFn,destroy:function(){if(!this.isDestroyed){if(this.fireEvent("beforedestroy",this)!==false){this.destroying=true;this.beforeDestroy();if(this.ownerCt&&this.ownerCt.remove){this.ownerCt.remove(this,false)}if(this.rendered){this.el.remove();if(this.actionMode=="container"||this.removeMode=="container"){this.container.remove()}}if(this.focusTask&&this.focusTask.cancel){this.focusTask.cancel()}this.onDestroy();Ext.ComponentMgr.unregister(this);this.fireEvent("destroy",this);this.purgeListeners();this.destroying=false;this.isDestroyed=true}}},deleteMembers:function(){var b=arguments;for(var c=0,a=b.length;c<a;++c){delete this[b[c]]}},beforeDestroy:Ext.emptyFn,onDestroy:Ext.emptyFn,getEl:function(){return this.el},getContentTarget:function(){return this.el},getId:function(){return this.id||(this.id="ext-comp-"+(++Ext.Component.AUTO_ID))},getItemId:function(){return this.itemId||this.getId()},focus:function(b,a){if(a){this.focusTask=new Ext.util.DelayedTask(this.focus,this,[b,false]);this.focusTask.delay(Ext.isNumber(a)?a:10);return this}if(this.rendered&&!this.isDestroyed){this.el.focus();if(b===true){this.el.dom.select()}}return this},blur:function(){if(this.rendered){this.el.blur()}return this},disable:function(a){if(this.rendered){this.onDisable()}this.disabled=true;if(a!==true){this.fireEvent("disable",this)}return this},onDisable:function(){this.getActionEl().addClass(this.disabledClass);this.el.dom.disabled=true},enable:function(){if(this.rendered){this.onEnable()}this.disabled=false;this.fireEvent("enable",this);return this},onEnable:function(){this.getActionEl().removeClass(this.disabledClass);this.el.dom.disabled=false},setDisabled:function(a){return this[a?"disable":"enable"]()},show:function(){if(this.fireEvent("beforeshow",this)!==false){this.hidden=false;if(this.autoRender){this.render(Ext.isBoolean(this.autoRender)?Ext.getBody():this.autoRender)}if(this.rendered){this.onShow()}this.fireEvent("show",this)}return this},onShow:function(){this.getVisibilityEl().removeClass("x-hide-"+this.hideMode)},hide:function(){if(this.fireEvent("beforehide",this)!==false){this.doHide();this.fireEvent("hide",this)}return this},doHide:function(){this.hidden=true;if(this.rendered){this.onHide()}},onHide:function(){this.getVisibilityEl().addClass("x-hide-"+this.hideMode)},getVisibilityEl:function(){return this.hideParent?this.container:this.getActionEl()},setVisible:function(a){return this[a?"show":"hide"]()},isVisible:function(){return this.rendered&&this.getVisibilityEl().isVisible()},cloneConfig:function(b){b=b||{};var c=b.id||Ext.id();var a=Ext.applyIf(b,this.initialConfig);a.id=c;return new this.constructor(a)},getXType:function(){return this.constructor.xtype},isXType:function(b,a){if(Ext.isFunction(b)){b=b.xtype}else{if(Ext.isObject(b)){b=b.constructor.xtype}}return !a?("/"+this.getXTypes()+"/").indexOf("/"+b+"/")!=-1:this.constructor.xtype==b},getXTypes:function(){var a=this.constructor;if(!a.xtypes){var d=[],b=this;while(b&&b.constructor.xtype){d.unshift(b.constructor.xtype);b=b.constructor.superclass}a.xtypeChain=d;a.xtypes=d.join("/")}return a.xtypes},findParentBy:function(a){for(var b=this.ownerCt;(b!=null)&&!a(b,this);b=b.ownerCt){}return b||null},findParentByType:function(b,a){return this.findParentBy(function(d){return d.isXType(b,a)})},bubble:function(c,b,a){var d=this;while(d){if(c.apply(b||d,a||[d])===false){break}d=d.ownerCt}return this},getPositionEl:function(){return this.positionEl||this.el},purgeListeners:function(){Ext.Component.superclass.purgeListeners.call(this);if(this.mons){this.on("beforedestroy",this.clearMons,this,{single:true})}},clearMons:function(){Ext.each(this.mons,function(a){a.item.un(a.ename,a.fn,a.scope)},this);this.mons=[]},createMons:function(){if(!this.mons){this.mons=[];this.on("beforedestroy",this.clearMons,this,{single:true})}},mon:function(g,b,d,c,a){this.createMons();if(Ext.isObject(b)){var j=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;var i=b;for(var h in i){if(j.test(h)){continue}if(Ext.isFunction(i[h])){this.mons.push({item:g,ename:h,fn:i[h],scope:i.scope});g.on(h,i[h],i.scope,i)}else{this.mons.push({item:g,ename:h,fn:i[h],scope:i.scope});g.on(h,i[h])}}return}this.mons.push({item:g,ename:b,fn:d,scope:c});g.on(b,d,c,a)},mun:function(h,c,g,e){var j,d;this.createMons();for(var b=0,a=this.mons.length;b<a;++b){d=this.mons[b];if(h===d.item&&c==d.ename&&g===d.fn&&e===d.scope){this.mons.splice(b,1);h.un(c,g,e);j=true;break}}return j},nextSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a!=-1&&a+1<this.ownerCt.items.getCount()){return this.ownerCt.items.itemAt(a+1)}}return null},previousSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a>0){return this.ownerCt.items.itemAt(a-1)}}return null},getBubbleTarget:function(){return this.ownerCt}});Ext.reg("component",Ext.Component);Ext.Action=Ext.extend(Object,{constructor:function(a){this.initialConfig=a;this.itemId=a.itemId=(a.itemId||a.id||Ext.id());this.items=[]},isAction:true,setText:function(a){this.initialConfig.text=a;this.callEach("setText",[a])},getText:function(){return this.initialConfig.text},setIconClass:function(a){this.initialConfig.iconCls=a;this.callEach("setIconClass",[a])},getIconClass:function(){return this.initialConfig.iconCls},setDisabled:function(a){this.initialConfig.disabled=a;this.callEach("setDisabled",[a])},enable:function(){this.setDisabled(false)},disable:function(){this.setDisabled(true)},isDisabled:function(){return this.initialConfig.disabled},setHidden:function(a){this.initialConfig.hidden=a;this.callEach("setVisible",[!a])},show:function(){this.setHidden(false)},hide:function(){this.setHidden(true)},isHidden:function(){return this.initialConfig.hidden},setHandler:function(b,a){this.initialConfig.handler=b;this.initialConfig.scope=a;this.callEach("setHandler",[b,a])},each:function(b,a){Ext.each(this.items,b,a)},callEach:function(e,b){var d=this.items;for(var c=0,a=d.length;c<a;c++){d[c][e].apply(d[c],b)}},addComponent:function(a){this.items.push(a);a.on("destroy",this.removeComponent,this)},removeComponent:function(a){this.items.remove(a)},execute:function(){this.initialConfig.handler.apply(this.initialConfig.scope||window,arguments)}});(function(){Ext.Layer=function(d,c){d=d||{};var e=Ext.DomHelper,h=d.parentEl,g=h?Ext.getDom(h):document.body;if(c){this.dom=Ext.getDom(c)}if(!this.dom){var i=d.dh||{tag:"div",cls:"x-layer"};this.dom=e.append(g,i)}if(d.cls){this.addClass(d.cls)}this.constrain=d.constrain!==false;this.setVisibilityMode(Ext.Element.VISIBILITY);if(d.id){this.id=this.dom.id=d.id}else{this.id=Ext.id(this.dom)}this.zindex=d.zindex||this.getZIndex();this.position("absolute",this.zindex);if(d.shadow){this.shadowOffset=d.shadowOffset||4;this.shadow=new Ext.Shadow({offset:this.shadowOffset,mode:d.shadow})}else{this.shadowOffset=0}this.useShim=d.shim!==false&&Ext.useShims;this.useDisplay=d.useDisplay;this.hide()};var a=Ext.Element.prototype;var b=[];Ext.extend(Ext.Layer,Ext.Element,{getZIndex:function(){return this.zindex||parseInt((this.getShim()||this).getStyle("z-index"),10)||11000},getShim:function(){if(!this.useShim){return null}if(this.shim){return this.shim}var d=b.shift();if(!d){d=this.createShim();d.enableDisplayMode("block");d.dom.style.display="none";d.dom.style.visibility="visible"}var c=this.dom.parentNode;if(d.dom.parentNode!=c){c.insertBefore(d.dom,this.dom)}d.setStyle("z-index",this.getZIndex()-2);this.shim=d;return d},hideShim:function(){if(this.shim){this.shim.setDisplayed(false);b.push(this.shim);delete this.shim}},disableShadow:function(){if(this.shadow){this.shadowDisabled=true;this.shadow.hide();this.lastShadowOffset=this.shadowOffset;this.shadowOffset=0}},enableShadow:function(c){if(this.shadow){this.shadowDisabled=false;if(Ext.isDefined(this.lastShadowOffset)){this.shadowOffset=this.lastShadowOffset;delete this.lastShadowOffset}if(c){this.sync(true)}}},sync:function(d){var n=this.shadow;if(!this.updating&&this.isVisible()&&(n||this.useShim)){var i=this.getShim(),m=this.getWidth(),j=this.getHeight(),e=this.getLeft(true),o=this.getTop(true);if(n&&!this.shadowDisabled){if(d&&!n.isVisible()){n.show(this)}else{n.realign(e,o,m,j)}if(i){if(d){i.show()}var k=n.el.getXY(),g=i.dom.style,c=n.el.getSize();g.left=(k[0])+"px";g.top=(k[1])+"px";g.width=(c.width)+"px";g.height=(c.height)+"px"}}else{if(i){if(d){i.show()}i.setSize(m,j);i.setLeftTop(e,o)}}}},destroy:function(){this.hideShim();if(this.shadow){this.shadow.hide()}this.removeAllListeners();Ext.removeNode(this.dom);delete this.dom},remove:function(){this.destroy()},beginUpdate:function(){this.updating=true},endUpdate:function(){this.updating=false;this.sync(true)},hideUnders:function(c){if(this.shadow){this.shadow.hide()}this.hideShim()},constrainXY:function(){if(this.constrain){var j=Ext.lib.Dom.getViewWidth(),d=Ext.lib.Dom.getViewHeight();var o=Ext.getDoc().getScroll();var n=this.getXY();var k=n[0],i=n[1];var c=this.shadowOffset;var l=this.dom.offsetWidth+c,e=this.dom.offsetHeight+c;var g=false;if((k+l)>j+o.left){k=j-l-c;g=true}if((i+e)>d+o.top){i=d-e-c;g=true}if(k<o.left){k=o.left;g=true}if(i<o.top){i=o.top;g=true}if(g){if(this.avoidY){var m=this.avoidY;if(i<=m&&(i+e)>=m){i=m-e-5}}n=[k,i];this.storeXY(n);a.setXY.call(this,n);this.sync()}}return this},getConstrainOffset:function(){return this.shadowOffset},isVisible:function(){return this.visible},showAction:function(){this.visible=true;if(this.useDisplay===true){this.setDisplayed("")}else{if(this.lastXY){a.setXY.call(this,this.lastXY)}else{if(this.lastLT){a.setLeftTop.call(this,this.lastLT[0],this.lastLT[1])}}}},hideAction:function(){this.visible=false;if(this.useDisplay===true){this.setDisplayed(false)}else{this.setLeftTop(-10000,-10000)}},setVisible:function(i,h,k,l,j){if(i){this.showAction()}if(h&&i){var g=function(){this.sync(true);if(l){l()}}.createDelegate(this);a.setVisible.call(this,true,true,k,g,j)}else{if(!i){this.hideUnders(true)}var g=l;if(h){g=function(){this.hideAction();if(l){l()}}.createDelegate(this)}a.setVisible.call(this,i,h,k,g,j);if(i){this.sync(true)}else{if(!h){this.hideAction()}}}return this},storeXY:function(c){delete this.lastLT;this.lastXY=c},storeLeftTop:function(d,c){delete this.lastXY;this.lastLT=[d,c]},beforeFx:function(){this.beforeAction();return Ext.Layer.superclass.beforeFx.apply(this,arguments)},afterFx:function(){Ext.Layer.superclass.afterFx.apply(this,arguments);this.sync(this.isVisible())},beforeAction:function(){if(!this.updating&&this.shadow){this.shadow.hide()}},setLeft:function(c){this.storeLeftTop(c,this.getTop(true));a.setLeft.apply(this,arguments);this.sync();return this},setTop:function(c){this.storeLeftTop(this.getLeft(true),c);a.setTop.apply(this,arguments);this.sync();return this},setLeftTop:function(d,c){this.storeLeftTop(d,c);a.setLeftTop.apply(this,arguments);this.sync();return this},setXY:function(j,h,k,l,i){this.fixDisplay();this.beforeAction();this.storeXY(j);var g=this.createCB(l);a.setXY.call(this,j,h,k,g,i);if(!h){g()}return this},createCB:function(e){var d=this;return function(){d.constrainXY();d.sync(true);if(e){e()}}},setX:function(g,h,j,k,i){this.setXY([g,this.getY()],h,j,k,i);return this},setY:function(k,g,i,j,h){this.setXY([this.getX(),k],g,i,j,h);return this},setSize:function(j,k,i,m,n,l){this.beforeAction();var g=this.createCB(n);a.setSize.call(this,j,k,i,m,g,l);if(!i){g()}return this},setWidth:function(i,h,k,l,j){this.beforeAction();var g=this.createCB(l);a.setWidth.call(this,i,h,k,g,j);if(!h){g()}return this},setHeight:function(j,i,l,m,k){this.beforeAction();var g=this.createCB(m);a.setHeight.call(this,j,i,l,g,k);if(!i){g()}return this},setBounds:function(o,m,p,i,n,k,l,j){this.beforeAction();var g=this.createCB(l);if(!n){this.storeXY([o,m]);a.setXY.call(this,[o,m]);a.setSize.call(this,p,i,n,k,g,j);g()}else{a.setBounds.call(this,o,m,p,i,n,k,g,j)}return this},setZIndex:function(c){this.zindex=c;this.setStyle("z-index",c+2);if(this.shadow){this.shadow.setZIndex(c+1)}if(this.shim){this.shim.setStyle("z-index",c)}return this}})})();Ext.Shadow=function(d){Ext.apply(this,d);if(typeof this.mode!="string"){this.mode=this.defaultMode}var e=this.offset,c={h:0},b=Math.floor(this.offset/2);switch(this.mode.toLowerCase()){case"drop":c.w=0;c.l=c.t=e;c.t-=1;if(Ext.isIE){c.l-=this.offset+b;c.t-=this.offset+b;c.w-=b;c.h-=b;c.t+=1}break;case"sides":c.w=(e*2);c.l=-e;c.t=e-1;if(Ext.isIE){c.l-=(this.offset-b);c.t-=this.offset+b;c.l+=1;c.w-=(this.offset-b)*2;c.w-=b+1;c.h-=1}break;case"frame":c.w=c.h=(e*2);c.l=c.t=-e;c.t+=1;c.h-=2;if(Ext.isIE){c.l-=(this.offset-b);c.t-=(this.offset-b);c.l+=1;c.w-=(this.offset+b+1);c.h-=(this.offset+b);c.h+=1}break}this.adjusts=c};Ext.Shadow.prototype={offset:4,defaultMode:"drop",show:function(a){a=Ext.get(a);if(!this.el){this.el=Ext.Shadow.Pool.pull();if(this.el.dom.nextSibling!=a.dom){this.el.insertBefore(a)}}this.el.setStyle("z-index",this.zIndex||parseInt(a.getStyle("z-index"),10)-1);if(Ext.isIE){this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")"}this.realign(a.getLeft(true),a.getTop(true),a.getWidth(),a.getHeight());this.el.dom.style.display="block"},isVisible:function(){return this.el?true:false},realign:function(b,r,q,g){if(!this.el){return}var n=this.adjusts,k=this.el.dom,u=k.style,i=0,p=(q+n.w),e=(g+n.h),j=p+"px",o=e+"px",m,c;u.left=(b+n.l)+"px";u.top=(r+n.t)+"px";if(u.width!=j||u.height!=o){u.width=j;u.height=o;if(!Ext.isIE){m=k.childNodes;c=Math.max(0,(p-12))+"px";m[0].childNodes[1].style.width=c;m[1].childNodes[1].style.width=c;m[2].childNodes[1].style.width=c;m[1].style.height=Math.max(0,(e-12))+"px"}}},hide:function(){if(this.el){this.el.dom.style.display="none";Ext.Shadow.Pool.push(this.el);delete this.el}},setZIndex:function(a){this.zIndex=a;if(this.el){this.el.setStyle("z-index",a)}}};Ext.Shadow.Pool=function(){var b=[],a=Ext.isIE?'<div class="x-ie-shadow"></div>':'<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';return{pull:function(){var c=b.shift();if(!c){c=Ext.get(Ext.DomHelper.insertHtml("beforeBegin",document.body.firstChild,a));c.autoBoxAdjust=false}return c},push:function(c){b.push(c)}}}();Ext.BoxComponent=Ext.extend(Ext.Component,{initComponent:function(){Ext.BoxComponent.superclass.initComponent.call(this);this.addEvents("resize","move")},boxReady:false,deferHeight:false,setSize:function(b,d){if(typeof b=="object"){d=b.height;b=b.width}if(Ext.isDefined(b)&&Ext.isDefined(this.boxMinWidth)&&(b<this.boxMinWidth)){b=this.boxMinWidth}if(Ext.isDefined(d)&&Ext.isDefined(this.boxMinHeight)&&(d<this.boxMinHeight)){d=this.boxMinHeight}if(Ext.isDefined(b)&&Ext.isDefined(this.boxMaxWidth)&&(b>this.boxMaxWidth)){b=this.boxMaxWidth}if(Ext.isDefined(d)&&Ext.isDefined(this.boxMaxHeight)&&(d>this.boxMaxHeight)){d=this.boxMaxHeight}if(!this.boxReady){this.width=b;this.height=d;return this}if(this.cacheSizes!==false&&this.lastSize&&this.lastSize.width==b&&this.lastSize.height==d){return this}this.lastSize={width:b,height:d};var c=this.adjustSize(b,d),g=c.width,a=c.height,e;if(g!==undefined||a!==undefined){e=this.getResizeEl();if(!this.deferHeight&&g!==undefined&&a!==undefined){e.setSize(g,a)}else{if(!this.deferHeight&&a!==undefined){e.setHeight(a)}else{if(g!==undefined){e.setWidth(g)}}}this.onResize(g,a,b,d);this.fireEvent("resize",this,g,a,b,d)}return this},setWidth:function(a){return this.setSize(a)},setHeight:function(a){return this.setSize(undefined,a)},getSize:function(){return this.getResizeEl().getSize()},getWidth:function(){return this.getResizeEl().getWidth()},getHeight:function(){return this.getResizeEl().getHeight()},getOuterSize:function(){var a=this.getResizeEl();return{width:a.getWidth()+a.getMargins("lr"),height:a.getHeight()+a.getMargins("tb")}},getPosition:function(a){var b=this.getPositionEl();if(a===true){return[b.getLeft(true),b.getTop(true)]}return this.xy||b.getXY()},getBox:function(a){var c=this.getPosition(a);var b=this.getSize();b.x=c[0];b.y=c[1];return b},updateBox:function(a){this.setSize(a.width,a.height);this.setPagePosition(a.x,a.y);return this},getResizeEl:function(){return this.resizeEl||this.el},setAutoScroll:function(a){if(this.rendered){this.getContentTarget().setOverflow(a?"auto":"")}this.autoScroll=a;return this},setPosition:function(a,g){if(a&&typeof a[1]=="number"){g=a[1];a=a[0]}this.x=a;this.y=g;if(!this.boxReady){return this}var b=this.adjustPosition(a,g);var e=b.x,d=b.y;var c=this.getPositionEl();if(e!==undefined||d!==undefined){if(e!==undefined&&d!==undefined){c.setLeftTop(e,d)}else{if(e!==undefined){c.setLeft(e)}else{if(d!==undefined){c.setTop(d)}}}this.onPosition(e,d);this.fireEvent("move",this,e,d)}return this},setPagePosition:function(a,c){if(a&&typeof a[1]=="number"){c=a[1];a=a[0]}this.pageX=a;this.pageY=c;if(!this.boxReady){return}if(a===undefined||c===undefined){return}var b=this.getPositionEl().translatePoints(a,c);this.setPosition(b.left,b.top);return this},afterRender:function(){Ext.BoxComponent.superclass.afterRender.call(this);if(this.resizeEl){this.resizeEl=Ext.get(this.resizeEl)}if(this.positionEl){this.positionEl=Ext.get(this.positionEl)}this.boxReady=true;Ext.isDefined(this.autoScroll)&&this.setAutoScroll(this.autoScroll);this.setSize(this.width,this.height);if(this.x||this.y){this.setPosition(this.x,this.y)}else{if(this.pageX||this.pageY){this.setPagePosition(this.pageX,this.pageY)}}},syncSize:function(){delete this.lastSize;this.setSize(this.autoWidth?undefined:this.getResizeEl().getWidth(),this.autoHeight?undefined:this.getResizeEl().getHeight());return this},onResize:function(d,b,a,c){},onPosition:function(a,b){},adjustSize:function(a,b){if(this.autoWidth){a="auto"}if(this.autoHeight){b="auto"}return{width:a,height:b}},adjustPosition:function(a,b){return{x:a,y:b}}});Ext.reg("box",Ext.BoxComponent);Ext.Spacer=Ext.extend(Ext.BoxComponent,{autoEl:"div"});Ext.reg("spacer",Ext.Spacer);Ext.SplitBar=function(c,e,b,d,a){this.el=Ext.get(c,true);this.el.dom.unselectable="on";this.resizingEl=Ext.get(e,true);this.orientation=b||Ext.SplitBar.HORIZONTAL;this.minSize=0;this.maxSize=2000;this.animate=false;this.useShim=false;this.shim=null;if(!a){this.proxy=Ext.SplitBar.createProxy(this.orientation)}else{this.proxy=Ext.get(a).dom}this.dd=new Ext.dd.DDProxy(this.el.dom.id,"XSplitBars",{dragElId:this.proxy.id});this.dd.b4StartDrag=this.onStartProxyDrag.createDelegate(this);this.dd.endDrag=this.onEndProxyDrag.createDelegate(this);this.dragSpecs={};this.adapter=new Ext.SplitBar.BasicLayoutAdapter();this.adapter.init(this);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.placement=d||(this.el.getX()>this.resizingEl.getX()?Ext.SplitBar.LEFT:Ext.SplitBar.RIGHT);this.el.addClass("x-splitbar-h")}else{this.placement=d||(this.el.getY()>this.resizingEl.getY()?Ext.SplitBar.TOP:Ext.SplitBar.BOTTOM);this.el.addClass("x-splitbar-v")}this.addEvents("resize","moved","beforeresize","beforeapply");Ext.SplitBar.superclass.constructor.call(this)};Ext.extend(Ext.SplitBar,Ext.util.Observable,{onStartProxyDrag:function(a,e){this.fireEvent("beforeresize",this);this.overlay=Ext.DomHelper.append(document.body,{cls:"x-drag-overlay",html:"&#160;"},true);this.overlay.unselectable();this.overlay.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.overlay.show();Ext.get(this.proxy).setDisplayed("block");var c=this.adapter.getElementSize(this);this.activeMinSize=this.getMinimumSize();this.activeMaxSize=this.getMaximumSize();var d=c-this.activeMinSize;var b=Math.max(this.activeMaxSize-c,0);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.dd.resetConstraints();this.dd.setXConstraint(this.placement==Ext.SplitBar.LEFT?d:b,this.placement==Ext.SplitBar.LEFT?b:d,this.tickSize);this.dd.setYConstraint(0,0)}else{this.dd.resetConstraints();this.dd.setXConstraint(0,0);this.dd.setYConstraint(this.placement==Ext.SplitBar.TOP?d:b,this.placement==Ext.SplitBar.TOP?b:d,this.tickSize)}this.dragSpecs.startSize=c;this.dragSpecs.startPoint=[a,e];Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd,a,e)},onEndProxyDrag:function(c){Ext.get(this.proxy).setDisplayed(false);var b=Ext.lib.Event.getXY(c);if(this.overlay){Ext.destroy(this.overlay);delete this.overlay}var a;if(this.orientation==Ext.SplitBar.HORIZONTAL){a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.LEFT?b[0]-this.dragSpecs.startPoint[0]:this.dragSpecs.startPoint[0]-b[0])}else{a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.TOP?b[1]-this.dragSpecs.startPoint[1]:this.dragSpecs.startPoint[1]-b[1])}a=Math.min(Math.max(a,this.activeMinSize),this.activeMaxSize);if(a!=this.dragSpecs.startSize){if(this.fireEvent("beforeapply",this,a)!==false){this.adapter.setElementSize(this,a);this.fireEvent("moved",this,a);this.fireEvent("resize",this,a)}}},getAdapter:function(){return this.adapter},setAdapter:function(a){this.adapter=a;this.adapter.init(this)},getMinimumSize:function(){return this.minSize},setMinimumSize:function(a){this.minSize=a},getMaximumSize:function(){return this.maxSize},setMaximumSize:function(a){this.maxSize=a},setCurrentSize:function(b){var a=this.animate;this.animate=false;this.adapter.setElementSize(this,b);this.animate=a},destroy:function(a){Ext.destroy(this.shim,Ext.get(this.proxy));this.dd.unreg();if(a){this.el.remove()}this.purgeListeners()}});Ext.SplitBar.createProxy=function(b){var c=new Ext.Element(document.createElement("div"));document.body.appendChild(c.dom);c.unselectable();var a="x-splitbar-proxy";c.addClass(a+" "+(b==Ext.SplitBar.HORIZONTAL?a+"-h":a+"-v"));return c.dom};Ext.SplitBar.BasicLayoutAdapter=function(){};Ext.SplitBar.BasicLayoutAdapter.prototype={init:function(a){},getElementSize:function(a){if(a.orientation==Ext.SplitBar.HORIZONTAL){return a.resizingEl.getWidth()}else{return a.resizingEl.getHeight()}},setElementSize:function(b,a,c){if(b.orientation==Ext.SplitBar.HORIZONTAL){if(!b.animate){b.resizingEl.setWidth(a);if(c){c(b,a)}}else{b.resizingEl.setWidth(a,true,0.1,c,"easeOut")}}else{if(!b.animate){b.resizingEl.setHeight(a);if(c){c(b,a)}}else{b.resizingEl.setHeight(a,true,0.1,c,"easeOut")}}}};Ext.SplitBar.AbsoluteLayoutAdapter=function(a){this.basic=new Ext.SplitBar.BasicLayoutAdapter();this.container=Ext.get(a)};Ext.SplitBar.AbsoluteLayoutAdapter.prototype={init:function(a){this.basic.init(a)},getElementSize:function(a){return this.basic.getElementSize(a)},setElementSize:function(b,a,c){this.basic.setElementSize(b,a,this.moveSplitter.createDelegate(this,[b]))},moveSplitter:function(a){var b=Ext.SplitBar;switch(a.placement){case b.LEFT:a.el.setX(a.resizingEl.getRight());break;case b.RIGHT:a.el.setStyle("right",(this.container.getWidth()-a.resizingEl.getLeft())+"px");break;case b.TOP:a.el.setY(a.resizingEl.getBottom());break;case b.BOTTOM:a.el.setY(a.resizingEl.getTop()-a.el.getHeight());break}}};Ext.SplitBar.VERTICAL=1;Ext.SplitBar.HORIZONTAL=2;Ext.SplitBar.LEFT=1;Ext.SplitBar.RIGHT=2;Ext.SplitBar.TOP=3;Ext.SplitBar.BOTTOM=4;Ext.Container=Ext.extend(Ext.BoxComponent,{bufferResize:50,autoDestroy:true,forceLayout:false,defaultType:"panel",resizeEvent:"resize",bubbleEvents:["add","remove"],initComponent:function(){Ext.Container.superclass.initComponent.call(this);this.addEvents("afterlayout","beforeadd","beforeremove","add","remove");var a=this.items;if(a){delete this.items;this.add(a)}},initItems:function(){if(!this.items){this.items=new Ext.util.MixedCollection(false,this.getComponentId);this.getLayout()}},setLayout:function(a){if(this.layout&&this.layout!=a){this.layout.setContainer(null)}this.layout=a;this.initItems();a.setContainer(this)},afterRender:function(){Ext.Container.superclass.afterRender.call(this);if(!this.layout){this.layout="auto"}if(Ext.isObject(this.layout)&&!this.layout.layout){this.layoutConfig=this.layout;this.layout=this.layoutConfig.type}if(Ext.isString(this.layout)){this.layout=new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig)}this.setLayout(this.layout);if(this.activeItem!==undefined&&this.layout.setActiveItem){var a=this.activeItem;delete this.activeItem;this.layout.setActiveItem(a)}if(!this.ownerCt){this.doLayout(false,true)}if(this.monitorResize===true){Ext.EventManager.onWindowResize(this.doLayout,this,[false])}},getLayoutTarget:function(){return this.el},getComponentId:function(a){return a.getItemId()},add:function(b){this.initItems();var e=arguments.length>1;if(e||Ext.isArray(b)){var a=[];Ext.each(e?arguments:b,function(h){a.push(this.add(h))},this);return a}var g=this.lookupComponent(this.applyDefaults(b));var d=this.items.length;if(this.fireEvent("beforeadd",this,g,d)!==false&&this.onBeforeAdd(g)!==false){this.items.add(g);g.onAdded(this,d);this.onAdd(g);this.fireEvent("add",this,g,d)}return g},onAdd:function(a){},onAdded:function(a,b){this.ownerCt=a;this.initRef();this.cascade(function(d){d.initRef()});this.fireEvent("added",this,a,b)},insert:function(e,b){var d=arguments,h=d.length,a=[],g,j;this.initItems();if(h>2){for(g=h-1;g>=1;--g){a.push(this.insert(e,d[g]))}return a}j=this.lookupComponent(this.applyDefaults(b));e=Math.min(e,this.items.length);if(this.fireEvent("beforeadd",this,j,e)!==false&&this.onBeforeAdd(j)!==false){if(j.ownerCt==this){this.items.remove(j)}this.items.insert(e,j);j.onAdded(this,e);this.onAdd(j);this.fireEvent("add",this,j,e)}return j},applyDefaults:function(b){var a=this.defaults;if(a){if(Ext.isFunction(a)){a=a.call(this,b)}if(Ext.isString(b)){b=Ext.ComponentMgr.get(b);Ext.apply(b,a)}else{if(!b.events){Ext.applyIf(b.isAction?b.initialConfig:b,a)}else{Ext.apply(b,a)}}}return b},onBeforeAdd:function(a){if(a.ownerCt){a.ownerCt.remove(a,false)}if(this.hideBorders===true){a.border=(a.border===true)}},remove:function(a,b){this.initItems();var d=this.getComponent(a);if(d&&this.fireEvent("beforeremove",this,d)!==false){this.doRemove(d,b);this.fireEvent("remove",this,d)}return d},onRemove:function(a){},doRemove:function(e,d){var b=this.layout,a=b&&this.rendered;if(a){b.onRemove(e)}this.items.remove(e);e.onRemoved();this.onRemove(e);if(d===true||(d!==false&&this.autoDestroy)){e.destroy()}if(a){b.afterRemove(e)}},removeAll:function(c){this.initItems();var e,g=[],b=[];this.items.each(function(h){g.push(h)});for(var d=0,a=g.length;d<a;++d){e=g[d];this.remove(e,c);if(e.ownerCt!==this){b.push(e)}}return b},getComponent:function(a){if(Ext.isObject(a)){a=a.getItemId()}return this.items.get(a)},lookupComponent:function(a){if(Ext.isString(a)){return Ext.ComponentMgr.get(a)}else{if(!a.events){return this.createComponent(a)}}return a},createComponent:function(a,d){if(a.render){return a}var b=Ext.create(Ext.apply({ownerCt:this},a),d||this.defaultType);delete b.initialConfig.ownerCt;delete b.ownerCt;return b},canLayout:function(){var a=this.getVisibilityEl();return a&&a.dom&&!a.isStyle("display","none")},doLayout:function(g,e){var k=this.rendered,j=e||this.forceLayout;if(this.collapsed||!this.canLayout()){this.deferLayout=this.deferLayout||!g;if(!j){return}g=g&&!this.deferLayout}else{delete this.deferLayout}if(k&&this.layout){this.layout.layout()}if(g!==true&&this.items){var d=this.items.items;for(var b=0,a=d.length;b<a;b++){var h=d[b];if(h.doLayout){h.doLayout(false,j)}}}if(k){this.onLayout(g,j)}this.hasLayout=true;delete this.forceLayout},onLayout:Ext.emptyFn,shouldBufferLayout:function(){var a=this.hasLayout;if(this.ownerCt){return a?!this.hasLayoutPending():false}return a},hasLayoutPending:function(){var a=false;this.ownerCt.bubble(function(b){if(b.layoutPending){a=true;return false}});return a},onShow:function(){Ext.Container.superclass.onShow.call(this);if(Ext.isDefined(this.deferLayout)){delete this.deferLayout;this.doLayout(true)}},getLayout:function(){if(!this.layout){var a=new Ext.layout.AutoLayout(this.layoutConfig);this.setLayout(a)}return this.layout},beforeDestroy:function(){var a;if(this.items){while(a=this.items.first()){this.doRemove(a,true)}}if(this.monitorResize){Ext.EventManager.removeResizeListener(this.doLayout,this)}Ext.destroy(this.layout);Ext.Container.superclass.beforeDestroy.call(this)},cascade:function(g,e,b){if(g.apply(e||this,b||[this])!==false){if(this.items){var d=this.items.items;for(var c=0,a=d.length;c<a;c++){if(d[c].cascade){d[c].cascade(g,e,b)}else{g.apply(e||d[c],b||[d[c]])}}}}return this},findById:function(c){var a=null,b=this;this.cascade(function(d){if(b!=d&&d.id===c){a=d;return false}});return a},findByType:function(b,a){return this.findBy(function(d){return d.isXType(b,a)})},find:function(b,a){return this.findBy(function(d){return d[b]===a})},findBy:function(d,c){var a=[],b=this;this.cascade(function(e){if(b!=e&&d.call(c||e,e,b)===true){a.push(e)}});return a},get:function(a){return this.getComponent(a)}});Ext.Container.LAYOUTS={};Ext.reg("container",Ext.Container);Ext.layout.ContainerLayout=Ext.extend(Object,{monitorResize:false,activeItem:null,constructor:function(a){this.id=Ext.id(null,"ext-layout-");Ext.apply(this,a)},type:"container",IEMeasureHack:function(k,g){var a=k.dom.childNodes,b=a.length,n,m=[],l,h,j;for(h=0;h<b;h++){n=a[h];l=Ext.get(n);if(l){m[h]=l.getStyle("display");l.setStyle({display:"none"})}}j=k?k.getViewSize(g):{};for(h=0;h<b;h++){n=a[h];l=Ext.get(n);if(l){l.setStyle({display:m[h]})}}return j},getLayoutTargetSize:Ext.EmptyFn,layout:function(){var a=this.container,b=a.getLayoutTarget();if(!(this.hasLayout||Ext.isEmpty(this.targetCls))){b.addClass(this.targetCls)}this.onLayout(a,b);a.fireEvent("afterlayout",a,this)},onLayout:function(a,b){this.renderAll(a,b)},isValidParent:function(b,a){return a&&b.getPositionEl().dom.parentNode==(a.dom||a)},renderAll:function(e,g){var b=e.items.items,d,h,a=b.length;for(d=0;d<a;d++){h=b[d];if(h&&(!h.rendered||!this.isValidParent(h,g))){this.renderItem(h,d,g)}}},renderItem:function(d,a,b){if(d){if(!d.rendered){d.render(b,a);this.configureItem(d)}else{if(!this.isValidParent(d,b)){if(Ext.isNumber(a)){a=b.dom.childNodes[a]}b.dom.insertBefore(d.getPositionEl().dom,a||null);d.container=b;this.configureItem(d)}}}},getRenderedItems:function(g){var e=g.getLayoutTarget(),h=g.items.items,a=h.length,d,j,b=[];for(d=0;d<a;d++){if((j=h[d]).rendered&&this.isValidParent(j,e)&&j.shouldLayout!==false){b.push(j)}}return b},configureItem:function(b){if(this.extraCls){var a=b.getPositionEl?b.getPositionEl():b;a.addClass(this.extraCls)}if(b.doLayout&&this.forceLayout){b.doLayout()}if(this.renderHidden&&b!=this.activeItem){b.hide()}},onRemove:function(b){if(this.activeItem==b){delete this.activeItem}if(b.rendered&&this.extraCls){var a=b.getPositionEl?b.getPositionEl():b;a.removeClass(this.extraCls)}},afterRemove:function(a){if(a.removeRestore){a.removeMode="container";delete a.removeRestore}},onResize:function(){var c=this.container,a;if(c.collapsed){return}if(a=c.bufferResize&&c.shouldBufferLayout()){if(!this.resizeTask){this.resizeTask=new Ext.util.DelayedTask(this.runLayout,this);this.resizeBuffer=Ext.isNumber(a)?a:50}c.layoutPending=true;this.resizeTask.delay(this.resizeBuffer)}else{this.runLayout()}},runLayout:function(){var a=this.container;this.layout();a.onLayout();delete a.layoutPending},setContainer:function(b){if(this.monitorResize&&b!=this.container){var a=this.container;if(a){a.un(a.resizeEvent,this.onResize,this)}if(b){b.on(b.resizeEvent,this.onResize,this)}}this.container=b},parseMargins:function(b){if(Ext.isNumber(b)){b=b.toString()}var c=b.split(" "),a=c.length;if(a==1){c[1]=c[2]=c[3]=c[0]}else{if(a==2){c[2]=c[0];c[3]=c[1]}else{if(a==3){c[3]=c[1]}}}return{top:parseInt(c[0],10)||0,right:parseInt(c[1],10)||0,bottom:parseInt(c[2],10)||0,left:parseInt(c[3],10)||0}},fieldTpl:(function(){var a=new Ext.Template('<div class="x-form-item {itemCls}" tabIndex="-1">','<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>','<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">','</div><div class="{clearCls}"></div>',"</div>");a.disableFormats=true;return a.compile()})(),destroy:function(){if(this.resizeTask&&this.resizeTask.cancel){this.resizeTask.cancel()}if(this.container){this.container.un(this.container.resizeEvent,this.onResize,this)}if(!Ext.isEmpty(this.targetCls)){var a=this.container.getLayoutTarget();if(a){a.removeClass(this.targetCls)}}}});Ext.layout.AutoLayout=Ext.extend(Ext.layout.ContainerLayout,{type:"auto",monitorResize:true,onLayout:function(d,g){Ext.layout.AutoLayout.superclass.onLayout.call(this,d,g);var e=this.getRenderedItems(d),a=e.length,b,h;for(b=0;b<a;b++){h=e[b];if(h.doLayout){h.doLayout(true)}}}});Ext.Container.LAYOUTS.auto=Ext.layout.AutoLayout;Ext.layout.FitLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:"fit",getLayoutTargetSize:function(){var a=this.container.getLayoutTarget();if(!a){return{}}return a.getStyleSize()},onLayout:function(a,b){Ext.layout.FitLayout.superclass.onLayout.call(this,a,b);if(!a.collapsed){this.setItemSize(this.activeItem||a.items.itemAt(0),this.getLayoutTargetSize())}},setItemSize:function(b,a){if(b&&a.height>0){b.setSize(a)}}});Ext.Container.LAYOUTS.fit=Ext.layout.FitLayout;Ext.layout.CardLayout=Ext.extend(Ext.layout.FitLayout,{deferredRender:false,layoutOnCardChange:false,renderHidden:true,type:"card",setActiveItem:function(d){var a=this.activeItem,b=this.container;d=b.getComponent(d);if(d&&a!=d){if(a){a.hide();if(a.hidden!==true){return false}a.fireEvent("deactivate",a)}var c=d.doLayout&&(this.layoutOnCardChange||!d.rendered);this.activeItem=d;delete d.deferLayout;d.show();this.layout();if(c){d.doLayout()}d.fireEvent("activate",d)}},renderAll:function(a,b){if(this.deferredRender){this.renderItem(this.activeItem,undefined,b)}else{Ext.layout.CardLayout.superclass.renderAll.call(this,a,b)}}});Ext.Container.LAYOUTS.card=Ext.layout.CardLayout;Ext.layout.AnchorLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:"anchor",defaultAnchor:"100%",parseAnchorRE:/^(r|right|b|bottom)$/i,getLayoutTargetSize:function(){var b=this.container.getLayoutTarget(),a={};if(b){a=b.getViewSize();if(Ext.isIE&&Ext.isStrict&&a.width==0){a=b.getStyleSize()}a.width-=b.getPadding("lr");a.height-=b.getPadding("tb")}return a},onLayout:function(m,w){Ext.layout.AnchorLayout.superclass.onLayout.call(this,m,w);var p=this.getLayoutTargetSize(),k=p.width,o=p.height,q=w.getStyle("overflow"),n=this.getRenderedItems(m),t=n.length,g=[],j,a,v,l,h,c,e,d,u=0,s,b;if(k<20&&o<20){return}if(m.anchorSize){if(typeof m.anchorSize=="number"){a=m.anchorSize}else{a=m.anchorSize.width;v=m.anchorSize.height}}else{a=m.initialConfig.width;v=m.initialConfig.height}for(s=0;s<t;s++){l=n[s];b=l.getPositionEl();if(!l.anchor&&l.items&&!Ext.isNumber(l.width)&&!(Ext.isIE6&&Ext.isStrict)){l.anchor=this.defaultAnchor}if(l.anchor){h=l.anchorSpec;if(!h){d=l.anchor.split(" ");l.anchorSpec=h={right:this.parseAnchor(d[0],l.initialConfig.width,a),bottom:this.parseAnchor(d[1],l.initialConfig.height,v)}}c=h.right?this.adjustWidthAnchor(h.right(k)-b.getMargins("lr"),l):undefined;e=h.bottom?this.adjustHeightAnchor(h.bottom(o)-b.getMargins("tb"),l):undefined;if(c||e){g.push({component:l,width:c||undefined,height:e||undefined})}}}for(s=0,t=g.length;s<t;s++){j=g[s];j.component.setSize(j.width,j.height)}if(q&&q!="hidden"&&!this.adjustmentPass){var r=this.getLayoutTargetSize();if(r.width!=p.width||r.height!=p.height){this.adjustmentPass=true;this.onLayout(m,w)}}delete this.adjustmentPass},parseAnchor:function(c,h,b){if(c&&c!="none"){var e;if(this.parseAnchorRE.test(c)){var g=b-h;return function(a){if(a!==e){e=a;return a-g}}}else{if(c.indexOf("%")!=-1){var d=parseFloat(c.replace("%",""))*0.01;return function(a){if(a!==e){e=a;return Math.floor(a*d)}}}else{c=parseInt(c,10);if(!isNaN(c)){return function(a){if(a!==e){e=a;return a+c}}}}}}return false},adjustWidthAnchor:function(b,a){return b},adjustHeightAnchor:function(b,a){return b}});Ext.Container.LAYOUTS.anchor=Ext.layout.AnchorLayout;Ext.layout.ColumnLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:"column",extraCls:"x-column",scrollOffset:0,targetCls:"x-column-layout-ct",isValidParent:function(b,a){return this.innerCt&&b.getPositionEl().dom.parentNode==this.innerCt.dom},getLayoutTargetSize:function(){var b=this.container.getLayoutTarget(),a;if(b){a=b.getViewSize();if(Ext.isIE&&Ext.isStrict&&a.width==0){a=b.getStyleSize()}a.width-=b.getPadding("lr");a.height-=b.getPadding("tb")}return a},renderAll:function(a,b){if(!this.innerCt){this.innerCt=b.createChild({cls:"x-column-inner"});this.innerCt.createChild({cls:"x-clear"})}Ext.layout.ColumnLayout.superclass.renderAll.call(this,a,this.innerCt)},onLayout:function(e,k){var g=e.items.items,j=g.length,n,b,a,o=[];this.renderAll(e,k);var r=this.getLayoutTargetSize();if(r.width<1&&r.height<1){return}var p=r.width-this.scrollOffset,d=r.height,q=p;this.innerCt.setWidth(p);for(b=0;b<j;b++){n=g[b];a=n.getPositionEl().getMargins("lr");o[b]=a;if(!n.columnWidth){q-=(n.getWidth()+a)}}q=q<0?0:q;for(b=0;b<j;b++){n=g[b];a=o[b];if(n.columnWidth){n.setSize(Math.floor(n.columnWidth*q)-a)}}if(Ext.isIE){if(b=k.getStyle("overflow")&&b!="hidden"&&!this.adjustmentPass){var l=this.getLayoutTargetSize();if(l.width!=r.width){this.adjustmentPass=true;this.onLayout(e,k)}}}delete this.adjustmentPass}});Ext.Container.LAYOUTS.column=Ext.layout.ColumnLayout;Ext.layout.BorderLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,rendered:false,type:"border",targetCls:"x-border-layout-ct",getLayoutTargetSize:function(){var a=this.container.getLayoutTarget();return a?a.getViewSize():{}},onLayout:function(g,I){var j,B,F,o,x=g.items.items,C=x.length;if(!this.rendered){j=[];for(B=0;B<C;B++){F=x[B];o=F.region;if(F.collapsed){j.push(F)}F.collapsed=false;if(!F.rendered){F.render(I,B);F.getPositionEl().addClass("x-border-panel")}this[o]=o!="center"&&F.split?new Ext.layout.BorderLayout.SplitRegion(this,F.initialConfig,o):new Ext.layout.BorderLayout.Region(this,F.initialConfig,o);this[o].render(I,F)}this.rendered=true}var v=this.getLayoutTargetSize();if(v.width<20||v.height<20){if(j){this.restoreCollapsed=j}return}else{if(this.restoreCollapsed){j=this.restoreCollapsed;delete this.restoreCollapsed}}var t=v.width,D=v.height,r=t,A=D,p=0,q=0,y=this.north,u=this.south,l=this.west,E=this.east,F=this.center,H,z,d,G;if(!F&&Ext.layout.BorderLayout.WARN!==false){throw"No center region defined in BorderLayout "+g.id}if(y&&y.isVisible()){H=y.getSize();z=y.getMargins();H.width=t-(z.left+z.right);H.x=z.left;H.y=z.top;p=H.height+H.y+z.bottom;A-=p;y.applyLayout(H)}if(u&&u.isVisible()){H=u.getSize();z=u.getMargins();H.width=t-(z.left+z.right);H.x=z.left;G=(H.height+z.top+z.bottom);H.y=D-G+z.top;A-=G;u.applyLayout(H)}if(l&&l.isVisible()){H=l.getSize();z=l.getMargins();H.height=A-(z.top+z.bottom);H.x=z.left;H.y=p+z.top;d=(H.width+z.left+z.right);q+=d;r-=d;l.applyLayout(H)}if(E&&E.isVisible()){H=E.getSize();z=E.getMargins();H.height=A-(z.top+z.bottom);d=(H.width+z.left+z.right);H.x=t-d+z.left;H.y=p+z.top;r-=d;E.applyLayout(H)}if(F){z=F.getMargins();var k={x:q+z.left,y:p+z.top,width:r-(z.left+z.right),height:A-(z.top+z.bottom)};F.applyLayout(k)}if(j){for(B=0,C=j.length;B<C;B++){j[B].collapse(false)}}if(Ext.isIE&&Ext.isStrict){I.repaint()}if(B=I.getStyle("overflow")&&B!="hidden"&&!this.adjustmentPass){var a=this.getLayoutTargetSize();if(a.width!=v.width||a.height!=v.height){this.adjustmentPass=true;this.onLayout(g,I)}}delete this.adjustmentPass},destroy:function(){var b=["north","south","east","west"],a,c;for(a=0;a<b.length;a++){c=this[b[a]];if(c){if(c.destroy){c.destroy()}else{if(c.split){c.split.destroy(true)}}}}Ext.layout.BorderLayout.superclass.destroy.call(this)}});Ext.layout.BorderLayout.Region=function(b,a,c){Ext.apply(this,a);this.layout=b;this.position=c;this.state={};if(typeof this.margins=="string"){this.margins=this.layout.parseMargins(this.margins)}this.margins=Ext.applyIf(this.margins||{},this.defaultMargins);if(this.collapsible){if(typeof this.cmargins=="string"){this.cmargins=this.layout.parseMargins(this.cmargins)}if(this.collapseMode=="mini"&&!this.cmargins){this.cmargins={left:0,top:0,right:0,bottom:0}}else{this.cmargins=Ext.applyIf(this.cmargins||{},c=="north"||c=="south"?this.defaultNSCMargins:this.defaultEWCMargins)}}};Ext.layout.BorderLayout.Region.prototype={collapsible:false,split:false,floatable:true,minWidth:50,minHeight:50,defaultMargins:{left:0,top:0,right:0,bottom:0},defaultNSCMargins:{left:5,top:5,right:5,bottom:5},defaultEWCMargins:{left:5,top:0,right:5,bottom:0},floatingZIndex:100,isCollapsed:false,render:function(b,c){this.panel=c;c.el.enableDisplayMode();this.targetEl=b;this.el=c.el;var a=c.getState,d=this.position;c.getState=function(){return Ext.apply(a.call(c)||{},this.state)}.createDelegate(this);if(d!="center"){c.allowQueuedExpand=false;c.on({beforecollapse:this.beforeCollapse,collapse:this.onCollapse,beforeexpand:this.beforeExpand,expand:this.onExpand,hide:this.onHide,show:this.onShow,scope:this});if(this.collapsible||this.floatable){c.collapseEl="el";c.slideAnchor=this.getSlideAnchor()}if(c.tools&&c.tools.toggle){c.tools.toggle.addClass("x-tool-collapse-"+d);c.tools.toggle.addClassOnOver("x-tool-collapse-"+d+"-over")}}},getCollapsedEl:function(){if(!this.collapsedEl){if(!this.toolTemplate){var b=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');b.disableFormats=true;b.compile();Ext.layout.BorderLayout.Region.prototype.toolTemplate=b}this.collapsedEl=this.targetEl.createChild({cls:"x-layout-collapsed x-layout-collapsed-"+this.position,id:this.panel.id+"-xcollapsed"});this.collapsedEl.enableDisplayMode("block");if(this.collapseMode=="mini"){this.collapsedEl.addClass("x-layout-cmini-"+this.position);this.miniCollapsedEl=this.collapsedEl.createChild({cls:"x-layout-mini x-layout-mini-"+this.position,html:"&#160;"});this.miniCollapsedEl.addClassOnOver("x-layout-mini-over");this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this.onExpandClick,this,{stopEvent:true})}else{if(this.collapsible!==false&&!this.hideCollapseTool){var a=this.expandToolEl=this.toolTemplate.append(this.collapsedEl.dom,{id:"expand-"+this.position},true);a.addClassOnOver("x-tool-expand-"+this.position+"-over");a.on("click",this.onExpandClick,this,{stopEvent:true})}if(this.floatable!==false||this.titleCollapse){this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this[this.floatable?"collapseClick":"onExpandClick"],this)}}}return this.collapsedEl},onExpandClick:function(a){if(this.isSlid){this.panel.expand(false)}else{this.panel.expand()}},onCollapseClick:function(a){this.panel.collapse()},beforeCollapse:function(c,a){this.lastAnim=a;if(this.splitEl){this.splitEl.hide()}this.getCollapsedEl().show();var b=this.panel.getEl();this.originalZIndex=b.getStyle("z-index");b.setStyle("z-index",100);this.isCollapsed=true;this.layout.layout()},onCollapse:function(a){this.panel.el.setStyle("z-index",1);if(this.lastAnim===false||this.panel.animCollapse===false){this.getCollapsedEl().dom.style.visibility="visible"}else{this.getCollapsedEl().slideIn(this.panel.slideAnchor,{duration:0.2})}this.state.collapsed=true;this.panel.saveState()},beforeExpand:function(a){if(this.isSlid){this.afterSlideIn()}var b=this.getCollapsedEl();this.el.show();if(this.position=="east"||this.position=="west"){this.panel.setSize(undefined,b.getHeight())}else{this.panel.setSize(b.getWidth(),undefined)}b.hide();b.dom.style.visibility="hidden";this.panel.el.setStyle("z-index",this.floatingZIndex)},onExpand:function(){this.isCollapsed=false;if(this.splitEl){this.splitEl.show()}this.layout.layout();this.panel.el.setStyle("z-index",this.originalZIndex);this.state.collapsed=false;this.panel.saveState()},collapseClick:function(a){if(this.isSlid){a.stopPropagation();this.slideIn()}else{a.stopPropagation();this.slideOut()}},onHide:function(){if(this.isCollapsed){this.getCollapsedEl().hide()}else{if(this.splitEl){this.splitEl.hide()}}},onShow:function(){if(this.isCollapsed){this.getCollapsedEl().show()}else{if(this.splitEl){this.splitEl.show()}}},isVisible:function(){return !this.panel.hidden},getMargins:function(){return this.isCollapsed&&this.cmargins?this.cmargins:this.margins},getSize:function(){return this.isCollapsed?this.getCollapsedEl().getSize():this.panel.getSize()},setPanel:function(a){this.panel=a},getMinWidth:function(){return this.minWidth},getMinHeight:function(){return this.minHeight},applyLayoutCollapsed:function(a){var b=this.getCollapsedEl();b.setLeftTop(a.x,a.y);b.setSize(a.width,a.height)},applyLayout:function(a){if(this.isCollapsed){this.applyLayoutCollapsed(a)}else{this.panel.setPosition(a.x,a.y);this.panel.setSize(a.width,a.height)}},beforeSlide:function(){this.panel.beforeEffect()},afterSlide:function(){this.panel.afterEffect()},initAutoHide:function(){if(this.autoHide!==false){if(!this.autoHideHd){this.autoHideSlideTask=new Ext.util.DelayedTask(this.slideIn,this);this.autoHideHd={mouseout:function(a){if(!a.within(this.el,true)){this.autoHideSlideTask.delay(500)}},mouseover:function(a){this.autoHideSlideTask.cancel()},scope:this}}this.el.on(this.autoHideHd);this.collapsedEl.on(this.autoHideHd)}},clearAutoHide:function(){if(this.autoHide!==false){this.el.un("mouseout",this.autoHideHd.mouseout);this.el.un("mouseover",this.autoHideHd.mouseover);this.collapsedEl.un("mouseout",this.autoHideHd.mouseout);this.collapsedEl.un("mouseover",this.autoHideHd.mouseover)}},clearMonitor:function(){Ext.getDoc().un("click",this.slideInIf,this)},slideOut:function(){if(this.isSlid||this.el.hasActiveFx()){return}this.isSlid=true;var b=this.panel.tools,c,a;if(b&&b.toggle){b.toggle.hide()}this.el.show();a=this.panel.collapsed;this.panel.collapsed=false;if(this.position=="east"||this.position=="west"){c=this.panel.deferHeight;this.panel.deferHeight=false;this.panel.setSize(undefined,this.collapsedEl.getHeight());this.panel.deferHeight=c}else{this.panel.setSize(this.collapsedEl.getWidth(),undefined)}this.panel.collapsed=a;this.restoreLT=[this.el.dom.style.left,this.el.dom.style.top];this.el.alignTo(this.collapsedEl,this.getCollapseAnchor());this.el.setStyle("z-index",this.floatingZIndex+2);this.panel.el.replaceClass("x-panel-collapsed","x-panel-floating");if(this.animFloat!==false){this.beforeSlide();this.el.slideIn(this.getSlideAnchor(),{callback:function(){this.afterSlide();this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)},scope:this,block:true})}else{this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)}},afterSlideIn:function(){this.clearAutoHide();this.isSlid=false;this.clearMonitor();this.el.setStyle("z-index","");this.panel.el.replaceClass("x-panel-floating","x-panel-collapsed");this.el.dom.style.left=this.restoreLT[0];this.el.dom.style.top=this.restoreLT[1];var a=this.panel.tools;if(a&&a.toggle){a.toggle.show()}},slideIn:function(a){if(!this.isSlid||this.el.hasActiveFx()){Ext.callback(a);return}this.isSlid=false;if(this.animFloat!==false){this.beforeSlide();this.el.slideOut(this.getSlideAnchor(),{callback:function(){this.el.hide();this.afterSlide();this.afterSlideIn();Ext.callback(a)},scope:this,block:true})}else{this.el.hide();this.afterSlideIn()}},slideInIf:function(a){if(!a.within(this.el)){this.slideIn()}},anchors:{west:"left",east:"right",north:"top",south:"bottom"},sanchors:{west:"l",east:"r",north:"t",south:"b"},canchors:{west:"tl-tr",east:"tr-tl",north:"tl-bl",south:"bl-tl"},getAnchor:function(){return this.anchors[this.position]},getCollapseAnchor:function(){return this.canchors[this.position]},getSlideAnchor:function(){return this.sanchors[this.position]},getAlignAdj:function(){var a=this.cmargins;switch(this.position){case"west":return[0,0];break;case"east":return[0,0];break;case"north":return[0,0];break;case"south":return[0,0];break}},getExpandAdj:function(){var b=this.collapsedEl,a=this.cmargins;switch(this.position){case"west":return[-(a.right+b.getWidth()+a.left),0];break;case"east":return[a.right+b.getWidth()+a.left,0];break;case"north":return[0,-(a.top+a.bottom+b.getHeight())];break;case"south":return[0,a.top+a.bottom+b.getHeight()];break}},destroy:function(){if(this.autoHideSlideTask&&this.autoHideSlideTask.cancel){this.autoHideSlideTask.cancel()}Ext.destroyMembers(this,"miniCollapsedEl","collapsedEl","expandToolEl")}};Ext.layout.BorderLayout.SplitRegion=function(b,a,c){Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this,b,a,c);this.applyLayout=this.applyFns[c]};Ext.extend(Ext.layout.BorderLayout.SplitRegion,Ext.layout.BorderLayout.Region,{splitTip:"Drag to resize.",collapsibleSplitTip:"Drag to resize. Double click to hide.",useSplitTips:false,splitSettings:{north:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.TOP,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},south:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.BOTTOM,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},east:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.RIGHT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"},west:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.LEFT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"}},applyFns:{west:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;this.panel.setPosition(c.x,c.y);var a=d.offsetWidth;b.left=(c.x+c.width-a)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},east:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetWidth;this.panel.setPosition(c.x+a,c.y);b.left=(c.x)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},north:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y);b.left=(c.x)+"px";b.top=(c.y+c.height-a)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)},south:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y+a);b.left=(c.x)+"px";b.top=(c.y)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)}},render:function(a,c){Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this,a,c);var d=this.position;this.splitEl=a.createChild({cls:"x-layout-split x-layout-split-"+d,html:"&#160;",id:this.panel.id+"-xsplit"});if(this.collapseMode=="mini"){this.miniSplitEl=this.splitEl.createChild({cls:"x-layout-mini x-layout-mini-"+d,html:"&#160;"});this.miniSplitEl.addClassOnOver("x-layout-mini-over");this.miniSplitEl.on("click",this.onCollapseClick,this,{stopEvent:true})}var b=this.splitSettings[d];this.split=new Ext.SplitBar(this.splitEl.dom,c.el,b.orientation);this.split.tickSize=this.tickSize;this.split.placement=b.placement;this.split.getMaximumSize=this[b.maxFn].createDelegate(this);this.split.minSize=this.minSize||this[b.minProp];this.split.on("beforeapply",this.onSplitMove,this);this.split.useShim=this.useShim===true;this.maxSize=this.maxSize||this[b.maxProp];if(c.hidden){this.splitEl.hide()}if(this.useSplitTips){this.splitEl.dom.title=this.collapsible?this.collapsibleSplitTip:this.splitTip}if(this.collapsible){this.splitEl.on("dblclick",this.onCollapseClick,this)}},getSize:function(){if(this.isCollapsed){return this.collapsedEl.getSize()}var a=this.panel.getSize();if(this.position=="north"||this.position=="south"){a.height+=this.splitEl.dom.offsetHeight}else{a.width+=this.splitEl.dom.offsetWidth}return a},getHMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getWidth()+a.el.getWidth())-a.getMinWidth())},getVMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getHeight()+a.el.getHeight())-a.getMinHeight())},onSplitMove:function(b,a){var c=this.panel.getSize();this.lastSplitSize=a;if(this.position=="north"||this.position=="south"){this.panel.setSize(c.width,a);this.state.height=a}else{this.panel.setSize(a,c.height);this.state.width=a}this.layout.layout();this.panel.saveState();return false},getSplitBar:function(){return this.split},destroy:function(){Ext.destroy(this.miniSplitEl,this.split,this.splitEl);Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this)}});Ext.Container.LAYOUTS.border=Ext.layout.BorderLayout;Ext.layout.FormLayout=Ext.extend(Ext.layout.AnchorLayout,{labelSeparator:":",trackLabels:true,type:"form",onRemove:function(d){Ext.layout.FormLayout.superclass.onRemove.call(this,d);if(this.trackLabels){d.un("show",this.onFieldShow,this);d.un("hide",this.onFieldHide,this)}var b=d.getPositionEl(),a=d.getItemCt&&d.getItemCt();if(d.rendered&&a){if(b&&b.dom){b.insertAfter(a)}Ext.destroy(a);Ext.destroyMembers(d,"label","itemCt");if(d.customItemCt){Ext.destroyMembers(d,"getItemCt","customItemCt")}}},setContainer:function(a){Ext.layout.FormLayout.superclass.setContainer.call(this,a);if(a.labelAlign){a.addClass("x-form-label-"+a.labelAlign)}if(a.hideLabels){Ext.apply(this,{labelStyle:"display:none",elementStyle:"padding-left:0;",labelAdjust:0})}else{this.labelSeparator=Ext.isDefined(a.labelSeparator)?a.labelSeparator:this.labelSeparator;a.labelWidth=a.labelWidth||100;if(Ext.isNumber(a.labelWidth)){var b=Ext.isNumber(a.labelPad)?a.labelPad:5;Ext.apply(this,{labelAdjust:a.labelWidth+b,labelStyle:"width:"+a.labelWidth+"px;",elementStyle:"padding-left:"+(a.labelWidth+b)+"px"})}if(a.labelAlign=="top"){Ext.apply(this,{labelStyle:"width:auto;",labelAdjust:0,elementStyle:"padding-left:0;"})}}},isHide:function(a){return a.hideLabel||this.container.hideLabels},onFieldShow:function(a){a.getItemCt().removeClass("x-hide-"+a.hideMode);if(a.isComposite){a.doLayout()}},onFieldHide:function(a){a.getItemCt().addClass("x-hide-"+a.hideMode)},getLabelStyle:function(e){var b="",c=[this.labelStyle,e];for(var d=0,a=c.length;d<a;++d){if(c[d]){b+=c[d];if(b.substr(-1,1)!=";"){b+=";"}}}return b},renderItem:function(e,a,d){if(e&&(e.isFormField||e.fieldLabel)&&e.inputType!="hidden"){var b=this.getTemplateArgs(e);if(Ext.isNumber(a)){a=d.dom.childNodes[a]||null}if(a){e.itemCt=this.fieldTpl.insertBefore(a,b,true)}else{e.itemCt=this.fieldTpl.append(d,b,true)}if(!e.getItemCt){Ext.apply(e,{getItemCt:function(){return e.itemCt},customItemCt:true})}e.label=e.getItemCt().child("label.x-form-item-label");if(!e.rendered){e.render("x-form-el-"+e.id)}else{if(!this.isValidParent(e,d)){Ext.fly("x-form-el-"+e.id).appendChild(e.getPositionEl())}}if(this.trackLabels){if(e.hidden){this.onFieldHide(e)}e.on({scope:this,show:this.onFieldShow,hide:this.onFieldHide})}this.configureItem(e)}else{Ext.layout.FormLayout.superclass.renderItem.apply(this,arguments)}},getTemplateArgs:function(c){var a=!c.fieldLabel||c.hideLabel,b=(c.itemCls||this.container.itemCls||"")+(c.hideLabel?" x-hide-label":"");if(Ext.isIE9&&Ext.isIEQuirks&&c instanceof Ext.form.TextField){b+=" x-input-wrapper"}return{id:c.id,label:c.fieldLabel,itemCls:b,clearCls:c.clearCls||"x-form-clear-left",labelStyle:this.getLabelStyle(c.labelStyle),elementStyle:this.elementStyle||"",labelSeparator:a?"":(Ext.isDefined(c.labelSeparator)?c.labelSeparator:this.labelSeparator)}},adjustWidthAnchor:function(a,d){if(d.label&&!this.isHide(d)&&(this.container.labelAlign!="top")){var b=Ext.isIE6||(Ext.isIE&&!Ext.isStrict);return a-this.labelAdjust+(b?-3:0)}return a},adjustHeightAnchor:function(a,b){if(b.label&&!this.isHide(b)&&(this.container.labelAlign=="top")){return a-b.label.getHeight()}return a},isValidParent:function(b,a){return a&&this.container.getEl().contains(b.getPositionEl())}});Ext.Container.LAYOUTS.form=Ext.layout.FormLayout;Ext.layout.AccordionLayout=Ext.extend(Ext.layout.FitLayout,{fill:true,autoWidth:true,titleCollapse:true,hideCollapseTool:false,collapseFirst:false,animate:false,sequence:false,activeOnTop:false,type:"accordion",renderItem:function(a){if(this.animate===false){a.animCollapse=false}a.collapsible=true;if(this.autoWidth){a.autoWidth=true}if(this.titleCollapse){a.titleCollapse=true}if(this.hideCollapseTool){a.hideCollapseTool=true}if(this.collapseFirst!==undefined){a.collapseFirst=this.collapseFirst}if(!this.activeItem&&!a.collapsed){this.setActiveItem(a,true)}else{if(this.activeItem&&this.activeItem!=a){a.collapsed=true}}Ext.layout.AccordionLayout.superclass.renderItem.apply(this,arguments);a.header.addClass("x-accordion-hd");a.on("beforeexpand",this.beforeExpand,this)},onRemove:function(a){Ext.layout.AccordionLayout.superclass.onRemove.call(this,a);if(a.rendered){a.header.removeClass("x-accordion-hd")}a.un("beforeexpand",this.beforeExpand,this)},beforeExpand:function(c,b){var a=this.activeItem;if(a){if(this.sequence){delete this.activeItem;if(!a.collapsed){a.collapse({callback:function(){c.expand(b||true)},scope:this});return false}}else{a.collapse(this.animate)}}this.setActive(c);if(this.activeOnTop){c.el.dom.parentNode.insertBefore(c.el.dom,c.el.dom.parentNode.firstChild)}this.layout()},setItemSize:function(g,e){if(this.fill&&g){var d=0,c,b=this.getRenderedItems(this.container),a=b.length,h;for(c=0;c<a;c++){if((h=b[c])!=g&&!h.hidden){d+=h.header.getHeight()}}e.height-=d;g.setSize(e)}},setActiveItem:function(a){this.setActive(a,true)},setActive:function(c,b){var a=this.activeItem;c=this.container.getComponent(c);if(a!=c){if(c.rendered&&c.collapsed&&b){c.expand()}else{if(a){a.fireEvent("deactivate",a)}this.activeItem=c;c.fireEvent("activate",c)}}}});Ext.Container.LAYOUTS.accordion=Ext.layout.AccordionLayout;Ext.layout.Accordion=Ext.layout.AccordionLayout;Ext.layout.TableLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:false,type:"table",targetCls:"x-table-layout-ct",tableAttrs:null,setContainer:function(a){Ext.layout.TableLayout.superclass.setContainer.call(this,a);this.currentRow=0;this.currentColumn=0;this.cells=[]},onLayout:function(d,g){var e=d.items.items,a=e.length,h,b;if(!this.table){g.addClass("x-table-layout-ct");this.table=g.createChild(Ext.apply({tag:"table",cls:"x-table-layout",cellspacing:0,cn:{tag:"tbody"}},this.tableAttrs),null,true)}this.renderAll(d,g)},getRow:function(a){var b=this.table.tBodies[0].childNodes[a];if(!b){b=document.createElement("tr");this.table.tBodies[0].appendChild(b)}return b},getNextCell:function(j){var a=this.getNextNonSpan(this.currentColumn,this.currentRow);var g=this.currentColumn=a[0],e=this.currentRow=a[1];for(var i=e;i<e+(j.rowspan||1);i++){if(!this.cells[i]){this.cells[i]=[]}for(var d=g;d<g+(j.colspan||1);d++){this.cells[i][d]=true}}var h=document.createElement("td");if(j.cellId){h.id=j.cellId}var b="x-table-layout-cell";if(j.cellCls){b+=" "+j.cellCls}h.className=b;if(j.colspan){h.colSpan=j.colspan}if(j.rowspan){h.rowSpan=j.rowspan}this.getRow(e).appendChild(h);return h},getNextNonSpan:function(a,c){var b=this.columns;while((b&&a>=b)||(this.cells[c]&&this.cells[c][a])){if(b&&a>=b){c++;a=0}else{a++}}return[a,c]},renderItem:function(e,a,d){if(!this.table){this.table=d.createChild(Ext.apply({tag:"table",cls:"x-table-layout",cellspacing:0,cn:{tag:"tbody"}},this.tableAttrs),null,true)}if(e&&!e.rendered){e.render(this.getNextCell(e));this.configureItem(e)}else{if(e&&!this.isValidParent(e,d)){var b=this.getNextCell(e);b.insertBefore(e.getPositionEl().dom,null);e.container=Ext.get(b);this.configureItem(e)}}},isValidParent:function(b,a){return b.getPositionEl().up("table",5).dom.parentNode===(a.dom||a)},destroy:function(){delete this.table;Ext.layout.TableLayout.superclass.destroy.call(this)}});Ext.Container.LAYOUTS.table=Ext.layout.TableLayout;Ext.layout.AbsoluteLayout=Ext.extend(Ext.layout.AnchorLayout,{extraCls:"x-abs-layout-item",type:"absolute",onLayout:function(a,b){b.position();this.paddingLeft=b.getPadding("l");this.paddingTop=b.getPadding("t");Ext.layout.AbsoluteLayout.superclass.onLayout.call(this,a,b)},adjustWidthAnchor:function(b,a){return b?b-a.getPosition(true)[0]+this.paddingLeft:b},adjustHeightAnchor:function(b,a){return b?b-a.getPosition(true)[1]+this.paddingTop:b}});Ext.Container.LAYOUTS.absolute=Ext.layout.AbsoluteLayout;Ext.layout.BoxLayout=Ext.extend(Ext.layout.ContainerLayout,{defaultMargins:{left:0,top:0,right:0,bottom:0},padding:"0",pack:"start",monitorResize:true,type:"box",scrollOffset:0,extraCls:"x-box-item",targetCls:"x-box-layout-ct",innerCls:"x-box-inner",constructor:function(a){Ext.layout.BoxLayout.superclass.constructor.call(this,a);if(Ext.isString(this.defaultMargins)){this.defaultMargins=this.parseMargins(this.defaultMargins)}var d=this.overflowHandler;if(typeof d=="string"){d={type:d}}var c="none";if(d&&d.type!=undefined){c=d.type}var b=Ext.layout.boxOverflow[c];if(b[this.type]){b=b[this.type]}this.overflowHandler=new b(this,d)},onLayout:function(b,h){Ext.layout.BoxLayout.superclass.onLayout.call(this,b,h);var d=this.getLayoutTargetSize(),i=this.getVisibleItems(b),c=this.calculateChildBoxes(i,d),g=c.boxes,j=c.meta;if(d.width>0){var k=this.overflowHandler,a=j.tooNarrow?"handleOverflow":"clearOverflow";var e=k[a](c,d);if(e){if(e.targetSize){d=e.targetSize}if(e.recalculate){i=this.getVisibleItems(b);c=this.calculateChildBoxes(i,d);g=c.boxes}}}this.layoutTargetLastSize=d;this.childBoxCache=c;this.updateInnerCtSize(d,c);this.updateChildBoxes(g);this.handleTargetOverflow(d,b,h)},updateChildBoxes:function(c){for(var b=0,e=c.length;b<e;b++){var d=c[b],a=d.component;if(d.dirtySize){a.setSize(d.width,d.height)}if(isNaN(d.left)||isNaN(d.top)){continue}a.setPosition(d.left,d.top)}},updateInnerCtSize:function(c,h){var i=this.align,g=this.padding,e=c.width,a=c.height;if(this.type=="hbox"){var b=e,d=h.meta.maxHeight+g.top+g.bottom;if(i=="stretch"){d=a}else{if(i=="middle"){d=Math.max(a,d)}}}else{var d=a,b=h.meta.maxWidth+g.left+g.right;if(i=="stretch"){b=e}else{if(i=="center"){b=Math.max(e,b)}}}this.innerCt.setSize(b||undefined,d||undefined)},handleTargetOverflow:function(d,a,c){var e=c.getStyle("overflow");if(e&&e!="hidden"&&!this.adjustmentPass){var b=this.getLayoutTargetSize();if(b.width!=d.width||b.height!=d.height){this.adjustmentPass=true;this.onLayout(a,c)}}delete this.adjustmentPass},isValidParent:function(b,a){return this.innerCt&&b.getPositionEl().dom.parentNode==this.innerCt.dom},getVisibleItems:function(g){var g=g||this.container,e=g.getLayoutTarget(),h=g.items.items,a=h.length,d,j,b=[];for(d=0;d<a;d++){if((j=h[d]).rendered&&this.isValidParent(j,e)&&j.hidden!==true&&j.collapsed!==true&&j.shouldLayout!==false){b.push(j)}}return b},renderAll:function(a,b){if(!this.innerCt){this.innerCt=b.createChild({cls:this.innerCls});this.padding=this.parseMargins(this.padding)}Ext.layout.BoxLayout.superclass.renderAll.call(this,a,this.innerCt)},getLayoutTargetSize:function(){var b=this.container.getLayoutTarget(),a;if(b){a=b.getViewSize();if(Ext.isIE&&Ext.isStrict&&a.width==0){a=b.getStyleSize()}a.width-=b.getPadding("lr");a.height-=b.getPadding("tb")}return a},renderItem:function(a){if(Ext.isString(a.margins)){a.margins=this.parseMargins(a.margins)}else{if(!a.margins){a.margins=this.defaultMargins}}Ext.layout.BoxLayout.superclass.renderItem.apply(this,arguments)},destroy:function(){Ext.destroy(this.overflowHandler);Ext.layout.BoxLayout.superclass.destroy.apply(this,arguments)}});Ext.layout.boxOverflow.None=Ext.extend(Object,{constructor:function(b,a){this.layout=b;Ext.apply(this,a||{})},handleOverflow:Ext.emptyFn,clearOverflow:Ext.emptyFn});Ext.layout.boxOverflow.none=Ext.layout.boxOverflow.None;Ext.layout.boxOverflow.Menu=Ext.extend(Ext.layout.boxOverflow.None,{afterCls:"x-strip-right",noItemsMenuText:'<div class="x-toolbar-no-items">(None)</div>',constructor:function(a){Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this,arguments);this.menuItems=[]},createInnerElements:function(){if(!this.afterCt){this.afterCt=this.layout.innerCt.insertSibling({cls:this.afterCls},"before")}},clearOverflow:function(a,g){var e=g.width+(this.afterCt?this.afterCt.getWidth():0),b=this.menuItems;this.hideTrigger();for(var c=0,d=b.length;c<d;c++){b.pop().component.show()}return{targetSize:{height:g.height,width:e}}},showTrigger:function(){this.createMenu();this.menuTrigger.show()},hideTrigger:function(){if(this.menuTrigger!=undefined){this.menuTrigger.hide()}},beforeMenuShow:function(h){var b=this.menuItems,a=b.length,g,e;var c=function(j,i){return j.isXType("buttongroup")&&!(i instanceof Ext.Toolbar.Separator)};this.clearMenu();h.removeAll();for(var d=0;d<a;d++){g=b[d].component;if(e&&(c(g,e)||c(e,g))){h.add("-")}this.addComponentToMenu(h,g);e=g}if(h.items.length<1){h.add(this.noItemsMenuText)}},createMenuConfig:function(c,a){var b=Ext.apply({},c.initialConfig),d=c.toggleGroup;Ext.copyTo(b,c,["iconCls","icon","itemId","disabled","handler","scope","menu"]);Ext.apply(b,{text:c.overflowText||c.text,hideOnClick:a});if(d||c.enableToggle){Ext.apply(b,{group:d,checked:c.pressed,listeners:{checkchange:function(g,e){c.toggle(e)}}})}delete b.ownerCt;delete b.xtype;delete b.id;return b},addComponentToMenu:function(b,a){if(a instanceof Ext.Toolbar.Separator){b.add("-")}else{if(Ext.isFunction(a.isXType)){if(a.isXType("splitbutton")){b.add(this.createMenuConfig(a,true))}else{if(a.isXType("button")){b.add(this.createMenuConfig(a,!a.menu))}else{if(a.isXType("buttongroup")){a.items.each(function(c){this.addComponentToMenu(b,c)},this)}}}}}},clearMenu:function(){var a=this.moreMenu;if(a&&a.items){a.items.each(function(b){delete b.menu})}},createMenu:function(){if(!this.menuTrigger){this.createInnerElements();this.menu=new Ext.menu.Menu({ownerCt:this.layout.container,listeners:{scope:this,beforeshow:this.beforeMenuShow}});this.menuTrigger=new Ext.Button({iconCls:"x-toolbar-more-icon",cls:"x-toolbar-more",menu:this.menu,renderTo:this.afterCt})}},destroy:function(){Ext.destroy(this.menu,this.menuTrigger)}});Ext.layout.boxOverflow.menu=Ext.layout.boxOverflow.Menu;Ext.layout.boxOverflow.HorizontalMenu=Ext.extend(Ext.layout.boxOverflow.Menu,{constructor:function(){Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this,arguments);var c=this,b=c.layout,a=b.calculateChildBoxes;b.calculateChildBoxes=function(d,i){var l=a.apply(b,arguments),k=l.meta,e=c.menuItems;var j=0;for(var g=0,h=e.length;g<h;g++){j+=e[g].width}k.minimumWidth+=j;k.tooNarrow=k.minimumWidth>i.width;return l}},handleOverflow:function(d,h){this.showTrigger();var k=h.width-this.afterCt.getWidth(),l=d.boxes,e=0,r=false;for(var o=0,c=l.length;o<c;o++){e+=l[o].width}var a=k-e,g=0;for(var o=0,c=this.menuItems.length;o<c;o++){var n=this.menuItems[o],m=n.component,b=n.width;if(b<a){m.show();a-=b;g++;r=true}else{break}}if(r){this.menuItems=this.menuItems.slice(g)}else{for(var j=l.length-1;j>=0;j--){var q=l[j].component,p=l[j].left+l[j].width;if(p>=k){this.menuItems.unshift({component:q,width:l[j].width});q.hide()}else{break}}}if(this.menuItems.length==0){this.hideTrigger()}return{targetSize:{height:h.height,width:k},recalculate:r}}});Ext.layout.boxOverflow.menu.hbox=Ext.layout.boxOverflow.HorizontalMenu;Ext.layout.boxOverflow.Scroller=Ext.extend(Ext.layout.boxOverflow.None,{animateScroll:true,scrollIncrement:100,wheelIncrement:3,scrollRepeatInterval:400,scrollDuration:0.4,beforeCls:"x-strip-left",afterCls:"x-strip-right",scrollerCls:"x-strip-scroller",beforeScrollerCls:"x-strip-scroller-left",afterScrollerCls:"x-strip-scroller-right",createWheelListener:function(){this.layout.innerCt.on({scope:this,mousewheel:function(a){a.stopEvent();this.scrollBy(a.getWheelDelta()*this.wheelIncrement*-1,false)}})},handleOverflow:function(a,b){this.createInnerElements();this.showScrollers()},clearOverflow:function(){this.hideScrollers()},showScrollers:function(){this.createScrollers();this.beforeScroller.show();this.afterScroller.show();this.updateScrollButtons()},hideScrollers:function(){if(this.beforeScroller!=undefined){this.beforeScroller.hide();this.afterScroller.hide()}},createScrollers:function(){if(!this.beforeScroller&&!this.afterScroller){var a=this.beforeCt.createChild({cls:String.format("{0} {1} ",this.scrollerCls,this.beforeScrollerCls)});var b=this.afterCt.createChild({cls:String.format("{0} {1}",this.scrollerCls,this.afterScrollerCls)});a.addClassOnOver(this.beforeScrollerCls+"-hover");b.addClassOnOver(this.afterScrollerCls+"-hover");a.setVisibilityMode(Ext.Element.DISPLAY);b.setVisibilityMode(Ext.Element.DISPLAY);this.beforeRepeater=new Ext.util.ClickRepeater(a,{interval:this.scrollRepeatInterval,handler:this.scrollLeft,scope:this});this.afterRepeater=new Ext.util.ClickRepeater(b,{interval:this.scrollRepeatInterval,handler:this.scrollRight,scope:this});this.beforeScroller=a;this.afterScroller=b}},destroy:function(){Ext.destroy(this.beforeScroller,this.afterScroller,this.beforeRepeater,this.afterRepeater,this.beforeCt,this.afterCt)},scrollBy:function(b,a){this.scrollTo(this.getScrollPosition()+b,a)},getItem:function(a){if(Ext.isString(a)){a=Ext.getCmp(a)}else{if(Ext.isNumber(a)){a=this.items[a]}}return a},getScrollAnim:function(){return{duration:this.scrollDuration,callback:this.updateScrollButtons,scope:this}},updateScrollButtons:function(){if(this.beforeScroller==undefined||this.afterScroller==undefined){return}var d=this.atExtremeBefore()?"addClass":"removeClass",c=this.atExtremeAfter()?"addClass":"removeClass",a=this.beforeScrollerCls+"-disabled",b=this.afterScrollerCls+"-disabled";this.beforeScroller[d](a);this.afterScroller[c](b);this.scrolling=false},atExtremeBefore:function(){return this.getScrollPosition()===0},scrollLeft:function(a){this.scrollBy(-this.scrollIncrement,a)},scrollRight:function(a){this.scrollBy(this.scrollIncrement,a)},scrollToItem:function(d,b){d=this.getItem(d);if(d!=undefined){var a=this.getItemVisibility(d);if(!a.fullyVisible){var c=d.getBox(true,true),e=c.x;if(a.hiddenRight){e-=(this.layout.innerCt.getWidth()-c.width)}this.scrollTo(e,b)}}},getItemVisibility:function(e){var d=this.getItem(e).getBox(true,true),a=d.x,c=d.x+d.width,g=this.getScrollPosition(),b=this.layout.innerCt.getWidth()+g;return{hiddenLeft:a<g,hiddenRight:c>b,fullyVisible:a>g&&c<b}}});Ext.layout.boxOverflow.scroller=Ext.layout.boxOverflow.Scroller;Ext.layout.boxOverflow.VerticalScroller=Ext.extend(Ext.layout.boxOverflow.Scroller,{scrollIncrement:75,wheelIncrement:2,handleOverflow:function(a,b){Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this,arguments);return{targetSize:{height:b.height-(this.beforeCt.getHeight()+this.afterCt.getHeight()),width:b.width}}},createInnerElements:function(){var a=this.layout.innerCt;if(!this.beforeCt){this.beforeCt=a.insertSibling({cls:this.beforeCls},"before");this.afterCt=a.insertSibling({cls:this.afterCls},"after");this.createWheelListener()}},scrollTo:function(a,b){var d=this.getScrollPosition(),c=a.constrain(0,this.getMaxScrollBottom());if(c!=d&&!this.scrolling){if(b==undefined){b=this.animateScroll}this.layout.innerCt.scrollTo("top",c,b?this.getScrollAnim():false);if(b){this.scrolling=true}else{this.scrolling=false;this.updateScrollButtons()}}},getScrollPosition:function(){return parseInt(this.layout.innerCt.dom.scrollTop,10)||0},getMaxScrollBottom:function(){return this.layout.innerCt.dom.scrollHeight-this.layout.innerCt.getHeight()},atExtremeAfter:function(){return this.getScrollPosition()>=this.getMaxScrollBottom()}});Ext.layout.boxOverflow.scroller.vbox=Ext.layout.boxOverflow.VerticalScroller;Ext.layout.boxOverflow.HorizontalScroller=Ext.extend(Ext.layout.boxOverflow.Scroller,{handleOverflow:function(a,b){Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this,arguments);return{targetSize:{height:b.height,width:b.width-(this.beforeCt.getWidth()+this.afterCt.getWidth())}}},createInnerElements:function(){var a=this.layout.innerCt;if(!this.beforeCt){this.afterCt=a.insertSibling({cls:this.afterCls},"before");this.beforeCt=a.insertSibling({cls:this.beforeCls},"before");this.createWheelListener()}},scrollTo:function(a,b){var d=this.getScrollPosition(),c=a.constrain(0,this.getMaxScrollRight());if(c!=d&&!this.scrolling){if(b==undefined){b=this.animateScroll}this.layout.innerCt.scrollTo("left",c,b?this.getScrollAnim():false);if(b){this.scrolling=true}else{this.scrolling=false;this.updateScrollButtons()}}},getScrollPosition:function(){return parseInt(this.layout.innerCt.dom.scrollLeft,10)||0},getMaxScrollRight:function(){return this.layout.innerCt.dom.scrollWidth-this.layout.innerCt.getWidth()},atExtremeAfter:function(){return this.getScrollPosition()>=this.getMaxScrollRight()}});Ext.layout.boxOverflow.scroller.hbox=Ext.layout.boxOverflow.HorizontalScroller;Ext.layout.HBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"top",type:"hbox",calculateChildBoxes:function(r,b){var F=r.length,R=this.padding,D=R.top,U=R.left,y=D+R.bottom,O=U+R.right,a=b.width-this.scrollOffset,e=b.height,o=Math.max(0,e-y),P=this.pack=="start",W=this.pack=="center",A=this.pack=="end",L=0,Q=0,T=0,l=0,X=0,H=[],k,J,M,V,w,j,S,I,c,x,q,N;for(S=0;S<F;S++){k=r[S];M=k.height;J=k.width;j=!k.hasLayout&&typeof k.doLayout=="function";if(typeof J!="number"){if(k.flex&&!J){T+=k.flex}else{if(!J&&j){k.doLayout()}V=k.getSize();J=V.width;M=V.height}}w=k.margins;x=w.left+w.right;L+=x+(J||0);l+=x+(k.flex?k.minWidth||0:J);X+=x+(k.minWidth||J||0);if(typeof M!="number"){if(j){k.doLayout()}M=k.getHeight()}Q=Math.max(Q,M+w.top+w.bottom);H.push({component:k,height:M||undefined,width:J||undefined})}var K=l-a,p=X>a;var n=Math.max(0,a-L-O);if(p){for(S=0;S<F;S++){H[S].width=r[S].minWidth||r[S].width||H[S].width}}else{if(K>0){var C=[];for(var E=0,v=F;E<v;E++){var B=r[E],t=B.minWidth||0;if(B.flex){H[E].width=t}else{C.push({minWidth:t,available:H[E].width-t,index:E})}}C.sort(function(Y,i){return Y.available>i.available?1:-1});for(var S=0,v=C.length;S<v;S++){var G=C[S].index;if(G==undefined){continue}var B=r[G],m=H[G],u=m.width,t=B.minWidth,d=Math.max(t,u-Math.ceil(K/(v-S))),g=u-d;H[G].width=d;K-=g}}else{var h=n,s=T;for(S=0;S<F;S++){k=r[S];I=H[S];w=k.margins;q=w.top+w.bottom;if(P&&k.flex&&!k.width){c=Math.ceil((k.flex/s)*h);h-=c;s-=k.flex;I.width=c;I.dirtySize=true}}}}if(W){U+=n/2}else{if(A){U+=n}}for(S=0;S<F;S++){k=r[S];I=H[S];w=k.margins;U+=w.left;q=w.top+w.bottom;I.left=U;I.top=D+w.top;switch(this.align){case"stretch":N=o-q;I.height=N.constrain(k.minHeight||0,k.maxHeight||1000000);I.dirtySize=true;break;case"stretchmax":N=Q-q;I.height=N.constrain(k.minHeight||0,k.maxHeight||1000000);I.dirtySize=true;break;case"middle":var z=o-I.height-q;if(z>0){I.top=D+q+(z/2)}}U+=I.width+w.right}return{boxes:H,meta:{maxHeight:Q,nonFlexWidth:L,desiredWidth:l,minimumWidth:X,shortfall:l-a,tooNarrow:p}}}});Ext.Container.LAYOUTS.hbox=Ext.layout.HBoxLayout;Ext.layout.VBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"left",type:"vbox",calculateChildBoxes:function(o,b){var E=o.length,R=this.padding,C=R.top,V=R.left,x=C+R.bottom,O=V+R.right,a=b.width-this.scrollOffset,c=b.height,K=Math.max(0,a-O),P=this.pack=="start",X=this.pack=="center",z=this.pack=="end",k=0,u=0,U=0,L=0,m=0,G=[],h,I,N,W,t,g,T,H,S,w,n,d,r;for(T=0;T<E;T++){h=o[T];N=h.height;I=h.width;g=!h.hasLayout&&typeof h.doLayout=="function";if(typeof N!="number"){if(h.flex&&!N){U+=h.flex}else{if(!N&&g){h.doLayout()}W=h.getSize();I=W.width;N=W.height}}t=h.margins;n=t.top+t.bottom;k+=n+(N||0);L+=n+(h.flex?h.minHeight||0:N);m+=n+(h.minHeight||N||0);if(typeof I!="number"){if(g){h.doLayout()}I=h.getWidth()}u=Math.max(u,I+t.left+t.right);G.push({component:h,height:N||undefined,width:I||undefined})}var M=L-c,l=m>c;var q=Math.max(0,(c-k-x));if(l){for(T=0,r=E;T<r;T++){G[T].height=o[T].minHeight||o[T].height||G[T].height}}else{if(M>0){var J=[];for(var D=0,r=E;D<r;D++){var A=o[D],s=A.minHeight||0;if(A.flex){G[D].height=s}else{J.push({minHeight:s,available:G[D].height-s,index:D})}}J.sort(function(Y,i){return Y.available>i.available?1:-1});for(var T=0,r=J.length;T<r;T++){var F=J[T].index;if(F==undefined){continue}var A=o[F],j=G[F],v=j.height,s=A.minHeight,B=Math.max(s,v-Math.ceil(M/(r-T))),e=v-B;G[F].height=B;M-=e}}else{var Q=q,p=U;for(T=0;T<E;T++){h=o[T];H=G[T];t=h.margins;w=t.left+t.right;if(P&&h.flex&&!h.height){S=Math.ceil((h.flex/p)*Q);Q-=S;p-=h.flex;H.height=S;H.dirtySize=true}}}}if(X){C+=q/2}else{if(z){C+=q}}for(T=0;T<E;T++){h=o[T];H=G[T];t=h.margins;C+=t.top;w=t.left+t.right;H.left=V+t.left;H.top=C;switch(this.align){case"stretch":d=K-w;H.width=d.constrain(h.minWidth||0,h.maxWidth||1000000);H.dirtySize=true;break;case"stretchmax":d=u-w;H.width=d.constrain(h.minWidth||0,h.maxWidth||1000000);H.dirtySize=true;break;case"center":var y=K-H.width-w;if(y>0){H.left=V+w+(y/2)}}C+=H.height+t.bottom}return{boxes:G,meta:{maxWidth:u,nonFlexHeight:k,desiredHeight:L,minimumHeight:m,shortfall:L-c,tooNarrow:l}}}});Ext.Container.LAYOUTS.vbox=Ext.layout.VBoxLayout;Ext.layout.ToolbarLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:"toolbar",triggerWidth:18,noItemsMenuText:'<div class="x-toolbar-no-items">(None)</div>',lastOverflow:false,tableHTML:['<table cellspacing="0" class="x-toolbar-ct">',"<tbody>","<tr>",'<td class="x-toolbar-left" align="{0}">','<table cellspacing="0">',"<tbody>",'<tr class="x-toolbar-left-row"></tr>',"</tbody>","</table>","</td>",'<td class="x-toolbar-right" align="right">','<table cellspacing="0" class="x-toolbar-right-ct">',"<tbody>","<tr>","<td>",'<table cellspacing="0">',"<tbody>",'<tr class="x-toolbar-right-row"></tr>',"</tbody>","</table>","</td>","<td>",'<table cellspacing="0">',"<tbody>",'<tr class="x-toolbar-extras-row"></tr>',"</tbody>","</table>","</td>","</tr>","</tbody>","</table>","</td>","</tr>","</tbody>","</table>"].join(""),onLayout:function(e,j){if(!this.leftTr){var h=e.buttonAlign=="center"?"center":"left";j.addClass("x-toolbar-layout-ct");j.insertHtml("beforeEnd",String.format(this.tableHTML,h));this.leftTr=j.child("tr.x-toolbar-left-row",true);this.rightTr=j.child("tr.x-toolbar-right-row",true);this.extrasTr=j.child("tr.x-toolbar-extras-row",true);if(this.hiddenItem==undefined){this.hiddenItems=[]}}var k=e.buttonAlign=="right"?this.rightTr:this.leftTr,l=e.items.items,d=0;for(var b=0,g=l.length,m;b<g;b++,d++){m=l[b];if(m.isFill){k=this.rightTr;d=-1}else{if(!m.rendered){m.render(this.insertCell(m,k,d));this.configureItem(m)}else{if(!m.xtbHidden&&!this.isValidParent(m,k.childNodes[d])){var a=this.insertCell(m,k,d);a.appendChild(m.getPositionEl().dom);m.container=Ext.get(a)}}}}this.cleanup(this.leftTr);this.cleanup(this.rightTr);this.cleanup(this.extrasTr);this.fitToSize(j)},cleanup:function(b){var e=b.childNodes,a,d;for(a=e.length-1;a>=0&&(d=e[a]);a--){if(!d.firstChild){b.removeChild(d)}}},insertCell:function(e,b,a){var d=document.createElement("td");d.className="x-toolbar-cell";b.insertBefore(d,b.childNodes[a]||null);return d},hideItem:function(a){this.hiddenItems.push(a);a.xtbHidden=true;a.xtbWidth=a.getPositionEl().dom.parentNode.offsetWidth;a.hide()},unhideItem:function(a){a.show();a.xtbHidden=false;this.hiddenItems.remove(a)},getItemWidth:function(a){return a.hidden?(a.xtbWidth||0):a.getPositionEl().dom.parentNode.offsetWidth},fitToSize:function(k){if(this.container.enableOverflow===false){return}var b=k.dom.clientWidth,j=k.dom.firstChild.offsetWidth,m=b-this.triggerWidth,a=this.lastWidth||0,c=this.hiddenItems,e=c.length!=0,n=b>=a;this.lastWidth=b;if(j>b||(e&&n)){var l=this.container.items.items,h=l.length,d=0,o;for(var g=0;g<h;g++){o=l[g];if(!o.isFill){d+=this.getItemWidth(o);if(d>m){if(!(o.hidden||o.xtbHidden)){this.hideItem(o)}}else{if(o.xtbHidden){this.unhideItem(o)}}}}}e=c.length!=0;if(e){this.initMore();if(!this.lastOverflow){this.container.fireEvent("overflowchange",this.container,true);this.lastOverflow=true}}else{if(this.more){this.clearMenu();this.more.destroy();delete this.more;if(this.lastOverflow){this.container.fireEvent("overflowchange",this.container,false);this.lastOverflow=false}}}},createMenuConfig:function(c,a){var b=Ext.apply({},c.initialConfig),d=c.toggleGroup;Ext.copyTo(b,c,["iconCls","icon","itemId","disabled","handler","scope","menu"]);Ext.apply(b,{text:c.overflowText||c.text,hideOnClick:a});if(d||c.enableToggle){Ext.apply(b,{group:d,checked:c.pressed,listeners:{checkchange:function(g,e){c.toggle(e)}}})}delete b.ownerCt;delete b.xtype;delete b.id;return b},addComponentToMenu:function(b,a){if(a instanceof Ext.Toolbar.Separator){b.add("-")}else{if(Ext.isFunction(a.isXType)){if(a.isXType("splitbutton")){b.add(this.createMenuConfig(a,true))}else{if(a.isXType("button")){b.add(this.createMenuConfig(a,!a.menu))}else{if(a.isXType("buttongroup")){a.items.each(function(c){this.addComponentToMenu(b,c)},this)}}}}}},clearMenu:function(){var a=this.moreMenu;if(a&&a.items){a.items.each(function(b){delete b.menu})}},beforeMoreShow:function(h){var b=this.container.items.items,a=b.length,g,e;var c=function(j,i){return j.isXType("buttongroup")&&!(i instanceof Ext.Toolbar.Separator)};this.clearMenu();h.removeAll();for(var d=0;d<a;d++){g=b[d];if(g.xtbHidden){if(e&&(c(g,e)||c(e,g))){h.add("-")}this.addComponentToMenu(h,g);e=g}}if(h.items.length<1){h.add(this.noItemsMenuText)}},initMore:function(){if(!this.more){this.moreMenu=new Ext.menu.Menu({ownerCt:this.container,listeners:{beforeshow:this.beforeMoreShow,scope:this}});this.more=new Ext.Button({iconCls:"x-toolbar-more-icon",cls:"x-toolbar-more",menu:this.moreMenu,ownerCt:this.container});var a=this.insertCell(this.more,this.extrasTr,100);this.more.render(a)}},destroy:function(){Ext.destroy(this.more,this.moreMenu);delete this.leftTr;delete this.rightTr;delete this.extrasTr;Ext.layout.ToolbarLayout.superclass.destroy.call(this)}});Ext.Container.LAYOUTS.toolbar=Ext.layout.ToolbarLayout;Ext.layout.MenuLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:"menu",setContainer:function(a){this.monitorResize=!a.floating;a.on("autosize",this.doAutoSize,this);Ext.layout.MenuLayout.superclass.setContainer.call(this,a)},renderItem:function(g,b,e){if(!this.itemTpl){this.itemTpl=Ext.layout.MenuLayout.prototype.itemTpl=new Ext.XTemplate('<li id="{itemId}" class="{itemCls}">','<tpl if="needsIcon">','<img alt="{altText}" src="{icon}" class="{iconCls}"/>',"</tpl>","</li>")}if(g&&!g.rendered){if(Ext.isNumber(b)){b=e.dom.childNodes[b]}var d=this.getItemArgs(g);g.render(g.positionEl=b?this.itemTpl.insertBefore(b,d,true):this.itemTpl.append(e,d,true));g.positionEl.menuItemId=g.getItemId();if(!d.isMenuItem&&d.needsIcon){g.positionEl.addClass("x-menu-list-item-indent")}this.configureItem(g)}else{if(g&&!this.isValidParent(g,e)){if(Ext.isNumber(b)){b=e.dom.childNodes[b]}e.dom.insertBefore(g.getActionEl().dom,b||null)}}},getItemArgs:function(d){var a=d instanceof Ext.menu.Item,b=!(a||d instanceof Ext.menu.Separator);return{isMenuItem:a,needsIcon:b&&(d.icon||d.iconCls),icon:d.icon||Ext.BLANK_IMAGE_URL,iconCls:"x-menu-item-icon "+(d.iconCls||""),itemId:"x-menu-el-"+d.id,itemCls:"x-menu-list-item ",altText:d.altText||""}},isValidParent:function(b,a){return b.el.up("li.x-menu-list-item",5).dom.parentNode===(a.dom||a)},onLayout:function(a,b){Ext.layout.MenuLayout.superclass.onLayout.call(this,a,b);this.doAutoSize()},doAutoSize:function(){var c=this.container,a=c.width;if(c.floating){if(a){c.setWidth(a)}else{if(Ext.isIE){c.setWidth(Ext.isStrict&&(Ext.isIE7||Ext.isIE8||Ext.isIE9)?"auto":c.minWidth);var d=c.getEl(),b=d.dom.offsetWidth;c.setWidth(c.getLayoutTarget().getWidth()+d.getFrameWidth("lr"))}}}}});Ext.Container.LAYOUTS.menu=Ext.layout.MenuLayout;Ext.Viewport=Ext.extend(Ext.Container,{initComponent:function(){Ext.Viewport.superclass.initComponent.call(this);document.getElementsByTagName("html")[0].className+=" x-viewport";this.el=Ext.getBody();this.el.setHeight=Ext.emptyFn;this.el.setWidth=Ext.emptyFn;this.el.setSize=Ext.emptyFn;this.el.dom.scroll="no";this.allowDomMove=false;this.autoWidth=true;this.autoHeight=true;Ext.EventManager.onWindowResize(this.fireResize,this);this.renderTo=this.el},fireResize:function(a,b){this.fireEvent("resize",this,a,b,a,b)}});Ext.reg("viewport",Ext.Viewport);Ext.Panel=Ext.extend(Ext.Container,{baseCls:"x-panel",collapsedCls:"x-panel-collapsed",maskDisabled:true,animCollapse:Ext.enableFx,headerAsText:true,buttonAlign:"right",collapsed:false,collapseFirst:true,minButtonWidth:75,elements:"body",preventBodyReset:false,padding:undefined,resizeEvent:"bodyresize",toolTarget:"header",collapseEl:"bwrap",slideAnchor:"t",disabledClass:"",deferHeight:true,expandDefaults:{duration:0.25},collapseDefaults:{duration:0.25},initComponent:function(){Ext.Panel.superclass.initComponent.call(this);this.addEvents("bodyresize","titlechange","iconchange","collapse","expand","beforecollapse","beforeexpand","beforeclose","close","activate","deactivate");if(this.unstyled){this.baseCls="x-plain"}this.toolbars=[];if(this.tbar){this.elements+=",tbar";this.topToolbar=this.createToolbar(this.tbar);this.tbar=null}if(this.bbar){this.elements+=",bbar";this.bottomToolbar=this.createToolbar(this.bbar);this.bbar=null}if(this.header===true){this.elements+=",header";this.header=null}else{if(this.headerCfg||(this.title&&this.header!==false)){this.elements+=",header"}}if(this.footerCfg||this.footer===true){this.elements+=",footer";this.footer=null}if(this.buttons){this.fbar=this.buttons;this.buttons=null}if(this.fbar){this.createFbar(this.fbar)}if(this.autoLoad){this.on("render",this.doAutoLoad,this,{delay:10})}},createFbar:function(b){var a=this.minButtonWidth;this.elements+=",footer";this.fbar=this.createToolbar(b,{buttonAlign:this.buttonAlign,toolbarCls:"x-panel-fbar",enableOverflow:false,defaults:function(d){return{minWidth:d.minWidth||a}}});this.fbar.items.each(function(d){d.minWidth=d.minWidth||this.minButtonWidth},this);this.buttons=this.fbar.items.items},createToolbar:function(b,c){var a;if(Ext.isArray(b)){b={items:b}}a=b.events?Ext.apply(b,c):this.createComponent(Ext.apply({},b,c),"toolbar");this.toolbars.push(a);return a},createElement:function(a,c){if(this[a]){c.appendChild(this[a].dom);return}if(a==="bwrap"||this.elements.indexOf(a)!=-1){if(this[a+"Cfg"]){this[a]=Ext.fly(c).createChild(this[a+"Cfg"])}else{var b=document.createElement("div");b.className=this[a+"Cls"];this[a]=Ext.get(c.appendChild(b))}if(this[a+"CssClass"]){this[a].addClass(this[a+"CssClass"])}if(this[a+"Style"]){this[a].applyStyles(this[a+"Style"])}}},onRender:function(g,e){Ext.Panel.superclass.onRender.call(this,g,e);this.createClasses();var a=this.el,h=a.dom,k,i;if(this.collapsible&&!this.hideCollapseTool){this.tools=this.tools?this.tools.slice(0):[];this.tools[this.collapseFirst?"unshift":"push"]({id:"toggle",handler:this.toggleCollapse,scope:this})}if(this.tools){i=this.tools;this.elements+=(this.header!==false)?",header":""}this.tools={};a.addClass(this.baseCls);if(h.firstChild){this.header=a.down("."+this.headerCls);this.bwrap=a.down("."+this.bwrapCls);var j=this.bwrap?this.bwrap:a;this.tbar=j.down("."+this.tbarCls);this.body=j.down("."+this.bodyCls);this.bbar=j.down("."+this.bbarCls);this.footer=j.down("."+this.footerCls);this.fromMarkup=true}if(this.preventBodyReset===true){a.addClass("x-panel-reset")}if(this.cls){a.addClass(this.cls)}if(this.buttons){this.elements+=",footer"}if(this.frame){a.insertHtml("afterBegin",String.format(Ext.Element.boxMarkup,this.baseCls));this.createElement("header",h.firstChild.firstChild.firstChild);this.createElement("bwrap",h);k=this.bwrap.dom;var c=h.childNodes[1],b=h.childNodes[2];k.appendChild(c);k.appendChild(b);var l=k.firstChild.firstChild.firstChild;this.createElement("tbar",l);this.createElement("body",l);this.createElement("bbar",l);this.createElement("footer",k.lastChild.firstChild.firstChild);if(!this.footer){this.bwrap.dom.lastChild.className+=" x-panel-nofooter"}this.ft=Ext.get(this.bwrap.dom.lastChild);this.mc=Ext.get(l)}else{this.createElement("header",h);this.createElement("bwrap",h);k=this.bwrap.dom;this.createElement("tbar",k);this.createElement("body",k);this.createElement("bbar",k);this.createElement("footer",k);if(!this.header){this.body.addClass(this.bodyCls+"-noheader");if(this.tbar){this.tbar.addClass(this.tbarCls+"-noheader")}}}if(Ext.isDefined(this.padding)){this.body.setStyle("padding",this.body.addUnits(this.padding))}if(this.border===false){this.el.addClass(this.baseCls+"-noborder");this.body.addClass(this.bodyCls+"-noborder");if(this.header){this.header.addClass(this.headerCls+"-noborder")}if(this.footer){this.footer.addClass(this.footerCls+"-noborder")}if(this.tbar){this.tbar.addClass(this.tbarCls+"-noborder")}if(this.bbar){this.bbar.addClass(this.bbarCls+"-noborder")}}if(this.bodyBorder===false){this.body.addClass(this.bodyCls+"-noborder")}this.bwrap.enableDisplayMode("block");if(this.header){this.header.unselectable();if(this.headerAsText){this.header.dom.innerHTML='<span class="'+this.headerTextCls+'">'+this.header.dom.innerHTML+"</span>";if(this.iconCls){this.setIconClass(this.iconCls)}}}if(this.floating){this.makeFloating(this.floating)}if(this.collapsible&&this.titleCollapse&&this.header){this.mon(this.header,"click",this.toggleCollapse,this);this.header.setStyle("cursor","pointer")}if(i){this.addTool.apply(this,i)}if(this.fbar){this.footer.addClass("x-panel-btns");this.fbar.ownerCt=this;this.fbar.render(this.footer);this.footer.createChild({cls:"x-clear"})}if(this.tbar&&this.topToolbar){this.topToolbar.ownerCt=this;this.topToolbar.render(this.tbar)}if(this.bbar&&this.bottomToolbar){this.bottomToolbar.ownerCt=this;this.bottomToolbar.render(this.bbar)}},setIconClass:function(b){var a=this.iconCls;this.iconCls=b;if(this.rendered&&this.header){if(this.frame){this.header.addClass("x-panel-icon");this.header.replaceClass(a,this.iconCls)}else{var e=this.header,c=e.child("img.x-panel-inline-icon");if(c){Ext.fly(c).replaceClass(a,this.iconCls)}else{var d=e.child("span."+this.headerTextCls);if(d){Ext.DomHelper.insertBefore(d.dom,{tag:"img",alt:"",src:Ext.BLANK_IMAGE_URL,cls:"x-panel-inline-icon "+this.iconCls})}}}}this.fireEvent("iconchange",this,b,a)},makeFloating:function(a){this.floating=true;this.el=new Ext.Layer(Ext.apply({},a,{shadow:Ext.isDefined(this.shadow)?this.shadow:"sides",shadowOffset:this.shadowOffset,constrain:false,shim:this.shim===false?false:undefined}),this.el)},getTopToolbar:function(){return this.topToolbar},getBottomToolbar:function(){return this.bottomToolbar},getFooterToolbar:function(){return this.fbar},addButton:function(a,c,b){if(!this.fbar){this.createFbar([])}if(c){if(Ext.isString(a)){a={text:a}}a=Ext.apply({handler:c,scope:b},a)}return this.fbar.add(a)},addTool:function(){if(!this.rendered){if(!this.tools){this.tools=[]}Ext.each(arguments,function(a){this.tools.push(a)},this);return}if(!this[this.toolTarget]){return}if(!this.toolTemplate){var h=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');h.disableFormats=true;h.compile();Ext.Panel.prototype.toolTemplate=h}for(var g=0,d=arguments,c=d.length;g<c;g++){var b=d[g];if(!this.tools[b.id]){var j="x-tool-"+b.id+"-over";var e=this.toolTemplate.insertFirst(this[this.toolTarget],b,true);this.tools[b.id]=e;e.enableDisplayMode("block");this.mon(e,"click",this.createToolHandler(e,b,j,this));if(b.on){this.mon(e,b.on)}if(b.hidden){e.hide()}if(b.qtip){if(Ext.isObject(b.qtip)){Ext.QuickTips.register(Ext.apply({target:e.id},b.qtip))}else{e.dom.qtip=b.qtip}}e.addClassOnOver(j)}}},onLayout:function(b,a){Ext.Panel.superclass.onLayout.apply(this,arguments);if(this.hasLayout&&this.toolbars.length>0){Ext.each(this.toolbars,function(c){c.doLayout(undefined,a)});this.syncHeight()}},syncHeight:function(){var b=this.toolbarHeight,c=this.body,a=this.lastSize.height,d;if(this.autoHeight||!Ext.isDefined(a)||a=="auto"){return}if(b!=this.getToolbarHeight()){b=Math.max(0,a-this.getFrameHeight());c.setHeight(b);d=c.getSize();this.toolbarHeight=this.getToolbarHeight();this.onBodyResize(d.width,d.height)}},onShow:function(){if(this.floating){return this.el.show()}Ext.Panel.superclass.onShow.call(this)},onHide:function(){if(this.floating){return this.el.hide()}Ext.Panel.superclass.onHide.call(this)},createToolHandler:function(c,a,d,b){return function(g){c.removeClass(d);if(a.stopEvent!==false){g.stopEvent()}if(a.handler){a.handler.call(a.scope||c,g,c,b,a)}}},afterRender:function(){if(this.floating&&!this.hidden){this.el.show()}if(this.title){this.setTitle(this.title)}Ext.Panel.superclass.afterRender.call(this);if(this.collapsed){this.collapsed=false;this.collapse(false)}this.initEvents()},getKeyMap:function(){if(!this.keyMap){this.keyMap=new Ext.KeyMap(this.el,this.keys)}return this.keyMap},initEvents:function(){if(this.keys){this.getKeyMap()}if(this.draggable){this.initDraggable()}if(this.toolbars.length>0){Ext.each(this.toolbars,function(a){a.doLayout();a.on({scope:this,afterlayout:this.syncHeight,remove:this.syncHeight})},this);this.syncHeight()}},initDraggable:function(){this.dd=new Ext.Panel.DD(this,Ext.isBoolean(this.draggable)?null:this.draggable)},beforeEffect:function(a){if(this.floating){this.el.beforeAction()}if(a!==false){this.el.addClass("x-panel-animated")}},afterEffect:function(a){this.syncShadow();this.el.removeClass("x-panel-animated")},createEffect:function(c,b,d){var e={scope:d,block:true};if(c===true){e.callback=b;return e}else{if(!c.callback){e.callback=b}else{e.callback=function(){b.call(d);Ext.callback(c.callback,c.scope)}}}return Ext.applyIf(e,c)},collapse:function(b){if(this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforecollapse",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.beforeEffect(a);this.onCollapse(a,b);return this},onCollapse:function(a,b){if(a){this[this.collapseEl].slideOut(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterCollapse,this),this.collapseDefaults))}else{this[this.collapseEl].hide(this.hideMode);this.afterCollapse(false)}},afterCollapse:function(a){this.collapsed=true;this.el.addClass(this.collapsedCls);if(a!==false){this[this.collapseEl].hide(this.hideMode)}this.afterEffect(a);this.cascade(function(b){if(b.lastSize){b.lastSize={width:undefined,height:undefined}}});this.fireEvent("collapse",this)},expand:function(b){if(!this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforeexpand",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.el.removeClass(this.collapsedCls);this.beforeEffect(a);this.onExpand(a,b);return this},onExpand:function(a,b){if(a){this[this.collapseEl].slideIn(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterExpand,this),this.expandDefaults))}else{this[this.collapseEl].show(this.hideMode);this.afterExpand(false)}},afterExpand:function(a){this.collapsed=false;if(a!==false){this[this.collapseEl].show(this.hideMode)}this.afterEffect(a);if(this.deferLayout){delete this.deferLayout;this.doLayout(true)}this.fireEvent("expand",this)},toggleCollapse:function(a){this[this.collapsed?"expand":"collapse"](a);return this},onDisable:function(){if(this.rendered&&this.maskDisabled){this.el.mask()}Ext.Panel.superclass.onDisable.call(this)},onEnable:function(){if(this.rendered&&this.maskDisabled){this.el.unmask()}Ext.Panel.superclass.onEnable.call(this)},onResize:function(g,d,c,e){var a=g,b=d;if(Ext.isDefined(a)||Ext.isDefined(b)){if(!this.collapsed){if(Ext.isNumber(a)){this.body.setWidth(a=this.adjustBodyWidth(a-this.getFrameWidth()))}else{if(a=="auto"){a=this.body.setWidth("auto").dom.offsetWidth}else{a=this.body.dom.offsetWidth}}if(this.tbar){this.tbar.setWidth(a);if(this.topToolbar){this.topToolbar.setSize(a)}}if(this.bbar){this.bbar.setWidth(a);if(this.bottomToolbar){this.bottomToolbar.setSize(a);if(Ext.isIE){this.bbar.setStyle("position","static");this.bbar.setStyle("position","")}}}if(this.footer){this.footer.setWidth(a);if(this.fbar){this.fbar.setSize(Ext.isIE?(a-this.footer.getFrameWidth("lr")):"auto")}}if(Ext.isNumber(b)){b=Math.max(0,b-this.getFrameHeight());this.body.setHeight(b)}else{if(b=="auto"){this.body.setHeight(b)}}if(this.disabled&&this.el._mask){this.el._mask.setSize(this.el.dom.clientWidth,this.el.getHeight())}}else{this.queuedBodySize={width:a,height:b};if(!this.queuedExpand&&this.allowQueuedExpand!==false){this.queuedExpand=true;this.on("expand",function(){delete this.queuedExpand;this.onResize(this.queuedBodySize.width,this.queuedBodySize.height)},this,{single:true})}}this.onBodyResize(a,b)}this.syncShadow();Ext.Panel.superclass.onResize.call(this,g,d,c,e)},onBodyResize:function(a,b){this.fireEvent("bodyresize",this,a,b)},getToolbarHeight:function(){var a=0;if(this.rendered){Ext.each(this.toolbars,function(b){a+=b.getHeight()},this)}return a},adjustBodyHeight:function(a){return a},adjustBodyWidth:function(a){return a},onPosition:function(){this.syncShadow()},getFrameWidth:function(){var b=this.el.getFrameWidth("lr")+this.bwrap.getFrameWidth("lr");if(this.frame){var a=this.bwrap.dom.firstChild;b+=(Ext.fly(a).getFrameWidth("l")+Ext.fly(a.firstChild).getFrameWidth("r"));b+=this.mc.getFrameWidth("lr")}return b},getFrameHeight:function(){var a=this.el.getFrameWidth("tb")+this.bwrap.getFrameWidth("tb");a+=(this.tbar?this.tbar.getHeight():0)+(this.bbar?this.bbar.getHeight():0);if(this.frame){a+=this.el.dom.firstChild.offsetHeight+this.ft.dom.offsetHeight+this.mc.getFrameWidth("tb")}else{a+=(this.header?this.header.getHeight():0)+(this.footer?this.footer.getHeight():0)}return a},getInnerWidth:function(){return this.getSize().width-this.getFrameWidth()},getInnerHeight:function(){return this.body.getHeight()},syncShadow:function(){if(this.floating){this.el.sync(true)}},getLayoutTarget:function(){return this.body},getContentTarget:function(){return this.body},setTitle:function(b,a){this.title=b;if(this.header&&this.headerAsText){this.header.child("span").update(b)}if(a){this.setIconClass(a)}this.fireEvent("titlechange",this,b);return this},getUpdater:function(){return this.body.getUpdater()},load:function(){var a=this.body.getUpdater();a.update.apply(a,arguments);return this},beforeDestroy:function(){Ext.Panel.superclass.beforeDestroy.call(this);if(this.header){this.header.removeAllListeners()}if(this.tools){for(var a in this.tools){Ext.destroy(this.tools[a])}}if(this.toolbars.length>0){Ext.each(this.toolbars,function(b){b.un("afterlayout",this.syncHeight,this);b.un("remove",this.syncHeight,this)},this)}if(Ext.isArray(this.buttons)){while(this.buttons.length){Ext.destroy(this.buttons[0])}}if(this.rendered){Ext.destroy(this.ft,this.header,this.footer,this.tbar,this.bbar,this.body,this.mc,this.bwrap,this.dd);if(this.fbar){Ext.destroy(this.fbar,this.fbar.el)}}Ext.destroy(this.toolbars)},createClasses:function(){this.headerCls=this.baseCls+"-header";this.headerTextCls=this.baseCls+"-header-text";this.bwrapCls=this.baseCls+"-bwrap";this.tbarCls=this.baseCls+"-tbar";this.bodyCls=this.baseCls+"-body";this.bbarCls=this.baseCls+"-bbar";this.footerCls=this.baseCls+"-footer"},createGhost:function(a,e,b){var d=document.createElement("div");d.className="x-panel-ghost "+(a?a:"");if(this.header){d.appendChild(this.el.dom.firstChild.cloneNode(true))}Ext.fly(d.appendChild(document.createElement("ul"))).setHeight(this.bwrap.getHeight());d.style.width=this.el.dom.offsetWidth+"px";if(!b){this.container.dom.appendChild(d)}else{Ext.getDom(b).appendChild(d)}if(e!==false&&this.el.useShim!==false){var c=new Ext.Layer({shadow:false,useDisplay:true,constrain:false},d);c.show();return c}else{return new Ext.Element(d)}},doAutoLoad:function(){var a=this.body.getUpdater();if(this.renderer){a.setRenderer(this.renderer)}a.update(Ext.isObject(this.autoLoad)?this.autoLoad:{url:this.autoLoad})},getTool:function(a){return this.tools[a]}});Ext.reg("panel",Ext.Panel);Ext.Editor=function(b,a){if(b.field){this.field=Ext.create(b.field,"textfield");a=Ext.apply({},b);delete a.field}else{this.field=b}Ext.Editor.superclass.constructor.call(this,a)};Ext.extend(Ext.Editor,Ext.Component,{allowBlur:true,value:"",alignment:"c-c?",offsets:[0,0],shadow:"frame",constrain:false,swallowKeys:true,completeOnEnter:true,cancelOnEsc:true,updateEl:false,initComponent:function(){Ext.Editor.superclass.initComponent.call(this);this.addEvents("beforestartedit","startedit","beforecomplete","complete","canceledit","specialkey")},onRender:function(b,a){this.el=new Ext.Layer({shadow:this.shadow,cls:"x-editor",parentEl:b,shim:this.shim,shadowOffset:this.shadowOffset||4,id:this.id,constrain:this.constrain});if(this.zIndex){this.el.setZIndex(this.zIndex)}this.el.setStyle("overflow",Ext.isGecko?"auto":"hidden");if(this.field.msgTarget!="title"){this.field.msgTarget="qtip"}this.field.inEditor=true;this.mon(this.field,{scope:this,blur:this.onBlur,specialkey:this.onSpecialKey});if(this.field.grow){this.mon(this.field,"autosize",this.el.sync,this.el,{delay:1})}this.field.render(this.el).show();this.field.getEl().dom.name="";if(this.swallowKeys){this.field.el.swallowEvent(["keypress","keydown"])}},onSpecialKey:function(g,d){var b=d.getKey(),a=this.completeOnEnter&&b==d.ENTER,c=this.cancelOnEsc&&b==d.ESC;if(a||c){d.stopEvent();if(a){this.completeEdit()}else{this.cancelEdit()}if(g.triggerBlur){g.triggerBlur()}}this.fireEvent("specialkey",g,d)},startEdit:function(b,c){if(this.editing){this.completeEdit()}this.boundEl=Ext.get(b);var a=c!==undefined?c:this.boundEl.dom.innerHTML;if(!this.rendered){this.render(this.parentEl||document.body)}if(this.fireEvent("beforestartedit",this,this.boundEl,a)!==false){this.startValue=a;this.field.reset();this.field.setValue(a);this.realign(true);this.editing=true;this.show()}},doAutoSize:function(){if(this.autoSize){var b=this.boundEl.getSize(),a=this.field.getSize();switch(this.autoSize){case"width":this.setSize(b.width,a.height);break;case"height":this.setSize(a.width,b.height);break;case"none":this.setSize(a.width,a.height);break;default:this.setSize(b.width,b.height)}}},setSize:function(a,b){delete this.field.lastSize;this.field.setSize(a,b);if(this.el){if(Ext.isGecko2||Ext.isOpera||(Ext.isIE7&&Ext.isStrict)){this.el.setSize(a,b)}this.el.sync()}},realign:function(a){if(a===true){this.doAutoSize()}this.el.alignTo(this.boundEl,this.alignment,this.offsets)},completeEdit:function(a){if(!this.editing){return}if(this.field.assertValue){this.field.assertValue()}var b=this.getValue();if(!this.field.isValid()){if(this.revertInvalid!==false){this.cancelEdit(a)}return}if(String(b)===String(this.startValue)&&this.ignoreNoChange){this.hideEdit(a);return}if(this.fireEvent("beforecomplete",this,b,this.startValue)!==false){b=this.getValue();if(this.updateEl&&this.boundEl){this.boundEl.update(b)}this.hideEdit(a);this.fireEvent("complete",this,b,this.startValue)}},onShow:function(){this.el.show();if(this.hideEl!==false){this.boundEl.hide()}this.field.show().focus(false,true);this.fireEvent("startedit",this.boundEl,this.startValue)},cancelEdit:function(a){if(this.editing){var b=this.getValue();this.setValue(this.startValue);this.hideEdit(a);this.fireEvent("canceledit",this,b,this.startValue)}},hideEdit:function(a){if(a!==true){this.editing=false;this.hide()}},onBlur:function(){if(this.allowBlur===true&&this.editing&&this.selectSameEditor!==true){this.completeEdit()}},onHide:function(){if(this.editing){this.completeEdit();return}this.field.blur();if(this.field.collapse){this.field.collapse()}this.el.hide();if(this.hideEl!==false){this.boundEl.show()}},setValue:function(a){this.field.setValue(a)},getValue:function(){return this.field.getValue()},beforeDestroy:function(){Ext.destroyMembers(this,"field");delete this.parentEl;delete this.boundEl}});Ext.reg("editor",Ext.Editor);Ext.ColorPalette=Ext.extend(Ext.Component,{itemCls:"x-color-palette",value:null,clickEvent:"click",ctype:"Ext.ColorPalette",allowReselect:false,colors:["000000","993300","333300","003300","003366","000080","333399","333333","800000","FF6600","808000","008000","008080","0000FF","666699","808080","FF0000","FF9900","99CC00","339966","33CCCC","3366FF","800080","969696","FF00FF","FFCC00","FFFF00","00FF00","00FFFF","00CCFF","993366","C0C0C0","FF99CC","FFCC99","FFFF99","CCFFCC","CCFFFF","99CCFF","CC99FF","FFFFFF"],initComponent:function(){Ext.ColorPalette.superclass.initComponent.call(this);this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope,true)}},onRender:function(b,a){this.autoEl={tag:"div",cls:this.itemCls};Ext.ColorPalette.superclass.onRender.call(this,b,a);var c=this.tpl||new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');c.overwrite(this.el,this.colors);this.mon(this.el,this.clickEvent,this.handleClick,this,{delegate:"a"});if(this.clickEvent!="click"){this.mon(this.el,"click",Ext.emptyFn,this,{delegate:"a",preventDefault:true})}},afterRender:function(){Ext.ColorPalette.superclass.afterRender.call(this);if(this.value){var a=this.value;this.value=null;this.select(a,true)}},handleClick:function(b,a){b.preventDefault();if(!this.disabled){var d=a.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];this.select(d.toUpperCase())}},select:function(b,a){b=b.replace("#","");if(b!=this.value||this.allowReselect){var c=this.el;if(this.value){c.child("a.color-"+this.value).removeClass("x-color-palette-sel")}c.child("a.color-"+b).addClass("x-color-palette-sel");this.value=b;if(a!==true){this.fireEvent("select",this,b)}}}});Ext.reg("colorpalette",Ext.ColorPalette);Ext.DatePicker=Ext.extend(Ext.BoxComponent,{todayText:"Today",okText:"&#160;OK&#160;",cancelText:"Cancel",todayTip:"{0} (Spacebar)",minText:"This date is before the minimum date",maxText:"This date is after the maximum date",format:"m/d/y",disabledDaysText:"Disabled",disabledDatesText:"Disabled",monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:"Next Month (Control+Right)",prevText:"Previous Month (Control+Left)",monthYearText:"Choose a month (Control+Up/Down to move years)",startDay:0,showToday:true,focusOnSelect:true,initHour:12,initComponent:function(){Ext.DatePicker.superclass.initComponent.call(this);this.value=this.value?this.value.clearTime(true):new Date().clearTime();this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope||this)}this.initDisabledDays()},initDisabledDays:function(){if(!this.disabledDatesRE&&this.disabledDates){var b=this.disabledDates,a=b.length-1,c="(?:";Ext.each(b,function(g,e){c+=Ext.isDate(g)?"^"+Ext.escapeRe(g.dateFormat(this.format))+"$":b[e];if(e!=a){c+="|"}},this);this.disabledDatesRE=new RegExp(c+")")}},setDisabledDates:function(a){if(Ext.isArray(a)){this.disabledDates=a;this.disabledDatesRE=null}else{this.disabledDatesRE=a}this.initDisabledDays();this.update(this.value,true)},setDisabledDays:function(a){this.disabledDays=a;this.update(this.value,true)},setMinDate:function(a){this.minDate=a;this.update(this.value,true)},setMaxDate:function(a){this.maxDate=a;this.update(this.value,true)},setValue:function(a){this.value=a.clearTime(true);this.update(this.value)},getValue:function(){return this.value},focus:function(){this.update(this.activeDate)},onEnable:function(a){Ext.DatePicker.superclass.onEnable.call(this);this.doDisabled(false);this.update(a?this.value:this.activeDate);if(Ext.isIE){this.el.repaint()}},onDisable:function(){Ext.DatePicker.superclass.onDisable.call(this);this.doDisabled(true);if(Ext.isIE&&!Ext.isIE8){Ext.each([].concat(this.textNodes,this.el.query("th span")),function(a){Ext.fly(a).repaint()})}},doDisabled:function(a){this.keyNav.setDisabled(a);this.prevRepeater.setDisabled(a);this.nextRepeater.setDisabled(a);if(this.showToday){this.todayKeyListener.setDisabled(a);this.todayBtn.setDisabled(a)}},onRender:function(e,b){var a=['<table cellspacing="0">','<tr><td class="x-date-left"><a href="#" title="',this.prevText,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',this.nextText,'">&#160;</a></td></tr>','<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],c=this.dayNames,h;for(h=0;h<7;h++){var k=this.startDay+h;if(k>6){k=k-7}a.push("<th><span>",c[k].substr(0,1),"</span></th>")}a[a.length]="</tr></thead><tbody><tr>";for(h=0;h<42;h++){if(h%7===0&&h!==0){a[a.length]="</tr><tr>"}a[a.length]='<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>'}a.push("</tr></tbody></table></td></tr>",this.showToday?'<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>':"",'</table><div class="x-date-mp"></div>');var j=document.createElement("div");j.className="x-date-picker";j.innerHTML=a.join("");e.dom.insertBefore(j,b);this.el=Ext.get(j);this.eventEl=Ext.get(j.firstChild);this.prevRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"),{handler:this.showPrevMonth,scope:this,preventDefault:true,stopDefault:true});this.nextRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"),{handler:this.showNextMonth,scope:this,preventDefault:true,stopDefault:true});this.monthPicker=this.el.down("div.x-date-mp");this.monthPicker.enableDisplayMode("block");this.keyNav=new Ext.KeyNav(this.eventEl,{left:function(d){if(d.ctrlKey){this.showPrevMonth()}else{this.update(this.activeDate.add("d",-1))}},right:function(d){if(d.ctrlKey){this.showNextMonth()}else{this.update(this.activeDate.add("d",1))}},up:function(d){if(d.ctrlKey){this.showNextYear()}else{this.update(this.activeDate.add("d",-7))}},down:function(d){if(d.ctrlKey){this.showPrevYear()}else{this.update(this.activeDate.add("d",7))}},pageUp:function(d){this.showNextMonth()},pageDown:function(d){this.showPrevMonth()},enter:function(d){d.stopPropagation();return true},scope:this});this.el.unselectable();this.cells=this.el.select("table.x-date-inner tbody td");this.textNodes=this.el.query("table.x-date-inner tbody span");this.mbtn=new Ext.Button({text:"&#160;",tooltip:this.monthYearText,renderTo:this.el.child("td.x-date-middle",true)});this.mbtn.el.child("em").addClass("x-btn-arrow");if(this.showToday){this.todayKeyListener=this.eventEl.addKeyListener(Ext.EventObject.SPACE,this.selectToday,this);var g=(new Date()).dateFormat(this.format);this.todayBtn=new Ext.Button({renderTo:this.el.child("td.x-date-bottom",true),text:String.format(this.todayText,g),tooltip:String.format(this.todayTip,g),handler:this.selectToday,scope:this})}this.mon(this.eventEl,"mousewheel",this.handleMouseWheel,this);this.mon(this.eventEl,"click",this.handleDateClick,this,{delegate:"a.x-date-date"});this.mon(this.mbtn,"click",this.showMonthPicker,this);this.onEnable(true)},createMonthPicker:function(){if(!this.monthPicker.dom.firstChild){var a=['<table border="0" cellspacing="0">'];for(var b=0;b<6;b++){a.push('<tr><td class="x-date-mp-month"><a href="#">',Date.getShortMonthName(b),"</a></td>",'<td class="x-date-mp-month x-date-mp-sep"><a href="#">',Date.getShortMonthName(b+6),"</a></td>",b===0?'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>':'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>')}a.push('<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',this.okText,'</button><button type="button" class="x-date-mp-cancel">',this.cancelText,"</button></td></tr>","</table>");this.monthPicker.update(a.join(""));this.mon(this.monthPicker,"click",this.onMonthClick,this);this.mon(this.monthPicker,"dblclick",this.onMonthDblClick,this);this.mpMonths=this.monthPicker.select("td.x-date-mp-month");this.mpYears=this.monthPicker.select("td.x-date-mp-year");this.mpMonths.each(function(c,d,e){e+=1;if((e%2)===0){c.dom.xmonth=5+Math.round(e*0.5)}else{c.dom.xmonth=Math.round((e-1)*0.5)}})}},showMonthPicker:function(){if(!this.disabled){this.createMonthPicker();var a=this.el.getSize();this.monthPicker.setSize(a);this.monthPicker.child("table").setSize(a);this.mpSelMonth=(this.activeDate||this.value).getMonth();this.updateMPMonth(this.mpSelMonth);this.mpSelYear=(this.activeDate||this.value).getFullYear();this.updateMPYear(this.mpSelYear);this.monthPicker.slideIn("t",{duration:0.2})}},updateMPYear:function(e){this.mpyear=e;var c=this.mpYears.elements;for(var b=1;b<=10;b++){var d=c[b-1],a;if((b%2)===0){a=e+Math.round(b*0.5);d.firstChild.innerHTML=a;d.xyear=a}else{a=e-(5-Math.round(b*0.5));d.firstChild.innerHTML=a;d.xyear=a}this.mpYears.item(b-1)[a==this.mpSelYear?"addClass":"removeClass"]("x-date-mp-sel")}},updateMPMonth:function(a){this.mpMonths.each(function(b,c,d){b[b.dom.xmonth==a?"addClass":"removeClass"]("x-date-mp-sel")})},selectMPMonth:function(a){},onMonthClick:function(g,b){g.stopEvent();var c=new Ext.Element(b),a;if(c.is("button.x-date-mp-cancel")){this.hideMonthPicker()}else{if(c.is("button.x-date-mp-ok")){var h=new Date(this.mpSelYear,this.mpSelMonth,(this.activeDate||this.value).getDate());if(h.getMonth()!=this.mpSelMonth){h=new Date(this.mpSelYear,this.mpSelMonth,1).getLastDateOfMonth()}this.update(h);this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-month",2))){this.mpMonths.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelMonth=a.dom.xmonth}else{if((a=c.up("td.x-date-mp-year",2))){this.mpYears.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelYear=a.dom.xyear}else{if(c.is("a.x-date-mp-prev")){this.updateMPYear(this.mpyear-10)}else{if(c.is("a.x-date-mp-next")){this.updateMPYear(this.mpyear+10)}}}}}}},onMonthDblClick:function(d,b){d.stopEvent();var c=new Ext.Element(b),a;if((a=c.up("td.x-date-mp-month",2))){this.update(new Date(this.mpSelYear,a.dom.xmonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-year",2))){this.update(new Date(a.dom.xyear,this.mpSelMonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}}},hideMonthPicker:function(a){if(this.monthPicker){if(a===true){this.monthPicker.hide()}else{this.monthPicker.slideOut("t",{duration:0.2})}}},showPrevMonth:function(a){this.update(this.activeDate.add("mo",-1))},showNextMonth:function(a){this.update(this.activeDate.add("mo",1))},showPrevYear:function(){this.update(this.activeDate.add("y",-1))},showNextYear:function(){this.update(this.activeDate.add("y",1))},handleMouseWheel:function(a){a.stopEvent();if(!this.disabled){var b=a.getWheelDelta();if(b>0){this.showPrevMonth()}else{if(b<0){this.showNextMonth()}}}},handleDateClick:function(b,a){b.stopEvent();if(!this.disabled&&a.dateValue&&!Ext.fly(a.parentNode).hasClass("x-date-disabled")){this.cancelFocus=this.focusOnSelect===false;this.setValue(new Date(a.dateValue));delete this.cancelFocus;this.fireEvent("select",this,this.value)}},selectToday:function(){if(this.todayBtn&&!this.todayBtn.disabled){this.setValue(new Date().clearTime());this.fireEvent("select",this,this.value)}},update:function(G,A){if(this.rendered){var a=this.activeDate,p=this.isVisible();this.activeDate=G;if(!A&&a&&this.el){var o=G.getTime();if(a.getMonth()==G.getMonth()&&a.getFullYear()==G.getFullYear()){this.cells.removeClass("x-date-selected");this.cells.each(function(d){if(d.dom.firstChild.dateValue==o){d.addClass("x-date-selected");if(p&&!this.cancelFocus){Ext.fly(d.dom.firstChild).focus(50)}return false}},this);return}}var k=G.getDaysInMonth(),q=G.getFirstDateOfMonth(),g=q.getDay()-this.startDay;if(g<0){g+=7}k+=g;var B=G.add("mo",-1),h=B.getDaysInMonth()-g,e=this.cells.elements,r=this.textNodes,D=(new Date(B.getFullYear(),B.getMonth(),h,this.initHour)),C=new Date().clearTime().getTime(),v=G.clearTime(true).getTime(),u=this.minDate?this.minDate.clearTime(true):Number.NEGATIVE_INFINITY,y=this.maxDate?this.maxDate.clearTime(true):Number.POSITIVE_INFINITY,F=this.disabledDatesRE,s=this.disabledDatesText,I=this.disabledDays?this.disabledDays.join(""):false,E=this.disabledDaysText,z=this.format;if(this.showToday){var m=new Date().clearTime(),c=(m<u||m>y||(F&&z&&F.test(m.dateFormat(z)))||(I&&I.indexOf(m.getDay())!=-1));if(!this.disabled){this.todayBtn.setDisabled(c);this.todayKeyListener[c?"disable":"enable"]()}}var l=function(J,d){d.title="";var i=D.clearTime(true).getTime();d.firstChild.dateValue=i;if(i==C){d.className+=" x-date-today";d.title=J.todayText}if(i==v){d.className+=" x-date-selected";if(p){Ext.fly(d.firstChild).focus(50)}}if(i<u){d.className=" x-date-disabled";d.title=J.minText;return}if(i>y){d.className=" x-date-disabled";d.title=J.maxText;return}if(I){if(I.indexOf(D.getDay())!=-1){d.title=E;d.className=" x-date-disabled"}}if(F&&z){var w=D.dateFormat(z);if(F.test(w)){d.title=s.replace("%0",w);d.className=" x-date-disabled"}}};var x=0;for(;x<g;x++){r[x].innerHTML=(++h);D.setDate(D.getDate()+1);e[x].className="x-date-prevday";l(this,e[x])}for(;x<k;x++){var b=x-g+1;r[x].innerHTML=(b);D.setDate(D.getDate()+1);e[x].className="x-date-active";l(this,e[x])}var H=0;for(;x<42;x++){r[x].innerHTML=(++H);D.setDate(D.getDate()+1);e[x].className="x-date-nextday";l(this,e[x])}this.mbtn.setText(this.monthNames[G.getMonth()]+" "+G.getFullYear());if(!this.internalRender){var j=this.el.dom.firstChild,n=j.offsetWidth;this.el.setWidth(n+this.el.getBorderWidth("lr"));Ext.fly(j).setWidth(n);this.internalRender=true;if(Ext.isOpera&&!this.secondPass){j.rows[0].cells[1].style.width=(n-(j.rows[0].cells[0].offsetWidth+j.rows[0].cells[2].offsetWidth))+"px";this.secondPass=true;this.update.defer(10,this,[G])}}}},beforeDestroy:function(){if(this.rendered){Ext.destroy(this.keyNav,this.monthPicker,this.eventEl,this.mbtn,this.nextRepeater,this.prevRepeater,this.cells.el,this.todayBtn);delete this.textNodes;delete this.cells.elements}}});Ext.reg("datepicker",Ext.DatePicker);Ext.LoadMask=function(c,b){this.el=Ext.get(c);Ext.apply(this,b);if(this.store){this.store.on({scope:this,beforeload:this.onBeforeLoad,load:this.onLoad,exception:this.onLoad});this.removeMask=Ext.value(this.removeMask,false)}else{var a=this.el.getUpdater();a.showLoadIndicator=false;a.on({scope:this,beforeupdate:this.onBeforeLoad,update:this.onLoad,failure:this.onLoad});this.removeMask=Ext.value(this.removeMask,true)}};Ext.LoadMask.prototype={msg:"Loading...",msgCls:"x-mask-loading",disabled:false,disable:function(){this.disabled=true},enable:function(){this.disabled=false},onLoad:function(){this.el.unmask(this.removeMask)},onBeforeLoad:function(){if(!this.disabled){this.el.mask(this.msg,this.msgCls)}},show:function(){this.onBeforeLoad()},hide:function(){this.onLoad()},destroy:function(){if(this.store){this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.onLoad,this)}else{var a=this.el.getUpdater();a.un("beforeupdate",this.onBeforeLoad,this);a.un("update",this.onLoad,this);a.un("failure",this.onLoad,this)}}};Ext.slider.Thumb=Ext.extend(Object,{dragging:false,constructor:function(a){Ext.apply(this,a||{},{cls:"x-slider-thumb",constrain:false});Ext.slider.Thumb.superclass.constructor.call(this,a);if(this.slider.vertical){Ext.apply(this,Ext.slider.Thumb.Vertical)}},render:function(){this.el=this.slider.innerEl.insertFirst({cls:this.cls});this.initEvents()},enable:function(){this.disabled=false;this.el.removeClass(this.slider.disabledClass)},disable:function(){this.disabled=true;this.el.addClass(this.slider.disabledClass)},initEvents:function(){var a=this.el;a.addClassOnOver("x-slider-thumb-over");this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeDragStart.createDelegate(this),onStart:this.onDragStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onDragEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(a)},onBeforeDragStart:function(a){if(this.disabled){return false}else{this.slider.promoteThumb(this);return true}},onDragStart:function(a){this.el.addClass("x-slider-thumb-drag");this.dragging=true;this.dragStartValue=this.value;this.slider.fireEvent("dragstart",this.slider,a,this)},onDrag:function(g){var c=this.slider,b=this.index,d=this.getNewValue();if(this.constrain){var a=c.thumbs[b+1],h=c.thumbs[b-1];if(h!=undefined&&d<=h.value){d=h.value}if(a!=undefined&&d>=a.value){d=a.value}}c.setValue(b,d,false);c.fireEvent("drag",c,g,this)},getNewValue:function(){var a=this.slider,b=a.innerEl.translatePoints(this.tracker.getXY());return Ext.util.Format.round(a.reverseValue(b.left),a.decimalPrecision)},onDragEnd:function(c){var a=this.slider,b=this.value;this.el.removeClass("x-slider-thumb-drag");this.dragging=false;a.fireEvent("dragend",a,c);if(this.dragStartValue!=b){a.fireEvent("changecomplete",a,b,this)}},destroy:function(){Ext.destroyMembers(this,"tracker","el")}});Ext.slider.MultiSlider=Ext.extend(Ext.BoxComponent,{vertical:false,minValue:0,maxValue:100,decimalPrecision:0,keyIncrement:1,increment:0,clickRange:[5,15],clickToChange:true,animate:true,constrainThumbs:true,topThumbZIndex:10000,initComponent:function(){if(!Ext.isDefined(this.value)){this.value=this.minValue}this.thumbs=[];Ext.slider.MultiSlider.superclass.initComponent.call(this);this.keyIncrement=Math.max(this.increment,this.keyIncrement);this.addEvents("beforechange","change","changecomplete","dragstart","drag","dragend");if(this.values==undefined||Ext.isEmpty(this.values)){this.values=[0]}var a=this.values;for(var b=0;b<a.length;b++){this.addThumb(a[b])}if(this.vertical){Ext.apply(this,Ext.slider.Vertical)}},addThumb:function(b){var a=new Ext.slider.Thumb({value:b,slider:this,index:this.thumbs.length,constrain:this.constrainThumbs});this.thumbs.push(a);if(this.rendered){a.render()}},promoteThumb:function(d){var a=this.thumbs,g,b;for(var e=0,c=a.length;e<c;e++){b=a[e];if(b==d){g=this.topThumbZIndex}else{g=""}b.el.setStyle("zIndex",g)}},onRender:function(){this.autoEl={cls:"x-slider "+(this.vertical?"x-slider-vert":"x-slider-horz"),cn:{cls:"x-slider-end",cn:{cls:"x-slider-inner",cn:[{tag:"a",cls:"x-slider-focus",href:"#",tabIndex:"-1",hidefocus:"on"}]}}};Ext.slider.MultiSlider.superclass.onRender.apply(this,arguments);this.endEl=this.el.first();this.innerEl=this.endEl.first();this.focusEl=this.innerEl.child(".x-slider-focus");for(var b=0;b<this.thumbs.length;b++){this.thumbs[b].render()}var a=this.innerEl.child(".x-slider-thumb");this.halfThumb=(this.vertical?a.getHeight():a.getWidth())/2;this.initEvents()},initEvents:function(){this.mon(this.el,{scope:this,mousedown:this.onMouseDown,keydown:this.onKeyDown});this.focusEl.swallowEvent("click",true)},onMouseDown:function(d){if(this.disabled){return}var c=false;for(var b=0;b<this.thumbs.length;b++){c=c||d.target==this.thumbs[b].el.dom}if(this.clickToChange&&!c){var a=this.innerEl.translatePoints(d.getXY());this.onClickChange(a)}this.focus()},onClickChange:function(c){if(c.top>this.clickRange[0]&&c.top<this.clickRange[1]){var a=this.getNearest(c,"left"),b=a.index;this.setValue(b,Ext.util.Format.round(this.reverseValue(c.left),this.decimalPrecision),undefined,true)}},getNearest:function(k,b){var m=b=="top"?this.innerEl.getHeight()-k[b]:k[b],g=this.reverseValue(m),j=(this.maxValue-this.minValue)+5,e=0,c=null;for(var d=0;d<this.thumbs.length;d++){var a=this.thumbs[d],l=a.value,h=Math.abs(l-g);if(Math.abs(h<=j)){c=a;e=d;j=h}}return c},onKeyDown:function(b){if(this.disabled||this.thumbs.length!==1){b.preventDefault();return}var a=b.getKey(),c;switch(a){case b.UP:case b.RIGHT:b.stopEvent();c=b.ctrlKey?this.maxValue:this.getValue(0)+this.keyIncrement;this.setValue(0,c,undefined,true);break;case b.DOWN:case b.LEFT:b.stopEvent();c=b.ctrlKey?this.minValue:this.getValue(0)-this.keyIncrement;this.setValue(0,c,undefined,true);break;default:b.preventDefault()}},doSnap:function(b){if(!(this.increment&&b)){return b}var d=b,c=this.increment,a=b%c;if(a!=0){d-=a;if(a*2>=c){d+=c}else{if(a*2<-c){d-=c}}}return d.constrain(this.minValue,this.maxValue)},afterRender:function(){Ext.slider.MultiSlider.superclass.afterRender.apply(this,arguments);for(var c=0;c<this.thumbs.length;c++){var b=this.thumbs[c];if(b.value!==undefined){var a=this.normalizeValue(b.value);if(a!==b.value){this.setValue(c,a,false)}else{this.moveThumb(c,this.translateValue(a),false)}}}},getRatio:function(){var a=this.innerEl.getWidth(),b=this.maxValue-this.minValue;return b==0?a:(a/b)},normalizeValue:function(a){a=this.doSnap(a);a=Ext.util.Format.round(a,this.decimalPrecision);a=a.constrain(this.minValue,this.maxValue);return a},setMinValue:function(e){this.minValue=e;var d=0,b=this.thumbs,a=b.length,c;for(;d<a;++d){c=b[d];c.value=c.value<e?e:c.value}this.syncThumb()},setMaxValue:function(e){this.maxValue=e;var d=0,b=this.thumbs,a=b.length,c;for(;d<a;++d){c=b[d];c.value=c.value>e?e:c.value}this.syncThumb()},setValue:function(d,c,b,g){var a=this.thumbs[d],e=a.el;c=this.normalizeValue(c);if(c!==a.value&&this.fireEvent("beforechange",this,c,a.value,a)!==false){a.value=c;if(this.rendered){this.moveThumb(d,this.translateValue(c),b!==false);this.fireEvent("change",this,c,a);if(g){this.fireEvent("changecomplete",this,c,a)}}}},translateValue:function(a){var b=this.getRatio();return(a*b)-(this.minValue*b)-this.halfThumb},reverseValue:function(b){var a=this.getRatio();return(b+(this.minValue*a))/a},moveThumb:function(d,c,b){var a=this.thumbs[d].el;if(!b||this.animate===false){a.setLeft(c)}else{a.shift({left:c,stopFx:true,duration:0.35})}},focus:function(){this.focusEl.focus(10)},onResize:function(c,e){var b=this.thumbs,a=b.length,d=0;for(;d<a;++d){b[d].el.stopFx()}if(Ext.isNumber(c)){this.innerEl.setWidth(c-(this.el.getPadding("l")+this.endEl.getPadding("r")))}this.syncThumb();Ext.slider.MultiSlider.superclass.onResize.apply(this,arguments)},onDisable:function(){Ext.slider.MultiSlider.superclass.onDisable.call(this);for(var b=0;b<this.thumbs.length;b++){var a=this.thumbs[b],c=a.el;a.disable();if(Ext.isIE){var d=c.getXY();c.hide();this.innerEl.addClass(this.disabledClass).dom.disabled=true;if(!this.thumbHolder){this.thumbHolder=this.endEl.createChild({cls:"x-slider-thumb "+this.disabledClass})}this.thumbHolder.show().setXY(d)}}},onEnable:function(){Ext.slider.MultiSlider.superclass.onEnable.call(this);for(var b=0;b<this.thumbs.length;b++){var a=this.thumbs[b],c=a.el;a.enable();if(Ext.isIE){this.innerEl.removeClass(this.disabledClass).dom.disabled=false;if(this.thumbHolder){this.thumbHolder.hide()}c.show();this.syncThumb()}}},syncThumb:function(){if(this.rendered){for(var a=0;a<this.thumbs.length;a++){this.moveThumb(a,this.translateValue(this.thumbs[a].value))}}},getValue:function(a){return this.thumbs[a].value},getValues:function(){var a=[];for(var b=0;b<this.thumbs.length;b++){a.push(this.thumbs[b].value)}return a},beforeDestroy:function(){var b=this.thumbs;for(var c=0,a=b.length;c<a;++c){b[c].destroy();b[c]=null}Ext.destroyMembers(this,"endEl","innerEl","focusEl","thumbHolder");Ext.slider.MultiSlider.superclass.beforeDestroy.call(this)}});Ext.reg("multislider",Ext.slider.MultiSlider);Ext.slider.SingleSlider=Ext.extend(Ext.slider.MultiSlider,{constructor:function(a){a=a||{};Ext.applyIf(a,{values:[a.value||0]});Ext.slider.SingleSlider.superclass.constructor.call(this,a)},getValue:function(){return Ext.slider.SingleSlider.superclass.getValue.call(this,0)},setValue:function(d,b){var c=Ext.toArray(arguments),a=c.length;if(a==1||(a<=3&&typeof arguments[1]!="number")){c.unshift(0)}return Ext.slider.SingleSlider.superclass.setValue.apply(this,c)},syncThumb:function(){return Ext.slider.SingleSlider.superclass.syncThumb.apply(this,[0].concat(arguments))},getNearest:function(){return this.thumbs[0]}});Ext.Slider=Ext.slider.SingleSlider;Ext.reg("slider",Ext.slider.SingleSlider);Ext.slider.Vertical={onResize:function(a,b){this.innerEl.setHeight(b-(this.el.getPadding("t")+this.endEl.getPadding("b")));this.syncThumb()},getRatio:function(){var b=this.innerEl.getHeight(),a=this.maxValue-this.minValue;return b/a},moveThumb:function(d,c,b){var a=this.thumbs[d],e=a.el;if(!b||this.animate===false){e.setBottom(c)}else{e.shift({bottom:c,stopFx:true,duration:0.35})}},onClickChange:function(c){if(c.left>this.clickRange[0]&&c.left<this.clickRange[1]){var a=this.getNearest(c,"top"),b=a.index,d=this.minValue+this.reverseValue(this.innerEl.getHeight()-c.top);this.setValue(b,Ext.util.Format.round(d,this.decimalPrecision),undefined,true)}}};Ext.slider.Thumb.Vertical={getNewValue:function(){var b=this.slider,c=b.innerEl,d=c.translatePoints(this.tracker.getXY()),a=c.getHeight()-d.top;return b.minValue+Ext.util.Format.round(a/b.getRatio(),b.decimalPrecision)}};Ext.ProgressBar=Ext.extend(Ext.BoxComponent,{baseCls:"x-progress",animate:false,waitTimer:null,initComponent:function(){Ext.ProgressBar.superclass.initComponent.call(this);this.addEvents("update")},onRender:function(d,a){var c=new Ext.Template('<div class="{cls}-wrap">','<div class="{cls}-inner">','<div class="{cls}-bar">','<div class="{cls}-text">',"<div>&#160;</div>","</div>","</div>",'<div class="{cls}-text {cls}-text-back">',"<div>&#160;</div>","</div>","</div>","</div>");this.el=a?c.insertBefore(a,{cls:this.baseCls},true):c.append(d,{cls:this.baseCls},true);if(this.id){this.el.dom.id=this.id}var b=this.el.dom.firstChild;this.progressBar=Ext.get(b.firstChild);if(this.textEl){this.textEl=Ext.get(this.textEl);delete this.textTopEl}else{this.textTopEl=Ext.get(this.progressBar.dom.firstChild);var e=Ext.get(b.childNodes[1]);this.textTopEl.setStyle("z-index",99).addClass("x-hidden");this.textEl=new Ext.CompositeElement([this.textTopEl.dom.firstChild,e.dom.firstChild]);this.textEl.setWidth(b.offsetWidth)}this.progressBar.setHeight(b.offsetHeight)},afterRender:function(){Ext.ProgressBar.superclass.afterRender.call(this);if(this.value){this.updateProgress(this.value,this.text)}else{this.updateText(this.text)}},updateProgress:function(c,d,b){this.value=c||0;if(d){this.updateText(d)}if(this.rendered&&!this.isDestroyed){var a=Math.floor(c*this.el.dom.firstChild.offsetWidth);this.progressBar.setWidth(a,b===true||(b!==false&&this.animate));if(this.textTopEl){this.textTopEl.removeClass("x-hidden").setWidth(a)}}this.fireEvent("update",this,c,d);return this},wait:function(b){if(!this.waitTimer){var a=this;b=b||{};this.updateText(b.text);this.waitTimer=Ext.TaskMgr.start({run:function(c){var d=b.increment||10;c-=1;this.updateProgress(((((c+d)%d)+1)*(100/d))*0.01,null,b.animate)},interval:b.interval||1000,duration:b.duration,onStop:function(){if(b.fn){b.fn.apply(b.scope||this)}this.reset()},scope:a})}return this},isWaiting:function(){return this.waitTimer!==null},updateText:function(a){this.text=a||"&#160;";if(this.rendered){this.textEl.update(this.text)}return this},syncProgressBar:function(){if(this.value){this.updateProgress(this.value,this.text)}return this},setSize:function(a,c){Ext.ProgressBar.superclass.setSize.call(this,a,c);if(this.textTopEl){var b=this.el.dom.firstChild;this.textEl.setSize(b.offsetWidth,b.offsetHeight)}this.syncProgressBar();return this},reset:function(a){this.updateProgress(0);if(this.textTopEl){this.textTopEl.addClass("x-hidden")}this.clearTimer();if(a===true){this.hide()}return this},clearTimer:function(){if(this.waitTimer){this.waitTimer.onStop=null;Ext.TaskMgr.stop(this.waitTimer);this.waitTimer=null}},onDestroy:function(){this.clearTimer();if(this.rendered){if(this.textEl.isComposite){this.textEl.clear()}Ext.destroyMembers(this,"textEl","progressBar","textTopEl")}Ext.ProgressBar.superclass.onDestroy.call(this)}});Ext.reg("progress",Ext.ProgressBar);(function(){var a=Ext.EventManager;var b=Ext.lib.Dom;Ext.dd.DragDrop=function(e,c,d){if(e){this.init(e,c,d)}};Ext.dd.DragDrop.prototype={id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true},moveOnly:false,unlock:function(){this.locked=false},isTarget:true,padding:null,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,b4StartDrag:function(c,d){},startDrag:function(c,d){},b4Drag:function(c){},onDrag:function(c){},onDragEnter:function(c,d){},b4DragOver:function(c){},onDragOver:function(c,d){},b4DragOut:function(c){},onDragOut:function(c,d){},b4DragDrop:function(c){},onDragDrop:function(c,d){},onInvalidDrop:function(c){},b4EndDrag:function(c){},endDrag:function(c){},b4MouseDown:function(c){},onMouseDown:function(c){},onMouseUp:function(c){},onAvailable:function(){},defaultPadding:{left:0,right:0,top:0,bottom:0},constrainTo:function(j,h,o){if(Ext.isNumber(h)){h={left:h,right:h,top:h,bottom:h}}h=h||this.defaultPadding;var l=Ext.get(this.getEl()).getBox(),d=Ext.get(j),n=d.getScroll(),k,e=d.dom;if(e==document.body){k={x:n.left,y:n.top,width:Ext.lib.Dom.getViewWidth(),height:Ext.lib.Dom.getViewHeight()}}else{var m=d.getXY();k={x:m[0],y:m[1],width:e.clientWidth,height:e.clientHeight}}var i=l.y-k.y,g=l.x-k.x;this.resetConstraints();this.setXConstraint(g-(h.left||0),k.width-g-l.width-(h.right||0),this.xTickSize);this.setYConstraint(i-(h.top||0),k.height-i-l.height-(h.bottom||0),this.yTickSize)},getEl:function(){if(!this._domRef){this._domRef=Ext.getDom(this.id)}return this._domRef},getDragEl:function(){return Ext.getDom(this.dragElId)},init:function(e,c,d){this.initTarget(e,c,d);a.on(this.id,"mousedown",this.handleMouseDown,this)},initTarget:function(e,c,d){this.config=d||{};this.DDM=Ext.dd.DDM;this.groups={};if(typeof e!=="string"){e=Ext.id(e)}this.id=e;this.addToGroup((c)?c:"default");this.handleElId=e;this.setDragElId(e);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();this.handleOnAvailable()},applyConfig:function(){this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false)},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable()},setPadding:function(e,c,g,d){if(!c&&0!==c){this.padding=[e,e,e,e]}else{if(!g&&0!==g){this.padding=[e,c,e,c]}else{this.padding=[e,c,g,d]}}},setInitPosition:function(g,e){var h=this.getEl();if(!this.DDM.verifyEl(h)){return}var d=g||0;var c=e||0;var i=b.getXY(h);this.initPageX=i[0]-d;this.initPageY=i[1]-c;this.lastPageX=i[0];this.lastPageY=i[1];this.setStartPosition(i)},setStartPosition:function(d){var c=d||b.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=c[0];this.startPageY=c[1]},addToGroup:function(c){this.groups[c]=true;this.DDM.regDragDrop(this,c)},removeFromGroup:function(c){if(this.groups[c]){delete this.groups[c]}this.DDM.removeDDFromGroup(this,c)},setDragElId:function(c){this.dragElId=c},setHandleElId:function(c){if(typeof c!=="string"){c=Ext.id(c)}this.handleElId=c;this.DDM.regHandle(this.id,c)},setOuterHandleElId:function(c){if(typeof c!=="string"){c=Ext.id(c)}a.on(c,"mousedown",this.handleMouseDown,this);this.setHandleElId(c);this.hasOuterHandles=true},unreg:function(){a.un(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this)},destroy:function(){this.unreg()},isLocked:function(){return(this.DDM.isLocked()||this.locked)},handleMouseDown:function(g,d){if(this.primaryButtonOnly&&g.button!=0){return}if(this.isLocked()){return}this.DDM.refreshCache(this.groups);var c=new Ext.lib.Point(Ext.lib.Event.getPageX(g),Ext.lib.Event.getPageY(g));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(c,this)){}else{if(this.clickValidator(g)){this.setStartPosition();this.b4MouseDown(g);this.onMouseDown(g);this.DDM.handleMouseDown(g,this);this.DDM.stopEvent(g)}else{}}},clickValidator:function(d){var c=d.getTarget();return(this.isValidHandleChild(c)&&(this.id==this.handleElId||this.DDM.handleWasClicked(c,this.id)))},addInvalidHandleType:function(c){var d=c.toUpperCase();this.invalidHandleTypes[d]=d},addInvalidHandleId:function(c){if(typeof c!=="string"){c=Ext.id(c)}this.invalidHandleIds[c]=c},addInvalidHandleClass:function(c){this.invalidHandleClasses.push(c)},removeInvalidHandleType:function(c){var d=c.toUpperCase();delete this.invalidHandleTypes[d]},removeInvalidHandleId:function(c){if(typeof c!=="string"){c=Ext.id(c)}delete this.invalidHandleIds[c]},removeInvalidHandleClass:function(d){for(var e=0,c=this.invalidHandleClasses.length;e<c;++e){if(this.invalidHandleClasses[e]==d){delete this.invalidHandleClasses[e]}}},isValidHandleChild:function(h){var g=true;var k;try{k=h.nodeName.toUpperCase()}catch(j){k=h.nodeName}g=g&&!this.invalidHandleTypes[k];g=g&&!this.invalidHandleIds[h.id];for(var d=0,c=this.invalidHandleClasses.length;g&&d<c;++d){g=!Ext.fly(h).hasClass(this.invalidHandleClasses[d])}return g},setXTicks:function(g,c){this.xTicks=[];this.xTickSize=c;var e={};for(var d=this.initPageX;d>=this.minX;d=d-c){if(!e[d]){this.xTicks[this.xTicks.length]=d;e[d]=true}}for(d=this.initPageX;d<=this.maxX;d=d+c){if(!e[d]){this.xTicks[this.xTicks.length]=d;e[d]=true}}this.xTicks.sort(this.DDM.numericSort)},setYTicks:function(g,c){this.yTicks=[];this.yTickSize=c;var e={};for(var d=this.initPageY;d>=this.minY;d=d-c){if(!e[d]){this.yTicks[this.yTicks.length]=d;e[d]=true}}for(d=this.initPageY;d<=this.maxY;d=d+c){if(!e[d]){this.yTicks[this.yTicks.length]=d;e[d]=true}}this.yTicks.sort(this.DDM.numericSort)},setXConstraint:function(e,d,c){this.leftConstraint=e;this.rightConstraint=d;this.minX=this.initPageX-e;this.maxX=this.initPageX+d;if(c){this.setXTicks(this.initPageX,c)}this.constrainX=true},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks()},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0},setYConstraint:function(c,e,d){this.topConstraint=c;this.bottomConstraint=e;this.minY=this.initPageY-c;this.maxY=this.initPageY+e;if(d){this.setYTicks(this.initPageY,d)}this.constrainY=true},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var d=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var c=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(d,c)}else{this.setInitPosition()}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize)}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize)}},getTick:function(k,g){if(!g){return k}else{if(g[0]>=k){return g[0]}else{for(var d=0,c=g.length;d<c;++d){var e=d+1;if(g[e]&&g[e]>=k){var j=k-g[d];var h=g[e]-k;return(h>j)?g[d]:g[e]}}return g[g.length-1]}}},toString:function(){return("DragDrop "+this.id)}}})();if(!Ext.dd.DragDropMgr){Ext.dd.DragDropMgr=function(){var a=Ext.EventManager;return{ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,init:function(){this.initialized=true},POINT:0,INTERSECT:1,mode:0,_execOnAll:function(d,c){for(var e in this.ids){for(var b in this.ids[e]){var g=this.ids[e][b];if(!this.isTypeOfDD(g)){continue}g[d].apply(g,c)}}},_onLoad:function(){this.init();a.on(document,"mouseup",this.handleMouseUp,this,true);a.on(document,"mousemove",this.handleMouseMove,this,true);a.on(window,"unload",this._onUnload,this,true);a.on(window,"resize",this._onResize,this,true)},_onResize:function(b){this._execOnAll("resetConstraints",[])},lock:function(){this.locked=true},unlock:function(){this.locked=false},isLocked:function(){return this.locked},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:350,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,regDragDrop:function(c,b){if(!this.initialized){this.init()}if(!this.ids[b]){this.ids[b]={}}this.ids[b][c.id]=c},removeDDFromGroup:function(d,b){if(!this.ids[b]){this.ids[b]={}}var c=this.ids[b];if(c&&c[d.id]){delete c[d.id]}},_remove:function(c){for(var b in c.groups){if(b&&this.ids[b]&&this.ids[b][c.id]){delete this.ids[b][c.id]}}delete this.handleIds[c.id]},regHandle:function(c,b){if(!this.handleIds[c]){this.handleIds[c]={}}this.handleIds[c][b]=b},isDragDrop:function(b){return(this.getDDById(b))?true:false},getRelated:function(h,c){var g=[];for(var e in h.groups){for(var d in this.ids[e]){var b=this.ids[e][d];if(!this.isTypeOfDD(b)){continue}if(!c||b.isTarget){g[g.length]=b}}}return g},isLegalTarget:function(g,e){var c=this.getRelated(g,true);for(var d=0,b=c.length;d<b;++d){if(c[d].id==e.id){return true}}return false},isTypeOfDD:function(b){return(b&&b.__ygDragDrop)},isHandle:function(c,b){return(this.handleIds[c]&&this.handleIds[c][b])},getDDById:function(c){for(var b in this.ids){if(this.ids[b][c]){return this.ids[b][c]}}return null},handleMouseDown:function(d,c){if(Ext.QuickTips){Ext.QuickTips.ddDisable()}if(this.dragCurrent){this.handleMouseUp(d)}this.currentTarget=d.getTarget();this.dragCurrent=c;var b=c.getEl();this.startX=d.getPageX();this.startY=d.getPageY();this.deltaX=this.startX-b.offsetLeft;this.deltaY=this.startY-b.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var e=Ext.dd.DDM;e.startDrag(e.startX,e.startY)},this.clickTimeThresh)},startDrag:function(b,c){clearTimeout(this.clickTimeout);if(this.dragCurrent){this.dragCurrent.b4StartDrag(b,c);this.dragCurrent.startDrag(b,c)}this.dragThreshMet=true},handleMouseUp:function(b){if(Ext.QuickTips){Ext.QuickTips.ddEnable()}if(!this.dragCurrent){return}clearTimeout(this.clickTimeout);if(this.dragThreshMet){this.fireEvents(b,true)}else{}this.stopDrag(b);this.stopEvent(b)},stopEvent:function(b){if(this.stopPropagation){b.stopPropagation()}if(this.preventDefault){b.preventDefault()}},stopDrag:function(b){if(this.dragCurrent){if(this.dragThreshMet){this.dragCurrent.b4EndDrag(b);this.dragCurrent.endDrag(b)}this.dragCurrent.onMouseUp(b)}this.dragCurrent=null;this.dragOvers={}},handleMouseMove:function(d){if(!this.dragCurrent){return true}if(Ext.isIE&&(d.button!==0&&d.button!==1&&d.button!==2)){this.stopEvent(d);return this.handleMouseUp(d)}if(!this.dragThreshMet){var c=Math.abs(this.startX-d.getPageX());var b=Math.abs(this.startY-d.getPageY());if(c>this.clickPixelThresh||b>this.clickPixelThresh){this.startDrag(this.startX,this.startY)}}if(this.dragThreshMet){this.dragCurrent.b4Drag(d);this.dragCurrent.onDrag(d);if(!this.dragCurrent.moveOnly){this.fireEvents(d,false)}}this.stopEvent(d);return true},fireEvents:function(n,o){var q=this.dragCurrent;if(!q||q.isLocked()){return}var r=n.getPoint();var b=[];var g=[];var l=[];var j=[];var d=[];for(var h in this.dragOvers){var c=this.dragOvers[h];if(!this.isTypeOfDD(c)){continue}if(!this.isOverTarget(r,c,this.mode)){g.push(c)}b[h]=true;delete this.dragOvers[h]}for(var p in q.groups){if("string"!=typeof p){continue}for(h in this.ids[p]){var k=this.ids[p][h];if(!this.isTypeOfDD(k)){continue}if(k.isTarget&&!k.isLocked()&&((k!=q)||(q.ignoreSelf===false))){if(this.isOverTarget(r,k,this.mode)){if(o){j.push(k)}else{if(!b[k.id]){d.push(k)}else{l.push(k)}this.dragOvers[k.id]=k}}}}}if(this.mode){if(g.length){q.b4DragOut(n,g);q.onDragOut(n,g)}if(d.length){q.onDragEnter(n,d)}if(l.length){q.b4DragOver(n,l);q.onDragOver(n,l)}if(j.length){q.b4DragDrop(n,j);q.onDragDrop(n,j)}}else{var m=0;for(h=0,m=g.length;h<m;++h){q.b4DragOut(n,g[h].id);q.onDragOut(n,g[h].id)}for(h=0,m=d.length;h<m;++h){q.onDragEnter(n,d[h].id)}for(h=0,m=l.length;h<m;++h){q.b4DragOver(n,l[h].id);q.onDragOver(n,l[h].id)}for(h=0,m=j.length;h<m;++h){q.b4DragDrop(n,j[h].id);q.onDragDrop(n,j[h].id)}}if(o&&!j.length){q.onInvalidDrop(n)}},getBestMatch:function(d){var g=null;var c=d.length;if(c==1){g=d[0]}else{for(var e=0;e<c;++e){var b=d[e];if(b.cursorIsOver){g=b;break}else{if(!g||g.overlap.getArea()<b.overlap.getArea()){g=b}}}}return g},refreshCache:function(c){for(var b in c){if("string"!=typeof b){continue}for(var d in this.ids[b]){var e=this.ids[b][d];if(this.isTypeOfDD(e)){var g=this.getLocation(e);if(g){this.locationCache[e.id]=g}else{delete this.locationCache[e.id]}}}}},verifyEl:function(c){if(c){var b;if(Ext.isIE){try{b=c.offsetParent}catch(d){}}else{b=c.offsetParent}if(b){return true}}return false},getLocation:function(j){if(!this.isTypeOfDD(j)){return null}var h=j.getEl(),o,g,d,q,p,s,c,n,i,m;try{o=Ext.lib.Dom.getXY(h)}catch(k){}if(!o){return null}g=o[0];d=g+h.offsetWidth;q=o[1];p=q+h.offsetHeight;s=q-j.padding[0];c=d+j.padding[1];n=p+j.padding[2];i=g-j.padding[3];m=new Ext.lib.Region(s,c,n,i);h=Ext.get(h.parentNode);while(h&&m){if(h.isScrollable()){m=m.intersect(h.getRegion())}h=h.parent()}return m},isOverTarget:function(k,b,d){var g=this.locationCache[b.id];if(!g||!this.useCache){g=this.getLocation(b);this.locationCache[b.id]=g}if(!g){return false}b.cursorIsOver=g.contains(k);var j=this.dragCurrent;if(!j||!j.getTargetCoord||(!d&&!j.constrainX&&!j.constrainY)){return b.cursorIsOver}b.overlap=null;var h=j.getTargetCoord(k.x,k.y);var c=j.getDragEl();var e=new Ext.lib.Region(h.y,h.x+c.offsetWidth,h.y+c.offsetHeight,h.x);var i=e.intersect(g);if(i){b.overlap=i;return(d)?true:b.cursorIsOver}else{return false}},_onUnload:function(c,b){a.removeListener(document,"mouseup",this.handleMouseUp,this);a.removeListener(document,"mousemove",this.handleMouseMove,this);a.removeListener(window,"resize",this._onResize,this);Ext.dd.DragDropMgr.unregAll()},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null}this._execOnAll("unreg",[]);for(var b in this.elementCache){delete this.elementCache[b]}this.elementCache={};this.ids={}},elementCache:{},getElWrapper:function(c){var b=this.elementCache[c];if(!b||!b.el){b=this.elementCache[c]=new this.ElementWrapper(Ext.getDom(c))}return b},getElement:function(b){return Ext.getDom(b)},getCss:function(c){var b=Ext.getDom(c);return(b)?b.style:null},ElementWrapper:function(b){this.el=b||null;this.id=this.el&&b.id;this.css=this.el&&b.style},getPosX:function(b){return Ext.lib.Dom.getX(b)},getPosY:function(b){return Ext.lib.Dom.getY(b)},swapNode:function(d,b){if(d.swapNode){d.swapNode(b)}else{var e=b.parentNode;var c=b.nextSibling;if(c==d){e.insertBefore(d,b)}else{if(b==d.nextSibling){e.insertBefore(b,d)}else{d.parentNode.replaceChild(b,d);e.insertBefore(d,c)}}}},getScroll:function(){var d,b,e=document.documentElement,c=document.body;if(e&&(e.scrollTop||e.scrollLeft)){d=e.scrollTop;b=e.scrollLeft}else{if(c){d=c.scrollTop;b=c.scrollLeft}else{}}return{top:d,left:b}},getStyle:function(c,b){return Ext.fly(c).getStyle(b)},getScrollTop:function(){return this.getScroll().top},getScrollLeft:function(){return this.getScroll().left},moveToEl:function(b,d){var c=Ext.lib.Dom.getXY(d);Ext.lib.Dom.setXY(b,c)},numericSort:function(d,c){return(d-c)},_timeoutCount:0,_addListeners:function(){var b=Ext.dd.DDM;if(Ext.lib.Event&&document){b._onLoad()}else{if(b._timeoutCount>2000){}else{setTimeout(b._addListeners,10);if(document&&document.body){b._timeoutCount+=1}}}},handleWasClicked:function(b,d){if(this.isHandle(d,b.id)){return true}else{var c=b.parentNode;while(c){if(this.isHandle(d,c.id)){return true}else{c=c.parentNode}}}return false}}}();Ext.dd.DDM=Ext.dd.DragDropMgr;Ext.dd.DDM._addListeners()}Ext.dd.DD=function(c,a,b){if(c){this.init(c,a,b)}};Ext.extend(Ext.dd.DD,Ext.dd.DragDrop,{scroll:true,autoOffset:function(c,b){var a=c-this.startPageX;var d=b-this.startPageY;this.setDelta(a,d)},setDelta:function(b,a){this.deltaX=b;this.deltaY=a},setDragElPos:function(c,b){var a=this.getDragEl();this.alignElWithMouse(a,c,b)},alignElWithMouse:function(c,h,g){var e=this.getTargetCoord(h,g);var b=c.dom?c:Ext.fly(c,"_dd");if(!this.deltaSetXY){var i=[e.x,e.y];b.setXY(i);var d=b.getLeft(true);var a=b.getTop(true);this.deltaSetXY=[d-e.x,a-e.y]}else{b.setLeftTop(e.x+this.deltaSetXY[0],e.y+this.deltaSetXY[1])}this.cachePosition(e.x,e.y);this.autoScroll(e.x,e.y,c.offsetHeight,c.offsetWidth);return e},cachePosition:function(b,a){if(b){this.lastPageX=b;this.lastPageY=a}else{var c=Ext.lib.Dom.getXY(this.getEl());this.lastPageX=c[0];this.lastPageY=c[1]}},autoScroll:function(l,k,e,m){if(this.scroll){var n=Ext.lib.Dom.getViewHeight();var b=Ext.lib.Dom.getViewWidth();var p=this.DDM.getScrollTop();var d=this.DDM.getScrollLeft();var j=e+k;var o=m+l;var i=(n+p-k-this.deltaY);var g=(b+d-l-this.deltaX);var c=40;var a=(document.all)?80:30;if(j>n&&i<c){window.scrollTo(d,p+a)}if(k<p&&p>0&&k-p<c){window.scrollTo(d,p-a)}if(o>b&&g<c){window.scrollTo(d+a,p)}if(l<d&&d>0&&l-d<c){window.scrollTo(d-a,p)}}},getTargetCoord:function(c,b){var a=c-this.deltaX;var d=b-this.deltaY;if(this.constrainX){if(a<this.minX){a=this.minX}if(a>this.maxX){a=this.maxX}}if(this.constrainY){if(d<this.minY){d=this.minY}if(d>this.maxY){d=this.maxY}}a=this.getTick(a,this.xTicks);d=this.getTick(d,this.yTicks);return{x:a,y:d}},applyConfig:function(){Ext.dd.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false)},b4MouseDown:function(a){this.autoOffset(a.getPageX(),a.getPageY())},b4Drag:function(a){this.setDragElPos(a.getPageX(),a.getPageY())},toString:function(){return("DD "+this.id)}});Ext.dd.DDProxy=function(c,a,b){if(c){this.init(c,a,b);this.initFrame()}};Ext.dd.DDProxy.dragElId="ygddfdiv";Ext.extend(Ext.dd.DDProxy,Ext.dd.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var b=this;var a=document.body;if(!a||!a.firstChild){setTimeout(function(){b.createFrame()},50);return}var d=this.getDragEl();if(!d){d=document.createElement("div");d.id=this.dragElId;var c=d.style;c.position="absolute";c.visibility="hidden";c.cursor="move";c.border="2px solid #aaa";c.zIndex=999;a.insertBefore(d,a.firstChild)}},initFrame:function(){this.createFrame()},applyConfig:function(){Ext.dd.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||Ext.dd.DDProxy.dragElId)},showFrame:function(e,d){var c=this.getEl();var a=this.getDragEl();var b=a.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(b.width,10)/2),Math.round(parseInt(b.height,10)/2))}this.setDragElPos(e,d);Ext.fly(a).show()},_resizeProxy:function(){if(this.resizeFrame){var a=this.getEl();Ext.fly(this.getDragEl()).setSize(a.offsetWidth,a.offsetHeight)}},b4MouseDown:function(b){var a=b.getPageX();var c=b.getPageY();this.autoOffset(a,c);this.setDragElPos(a,c)},b4StartDrag:function(a,b){this.showFrame(a,b)},b4EndDrag:function(a){Ext.fly(this.getDragEl()).hide()},endDrag:function(c){var b=this.getEl();var a=this.getDragEl();a.style.visibility="";this.beforeMove();b.style.visibility="hidden";Ext.dd.DDM.moveToEl(b,a);a.style.visibility="hidden";b.style.visibility="";this.afterDrag()},beforeMove:function(){},afterDrag:function(){},toString:function(){return("DDProxy "+this.id)}});Ext.dd.DDTarget=function(c,a,b){if(c){this.initTarget(c,a,b)}};Ext.extend(Ext.dd.DDTarget,Ext.dd.DragDrop,{getDragEl:Ext.emptyFn,isValidHandleChild:Ext.emptyFn,startDrag:Ext.emptyFn,endDrag:Ext.emptyFn,onDrag:Ext.emptyFn,onDragDrop:Ext.emptyFn,onDragEnter:Ext.emptyFn,onDragOut:Ext.emptyFn,onDragOver:Ext.emptyFn,onInvalidDrop:Ext.emptyFn,onMouseDown:Ext.emptyFn,onMouseUp:Ext.emptyFn,setXConstraint:Ext.emptyFn,setYConstraint:Ext.emptyFn,resetConstraints:Ext.emptyFn,clearConstraints:Ext.emptyFn,clearTicks:Ext.emptyFn,setInitPosition:Ext.emptyFn,setDragElId:Ext.emptyFn,setHandleElId:Ext.emptyFn,setOuterHandleElId:Ext.emptyFn,addInvalidHandleClass:Ext.emptyFn,addInvalidHandleId:Ext.emptyFn,addInvalidHandleType:Ext.emptyFn,removeInvalidHandleClass:Ext.emptyFn,removeInvalidHandleId:Ext.emptyFn,removeInvalidHandleType:Ext.emptyFn,toString:function(){return("DDTarget "+this.id)}});Ext.dd.DragTracker=Ext.extend(Ext.util.Observable,{active:false,tolerance:5,autoStart:false,constructor:function(a){Ext.apply(this,a);this.addEvents("mousedown","mouseup","mousemove","dragstart","dragend","drag");this.dragRegion=new Ext.lib.Region(0,0,0,0);if(this.el){this.initEl(this.el)}Ext.dd.DragTracker.superclass.constructor.call(this,a)},initEl:function(a){this.el=Ext.get(a);a.on("mousedown",this.onMouseDown,this,this.delegate?{delegate:this.delegate}:undefined)},destroy:function(){this.el.un("mousedown",this.onMouseDown,this);delete this.el},onMouseDown:function(b,a){if(this.fireEvent("mousedown",this,b)!==false&&this.onBeforeStart(b)!==false){this.startXY=this.lastXY=b.getXY();this.dragTarget=this.delegate?a:this.el.dom;if(this.preventDefault!==false){b.preventDefault()}Ext.getDoc().on({scope:this,mouseup:this.onMouseUp,mousemove:this.onMouseMove,selectstart:this.stopSelect});if(this.autoStart){this.timer=this.triggerStart.defer(this.autoStart===true?1000:this.autoStart,this,[b])}}},onMouseMove:function(d,c){if(this.active&&Ext.isIE&&!d.browserEvent.button){d.preventDefault();this.onMouseUp(d);return}d.preventDefault();var b=d.getXY(),a=this.startXY;this.lastXY=b;if(!this.active){if(Math.abs(a[0]-b[0])>this.tolerance||Math.abs(a[1]-b[1])>this.tolerance){this.triggerStart(d)}else{return}}this.fireEvent("mousemove",this,d);this.onDrag(d);this.fireEvent("drag",this,d)},onMouseUp:function(c){var b=Ext.getDoc(),a=this.active;b.un("mousemove",this.onMouseMove,this);b.un("mouseup",this.onMouseUp,this);b.un("selectstart",this.stopSelect,this);c.preventDefault();this.clearStart();this.active=false;delete this.elRegion;this.fireEvent("mouseup",this,c);if(a){this.onEnd(c);this.fireEvent("dragend",this,c)}},triggerStart:function(a){this.clearStart();this.active=true;this.onStart(a);this.fireEvent("dragstart",this,a)},clearStart:function(){if(this.timer){clearTimeout(this.timer);delete this.timer}},stopSelect:function(a){a.stopEvent();return false},onBeforeStart:function(a){},onStart:function(a){},onDrag:function(a){},onEnd:function(a){},getDragTarget:function(){return this.dragTarget},getDragCt:function(){return this.el},getXY:function(a){return a?this.constrainModes[a].call(this,this.lastXY):this.lastXY},getOffset:function(c){var b=this.getXY(c),a=this.startXY;return[a[0]-b[0],a[1]-b[1]]},constrainModes:{point:function(b){if(!this.elRegion){this.elRegion=this.getDragCt().getRegion()}var a=this.dragRegion;a.left=b[0];a.top=b[1];a.right=b[0];a.bottom=b[1];a.constrainTo(this.elRegion);return[a.left,a.top]}}});Ext.dd.ScrollManager=function(){var c=Ext.dd.DragDropMgr;var e={};var b=null;var i={};var h=function(l){b=null;a()};var j=function(){if(c.dragCurrent){c.refreshCache(c.dragCurrent.groups)}};var d=function(){if(c.dragCurrent){var l=Ext.dd.ScrollManager;var m=i.el.ddScrollConfig?i.el.ddScrollConfig.increment:l.increment;if(!l.animate){if(i.el.scroll(i.dir,m)){j()}}else{i.el.scroll(i.dir,m,true,l.animDuration,j)}}};var a=function(){if(i.id){clearInterval(i.id)}i.id=0;i.el=null;i.dir=""};var g=function(m,l){a();i.el=m;i.dir=l;var o=m.ddScrollConfig?m.ddScrollConfig.ddGroup:undefined,n=(m.ddScrollConfig&&m.ddScrollConfig.frequency)?m.ddScrollConfig.frequency:Ext.dd.ScrollManager.frequency;if(o===undefined||c.dragCurrent.ddGroup==o){i.id=setInterval(d,n)}};var k=function(o,q){if(q||!c.dragCurrent){return}var s=Ext.dd.ScrollManager;if(!b||b!=c.dragCurrent){b=c.dragCurrent;s.refreshCache()}var t=Ext.lib.Event.getXY(o);var u=new Ext.lib.Point(t[0],t[1]);for(var m in e){var n=e[m],l=n._region;var p=n.ddScrollConfig?n.ddScrollConfig:s;if(l&&l.contains(u)&&n.isScrollable()){if(l.bottom-u.y<=p.vthresh){if(i.el!=n){g(n,"down")}return}else{if(l.right-u.x<=p.hthresh){if(i.el!=n){g(n,"left")}return}else{if(u.y-l.top<=p.vthresh){if(i.el!=n){g(n,"up")}return}else{if(u.x-l.left<=p.hthresh){if(i.el!=n){g(n,"right")}return}}}}}}a()};c.fireEvents=c.fireEvents.createSequence(k,c);c.stopDrag=c.stopDrag.createSequence(h,c);return{register:function(n){if(Ext.isArray(n)){for(var m=0,l=n.length;m<l;m++){this.register(n[m])}}else{n=Ext.get(n);e[n.id]=n}},unregister:function(n){if(Ext.isArray(n)){for(var m=0,l=n.length;m<l;m++){this.unregister(n[m])}}else{n=Ext.get(n);delete e[n.id]}},vthresh:25,hthresh:25,increment:100,frequency:500,animate:true,animDuration:0.4,ddGroup:undefined,refreshCache:function(){for(var l in e){if(typeof e[l]=="object"){e[l]._region=e[l].getRegion()}}}}}();Ext.dd.Registry=function(){var d={};var b={};var a=0;var c=function(g,e){if(typeof g=="string"){return g}var h=g.id;if(!h&&e!==false){h="extdd-"+(++a);g.id=h}return h};return{register:function(j,k){k=k||{};if(typeof j=="string"){j=document.getElementById(j)}k.ddel=j;d[c(j)]=k;if(k.isHandle!==false){b[k.ddel.id]=k}if(k.handles){var h=k.handles;for(var g=0,e=h.length;g<e;g++){b[c(h[g])]=k}}},unregister:function(j){var l=c(j,false);var k=d[l];if(k){delete d[l];if(k.handles){var h=k.handles;for(var g=0,e=h.length;g<e;g++){delete b[c(h[g],false)]}}}},getHandle:function(e){if(typeof e!="string"){e=e.id}return b[e]},getHandleFromEvent:function(h){var g=Ext.lib.Event.getTarget(h);return g?b[g.id]:null},getTarget:function(e){if(typeof e!="string"){e=e.id}return d[e]},getTargetFromEvent:function(h){var g=Ext.lib.Event.getTarget(h);return g?d[g.id]||b[g.id]:null}}}();Ext.dd.StatusProxy=function(a){Ext.apply(this,a);this.id=this.id||Ext.id();this.el=new Ext.Layer({dh:{id:this.id,tag:"div",cls:"x-dd-drag-proxy "+this.dropNotAllowed,children:[{tag:"div",cls:"x-dd-drop-icon"},{tag:"div",cls:"x-dd-drag-ghost"}]},shadow:!a||a.shadow!==false});this.ghost=Ext.get(this.el.dom.childNodes[1]);this.dropStatus=this.dropNotAllowed};Ext.dd.StatusProxy.prototype={dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",setStatus:function(a){a=a||this.dropNotAllowed;if(this.dropStatus!=a){this.el.replaceClass(this.dropStatus,a);this.dropStatus=a}},reset:function(a){this.el.dom.className="x-dd-drag-proxy "+this.dropNotAllowed;this.dropStatus=this.dropNotAllowed;if(a){this.ghost.update("")}},update:function(a){if(typeof a=="string"){this.ghost.update(a)}else{this.ghost.update("");a.style.margin="0";this.ghost.dom.appendChild(a)}var b=this.ghost.dom.firstChild;if(b){Ext.fly(b).setStyle("float","none")}},getEl:function(){return this.el},getGhost:function(){return this.ghost},hide:function(a){this.el.hide();if(a){this.reset(true)}},stop:function(){if(this.anim&&this.anim.isAnimated&&this.anim.isAnimated()){this.anim.stop()}},show:function(){this.el.show()},sync:function(){this.el.sync()},repair:function(b,c,a){this.callback=c;this.scope=a;if(b&&this.animRepair!==false){this.el.addClass("x-dd-drag-repair");this.el.hideUnders(true);this.anim=this.el.shift({duration:this.repairDuration||0.5,easing:"easeOut",xy:b,stopFx:true,callback:this.afterRepair,scope:this})}else{this.afterRepair()}},afterRepair:function(){this.hide(true);if(typeof this.callback=="function"){this.callback.call(this.scope||this)}this.callback=null;this.scope=null},destroy:function(){Ext.destroy(this.ghost,this.el)}};Ext.dd.DragSource=function(b,a){this.el=Ext.get(b);if(!this.dragData){this.dragData={}}Ext.apply(this,a);if(!this.proxy){this.proxy=new Ext.dd.StatusProxy()}Ext.dd.DragSource.superclass.constructor.call(this,this.el.dom,this.ddGroup||this.group,{dragElId:this.proxy.id,resizeFrame:false,isTarget:false,scroll:this.scroll===true});this.dragging=false};Ext.extend(Ext.dd.DragSource,Ext.dd.DDProxy,{dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",getDragData:function(a){return this.dragData},onDragEnter:function(c,d){var b=Ext.dd.DragDropMgr.getDDById(d);this.cachedTarget=b;if(this.beforeDragEnter(b,c,d)!==false){if(b.isNotifyTarget){var a=b.notifyEnter(this,c,this.dragData);this.proxy.setStatus(a)}else{this.proxy.setStatus(this.dropAllowed)}if(this.afterDragEnter){this.afterDragEnter(b,c,d)}}},beforeDragEnter:function(b,a,c){return true},alignElWithMouse:function(){Ext.dd.DragSource.superclass.alignElWithMouse.apply(this,arguments);this.proxy.sync()},onDragOver:function(c,d){var b=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(d);if(this.beforeDragOver(b,c,d)!==false){if(b.isNotifyTarget){var a=b.notifyOver(this,c,this.dragData);this.proxy.setStatus(a)}if(this.afterDragOver){this.afterDragOver(b,c,d)}}},beforeDragOver:function(b,a,c){return true},onDragOut:function(b,c){var a=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(c);if(this.beforeDragOut(a,b,c)!==false){if(a.isNotifyTarget){a.notifyOut(this,b,this.dragData)}this.proxy.reset();if(this.afterDragOut){this.afterDragOut(a,b,c)}}this.cachedTarget=null},beforeDragOut:function(b,a,c){return true},onDragDrop:function(b,c){var a=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(c);if(this.beforeDragDrop(a,b,c)!==false){if(a.isNotifyTarget){if(a.notifyDrop(this,b,this.dragData)){this.onValidDrop(a,b,c)}else{this.onInvalidDrop(a,b,c)}}else{this.onValidDrop(a,b,c)}if(this.afterDragDrop){this.afterDragDrop(a,b,c)}}delete this.cachedTarget},beforeDragDrop:function(b,a,c){return true},onValidDrop:function(b,a,c){this.hideProxy();if(this.afterValidDrop){this.afterValidDrop(b,a,c)}},getRepairXY:function(b,a){return this.el.getXY()},onInvalidDrop:function(b,a,c){this.beforeInvalidDrop(b,a,c);if(this.cachedTarget){if(this.cachedTarget.isNotifyTarget){this.cachedTarget.notifyOut(this,a,this.dragData)}this.cacheTarget=null}this.proxy.repair(this.getRepairXY(a,this.dragData),this.afterRepair,this);if(this.afterInvalidDrop){this.afterInvalidDrop(a,c)}},afterRepair:function(){if(Ext.enableFx){this.el.highlight(this.hlColor||"c3daf9")}this.dragging=false},beforeInvalidDrop:function(b,a,c){return true},handleMouseDown:function(b){if(this.dragging){return}var a=this.getDragData(b);if(a&&this.onBeforeDrag(a,b)!==false){this.dragData=a;this.proxy.stop();Ext.dd.DragSource.superclass.handleMouseDown.apply(this,arguments)}},onBeforeDrag:function(a,b){return true},onStartDrag:Ext.emptyFn,startDrag:function(a,b){this.proxy.reset();this.dragging=true;this.proxy.update("");this.onInitDrag(a,b);this.proxy.show()},onInitDrag:function(a,c){var b=this.el.dom.cloneNode(true);b.id=Ext.id();this.proxy.update(b);this.onStartDrag(a,c);return true},getProxy:function(){return this.proxy},hideProxy:function(){this.proxy.hide();this.proxy.reset(true);this.dragging=false},triggerCacheRefresh:function(){Ext.dd.DDM.refreshCache(this.groups)},b4EndDrag:function(a){},endDrag:function(a){this.onEndDrag(this.dragData,a)},onEndDrag:function(a,b){},autoOffset:function(a,b){this.setDelta(-12,-20)},destroy:function(){Ext.dd.DragSource.superclass.destroy.call(this);Ext.destroy(this.proxy)}});Ext.dd.DropTarget=Ext.extend(Ext.dd.DDTarget,{constructor:function(b,a){this.el=Ext.get(b);Ext.apply(this,a);if(this.containerScroll){Ext.dd.ScrollManager.register(this.el)}Ext.dd.DropTarget.superclass.constructor.call(this,this.el.dom,this.ddGroup||this.group,{isTarget:true})},dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",isTarget:true,isNotifyTarget:true,notifyEnter:function(a,c,b){if(this.overClass){this.el.addClass(this.overClass)}return this.dropAllowed},notifyOver:function(a,c,b){return this.dropAllowed},notifyOut:function(a,c,b){if(this.overClass){this.el.removeClass(this.overClass)}},notifyDrop:function(a,c,b){return false},destroy:function(){Ext.dd.DropTarget.superclass.destroy.call(this);if(this.containerScroll){Ext.dd.ScrollManager.unregister(this.el)}}});Ext.dd.DragZone=Ext.extend(Ext.dd.DragSource,{constructor:function(b,a){Ext.dd.DragZone.superclass.constructor.call(this,b,a);if(this.containerScroll){Ext.dd.ScrollManager.register(this.el)}},getDragData:function(a){return Ext.dd.Registry.getHandleFromEvent(a)},onInitDrag:function(a,b){this.proxy.update(this.dragData.ddel.cloneNode(true));this.onStartDrag(a,b);return true},afterRepair:function(){if(Ext.enableFx){Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor||"c3daf9")}this.dragging=false},getRepairXY:function(a){return Ext.Element.fly(this.dragData.ddel).getXY()},destroy:function(){Ext.dd.DragZone.superclass.destroy.call(this);if(this.containerScroll){Ext.dd.ScrollManager.unregister(this.el)}}});Ext.dd.DropZone=function(b,a){Ext.dd.DropZone.superclass.constructor.call(this,b,a)};Ext.extend(Ext.dd.DropZone,Ext.dd.DropTarget,{getTargetFromEvent:function(a){return Ext.dd.Registry.getTargetFromEvent(a)},onNodeEnter:function(d,a,c,b){},onNodeOver:function(d,a,c,b){return this.dropAllowed},onNodeOut:function(d,a,c,b){},onNodeDrop:function(d,a,c,b){return false},onContainerOver:function(a,c,b){return this.dropNotAllowed},onContainerDrop:function(a,c,b){return false},notifyEnter:function(a,c,b){return this.dropNotAllowed},notifyOver:function(a,c,b){var d=this.getTargetFromEvent(c);if(!d){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,a,c,b);this.lastOverNode=null}return this.onContainerOver(a,c,b)}if(this.lastOverNode!=d){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,a,c,b)}this.onNodeEnter(d,a,c,b);this.lastOverNode=d}return this.onNodeOver(d,a,c,b)},notifyOut:function(a,c,b){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,a,c,b);this.lastOverNode=null}},notifyDrop:function(a,c,b){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,a,c,b);this.lastOverNode=null}var d=this.getTargetFromEvent(c);return d?this.onNodeDrop(d,a,c,b):this.onContainerDrop(a,c,b)},triggerCacheRefresh:function(){Ext.dd.DDM.refreshCache(this.groups)}});Ext.Element.addMethods({initDD:function(c,b,d){var a=new Ext.dd.DD(Ext.id(this.dom),c,b);return Ext.apply(a,d)},initDDProxy:function(c,b,d){var a=new Ext.dd.DDProxy(Ext.id(this.dom),c,b);return Ext.apply(a,d)},initDDTarget:function(c,b,d){var a=new Ext.dd.DDTarget(Ext.id(this.dom),c,b);return Ext.apply(a,d)}});Ext.data.Api=(function(){var a={};return{actions:{create:"create",read:"read",update:"update",destroy:"destroy"},restActions:{create:"POST",read:"GET",update:"PUT",destroy:"DELETE"},isAction:function(b){return(Ext.data.Api.actions[b])?true:false},getVerb:function(b){if(a[b]){return a[b]}for(var c in this.actions){if(this.actions[c]===b){a[b]=c;break}}return(a[b]!==undefined)?a[b]:null},isValid:function(b){var e=[];var d=this.actions;for(var c in b){if(!(c in d)){e.push(c)}}return(!e.length)?true:e},hasUniqueUrl:function(c,g){var b=(c.api[g])?c.api[g].url:null;var e=true;for(var d in c.api){if((e=(d===g)?true:(c.api[d].url!=b)?true:false)===false){break}}return e},prepare:function(b){if(!b.api){b.api={}}for(var d in this.actions){var c=this.actions[d];b.api[c]=b.api[c]||b.url||b.directFn;if(typeof(b.api[c])=="string"){b.api[c]={url:b.api[c],method:(b.restful===true)?Ext.data.Api.restActions[c]:undefined}}}},restify:function(b){b.restful=true;for(var c in this.restActions){b.api[this.actions[c]].method||(b.api[this.actions[c]].method=this.restActions[c])}b.onWrite=b.onWrite.createInterceptor(function(i,j,g,e){var d=j.reader;var h=new Ext.data.Response({action:i,raw:g});switch(g.status){case 200:return true;break;case 201:if(Ext.isEmpty(h.raw.responseText)){h.success=true}else{return true}break;case 204:h.success=true;h.data=null;break;default:return true;break}if(h.success===true){this.fireEvent("write",this,i,h.data,h,e,j.request.arg)}else{this.fireEvent("exception",this,"remote",i,j,h,e)}j.request.callback.call(j.request.scope,h.data,h,h.success);return false},b)}}})();Ext.data.Response=function(b,a){Ext.apply(this,b,{raw:a})};Ext.data.Response.prototype={message:null,success:false,status:null,root:null,raw:null,getMessage:function(){return this.message},getSuccess:function(){return this.success},getStatus:function(){return this.status},getRoot:function(){return this.root},getRawResponse:function(){return this.raw}};Ext.data.Api.Error=Ext.extend(Ext.Error,{constructor:function(b,a){this.arg=a;Ext.Error.call(this,b)},name:"Ext.data.Api"});Ext.apply(Ext.data.Api.Error.prototype,{lang:{"action-url-undefined":"No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.",invalid:"received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions","invalid-url":"Invalid url.  Please review your proxy configuration.",execute:'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'}});Ext.data.SortTypes={none:function(a){return a},stripTagsRE:/<\/?[^>]+>/gi,asText:function(a){return String(a).replace(this.stripTagsRE,"")},asUCText:function(a){return String(a).toUpperCase().replace(this.stripTagsRE,"")},asUCString:function(a){return String(a).toUpperCase()},asDate:function(a){if(!a){return 0}if(Ext.isDate(a)){return a.getTime()}return Date.parse(String(a))},asFloat:function(a){var b=parseFloat(String(a).replace(/,/g,""));return isNaN(b)?0:b},asInt:function(a){var b=parseInt(String(a).replace(/,/g,""),10);return isNaN(b)?0:b}};Ext.data.Record=function(a,b){this.id=(b||b===0)?b:Ext.data.Record.id(this);this.data=a||{}};Ext.data.Record.create=function(e){var c=Ext.extend(Ext.data.Record,{});var d=c.prototype;d.fields=new Ext.util.MixedCollection(false,function(g){return g.name});for(var b=0,a=e.length;b<a;b++){d.fields.add(new Ext.data.Field(e[b]))}c.getField=function(g){return d.fields.get(g)};return c};Ext.data.Record.PREFIX="ext-record";Ext.data.Record.AUTO_ID=1;Ext.data.Record.EDIT="edit";Ext.data.Record.REJECT="reject";Ext.data.Record.COMMIT="commit";Ext.data.Record.id=function(a){a.phantom=true;return[Ext.data.Record.PREFIX,"-",Ext.data.Record.AUTO_ID++].join("")};Ext.data.Record.prototype={dirty:false,editing:false,error:null,modified:null,phantom:false,join:function(a){this.store=a},set:function(a,c){var b=Ext.isPrimitive(c)?String:Ext.encode;if(b(this.data[a])==b(c)){return}this.dirty=true;if(!this.modified){this.modified={}}if(this.modified[a]===undefined){this.modified[a]=this.data[a]}this.data[a]=c;if(!this.editing){this.afterEdit()}},afterEdit:function(){if(this.store!=undefined&&typeof this.store.afterEdit=="function"){this.store.afterEdit(this)}},afterReject:function(){if(this.store){this.store.afterReject(this)}},afterCommit:function(){if(this.store){this.store.afterCommit(this)}},get:function(a){return this.data[a]},beginEdit:function(){this.editing=true;this.modified=this.modified||{}},cancelEdit:function(){this.editing=false;delete this.modified},endEdit:function(){this.editing=false;if(this.dirty){this.afterEdit()}},reject:function(b){var a=this.modified;for(var c in a){if(typeof a[c]!="function"){this.data[c]=a[c]}}this.dirty=false;delete this.modified;this.editing=false;if(b!==true){this.afterReject()}},commit:function(a){this.dirty=false;delete this.modified;this.editing=false;if(a!==true){this.afterCommit()}},getChanges:function(){var a=this.modified,b={};for(var c in a){if(a.hasOwnProperty(c)){b[c]=this.data[c]}}return b},hasError:function(){return this.error!==null},clearError:function(){this.error=null},copy:function(a){return new this.constructor(Ext.apply({},this.data),a||this.id)},isModified:function(a){return !!(this.modified&&this.modified.hasOwnProperty(a))},isValid:function(){return this.fields.find(function(a){return(a.allowBlank===false&&Ext.isEmpty(this.data[a.name]))?true:false},this)?false:true},markDirty:function(){this.dirty=true;if(!this.modified){this.modified={}}this.fields.each(function(a){this.modified[a.name]=this.data[a.name]},this)}};Ext.StoreMgr=Ext.apply(new Ext.util.MixedCollection(),{register:function(){for(var a=0,b;(b=arguments[a]);a++){this.add(b)}},unregister:function(){for(var a=0,b;(b=arguments[a]);a++){this.remove(this.lookup(b))}},lookup:function(e){if(Ext.isArray(e)){var b=["field1"],d=!Ext.isArray(e[0]);if(!d){for(var c=2,a=e[0].length;c<=a;++c){b.push("field"+c)}}return new Ext.data.ArrayStore({fields:b,data:e,expandData:d,autoDestroy:true,autoCreated:true})}return Ext.isObject(e)?(e.events?e:Ext.create(e,"store")):this.get(e)},getKey:function(a){return a.storeId}});Ext.data.Store=Ext.extend(Ext.util.Observable,{writer:undefined,remoteSort:false,autoDestroy:false,pruneModifiedRecords:false,lastOptions:null,autoSave:true,batch:true,restful:false,paramNames:undefined,defaultParamNames:{start:"start",limit:"limit",sort:"sort",dir:"dir"},isDestroyed:false,hasMultiSort:false,batchKey:"_ext_batch_",constructor:function(a){this.data=new Ext.util.MixedCollection(false);this.data.getKey=function(b){return b.id};this.removed=[];if(a&&a.data){this.inlineData=a.data;delete a.data}Ext.apply(this,a);this.baseParams=Ext.isObject(this.baseParams)?this.baseParams:{};this.paramNames=Ext.applyIf(this.paramNames||{},this.defaultParamNames);if((this.url||this.api)&&!this.proxy){this.proxy=new Ext.data.HttpProxy({url:this.url,api:this.api})}if(this.restful===true&&this.proxy){this.batch=false;Ext.data.Api.restify(this.proxy)}if(this.reader){if(!this.recordType){this.recordType=this.reader.recordType}if(this.reader.onMetaChange){this.reader.onMetaChange=this.reader.onMetaChange.createSequence(this.onMetaChange,this)}if(this.writer){if(this.writer instanceof (Ext.data.DataWriter)===false){this.writer=this.buildWriter(this.writer)}this.writer.meta=this.reader.meta;this.pruneModifiedRecords=true}}if(this.recordType){this.fields=this.recordType.prototype.fields}this.modified=[];this.addEvents("datachanged","metachange","add","remove","update","clear","exception","beforeload","load","loadexception","beforewrite","write","beforesave","save");if(this.proxy){this.relayEvents(this.proxy,["loadexception","exception"])}if(this.writer){this.on({scope:this,add:this.createRecords,remove:this.destroyRecord,update:this.updateRecord,clear:this.onClear})}this.sortToggle={};if(this.sortField){this.setDefaultSort(this.sortField,this.sortDir)}else{if(this.sortInfo){this.setDefaultSort(this.sortInfo.field,this.sortInfo.direction)}}Ext.data.Store.superclass.constructor.call(this);if(this.id){this.storeId=this.id;delete this.id}if(this.storeId){Ext.StoreMgr.register(this)}if(this.inlineData){this.loadData(this.inlineData);delete this.inlineData}else{if(this.autoLoad){this.load.defer(10,this,[typeof this.autoLoad=="object"?this.autoLoad:undefined])}}this.batchCounter=0;this.batches={}},buildWriter:function(b){var a=undefined,c=(b.format||"json").toLowerCase();switch(c){case"json":a=Ext.data.JsonWriter;break;case"xml":a=Ext.data.XmlWriter;break;default:a=Ext.data.JsonWriter}return new a(b)},destroy:function(){if(!this.isDestroyed){if(this.storeId){Ext.StoreMgr.unregister(this)}this.clearData();this.data=null;Ext.destroy(this.proxy);this.reader=this.writer=null;this.purgeListeners();this.isDestroyed=true}},add:function(c){var e,a,b,d;c=[].concat(c);if(c.length<1){return}for(e=0,a=c.length;e<a;e++){b=c[e];b.join(this);if(b.dirty||b.phantom){this.modified.push(b)}}d=this.data.length;this.data.addAll(c);if(this.snapshot){this.snapshot.addAll(c)}this.fireEvent("add",this,c,d)},addSorted:function(a){var b=this.findInsertIndex(a);this.insert(b,a)},doUpdate:function(a){var b=a.id;this.getById(b).join(null);this.data.replace(b,a);if(this.snapshot){this.snapshot.replace(b,a)}a.join(this);this.fireEvent("update",this,a,Ext.data.Record.COMMIT)},remove:function(a){if(Ext.isArray(a)){Ext.each(a,function(c){this.remove(c)},this);return}var b=this.data.indexOf(a);if(b>-1){a.join(null);this.data.removeAt(b)}if(this.pruneModifiedRecords){this.modified.remove(a)}if(this.snapshot){this.snapshot.remove(a)}if(b>-1){this.fireEvent("remove",this,a,b)}},removeAt:function(a){this.remove(this.getAt(a))},removeAll:function(b){var a=[];this.each(function(c){a.push(c)});this.clearData();if(this.snapshot){this.snapshot.clear()}if(this.pruneModifiedRecords){this.modified=[]}if(b!==true){this.fireEvent("clear",this,a)}},onClear:function(b,a){Ext.each(a,function(d,c){this.destroyRecord(this,d,c)},this)},insert:function(d,c){var e,a,b;c=[].concat(c);for(e=0,a=c.length;e<a;e++){b=c[e];this.data.insert(d+e,b);b.join(this);if(b.dirty||b.phantom){this.modified.push(b)}}if(this.snapshot){this.snapshot.addAll(c)}this.fireEvent("add",this,c,d)},indexOf:function(a){return this.data.indexOf(a)},indexOfId:function(a){return this.data.indexOfKey(a)},getById:function(a){return(this.snapshot||this.data).key(a)},getAt:function(a){return this.data.itemAt(a)},getRange:function(b,a){return this.data.getRange(b,a)},storeOptions:function(a){a=Ext.apply({},a);delete a.callback;delete a.scope;this.lastOptions=a},clearData:function(){this.data.each(function(a){a.join(null)});this.data.clear()},load:function(b){b=Ext.apply({},b);this.storeOptions(b);if(this.sortInfo&&this.remoteSort){var a=this.paramNames;b.params=Ext.apply({},b.params);b.params[a.sort]=this.sortInfo.field;b.params[a.dir]=this.sortInfo.direction}try{return this.execute("read",null,b)}catch(c){this.handleException(c);return false}},updateRecord:function(b,a,c){if(c==Ext.data.Record.EDIT&&this.autoSave===true&&(!a.phantom||(a.phantom&&a.isValid()))){this.save()}},createRecords:function(c,b,e){var d=this.modified,h=b.length,a,g;for(g=0;g<h;g++){a=b[g];if(a.phantom&&a.isValid()){a.markDirty();if(d.indexOf(a)==-1){d.push(a)}}}if(this.autoSave===true){this.save()}},destroyRecord:function(b,a,c){if(this.modified.indexOf(a)!=-1){this.modified.remove(a)}if(!a.phantom){this.removed.push(a);a.lastIndex=c;if(this.autoSave===true){this.save()}}},execute:function(e,a,c,b){if(!Ext.data.Api.isAction(e)){throw new Ext.data.Api.Error("execute",e)}c=Ext.applyIf(c||{},{params:{}});if(b!==undefined){this.addToBatch(b)}var d=true;if(e==="read"){d=this.fireEvent("beforeload",this,c);Ext.applyIf(c.params,this.baseParams)}else{if(this.writer.listful===true&&this.restful!==true){a=(Ext.isArray(a))?a:[a]}else{if(Ext.isArray(a)&&a.length==1){a=a.shift()}}if((d=this.fireEvent("beforewrite",this,e,a,c))!==false){this.writer.apply(c.params,this.baseParams,e,a)}}if(d!==false){if(this.writer&&this.proxy.url&&!this.proxy.restful&&!Ext.data.Api.hasUniqueUrl(this.proxy,e)){c.params.xaction=e}this.proxy.request(Ext.data.Api.actions[e],a,c.params,this.reader,this.createCallback(e,a,b),this,c)}return d},save:function(){if(!this.writer){throw new Ext.data.Store.Error("writer-undefined")}var h=[],j,k,e,c={},d;if(this.removed.length){h.push(["destroy",this.removed])}var b=[].concat(this.getModifiedRecords());if(b.length){var g=[];for(d=b.length-1;d>=0;d--){if(b[d].phantom===true){var a=b.splice(d,1).shift();if(a.isValid()){g.push(a)}}else{if(!b[d].isValid()){b.splice(d,1)}}}if(g.length){h.push(["create",g])}if(b.length){h.push(["update",b])}}j=h.length;if(j){e=++this.batchCounter;for(d=0;d<j;++d){k=h[d];c[k[0]]=k[1]}if(this.fireEvent("beforesave",this,c)!==false){for(d=0;d<j;++d){k=h[d];this.doTransaction(k[0],k[1],e)}return e}}return -1},doTransaction:function(e,b,c){function g(h){try{this.execute(e,h,undefined,c)}catch(i){this.handleException(i)}}if(this.batch===false){for(var d=0,a=b.length;d<a;d++){g.call(this,b[d])}}else{g.call(this,b)}},addToBatch:function(c){var a=this.batches,d=this.batchKey+c,e=a[d];if(!e){a[d]=e={id:c,count:0,data:{}}}++e.count},removeFromBatch:function(d,h,g){var c=this.batches,e=this.batchKey+d,i=c[e],a;if(i){a=i.data[h]||[];i.data[h]=a.concat(g);if(i.count===1){g=i.data;delete c[e];this.fireEvent("save",this,d,g)}else{--i.count}}},createCallback:function(c,a,b){var d=Ext.data.Api.actions;return(c=="read")?this.loadRecords:function(g,e,h){this["on"+Ext.util.Format.capitalize(c)+"Records"](h,a,[].concat(g));if(h===true){this.fireEvent("write",this,c,g,e,a)}this.removeFromBatch(b,c,g)}},clearModified:function(a){if(Ext.isArray(a)){for(var b=a.length-1;b>=0;b--){this.modified.splice(this.modified.indexOf(a[b]),1)}}else{this.modified.splice(this.modified.indexOf(a),1)}},reMap:function(b){if(Ext.isArray(b)){for(var d=0,a=b.length;d<a;d++){this.reMap(b[d])}}else{delete this.data.map[b._phid];this.data.map[b.id]=b;var c=this.data.keys.indexOf(b._phid);this.data.keys.splice(c,1,b.id);delete b._phid}},onCreateRecords:function(d,a,b){if(d===true){try{this.reader.realize(a,b)}catch(c){this.handleException(c);if(Ext.isArray(a)){this.onCreateRecords(d,a,b)}}}},onUpdateRecords:function(d,a,b){if(d===true){try{this.reader.update(a,b)}catch(c){this.handleException(c);if(Ext.isArray(a)){this.onUpdateRecords(d,a,b)}}}},onDestroyRecords:function(e,b,d){b=(b instanceof Ext.data.Record)?[b]:[].concat(b);for(var c=0,a=b.length;c<a;c++){this.removed.splice(this.removed.indexOf(b[c]),1)}if(e===false){for(c=b.length-1;c>=0;c--){this.insert(b[c].lastIndex,b[c])}}},handleException:function(a){Ext.handleError(a)},reload:function(a){this.load(Ext.applyIf(a||{},this.lastOptions))},loadRecords:function(b,l,h){var e,g;if(this.isDestroyed===true){return}if(!b||h===false){if(h!==false){this.fireEvent("load",this,[],l)}if(l.callback){l.callback.call(l.scope||this,[],l,false,b)}return}var a=b.records,j=b.totalRecords||a.length;if(!l||l.add!==true){if(this.pruneModifiedRecords){this.modified=[]}for(e=0,g=a.length;e<g;e++){a[e].join(this)}if(this.snapshot){this.data=this.snapshot;delete this.snapshot}this.clearData();this.data.addAll(a);this.totalLength=j;this.applySort();this.fireEvent("datachanged",this)}else{var k=[],d,c=0;for(e=0,g=a.length;e<g;++e){d=a[e];if(this.indexOfId(d.id)>-1){this.doUpdate(d)}else{k.push(d);++c}}this.totalLength=Math.max(j,this.data.length+c);this.add(k)}this.fireEvent("load",this,a,l);if(l.callback){l.callback.call(l.scope||this,a,l,true)}},loadData:function(c,a){var b=this.reader.readRecords(c);this.loadRecords(b,{add:a},true)},getCount:function(){return this.data.length||0},getTotalCount:function(){return this.totalLength||0},getSortState:function(){return this.sortInfo},applySort:function(){if((this.sortInfo||this.multiSortInfo)&&!this.remoteSort){this.sortData()}},sortData:function(){var a=this.hasMultiSort?this.multiSortInfo:this.sortInfo,k=a.direction||"ASC",h=a.sorters,c=[];if(!this.hasMultiSort){h=[{direction:k,field:a.field}]}for(var d=0,b=h.length;d<b;d++){c.push(this.createSortFunction(h[d].field,h[d].direction))}if(c.length==0){return}var g=k.toUpperCase()=="DESC"?-1:1;var e=function(n,m){var l=c[0].call(this,n,m);if(c.length>1){for(var p=1,o=c.length;p<o;p++){l=l||c[p].call(this,n,m)}}return g*l};this.data.sort(k,e);if(this.snapshot&&this.snapshot!=this.data){this.snapshot.sort(k,e)}},createSortFunction:function(c,b){b=b||"ASC";var a=b.toUpperCase()=="DESC"?-1:1;var d=this.fields.get(c).sortType;return function(g,e){var i=d(g.data[c]),h=d(e.data[c]);return a*(i>h?1:(i<h?-1:0))}},setDefaultSort:function(b,a){a=a?a.toUpperCase():"ASC";this.sortInfo={field:b,direction:a};this.sortToggle[b]=a},sort:function(b,a){if(Ext.isArray(arguments[0])){return this.multiSort.call(this,b,a)}else{return this.singleSort(b,a)}},singleSort:function(g,c){var e=this.fields.get(g);if(!e){return false}var b=e.name,a=this.sortInfo||null,d=this.sortToggle?this.sortToggle[b]:null;if(!c){if(a&&a.field==b){c=(this.sortToggle[b]||"ASC").toggle("ASC","DESC")}else{c=e.sortDir}}this.sortToggle[b]=c;this.sortInfo={field:b,direction:c};this.hasMultiSort=false;if(this.remoteSort){if(!this.load(this.lastOptions)){if(d){this.sortToggle[b]=d}if(a){this.sortInfo=a}}}else{this.applySort();this.fireEvent("datachanged",this)}return true},multiSort:function(b,a){this.hasMultiSort=true;a=a||"ASC";if(this.multiSortInfo&&a==this.multiSortInfo.direction){a=a.toggle("ASC","DESC")}this.multiSortInfo={sorters:b,direction:a};if(this.remoteSort){this.singleSort(b[0].field,b[0].direction)}else{this.applySort();this.fireEvent("datachanged",this)}},each:function(b,a){this.data.each(b,a)},getModifiedRecords:function(){return this.modified},sum:function(e,g,a){var c=this.data.items,b=0;g=g||0;a=(a||a===0)?a:c.length-1;for(var d=g;d<=a;d++){b+=(c[d].data[e]||0)}return b},createFilterFn:function(d,c,e,a,b){if(Ext.isEmpty(c,false)){return false}c=this.data.createValueMatcher(c,e,a,b);return function(g){return c.test(g.data[d])}},createMultipleFilterFn:function(a){return function(b){var k=true;for(var d=0,c=a.length;d<c;d++){var h=a[d],g=h.fn,e=h.scope;k=k&&g.call(e,b)}return k}},filter:function(n,m,h,k,e){var l;if(Ext.isObject(n)){n=[n]}if(Ext.isArray(n)){var b=[];for(var g=0,d=n.length;g<d;g++){var a=n[g],c=a.fn,o=a.scope||this;if(!Ext.isFunction(c)){c=this.createFilterFn(a.property,a.value,a.anyMatch,a.caseSensitive,a.exactMatch)}b.push({fn:c,scope:o})}l=this.createMultipleFilterFn(b)}else{l=this.createFilterFn(n,m,h,k,e)}return l?this.filterBy(l):this.clearFilter()},filterBy:function(b,a){this.snapshot=this.snapshot||this.data;this.data=this.queryBy(b,a||this);this.fireEvent("datachanged",this)},clearFilter:function(a){if(this.isFiltered()){this.data=this.snapshot;delete this.snapshot;if(a!==true){this.fireEvent("datachanged",this)}}},isFiltered:function(){return !!this.snapshot&&this.snapshot!=this.data},query:function(d,c,e,a){var b=this.createFilterFn(d,c,e,a);return b?this.queryBy(b):this.data.clone()},queryBy:function(b,a){var c=this.snapshot||this.data;return c.filterBy(b,a||this)},find:function(d,c,g,e,a){var b=this.createFilterFn(d,c,e,a);return b?this.data.findIndexBy(b,null,g):-1},findExact:function(b,a,c){return this.data.findIndexBy(function(d){return d.get(b)===a},this,c)},findBy:function(b,a,c){return this.data.findIndexBy(b,a,c)},collect:function(j,k,b){var h=(b===true&&this.snapshot)?this.snapshot.items:this.data.items;var m,n,a=[],c={};for(var e=0,g=h.length;e<g;e++){m=h[e].data[j];n=String(m);if((k||!Ext.isEmpty(m))&&!c[n]){c[n]=true;a[a.length]=m}}return a},afterEdit:function(a){if(this.modified.indexOf(a)==-1){this.modified.push(a)}this.fireEvent("update",this,a,Ext.data.Record.EDIT)},afterReject:function(a){this.modified.remove(a);this.fireEvent("update",this,a,Ext.data.Record.REJECT)},afterCommit:function(a){this.modified.remove(a);this.fireEvent("update",this,a,Ext.data.Record.COMMIT)},commitChanges:function(){var a=this.modified.slice(0),c=a.length,b;for(b=0;b<c;b++){a[b].commit()}this.modified=[];this.removed=[]},rejectChanges:function(){var a=this.modified.slice(0),e=this.removed.slice(0).reverse(),c=a.length,d=e.length,b;for(b=0;b<c;b++){a[b].reject()}for(b=0;b<d;b++){this.insert(e[b].lastIndex||0,e[b]);e[b].reject()}this.modified=[];this.removed=[]},onMetaChange:function(a){this.recordType=this.reader.recordType;this.fields=this.recordType.prototype.fields;delete this.snapshot;if(this.reader.meta.sortInfo){this.sortInfo=this.reader.meta.sortInfo}else{if(this.sortInfo&&!this.fields.get(this.sortInfo.field)){delete this.sortInfo}}if(this.writer){this.writer.meta=this.reader.meta}this.modified=[];this.fireEvent("metachange",this,this.reader.meta)},findInsertIndex:function(a){this.suspendEvents();var c=this.data.clone();this.data.add(a);this.applySort();var b=this.data.indexOf(a);this.data=c;this.resumeEvents();return b},setBaseParam:function(a,b){this.baseParams=this.baseParams||{};this.baseParams[a]=b}});Ext.reg("store",Ext.data.Store);Ext.data.Store.Error=Ext.extend(Ext.Error,{name:"Ext.data.Store"});Ext.apply(Ext.data.Store.Error.prototype,{lang:{"writer-undefined":"Attempted to execute a write-action without a DataWriter installed."}});Ext.data.Field=Ext.extend(Object,{constructor:function(b){if(Ext.isString(b)){b={name:b}}Ext.apply(this,b);var d=Ext.data.Types,a=this.sortType,c;if(this.type){if(Ext.isString(this.type)){this.type=Ext.data.Types[this.type.toUpperCase()]||d.AUTO}}else{this.type=d.AUTO}if(Ext.isString(a)){this.sortType=Ext.data.SortTypes[a]}else{if(Ext.isEmpty(a)){this.sortType=this.type.sortType}}if(!this.convert){this.convert=this.type.convert}},dateFormat:null,useNull:false,defaultValue:"",mapping:null,sortType:null,sortDir:"ASC",allowBlank:true});Ext.data.DataReader=function(a,b){this.meta=a;this.recordType=Ext.isArray(b)?Ext.data.Record.create(b):b;if(this.recordType){this.buildExtractors()}};Ext.data.DataReader.prototype={getTotal:Ext.emptyFn,getRoot:Ext.emptyFn,getMessage:Ext.emptyFn,getSuccess:Ext.emptyFn,getId:Ext.emptyFn,buildExtractors:Ext.emptyFn,extractValues:Ext.emptyFn,realize:function(a,c){if(Ext.isArray(a)){for(var b=a.length-1;b>=0;b--){if(Ext.isArray(c)){this.realize(a.splice(b,1).shift(),c.splice(b,1).shift())}else{this.realize(a.splice(b,1).shift(),c)}}}else{if(Ext.isArray(c)&&c.length==1){c=c.shift()}if(!this.isData(c)){throw new Ext.data.DataReader.Error("realize",a)}a.phantom=false;a._phid=a.id;a.id=this.getId(c);a.data=c;a.commit();a.store.reMap(a)}},update:function(a,c){if(Ext.isArray(a)){for(var b=a.length-1;b>=0;b--){if(Ext.isArray(c)){this.update(a.splice(b,1).shift(),c.splice(b,1).shift())}else{this.update(a.splice(b,1).shift(),c)}}}else{if(Ext.isArray(c)&&c.length==1){c=c.shift()}if(this.isData(c)){a.data=Ext.apply(a.data,c)}a.commit()}},extractData:function(k,a){var j=(this instanceof Ext.data.JsonReader)?"json":"node";var c=[];if(this.isData(k)&&!(this instanceof Ext.data.XmlReader)){k=[k]}var h=this.recordType.prototype.fields,o=h.items,m=h.length,c=[];if(a===true){var l=this.recordType;for(var e=0;e<k.length;e++){var b=k[e];var g=new l(this.extractValues(b,o,m),this.getId(b));g[j]=b;c.push(g)}}else{for(var e=0;e<k.length;e++){var d=this.extractValues(k[e],o,m);d[this.meta.idProperty]=this.getId(k[e]);c.push(d)}}return c},isData:function(a){return(a&&Ext.isObject(a)&&!Ext.isEmpty(this.getId(a)))?true:false},onMetaChange:function(a){delete this.ef;this.meta=a;this.recordType=Ext.data.Record.create(a.fields);this.buildExtractors()}};Ext.data.DataReader.Error=Ext.extend(Ext.Error,{constructor:function(b,a){this.arg=a;Ext.Error.call(this,b)},name:"Ext.data.DataReader"});Ext.apply(Ext.data.DataReader.Error.prototype,{lang:{update:"#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",realize:"#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.","invalid-response":"#readResponse received an invalid response from the server."}});Ext.data.DataWriter=function(a){Ext.apply(this,a)};Ext.data.DataWriter.prototype={writeAllFields:false,listful:false,apply:function(e,g,d,a){var c=[],b=d+"Record";if(Ext.isArray(a)){Ext.each(a,function(h){c.push(this[b](h))},this)}else{if(a instanceof Ext.data.Record){c=this[b](a)}}this.render(e,g,c)},render:Ext.emptyFn,updateRecord:Ext.emptyFn,createRecord:Ext.emptyFn,destroyRecord:Ext.emptyFn,toHash:function(g,c){var e=g.fields.map,d={},b=(this.writeAllFields===false&&g.phantom===false)?g.getChanges():g.data,a;Ext.iterate(b,function(i,h){if((a=e[i])){d[a.mapping?a.mapping:a.name]=h}});if(g.phantom){if(g.fields.containsKey(this.meta.idProperty)&&Ext.isEmpty(g.data[this.meta.idProperty])){delete d[this.meta.idProperty]}}else{d[this.meta.idProperty]=g.id}return d},toArray:function(b){var a=[];Ext.iterate(b,function(d,c){a.push({name:d,value:c})},this);return a}};Ext.data.DataProxy=function(a){a=a||{};this.api=a.api;this.url=a.url;this.restful=a.restful;this.listeners=a.listeners;this.prettyUrls=a.prettyUrls;this.addEvents("exception","beforeload","load","loadexception","beforewrite","write");Ext.data.DataProxy.superclass.constructor.call(this);try{Ext.data.Api.prepare(this)}catch(b){if(b instanceof Ext.data.Api.Error){b.toConsole()}}Ext.data.DataProxy.relayEvents(this,["beforewrite","write","exception"])};Ext.extend(Ext.data.DataProxy,Ext.util.Observable,{restful:false,setApi:function(){if(arguments.length==1){var a=Ext.data.Api.isValid(arguments[0]);if(a===true){this.api=arguments[0]}else{throw new Ext.data.Api.Error("invalid",a)}}else{if(arguments.length==2){if(!Ext.data.Api.isAction(arguments[0])){throw new Ext.data.Api.Error("invalid",arguments[0])}this.api[arguments[0]]=arguments[1]}}Ext.data.Api.prepare(this)},isApiAction:function(a){return(this.api[a])?true:false},request:function(e,b,g,a,h,d,c){if(!this.api[e]&&!this.load){throw new Ext.data.DataProxy.Error("action-undefined",e)}g=g||{};if((e===Ext.data.Api.actions.read)?this.fireEvent("beforeload",this,g):this.fireEvent("beforewrite",this,e,b,g)!==false){this.doRequest.apply(this,arguments)}else{h.call(d||this,null,c,false)}},load:null,doRequest:function(e,b,g,a,h,d,c){this.load(g,a,h,d,c)},onRead:Ext.emptyFn,onWrite:Ext.emptyFn,buildUrl:function(d,b){b=b||null;var c=(this.conn&&this.conn.url)?this.conn.url:(this.api[d])?this.api[d].url:this.url;if(!c){throw new Ext.data.Api.Error("invalid-url",d)}var e=null;var a=c.match(/(.*)(\.json|\.xml|\.html)$/);if(a){e=a[2];c=a[1]}if((this.restful===true||this.prettyUrls===true)&&b instanceof Ext.data.Record&&!b.phantom){c+="/"+b.id}return(e===null)?c:c+e},destroy:function(){this.purgeListeners()}});Ext.apply(Ext.data.DataProxy,Ext.util.Observable.prototype);Ext.util.Observable.call(Ext.data.DataProxy);Ext.data.DataProxy.Error=Ext.extend(Ext.Error,{constructor:function(b,a){this.arg=a;Ext.Error.call(this,b)},name:"Ext.data.DataProxy"});Ext.apply(Ext.data.DataProxy.Error.prototype,{lang:{"action-undefined":"DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.","api-invalid":"Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions."}});Ext.data.Request=function(a){Ext.apply(this,a)};Ext.data.Request.prototype={action:undefined,rs:undefined,params:undefined,callback:Ext.emptyFn,scope:undefined,reader:undefined};Ext.data.Response=function(a){Ext.apply(this,a)};Ext.data.Response.prototype={action:undefined,success:undefined,message:undefined,data:undefined,raw:undefined,records:undefined};Ext.data.ScriptTagProxy=function(a){Ext.apply(this,a);Ext.data.ScriptTagProxy.superclass.constructor.call(this,a);this.head=document.getElementsByTagName("head")[0]};Ext.data.ScriptTagProxy.TRANS_ID=1000;Ext.extend(Ext.data.ScriptTagProxy,Ext.data.DataProxy,{timeout:30000,callbackParam:"callback",nocache:true,doRequest:function(e,g,d,h,j,k,l){var c=Ext.urlEncode(Ext.apply(d,this.extraParams));var b=this.buildUrl(e,g);if(!b){throw new Ext.data.Api.Error("invalid-url",b)}b=Ext.urlAppend(b,c);if(this.nocache){b=Ext.urlAppend(b,"_dc="+(new Date().getTime()))}var a=++Ext.data.ScriptTagProxy.TRANS_ID;var m={id:a,action:e,cb:"stcCallback"+a,scriptId:"stcScript"+a,params:d,arg:l,url:b,callback:j,scope:k,reader:h};window[m.cb]=this.createCallback(e,g,m);b+=String.format("&{0}={1}",this.callbackParam,m.cb);if(this.autoAbort!==false){this.abort()}m.timeoutId=this.handleFailure.defer(this.timeout,this,[m]);var i=document.createElement("script");i.setAttribute("src",b);i.setAttribute("type","text/javascript");i.setAttribute("id",m.scriptId);this.head.appendChild(i);this.trans=m},createCallback:function(d,b,c){var a=this;return function(e){a.trans=false;a.destroyTrans(c,true);if(d===Ext.data.Api.actions.read){a.onRead.call(a,d,c,e)}else{a.onWrite.call(a,d,c,e,b)}}},onRead:function(d,c,b){var a;try{a=c.reader.readRecords(b)}catch(g){this.fireEvent("loadexception",this,c,b,g);this.fireEvent("exception",this,"response",d,c,b,g);c.callback.call(c.scope||window,null,c.arg,false);return}if(a.success===false){this.fireEvent("loadexception",this,c,b);this.fireEvent("exception",this,"remote",d,c,b,null)}else{this.fireEvent("load",this,b,c.arg)}c.callback.call(c.scope||window,a,c.arg,a.success)},onWrite:function(h,g,c,b){var a=g.reader;try{var d=a.readResponse(h,c)}catch(i){this.fireEvent("exception",this,"response",h,g,d,i);g.callback.call(g.scope||window,null,d,false);return}if(!d.success===true){this.fireEvent("exception",this,"remote",h,g,d,b);g.callback.call(g.scope||window,null,d,false);return}this.fireEvent("write",this,h,d.data,d,b,g.arg);g.callback.call(g.scope||window,d.data,d,true)},isLoading:function(){return this.trans?true:false},abort:function(){if(this.isLoading()){this.destroyTrans(this.trans)}},destroyTrans:function(b,a){this.head.removeChild(document.getElementById(b.scriptId));clearTimeout(b.timeoutId);if(a){window[b.cb]=undefined;try{delete window[b.cb]}catch(c){}}else{window[b.cb]=function(){window[b.cb]=undefined;try{delete window[b.cb]}catch(d){}}}},handleFailure:function(a){this.trans=false;this.destroyTrans(a,false);if(a.action===Ext.data.Api.actions.read){this.fireEvent("loadexception",this,null,a.arg)}this.fireEvent("exception",this,"response",a.action,{response:null,options:a.arg});a.callback.call(a.scope||window,null,a.arg,false)},destroy:function(){this.abort();Ext.data.ScriptTagProxy.superclass.destroy.call(this)}});Ext.data.HttpProxy=function(a){Ext.data.HttpProxy.superclass.constructor.call(this,a);this.conn=a;this.conn.url=null;this.useAjax=!a||!a.events;var c=Ext.data.Api.actions;this.activeRequest={};for(var b in c){this.activeRequest[c[b]]=undefined}};Ext.extend(Ext.data.HttpProxy,Ext.data.DataProxy,{getConnection:function(){return this.useAjax?Ext.Ajax:this.conn},setUrl:function(a,b){this.conn.url=a;if(b===true){this.url=a;this.api=null;Ext.data.Api.prepare(this)}},doRequest:function(g,d,i,c,b,e,a){var h={method:(this.api[g])?this.api[g]["method"]:undefined,request:{callback:b,scope:e,arg:a},reader:c,callback:this.createCallback(g,d),scope:this};if(i.jsonData){h.jsonData=i.jsonData}else{if(i.xmlData){h.xmlData=i.xmlData}else{h.params=i||{}}}this.conn.url=this.buildUrl(g,d);if(this.useAjax){Ext.applyIf(h,this.conn);if(this.activeRequest[g]){}this.activeRequest[g]=Ext.Ajax.request(h)}else{this.conn.request(h)}this.conn.url=null},createCallback:function(b,a){return function(e,d,c){this.activeRequest[b]=undefined;if(!d){if(b===Ext.data.Api.actions.read){this.fireEvent("loadexception",this,e,c)}this.fireEvent("exception",this,"response",b,e,c);e.request.callback.call(e.request.scope,null,e.request.arg,false);return}if(b===Ext.data.Api.actions.read){this.onRead(b,e,c)}else{this.onWrite(b,e,c,a)}}},onRead:function(d,h,b){var a;try{a=h.reader.read(b)}catch(g){this.fireEvent("loadexception",this,h,b,g);this.fireEvent("exception",this,"response",d,h,b,g);h.request.callback.call(h.request.scope,null,h.request.arg,false);return}if(a.success===false){this.fireEvent("loadexception",this,h,b);var c=h.reader.readResponse(d,b);this.fireEvent("exception",this,"remote",d,h,c,null)}else{this.fireEvent("load",this,h,h.request.arg)}h.request.callback.call(h.request.scope,a,h.request.arg,a.success)},onWrite:function(g,i,c,b){var a=i.reader;var d;try{d=a.readResponse(g,c)}catch(h){this.fireEvent("exception",this,"response",g,i,c,h);i.request.callback.call(i.request.scope,null,i.request.arg,false);return}if(d.success===true){this.fireEvent("write",this,g,d.data,d,b,i.request.arg)}else{this.fireEvent("exception",this,"remote",g,i,d,b)}i.request.callback.call(i.request.scope,d.data,d,d.success)},destroy:function(){if(!this.useAjax){this.conn.abort()}else{if(this.activeRequest){var b=Ext.data.Api.actions;for(var a in b){if(this.activeRequest[b[a]]){Ext.Ajax.abort(this.activeRequest[b[a]])}}}}Ext.data.HttpProxy.superclass.destroy.call(this)}});Ext.data.MemoryProxy=function(b){var a={};a[Ext.data.Api.actions.read]=true;Ext.data.MemoryProxy.superclass.constructor.call(this,{api:a});this.data=b};Ext.extend(Ext.data.MemoryProxy,Ext.data.DataProxy,{doRequest:function(b,c,a,d,h,i,j){a=a||{};var k;try{k=d.readRecords(this.data)}catch(g){this.fireEvent("loadexception",this,null,j,g);this.fireEvent("exception",this,"response",b,j,null,g);h.call(i,null,j,false);return}h.call(i,k,j,true)}});Ext.data.Types=new function(){var a=Ext.data.SortTypes;Ext.apply(this,{stripRe:/[\$,%]/g,AUTO:{convert:function(b){return b},sortType:a.none,type:"auto"},STRING:{convert:function(b){return(b===undefined||b===null)?"":String(b)},sortType:a.asUCString,type:"string"},INT:{convert:function(b){return b!==undefined&&b!==null&&b!==""?parseInt(String(b).replace(Ext.data.Types.stripRe,""),10):(this.useNull?null:0)},sortType:a.none,type:"int"},FLOAT:{convert:function(b){return b!==undefined&&b!==null&&b!==""?parseFloat(String(b).replace(Ext.data.Types.stripRe,""),10):(this.useNull?null:0)},sortType:a.none,type:"float"},BOOL:{convert:function(b){return b===true||b==="true"||b==1},sortType:a.none,type:"bool"},DATE:{convert:function(c){var d=this.dateFormat;if(!c){return null}if(Ext.isDate(c)){return c}if(d){if(d=="timestamp"){return new Date(c*1000)}if(d=="time"){return new Date(parseInt(c,10))}return Date.parseDate(c,d)}var b=Date.parse(c);return b?new Date(b):null},sortType:a.asDate,type:"date"}});Ext.apply(this,{BOOLEAN:this.BOOL,INTEGER:this.INT,NUMBER:this.FLOAT})};Ext.data.JsonWriter=Ext.extend(Ext.data.DataWriter,{encode:true,encodeDelete:false,constructor:function(a){Ext.data.JsonWriter.superclass.constructor.call(this,a)},render:function(c,d,b){if(this.encode===true){Ext.apply(c,d);c[this.meta.root]=Ext.encode(b)}else{var a=Ext.apply({},d);a[this.meta.root]=b;c.jsonData=a}},createRecord:function(a){return this.toHash(a)},updateRecord:function(a){return this.toHash(a)},destroyRecord:function(b){if(this.encodeDelete){var a={};a[this.meta.idProperty]=b.id;return a}else{return b.id}}});Ext.data.JsonReader=function(a,b){a=a||{};Ext.applyIf(a,{idProperty:"id",successProperty:"success",totalProperty:"total"});Ext.data.JsonReader.superclass.constructor.call(this,a,b||a.fields)};Ext.extend(Ext.data.JsonReader,Ext.data.DataReader,{read:function(a){var b=a.responseText;var c=Ext.decode(b);if(!c){throw {message:"JsonReader.read: Json object not found"}}return this.readRecords(c)},readResponse:function(e,b){var h=(b.responseText!==undefined)?Ext.decode(b.responseText):b;if(!h){throw new Ext.data.JsonReader.Error("response")}var a=this.getRoot(h),g=this.getSuccess(h);if(g&&e===Ext.data.Api.actions.create){var d=Ext.isDefined(a);if(d&&Ext.isEmpty(a)){throw new Ext.data.JsonReader.Error("root-empty",this.meta.root)}else{if(!d){throw new Ext.data.JsonReader.Error("root-undefined-response",this.meta.root)}}}var c=new Ext.data.Response({action:e,success:g,data:(a)?this.extractData(a,false):[],message:this.getMessage(h),raw:h});if(Ext.isEmpty(c.success)){throw new Ext.data.JsonReader.Error("successProperty-response",this.meta.successProperty)}return c},readRecords:function(a){this.jsonData=a;if(a.metaData){this.onMetaChange(a.metaData)}var m=this.meta,h=this.recordType,b=h.prototype.fields,l=b.items,i=b.length,j;var g=this.getRoot(a),e=g.length,d=e,k=true;if(m.totalProperty){j=parseInt(this.getTotal(a),10);if(!isNaN(j)){d=j}}if(m.successProperty){j=this.getSuccess(a);if(j===false||j==="false"){k=false}}return{success:k,records:this.extractData(g,true),totalRecords:d}},buildExtractors:function(){if(this.ef){return}var l=this.meta,h=this.recordType,e=h.prototype.fields,k=e.items,j=e.length;if(l.totalProperty){this.getTotal=this.createAccessor(l.totalProperty)}if(l.successProperty){this.getSuccess=this.createAccessor(l.successProperty)}if(l.messageProperty){this.getMessage=this.createAccessor(l.messageProperty)}this.getRoot=l.root?this.createAccessor(l.root):function(g){return g};if(l.id||l.idProperty){var d=this.createAccessor(l.id||l.idProperty);this.getId=function(i){var g=d(i);return(g===undefined||g==="")?null:g}}else{this.getId=function(){return null}}var c=[];for(var b=0;b<j;b++){e=k[b];var a=(e.mapping!==undefined&&e.mapping!==null)?e.mapping:e.name;c.push(this.createAccessor(a))}this.ef=c},simpleAccess:function(b,a){return b[a]},createAccessor:function(){var a=/[\[\.]/;return function(c){if(Ext.isEmpty(c)){return Ext.emptyFn}if(Ext.isFunction(c)){return c}var b=String(c).search(a);if(b>=0){return new Function("obj","return obj"+(b>0?".":"")+c)}return function(d){return d[c]}}}(),extractValues:function(h,d,a){var g,c={};for(var e=0;e<a;e++){g=d[e];var b=this.ef[e](h);c[g.name]=g.convert((b!==undefined)?b:g.defaultValue,h)}return c}});Ext.data.JsonReader.Error=Ext.extend(Ext.Error,{constructor:function(b,a){this.arg=a;Ext.Error.call(this,b)},name:"Ext.data.JsonReader"});Ext.apply(Ext.data.JsonReader.Error.prototype,{lang:{response:"An error occurred while json-decoding your server response","successProperty-response":'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',"root-undefined-config":'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',"idProperty-undefined":'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',"root-empty":'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'}});Ext.data.ArrayReader=Ext.extend(Ext.data.JsonReader,{readRecords:function(r){this.arrayData=r;var l=this.meta,d=l?Ext.num(l.idIndex,l.id):null,b=this.recordType,q=b.prototype.fields,z=[],e=true,g;var u=this.getRoot(r);for(var y=0,A=u.length;y<A;y++){var t=u[y],a={},p=((d||d===0)&&t[d]!==undefined&&t[d]!==""?t[d]:null);for(var x=0,m=q.length;x<m;x++){var B=q.items[x],w=B.mapping!==undefined&&B.mapping!==null?B.mapping:x;g=t[w]!==undefined?t[w]:B.defaultValue;g=B.convert(g,t);a[B.name]=g}var c=new b(a,p);c.json=t;z[z.length]=c}var h=z.length;if(l.totalProperty){g=parseInt(this.getTotal(r),10);if(!isNaN(g)){h=g}}if(l.successProperty){g=this.getSuccess(r);if(g===false||g==="false"){e=false}}return{success:e,records:z,totalRecords:h}}});Ext.data.ArrayStore=Ext.extend(Ext.data.Store,{constructor:function(a){Ext.data.ArrayStore.superclass.constructor.call(this,Ext.apply(a,{reader:new Ext.data.ArrayReader(a)}))},loadData:function(e,b){if(this.expandData===true){var d=[];for(var c=0,a=e.length;c<a;c++){d[d.length]=[e[c]]}e=d}Ext.data.ArrayStore.superclass.loadData.call(this,e,b)}});Ext.reg("arraystore",Ext.data.ArrayStore);Ext.data.SimpleStore=Ext.data.ArrayStore;Ext.reg("simplestore",Ext.data.SimpleStore);Ext.data.JsonStore=Ext.extend(Ext.data.Store,{constructor:function(a){Ext.data.JsonStore.superclass.constructor.call(this,Ext.apply(a,{reader:new Ext.data.JsonReader(a)}))}});Ext.reg("jsonstore",Ext.data.JsonStore);Ext.data.XmlWriter=function(a){Ext.data.XmlWriter.superclass.constructor.apply(this,arguments);this.tpl=(typeof(this.tpl)==="string")?new Ext.XTemplate(this.tpl).compile():this.tpl.compile()};Ext.extend(Ext.data.XmlWriter,Ext.data.DataWriter,{documentRoot:"xrequest",forceDocumentRoot:false,root:"records",xmlVersion:"1.0",xmlEncoding:"ISO-8859-15",tpl:'<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}></tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',render:function(b,c,a){c=this.toArray(c);b.xmlData=this.tpl.applyTemplate({version:this.xmlVersion,encoding:this.xmlEncoding,documentRoot:(c.length>0||this.forceDocumentRoot===true)?this.documentRoot:false,record:this.meta.record,root:this.root,baseParams:c,records:(Ext.isArray(a[0]))?a:[a]})},createRecord:function(a){return this.toArray(this.toHash(a))},updateRecord:function(a){return this.toArray(this.toHash(a))},destroyRecord:function(b){var a={};a[this.meta.idProperty]=b.id;return this.toArray(a)}});Ext.data.XmlReader=function(a,b){a=a||{};Ext.applyIf(a,{idProperty:a.idProperty||a.idPath||a.id,successProperty:a.successProperty||a.success});Ext.data.XmlReader.superclass.constructor.call(this,a,b||a.fields)};Ext.extend(Ext.data.XmlReader,Ext.data.DataReader,{read:function(a){var b=a.responseXML;if(!b){throw {message:"XmlReader.read: XML Document not available"}}return this.readRecords(b)},readRecords:function(d){this.xmlData=d;var a=d.documentElement||d,c=Ext.DomQuery,g=0,e=true;if(this.meta.totalProperty){g=this.getTotal(a,0)}if(this.meta.successProperty){e=this.getSuccess(a)}var b=this.extractData(c.select(this.meta.record,a),true);return{success:e,records:b,totalRecords:g||b.length}},readResponse:function(g,b){var e=Ext.DomQuery,h=b.responseXML,a=h.documentElement||h;var c=new Ext.data.Response({action:g,success:this.getSuccess(a),message:this.getMessage(a),data:this.extractData(e.select(this.meta.record,a)||e.select(this.meta.root,a),false),raw:h});if(Ext.isEmpty(c.success)){throw new Ext.data.DataReader.Error("successProperty-response",this.meta.successProperty)}if(g===Ext.data.Api.actions.create){var d=Ext.isDefined(c.data);if(d&&Ext.isEmpty(c.data)){throw new Ext.data.JsonReader.Error("root-empty",this.meta.root)}else{if(!d){throw new Ext.data.JsonReader.Error("root-undefined-response",this.meta.root)}}}return c},getSuccess:function(){return true},buildExtractors:function(){if(this.ef){return}var l=this.meta,h=this.recordType,e=h.prototype.fields,k=e.items,j=e.length;if(l.totalProperty){this.getTotal=this.createAccessor(l.totalProperty)}if(l.successProperty){this.getSuccess=this.createAccessor(l.successProperty)}if(l.messageProperty){this.getMessage=this.createAccessor(l.messageProperty)}this.getRoot=function(g){return(!Ext.isEmpty(g[this.meta.record]))?g[this.meta.record]:g[this.meta.root]};if(l.idPath||l.idProperty){var d=this.createAccessor(l.idPath||l.idProperty);this.getId=function(g){var i=d(g)||g.id;return(i===undefined||i==="")?null:i}}else{this.getId=function(){return null}}var c=[];for(var b=0;b<j;b++){e=k[b];var a=(e.mapping!==undefined&&e.mapping!==null)?e.mapping:e.name;c.push(this.createAccessor(a))}this.ef=c},createAccessor:function(){var a=Ext.DomQuery;return function(b){if(Ext.isFunction(b)){return b}switch(b){case this.meta.totalProperty:return function(c,d){return a.selectNumber(b,c,d)};break;case this.meta.successProperty:return function(d,e){var c=a.selectValue(b,d,true);var g=c!==false&&c!=="false";return g};break;default:return function(c,d){return a.selectValue(b,c,d)};break}}}(),extractValues:function(h,d,a){var g,c={};for(var e=0;e<a;e++){g=d[e];var b=this.ef[e](h);c[g.name]=g.convert((b!==undefined)?b:g.defaultValue,h)}return c}});Ext.data.XmlStore=Ext.extend(Ext.data.Store,{constructor:function(a){Ext.data.XmlStore.superclass.constructor.call(this,Ext.apply(a,{reader:new Ext.data.XmlReader(a)}))}});Ext.reg("xmlstore",Ext.data.XmlStore);Ext.data.GroupingStore=Ext.extend(Ext.data.Store,{constructor:function(d){d=d||{};this.hasMultiSort=true;this.multiSortInfo=this.multiSortInfo||{sorters:[]};var e=this.multiSortInfo.sorters,c=d.groupField||this.groupField,b=d.sortInfo||this.sortInfo,a=d.groupDir||this.groupDir;if(c){e.push({field:c,direction:a})}if(b){e.push(b)}Ext.data.GroupingStore.superclass.constructor.call(this,d);this.addEvents("groupchange");this.applyGroupField()},remoteGroup:false,groupOnSort:false,groupDir:"ASC",clearGrouping:function(){this.groupField=false;if(this.remoteGroup){if(this.baseParams){delete this.baseParams.groupBy;delete this.baseParams.groupDir}var a=this.lastOptions;if(a&&a.params){delete a.params.groupBy;delete a.params.groupDir}this.reload()}else{this.sort();this.fireEvent("datachanged",this)}},groupBy:function(e,a,d){d=d?(String(d).toUpperCase()=="DESC"?"DESC":"ASC"):this.groupDir;if(this.groupField==e&&this.groupDir==d&&!a){return}var c=this.multiSortInfo.sorters;if(c.length>0&&c[0].field==this.groupField){c.shift()}this.groupField=e;this.groupDir=d;this.applyGroupField();var b=function(){this.fireEvent("groupchange",this,this.getGroupState())};if(this.groupOnSort){this.sort(e,d);b.call(this);return}if(this.remoteGroup){this.on("load",b,this,{single:true});this.reload()}else{this.sort(c);b.call(this)}},sort:function(h,c){if(this.remoteSort){return Ext.data.GroupingStore.superclass.sort.call(this,h,c)}var g=[];if(Ext.isArray(arguments[0])){g=arguments[0]}else{if(h==undefined){g=this.sortInfo?[this.sortInfo]:[]}else{var e=this.fields.get(h);if(!e){return false}var b=e.name,a=this.sortInfo||null,d=this.sortToggle?this.sortToggle[b]:null;if(!c){if(a&&a.field==b){c=(this.sortToggle[b]||"ASC").toggle("ASC","DESC")}else{c=e.sortDir}}this.sortToggle[b]=c;this.sortInfo={field:b,direction:c};g=[this.sortInfo]}}if(this.groupField){g.unshift({direction:this.groupDir,field:this.groupField})}return this.multiSort.call(this,g,c)},applyGroupField:function(){if(this.remoteGroup){if(!this.baseParams){this.baseParams={}}Ext.apply(this.baseParams,{groupBy:this.groupField,groupDir:this.groupDir});var a=this.lastOptions;if(a&&a.params){a.params.groupDir=this.groupDir;delete a.params.groupBy}}},applyGrouping:function(a){if(this.groupField!==false){this.groupBy(this.groupField,true,this.groupDir);return true}else{if(a===true){this.fireEvent("datachanged",this)}return false}},getGroupState:function(){return this.groupOnSort&&this.groupField!==false?(this.sortInfo?this.sortInfo.field:undefined):this.groupField}});Ext.reg("groupingstore",Ext.data.GroupingStore);Ext.data.DirectProxy=function(a){Ext.apply(this,a);if(typeof this.paramOrder=="string"){this.paramOrder=this.paramOrder.split(/[\s,|]/)}Ext.data.DirectProxy.superclass.constructor.call(this,a)};Ext.extend(Ext.data.DirectProxy,Ext.data.DataProxy,{paramOrder:undefined,paramsAsHash:true,directFn:undefined,doRequest:function(b,c,a,e,k,l,n){var j=[],h=this.api[b]||this.directFn;switch(b){case Ext.data.Api.actions.create:j.push(a.jsonData);break;case Ext.data.Api.actions.read:if(h.directCfg.method.len>0){if(this.paramOrder){for(var d=0,g=this.paramOrder.length;d<g;d++){j.push(a[this.paramOrder[d]])}}else{if(this.paramsAsHash){j.push(a)}}}break;case Ext.data.Api.actions.update:j.push(a.jsonData);break;case Ext.data.Api.actions.destroy:j.push(a.jsonData);break}var m={params:a||{},request:{callback:k,scope:l,arg:n},reader:e};j.push(this.createCallback(b,c,m),this);h.apply(window,j)},createCallback:function(d,a,b){var c=this;return function(e,g){if(!g.status){if(d===Ext.data.Api.actions.read){c.fireEvent("loadexception",c,b,g,null)}c.fireEvent("exception",c,"remote",d,b,g,null);b.request.callback.call(b.request.scope,null,b.request.arg,false);return}if(d===Ext.data.Api.actions.read){c.onRead(d,b,e,g)}else{c.onWrite(d,b,e,g,a)}}},onRead:function(g,e,a,d){var b;try{b=e.reader.readRecords(a)}catch(c){this.fireEvent("loadexception",this,e,d,c);this.fireEvent("exception",this,"response",g,e,d,c);e.request.callback.call(e.request.scope,null,e.request.arg,false);return}this.fireEvent("load",this,d,e.request.arg);e.request.callback.call(e.request.scope,b,e.request.arg,true)},onWrite:function(g,d,a,c,b){var e=d.reader.extractData(d.reader.getRoot(a),false);var h=d.reader.getSuccess(a);h=(h!==false);if(h){this.fireEvent("write",this,g,e,c,b,d.request.arg)}else{this.fireEvent("exception",this,"remote",g,d,a,b)}d.request.callback.call(d.request.scope,e,c,h)}});Ext.data.DirectStore=Ext.extend(Ext.data.Store,{constructor:function(a){var b=Ext.apply({},{batchTransactions:false},a);Ext.data.DirectStore.superclass.constructor.call(this,Ext.apply(b,{proxy:Ext.isDefined(b.proxy)?b.proxy:new Ext.data.DirectProxy(Ext.copyTo({},b,"paramOrder,paramsAsHash,directFn,api")),reader:(!Ext.isDefined(b.reader)&&b.fields)?new Ext.data.JsonReader(Ext.copyTo({},b,"totalProperty,root,idProperty"),b.fields):b.reader}))}});Ext.reg("directstore",Ext.data.DirectStore);Ext.Direct=Ext.extend(Ext.util.Observable,{exceptions:{TRANSPORT:"xhr",PARSE:"parse",LOGIN:"login",SERVER:"exception"},constructor:function(){this.addEvents("event","exception");this.transactions={};this.providers={}},addProvider:function(e){var c=arguments;if(c.length>1){for(var d=0,b=c.length;d<b;d++){this.addProvider(c[d])}return}if(!e.events){e=new Ext.Direct.PROVIDERS[e.type](e)}e.id=e.id||Ext.id();this.providers[e.id]=e;e.on("data",this.onProviderData,this);e.on("exception",this.onProviderException,this);if(!e.isConnected()){e.connect()}return e},getProvider:function(a){return this.providers[a]},removeProvider:function(b){var a=b.id?b:this.providers[b];a.un("data",this.onProviderData,this);a.un("exception",this.onProviderException,this);delete this.providers[a.id];return a},addTransaction:function(a){this.transactions[a.tid]=a;return a},removeTransaction:function(a){delete this.transactions[a.tid||a];return a},getTransaction:function(a){return this.transactions[a.tid||a]},onProviderData:function(d,c){if(Ext.isArray(c)){for(var b=0,a=c.length;b<a;b++){this.onProviderData(d,c[b])}return}if(c.name&&c.name!="event"&&c.name!="exception"){this.fireEvent(c.name,c)}else{if(c.type=="exception"){this.fireEvent("exception",c)}}this.fireEvent("event",c,d)},createEvent:function(a,b){return new Ext.Direct.eventTypes[a.type](Ext.apply(a,b))}});Ext.Direct=new Ext.Direct();Ext.Direct.TID=1;Ext.Direct.PROVIDERS={};Ext.Direct.Transaction=function(a){Ext.apply(this,a);this.tid=++Ext.Direct.TID;this.retryCount=0};Ext.Direct.Transaction.prototype={send:function(){this.provider.queueTransaction(this)},retry:function(){this.retryCount++;this.send()},getProvider:function(){return this.provider}};Ext.Direct.Event=function(a){Ext.apply(this,a)};Ext.Direct.Event.prototype={status:true,getData:function(){return this.data}};Ext.Direct.RemotingEvent=Ext.extend(Ext.Direct.Event,{type:"rpc",getTransaction:function(){return this.transaction||Ext.Direct.getTransaction(this.tid)}});Ext.Direct.ExceptionEvent=Ext.extend(Ext.Direct.RemotingEvent,{status:false,type:"exception"});Ext.Direct.eventTypes={rpc:Ext.Direct.RemotingEvent,event:Ext.Direct.Event,exception:Ext.Direct.ExceptionEvent};Ext.direct.Provider=Ext.extend(Ext.util.Observable,{priority:1,constructor:function(a){Ext.apply(this,a);this.addEvents("connect","disconnect","data","exception");Ext.direct.Provider.superclass.constructor.call(this,a)},isConnected:function(){return false},connect:Ext.emptyFn,disconnect:Ext.emptyFn});Ext.direct.JsonProvider=Ext.extend(Ext.direct.Provider,{parseResponse:function(a){if(!Ext.isEmpty(a.responseText)){if(typeof a.responseText=="object"){return a.responseText}return Ext.decode(a.responseText)}return null},getEvents:function(j){var g=null;try{g=this.parseResponse(j)}catch(h){var d=new Ext.Direct.ExceptionEvent({data:h,xhr:j,code:Ext.Direct.exceptions.PARSE,message:"Error parsing json response: \n\n "+g});return[d]}var c=[];if(Ext.isArray(g)){for(var b=0,a=g.length;b<a;b++){c.push(Ext.Direct.createEvent(g[b]))}}else{c.push(Ext.Direct.createEvent(g))}return c}});Ext.direct.PollingProvider=Ext.extend(Ext.direct.JsonProvider,{priority:3,interval:3000,constructor:function(a){Ext.direct.PollingProvider.superclass.constructor.call(this,a);this.addEvents("beforepoll","poll")},isConnected:function(){return !!this.pollTask},connect:function(){if(this.url&&!this.pollTask){this.pollTask=Ext.TaskMgr.start({run:function(){if(this.fireEvent("beforepoll",this)!==false){if(typeof this.url=="function"){this.url(this.baseParams)}else{Ext.Ajax.request({url:this.url,callback:this.onData,scope:this,params:this.baseParams})}}},interval:this.interval,scope:this});this.fireEvent("connect",this)}else{if(!this.url){throw"Error initializing PollingProvider, no url configured."}}},disconnect:function(){if(this.pollTask){Ext.TaskMgr.stop(this.pollTask);delete this.pollTask;this.fireEvent("disconnect",this)}},onData:function(d,j,h){if(j){var c=this.getEvents(h);for(var b=0,a=c.length;b<a;b++){var g=c[b];this.fireEvent("data",this,g)}}else{var g=new Ext.Direct.ExceptionEvent({data:g,code:Ext.Direct.exceptions.TRANSPORT,message:"Unable to connect to the server.",xhr:h});this.fireEvent("data",this,g)}}});Ext.Direct.PROVIDERS.polling=Ext.direct.PollingProvider;Ext.direct.RemotingProvider=Ext.extend(Ext.direct.JsonProvider,{enableBuffer:10,maxRetries:1,timeout:undefined,constructor:function(a){Ext.direct.RemotingProvider.superclass.constructor.call(this,a);this.addEvents("beforecall","call");this.namespace=(Ext.isString(this.namespace))?Ext.ns(this.namespace):this.namespace||window;this.transactions={};this.callBuffer=[]},initAPI:function(){var h=this.actions;for(var j in h){var d=this.namespace[j]||(this.namespace[j]={}),e=h[j];for(var g=0,b=e.length;g<b;g++){var a=e[g];d[a.name]=this.createMethod(j,a)}}},isConnected:function(){return !!this.connected},connect:function(){if(this.url){this.initAPI();this.connected=true;this.fireEvent("connect",this)}else{if(!this.url){throw"Error initializing RemotingProvider, no url configured."}}},disconnect:function(){if(this.connected){this.connected=false;this.fireEvent("disconnect",this)}},onData:function(a,h,j){if(h){var k=this.getEvents(j);for(var b=0,c=k.length;b<c;b++){var d=k[b],l=this.getTransaction(d);this.fireEvent("data",this,d);if(l){this.doCallback(l,d,true);Ext.Direct.removeTransaction(l)}}}else{var g=[].concat(a.ts);for(var b=0,c=g.length;b<c;b++){var l=this.getTransaction(g[b]);if(l&&l.retryCount<this.maxRetries){l.retry()}else{var d=new Ext.Direct.ExceptionEvent({data:d,transaction:l,code:Ext.Direct.exceptions.TRANSPORT,message:"Unable to connect to the server.",xhr:j});this.fireEvent("data",this,d);if(l){this.doCallback(l,d,false);Ext.Direct.removeTransaction(l)}}}}},getCallData:function(a){return{action:a.action,method:a.method,data:a.data,type:"rpc",tid:a.tid}},doSend:function(d){var g={url:this.url,callback:this.onData,scope:this,ts:d,timeout:this.timeout},b;if(Ext.isArray(d)){b=[];for(var c=0,a=d.length;c<a;c++){b.push(this.getCallData(d[c]))}}else{b=this.getCallData(d)}if(this.enableUrlEncode){var e={};e[Ext.isString(this.enableUrlEncode)?this.enableUrlEncode:"data"]=Ext.encode(b);g.params=e}else{g.jsonData=b}Ext.Ajax.request(g)},combineAndSend:function(){var a=this.callBuffer.length;if(a>0){this.doSend(a==1?this.callBuffer[0]:this.callBuffer);this.callBuffer=[]}},queueTransaction:function(a){if(a.form){this.processForm(a);return}this.callBuffer.push(a);if(this.enableBuffer){if(!this.callTask){this.callTask=new Ext.util.DelayedTask(this.combineAndSend,this)}this.callTask.delay(Ext.isNumber(this.enableBuffer)?this.enableBuffer:10)}else{this.combineAndSend()}},doCall:function(i,a,b){var h=null,e=b[a.len],g=b[a.len+1];if(a.len!==0){h=b.slice(0,a.len)}var d=new Ext.Direct.Transaction({provider:this,args:b,action:i,method:a.name,data:h,cb:g&&Ext.isFunction(e)?e.createDelegate(g):e});if(this.fireEvent("beforecall",this,d,a)!==false){Ext.Direct.addTransaction(d);this.queueTransaction(d);this.fireEvent("call",this,d,a)}},doForm:function(j,b,g,i,e){var d=new Ext.Direct.Transaction({provider:this,action:j,method:b.name,args:[g,i,e],cb:e&&Ext.isFunction(i)?i.createDelegate(e):i,isForm:true});if(this.fireEvent("beforecall",this,d,b)!==false){Ext.Direct.addTransaction(d);var a=String(g.getAttribute("enctype")).toLowerCase()=="multipart/form-data",h={extTID:d.tid,extAction:j,extMethod:b.name,extType:"rpc",extUpload:String(a)};Ext.apply(d,{form:Ext.getDom(g),isUpload:a,params:i&&Ext.isObject(i.params)?Ext.apply(h,i.params):h});this.fireEvent("call",this,d,b);this.processForm(d)}},processForm:function(a){Ext.Ajax.request({url:this.url,params:a.params,callback:this.onData,scope:this,form:a.form,isUpload:a.isUpload,ts:a})},createMethod:function(d,a){var b;if(!a.formHandler){b=function(){this.doCall(d,a,Array.prototype.slice.call(arguments,0))}.createDelegate(this)}else{b=function(e,g,c){this.doForm(d,a,e,g,c)}.createDelegate(this)}b.directCfg={action:d,method:a};return b},getTransaction:function(a){return a&&a.tid?Ext.Direct.getTransaction(a.tid):null},doCallback:function(c,g){var d=g.status?"success":"failure";if(c&&c.cb){var b=c.cb,a=Ext.isDefined(g.result)?g.result:g.data;if(Ext.isFunction(b)){b(a,g)}else{Ext.callback(b[d],b.scope,[a,g]);Ext.callback(b.callback,b.scope,[a,g])}}}});Ext.Direct.PROVIDERS.remoting=Ext.direct.RemotingProvider;Ext.Resizable=Ext.extend(Ext.util.Observable,{constructor:function(d,e){this.el=Ext.get(d);if(e&&e.wrap){e.resizeChild=this.el;this.el=this.el.wrap(typeof e.wrap=="object"?e.wrap:{cls:"xresizable-wrap"});this.el.id=this.el.dom.id=e.resizeChild.id+"-rzwrap";this.el.setStyle("overflow","hidden");this.el.setPositioning(e.resizeChild.getPositioning());e.resizeChild.clearPositioning();if(!e.width||!e.height){var g=e.resizeChild.getSize();this.el.setSize(g.width,g.height)}if(e.pinned&&!e.adjustments){e.adjustments="auto"}}this.proxy=this.el.createProxy({tag:"div",cls:"x-resizable-proxy",id:this.el.id+"-rzproxy"},Ext.getBody());this.proxy.unselectable();this.proxy.enableDisplayMode("block");Ext.apply(this,e);if(this.pinned){this.disableTrackOver=true;this.el.addClass("x-resizable-pinned")}var k=this.el.getStyle("position");if(k!="absolute"&&k!="fixed"){this.el.setStyle("position","relative")}if(!this.handles){this.handles="s,e,se";if(this.multiDirectional){this.handles+=",n,w"}}if(this.handles=="all"){this.handles="n s e w ne nw se sw"}var o=this.handles.split(/\s*?[,;]\s*?| /);var c=Ext.Resizable.positions;for(var j=0,l=o.length;j<l;j++){if(o[j]&&c[o[j]]){var n=c[o[j]];this[n]=new Ext.Resizable.Handle(this,n,this.disableTrackOver,this.transparent,this.handleCls)}}this.corner=this.southeast;if(this.handles.indexOf("n")!=-1||this.handles.indexOf("w")!=-1){this.updateBox=true}this.activeHandle=null;if(this.resizeChild){if(typeof this.resizeChild=="boolean"){this.resizeChild=Ext.get(this.el.dom.firstChild,true)}else{this.resizeChild=Ext.get(this.resizeChild,true)}}if(this.adjustments=="auto"){var b=this.resizeChild;var m=this.west,h=this.east,a=this.north,o=this.south;if(b&&(m||a)){b.position("relative");b.setLeft(m?m.el.getWidth():0);b.setTop(a?a.el.getHeight():0)}this.adjustments=[(h?-h.el.getWidth():0)+(m?-m.el.getWidth():0),(a?-a.el.getHeight():0)+(o?-o.el.getHeight():0)-1]}if(this.draggable){this.dd=this.dynamic?this.el.initDD(null):this.el.initDDProxy(null,{dragElId:this.proxy.id});this.dd.setHandleElId(this.resizeChild?this.resizeChild.id:this.el.id);if(this.constrainTo){this.dd.constrainTo(this.constrainTo)}}this.addEvents("beforeresize","resize");if(this.width!==null&&this.height!==null){this.resizeTo(this.width,this.height)}else{this.updateChildSize()}if(Ext.isIE){this.el.dom.style.zoom=1}Ext.Resizable.superclass.constructor.call(this)},adjustments:[0,0],animate:false,disableTrackOver:false,draggable:false,duration:0.35,dynamic:false,easing:"easeOutStrong",enabled:true,handles:false,multiDirectional:false,height:null,width:null,heightIncrement:0,widthIncrement:0,minHeight:5,minWidth:5,maxHeight:10000,maxWidth:10000,minX:0,minY:0,pinned:false,preserveRatio:false,resizeChild:false,transparent:false,resizeTo:function(b,a){this.el.setSize(b,a);this.updateChildSize();this.fireEvent("resize",this,b,a,null)},startSizing:function(c,b){this.fireEvent("beforeresize",this,c);if(this.enabled){if(!this.overlay){this.overlay=this.el.createProxy({tag:"div",cls:"x-resizable-overlay",html:"&#160;"},Ext.getBody());this.overlay.unselectable();this.overlay.enableDisplayMode("block");this.overlay.on({scope:this,mousemove:this.onMouseMove,mouseup:this.onMouseUp})}this.overlay.setStyle("cursor",b.el.getStyle("cursor"));this.resizing=true;this.startBox=this.el.getBox();this.startPoint=c.getXY();this.offsets=[(this.startBox.x+this.startBox.width)-this.startPoint[0],(this.startBox.y+this.startBox.height)-this.startPoint[1]];this.overlay.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.overlay.show();if(this.constrainTo){var a=Ext.get(this.constrainTo);this.resizeRegion=a.getRegion().adjust(a.getFrameWidth("t"),a.getFrameWidth("l"),-a.getFrameWidth("b"),-a.getFrameWidth("r"))}this.proxy.setStyle("visibility","hidden");this.proxy.show();this.proxy.setBox(this.startBox);if(!this.dynamic){this.proxy.setStyle("visibility","visible")}}},onMouseDown:function(a,b){if(this.enabled){b.stopEvent();this.activeHandle=a;this.startSizing(b,a)}},onMouseUp:function(b){this.activeHandle=null;var a=this.resizeElement();this.resizing=false;this.handleOut();this.overlay.hide();this.proxy.hide();this.fireEvent("resize",this,a.width,a.height,b)},updateChildSize:function(){if(this.resizeChild){var d=this.el;var e=this.resizeChild;var c=this.adjustments;if(d.dom.offsetWidth){var a=d.getSize(true);e.setSize(a.width+c[0],a.height+c[1])}if(Ext.isIE){setTimeout(function(){if(d.dom.offsetWidth){var g=d.getSize(true);e.setSize(g.width+c[0],g.height+c[1])}},10)}}},snap:function(c,e,b){if(!e||!c){return c}var d=c;var a=c%e;if(a>0){if(a>(e/2)){d=c+(e-a)}else{d=c-a}}return Math.max(b,d)},resizeElement:function(){var a=this.proxy.getBox();if(this.updateBox){this.el.setBox(a,false,this.animate,this.duration,null,this.easing)}else{this.el.setSize(a.width,a.height,this.animate,this.duration,null,this.easing)}this.updateChildSize();if(!this.dynamic){this.proxy.hide()}if(this.draggable&&this.constrainTo){this.dd.resetConstraints();this.dd.constrainTo(this.constrainTo)}return a},constrain:function(b,c,a,d){if(b-c<a){c=b-a}else{if(b-c>d){c=b-d}}return c},onMouseMove:function(z){if(this.enabled&&this.activeHandle){try{if(this.resizeRegion&&!this.resizeRegion.contains(z.getPoint())){return}var t=this.curSize||this.startBox,l=this.startBox.x,k=this.startBox.y,c=l,b=k,m=t.width,u=t.height,d=m,o=u,n=this.minWidth,A=this.minHeight,s=this.maxWidth,D=this.maxHeight,i=this.widthIncrement,a=this.heightIncrement,B=z.getXY(),r=-(this.startPoint[0]-Math.max(this.minX,B[0])),p=-(this.startPoint[1]-Math.max(this.minY,B[1])),j=this.activeHandle.position,E,g;switch(j){case"east":m+=r;m=Math.min(Math.max(n,m),s);break;case"south":u+=p;u=Math.min(Math.max(A,u),D);break;case"southeast":m+=r;u+=p;m=Math.min(Math.max(n,m),s);u=Math.min(Math.max(A,u),D);break;case"north":p=this.constrain(u,p,A,D);k+=p;u-=p;break;case"west":r=this.constrain(m,r,n,s);l+=r;m-=r;break;case"northeast":m+=r;m=Math.min(Math.max(n,m),s);p=this.constrain(u,p,A,D);k+=p;u-=p;break;case"northwest":r=this.constrain(m,r,n,s);p=this.constrain(u,p,A,D);k+=p;u-=p;l+=r;m-=r;break;case"southwest":r=this.constrain(m,r,n,s);u+=p;u=Math.min(Math.max(A,u),D);l+=r;m-=r;break}var q=this.snap(m,i,n);var C=this.snap(u,a,A);if(q!=m||C!=u){switch(j){case"northeast":k-=C-u;break;case"north":k-=C-u;break;case"southwest":l-=q-m;break;case"west":l-=q-m;break;case"northwest":l-=q-m;k-=C-u;break}m=q;u=C}if(this.preserveRatio){switch(j){case"southeast":case"east":u=o*(m/d);u=Math.min(Math.max(A,u),D);m=d*(u/o);break;case"south":m=d*(u/o);m=Math.min(Math.max(n,m),s);u=o*(m/d);break;case"northeast":m=d*(u/o);m=Math.min(Math.max(n,m),s);u=o*(m/d);break;case"north":E=m;m=d*(u/o);m=Math.min(Math.max(n,m),s);u=o*(m/d);l+=(E-m)/2;break;case"southwest":u=o*(m/d);u=Math.min(Math.max(A,u),D);E=m;m=d*(u/o);l+=E-m;break;case"west":g=u;u=o*(m/d);u=Math.min(Math.max(A,u),D);k+=(g-u)/2;E=m;m=d*(u/o);l+=E-m;break;case"northwest":E=m;g=u;u=o*(m/d);u=Math.min(Math.max(A,u),D);m=d*(u/o);k+=g-u;l+=E-m;break}}this.proxy.setBounds(l,k,m,u);if(this.dynamic){this.resizeElement()}}catch(v){}}},handleOver:function(){if(this.enabled){this.el.addClass("x-resizable-over")}},handleOut:function(){if(!this.resizing){this.el.removeClass("x-resizable-over")}},getEl:function(){return this.el},getResizeChild:function(){return this.resizeChild},destroy:function(b){Ext.destroy(this.dd,this.overlay,this.proxy);this.overlay=null;this.proxy=null;var c=Ext.Resizable.positions;for(var a in c){if(typeof c[a]!="function"&&this[c[a]]){this[c[a]].destroy()}}if(b){this.el.update("");Ext.destroy(this.el);this.el=null}this.purgeListeners()},syncHandleHeight:function(){var a=this.el.getHeight(true);if(this.west){this.west.el.setHeight(a)}if(this.east){this.east.el.setHeight(a)}}});Ext.Resizable.positions={n:"north",s:"south",e:"east",w:"west",se:"southeast",sw:"southwest",nw:"northwest",ne:"northeast"};Ext.Resizable.Handle=Ext.extend(Object,{constructor:function(d,g,c,e,a){if(!this.tpl){var b=Ext.DomHelper.createTemplate({tag:"div",cls:"x-resizable-handle x-resizable-handle-{0}"});b.compile();Ext.Resizable.Handle.prototype.tpl=b}this.position=g;this.rz=d;this.el=this.tpl.append(d.el.dom,[this.position],true);this.el.unselectable();if(e){this.el.setOpacity(0)}if(!Ext.isEmpty(a)){this.el.addClass(a)}this.el.on("mousedown",this.onMouseDown,this);if(!c){this.el.on({scope:this,mouseover:this.onMouseOver,mouseout:this.onMouseOut})}},afterResize:function(a){},onMouseDown:function(a){this.rz.onMouseDown(this,a)},onMouseOver:function(a){this.rz.handleOver(this,a)},onMouseOut:function(a){this.rz.handleOut(this,a)},destroy:function(){Ext.destroy(this.el);this.el=null}});Ext.Window=Ext.extend(Ext.Panel,{baseCls:"x-window",resizable:true,draggable:true,closable:true,closeAction:"close",constrain:false,constrainHeader:false,plain:false,minimizable:false,maximizable:false,minHeight:100,minWidth:200,expandOnShow:true,showAnimDuration:0.25,hideAnimDuration:0.25,collapsible:false,initHidden:undefined,hidden:true,elements:"header,body",frame:true,floating:true,initComponent:function(){this.initTools();Ext.Window.superclass.initComponent.call(this);this.addEvents("resize","maximize","minimize","restore");if(Ext.isDefined(this.initHidden)){this.hidden=this.initHidden}if(this.hidden===false){this.hidden=true;this.show()}},getState:function(){return Ext.apply(Ext.Window.superclass.getState.call(this)||{},this.getBox(true))},onRender:function(b,a){Ext.Window.superclass.onRender.call(this,b,a);if(this.plain){this.el.addClass("x-window-plain")}this.focusEl=this.el.createChild({tag:"a",href:"#",cls:"x-dlg-focus",tabIndex:"-1",html:"&#160;"});this.focusEl.swallowEvent("click",true);this.proxy=this.el.createProxy("x-window-proxy");this.proxy.enableDisplayMode("block");if(this.modal){this.mask=this.container.createChild({cls:"ext-el-mask"},this.el.dom);this.mask.enableDisplayMode("block");this.mask.hide();this.mon(this.mask,"click",this.focus,this)}if(this.maximizable){this.mon(this.header,"dblclick",this.toggleMaximize,this)}},initEvents:function(){Ext.Window.superclass.initEvents.call(this);if(this.animateTarget){this.setAnimateTarget(this.animateTarget)}if(this.resizable){this.resizer=new Ext.Resizable(this.el,{minWidth:this.minWidth,minHeight:this.minHeight,handles:this.resizeHandles||"all",pinned:true,resizeElement:this.resizerAction,handleCls:"x-window-handle"});this.resizer.window=this;this.mon(this.resizer,"beforeresize",this.beforeResize,this)}if(this.draggable){this.header.addClass("x-window-draggable")}this.mon(this.el,"mousedown",this.toFront,this);this.manager=this.manager||Ext.WindowMgr;this.manager.register(this);if(this.maximized){this.maximized=false;this.maximize()}if(this.closable){var a=this.getKeyMap();a.on(27,this.onEsc,this);a.disable()}},initDraggable:function(){this.dd=new Ext.Window.DD(this)},onEsc:function(a,b){if(this.activeGhost){this.unghost()}b.stopEvent();this[this.closeAction]()},beforeDestroy:function(){if(this.rendered){this.hide();this.clearAnchor();Ext.destroy(this.focusEl,this.resizer,this.dd,this.proxy,this.mask)}Ext.Window.superclass.beforeDestroy.call(this)},onDestroy:function(){if(this.manager){this.manager.unregister(this)}Ext.Window.superclass.onDestroy.call(this)},initTools:function(){if(this.minimizable){this.addTool({id:"minimize",handler:this.minimize.createDelegate(this,[])})}if(this.maximizable){this.addTool({id:"maximize",handler:this.maximize.createDelegate(this,[])});this.addTool({id:"restore",handler:this.restore.createDelegate(this,[]),hidden:true})}if(this.closable){this.addTool({id:"close",handler:this[this.closeAction].createDelegate(this,[])})}},resizerAction:function(){var a=this.proxy.getBox();this.proxy.hide();this.window.handleResize(a);return a},beforeResize:function(){this.resizer.minHeight=Math.max(this.minHeight,this.getFrameHeight()+40);this.resizer.minWidth=Math.max(this.minWidth,this.getFrameWidth()+40);this.resizeBox=this.el.getBox()},updateHandles:function(){if(Ext.isIE&&this.resizer){this.resizer.syncHandleHeight();this.el.repaint()}},handleResize:function(b){var a=this.resizeBox;if(a.x!=b.x||a.y!=b.y){this.updateBox(b)}else{this.setSize(b);if(Ext.isIE6&&Ext.isStrict){this.doLayout()}}this.focus();this.updateHandles();this.saveState()},focus:function(){var e=this.focusEl,a=this.defaultButton,c=typeof a,d,b;if(Ext.isDefined(a)){if(Ext.isNumber(a)&&this.fbar){e=this.fbar.items.get(a)}else{if(Ext.isString(a)){e=Ext.getCmp(a)}else{e=a}}d=e.getEl();b=Ext.getDom(this.container);if(d&&b){if(b!=document.body&&!Ext.lib.Region.getRegion(b).contains(Ext.lib.Region.getRegion(d.dom))){return}}}e=e||this.focusEl;e.focus.defer(10,e)},setAnimateTarget:function(a){a=Ext.get(a);this.animateTarget=a},beforeShow:function(){delete this.el.lastXY;delete this.el.lastLT;if(this.x===undefined||this.y===undefined){var a=this.el.getAlignToXY(this.container,"c-c");var b=this.el.translatePoints(a[0],a[1]);this.x=this.x===undefined?b.left:this.x;this.y=this.y===undefined?b.top:this.y}this.el.setLeftTop(this.x,this.y);if(this.expandOnShow){this.expand(false)}if(this.modal){Ext.getBody().addClass("x-body-masked");this.mask.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.mask.show()}},show:function(c,a,b){if(!this.rendered){this.render(Ext.getBody())}if(this.hidden===false){this.toFront();return this}if(this.fireEvent("beforeshow",this)===false){return this}if(a){this.on("show",a,b,{single:true})}this.hidden=false;if(Ext.isDefined(c)){this.setAnimateTarget(c)}this.beforeShow();if(this.animateTarget){this.animShow()}else{this.afterShow()}return this},afterShow:function(b){if(this.isDestroyed){return false}this.proxy.hide();this.el.setStyle("display","block");this.el.show();if(this.maximized){this.fitContainer()}if(Ext.isMac&&Ext.isGecko2){this.cascade(this.setAutoScroll)}if(this.monitorResize||this.modal||this.constrain||this.constrainHeader){Ext.EventManager.onWindowResize(this.onWindowResize,this)}this.doConstrain();this.doLayout();if(this.keyMap){this.keyMap.enable()}this.toFront();this.updateHandles();if(b&&(Ext.isIE||Ext.isWebKit)){var a=this.getSize();this.onResize(a.width,a.height)}this.onShow();this.fireEvent("show",this)},animShow:function(){this.proxy.show();this.proxy.setBox(this.animateTarget.getBox());this.proxy.setOpacity(0);var a=this.getBox();this.el.setStyle("display","none");this.proxy.shift(Ext.apply(a,{callback:this.afterShow.createDelegate(this,[true],false),scope:this,easing:"easeNone",duration:this.showAnimDuration,opacity:0.5}))},hide:function(c,a,b){if(this.hidden||this.fireEvent("beforehide",this)===false){return this}if(a){this.on("hide",a,b,{single:true})}this.hidden=true;if(c!==undefined){this.setAnimateTarget(c)}if(this.modal){this.mask.hide();Ext.getBody().removeClass("x-body-masked")}if(this.animateTarget){this.animHide()}else{this.el.hide();this.afterHide()}return this},afterHide:function(){this.proxy.hide();if(this.monitorResize||this.modal||this.constrain||this.constrainHeader){Ext.EventManager.removeResizeListener(this.onWindowResize,this)}if(this.keyMap){this.keyMap.disable()}this.onHide();this.fireEvent("hide",this)},animHide:function(){this.proxy.setOpacity(0.5);this.proxy.show();var a=this.getBox(false);this.proxy.setBox(a);this.el.hide();this.proxy.shift(Ext.apply(this.animateTarget.getBox(),{callback:this.afterHide,scope:this,duration:this.hideAnimDuration,easing:"easeNone",opacity:0}))},onShow:Ext.emptyFn,onHide:Ext.emptyFn,onWindowResize:function(){if(this.maximized){this.fitContainer()}if(this.modal){this.mask.setSize("100%","100%");var a=this.mask.dom.offsetHeight;this.mask.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true))}this.doConstrain()},doConstrain:function(){if(this.constrain||this.constrainHeader){var b;if(this.constrain){b={right:this.el.shadowOffset,left:this.el.shadowOffset,bottom:this.el.shadowOffset}}else{var a=this.getSize();b={right:-(a.width-100),bottom:-(a.height-25+this.el.getConstrainOffset())}}var c=this.el.getConstrainToXY(this.container,true,b);if(c){this.setPosition(c[0],c[1])}}},ghost:function(a){var c=this.createGhost(a);var b=this.getBox(true);c.setLeftTop(b.x,b.y);c.setWidth(b.width);this.el.hide();this.activeGhost=c;return c},unghost:function(b,a){if(!this.activeGhost){return}if(b!==false){this.el.show();this.focus.defer(10,this);if(Ext.isMac&&Ext.isGecko2){this.cascade(this.setAutoScroll)}}if(a!==false){this.setPosition(this.activeGhost.getLeft(true),this.activeGhost.getTop(true))}this.activeGhost.hide();this.activeGhost.remove();delete this.activeGhost},minimize:function(){this.fireEvent("minimize",this);return this},close:function(){if(this.fireEvent("beforeclose",this)!==false){if(this.hidden){this.doClose()}else{this.hide(null,this.doClose,this)}}},doClose:function(){this.fireEvent("close",this);this.destroy()},maximize:function(){if(!this.maximized){this.expand(false);this.restoreSize=this.getSize();this.restorePos=this.getPosition(true);if(this.maximizable){this.tools.maximize.hide();this.tools.restore.show()}this.maximized=true;this.el.disableShadow();if(this.dd){this.dd.lock()}if(this.collapsible){this.tools.toggle.hide()}this.el.addClass("x-window-maximized");this.container.addClass("x-window-maximized-ct");this.setPosition(0,0);this.fitContainer();this.fireEvent("maximize",this)}return this},restore:function(){if(this.maximized){var a=this.tools;this.el.removeClass("x-window-maximized");if(a.restore){a.restore.hide()}if(a.maximize){a.maximize.show()}this.setPosition(this.restorePos[0],this.restorePos[1]);this.setSize(this.restoreSize.width,this.restoreSize.height);delete this.restorePos;delete this.restoreSize;this.maximized=false;this.el.enableShadow(true);if(this.dd){this.dd.unlock()}if(this.collapsible&&a.toggle){a.toggle.show()}this.container.removeClass("x-window-maximized-ct");this.doConstrain();this.fireEvent("restore",this)}return this},toggleMaximize:function(){return this[this.maximized?"restore":"maximize"]()},fitContainer:function(){var a=this.container.getViewSize(false);this.setSize(a.width,a.height)},setZIndex:function(a){if(this.modal){this.mask.setStyle("z-index",a)}this.el.setZIndex(++a);a+=5;if(this.resizer){this.resizer.proxy.setStyle("z-index",++a)}this.lastZIndex=a},alignTo:function(b,a,c){var d=this.el.getAlignToXY(b,a,c);this.setPagePosition(d[0],d[1]);return this},anchorTo:function(c,e,d,b){this.clearAnchor();this.anchorTarget={el:c,alignment:e,offsets:d};Ext.EventManager.onWindowResize(this.doAnchor,this);var a=typeof b;if(a!="undefined"){Ext.EventManager.on(window,"scroll",this.doAnchor,this,{buffer:a=="number"?b:50})}return this.doAnchor()},doAnchor:function(){var a=this.anchorTarget;this.alignTo(a.el,a.alignment,a.offsets);return this},clearAnchor:function(){if(this.anchorTarget){Ext.EventManager.removeResizeListener(this.doAnchor,this);Ext.EventManager.un(window,"scroll",this.doAnchor,this);delete this.anchorTarget}return this},toFront:function(a){if(this.manager.bringToFront(this)){if(!a||!a.getTarget().focus){this.focus()}}return this},setActive:function(a){if(a){if(!this.maximized){this.el.enableShadow(true)}this.fireEvent("activate",this)}else{this.el.disableShadow();this.fireEvent("deactivate",this)}},toBack:function(){this.manager.sendToBack(this);return this},center:function(){var a=this.el.getAlignToXY(this.container,"c-c");this.setPagePosition(a[0],a[1]);return this}});Ext.reg("window",Ext.Window);Ext.Window.DD=Ext.extend(Ext.dd.DD,{constructor:function(a){this.win=a;Ext.Window.DD.superclass.constructor.call(this,a.el.id,"WindowDD-"+a.id);this.setHandleElId(a.header.id);this.scroll=false},moveOnly:true,headerOffsets:[100,25],startDrag:function(){var a=this.win;this.proxy=a.ghost(a.initialConfig.cls);if(a.constrain!==false){var c=a.el.shadowOffset;this.constrainTo(a.container,{right:c,left:c,bottom:c})}else{if(a.constrainHeader!==false){var b=this.proxy.getSize();this.constrainTo(a.container,{right:-(b.width-this.headerOffsets[0]),bottom:-(b.height-this.headerOffsets[1])})}}},b4Drag:Ext.emptyFn,onDrag:function(a){this.alignElWithMouse(this.proxy,a.getPageX(),a.getPageY())},endDrag:function(a){this.win.unghost();this.win.saveState()}});Ext.WindowGroup=function(){var g={};var d=[];var e=null;var c=function(j,i){return(!j._lastAccess||j._lastAccess<i._lastAccess)?-1:1};var h=function(){var l=d,j=l.length;if(j>0){l.sort(c);var k=l[0].manager.zseed;for(var m=0;m<j;m++){var n=l[m];if(n&&!n.hidden){n.setZIndex(k+(m*10))}}}a()};var b=function(i){if(i!=e){if(e){e.setActive(false)}e=i;if(i){i.setActive(true)}}};var a=function(){for(var j=d.length-1;j>=0;--j){if(!d[j].hidden){b(d[j]);return}}b(null)};return{zseed:9000,register:function(i){if(i.manager){i.manager.unregister(i)}i.manager=this;g[i.id]=i;d.push(i);i.on("hide",a)},unregister:function(i){delete i.manager;delete g[i.id];i.un("hide",a);d.remove(i)},get:function(i){return typeof i=="object"?i:g[i]},bringToFront:function(i){i=this.get(i);if(i!=e){i._lastAccess=new Date().getTime();h();return true}return false},sendToBack:function(i){i=this.get(i);i._lastAccess=-(new Date().getTime());h();return i},hideAll:function(){for(var i in g){if(g[i]&&typeof g[i]!="function"&&g[i].isVisible()){g[i].hide()}}},getActive:function(){return e},getBy:function(l,k){var m=[];for(var j=d.length-1;j>=0;--j){var n=d[j];if(l.call(k||n,n)!==false){m.push(n)}}return m},each:function(j,i){for(var k in g){if(g[k]&&typeof g[k]!="function"){if(j.call(i||g[k],g[k])===false){return}}}}}};Ext.WindowMgr=new Ext.WindowGroup();Ext.MessageBox=function(){var u,b,q,t,h,l,s,a,n,p,j,g,r,v,o,i="",d="",m=["ok","yes","no","cancel"];var c=function(x){r[x].blur();if(u.isVisible()){u.hide();w();Ext.callback(b.fn,b.scope||window,[x,v.dom.value,b],1)}};var w=function(){if(b&&b.cls){u.el.removeClass(b.cls)}n.reset()};var e=function(z,x,y){if(b&&b.closable!==false){u.hide();w()}if(y){y.stopEvent()}};var k=function(x){var z=0,y;if(!x){Ext.each(m,function(A){r[A].hide()});return z}u.footer.dom.style.display="";Ext.iterate(r,function(A,B){y=x[A];if(y){B.show();B.setText(Ext.isString(y)?y:Ext.MessageBox.buttonText[A]);z+=B.getEl().getWidth()+15}else{B.hide()}});return z};return{getDialog:function(x){if(!u){var z=[];r={};Ext.each(m,function(A){z.push(r[A]=new Ext.Button({text:this.buttonText[A],handler:c.createCallback(A),hideMode:"offsets"}))},this);u=new Ext.Window({autoCreate:true,title:x,resizable:false,constrain:true,constrainHeader:true,minimizable:false,maximizable:false,stateful:false,modal:true,shim:true,buttonAlign:"center",width:400,height:100,minHeight:80,plain:true,footer:true,closable:true,close:function(){if(b&&b.buttons&&b.buttons.no&&!b.buttons.cancel){c("no")}else{c("cancel")}},fbar:new Ext.Toolbar({items:z,enableOverflow:false})});u.render(document.body);u.getEl().addClass("x-window-dlg");q=u.mask;h=u.body.createChild({html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'});j=Ext.get(h.dom.firstChild);var y=h.dom.childNodes[1];l=Ext.get(y.firstChild);s=Ext.get(y.childNodes[2].firstChild);s.enableDisplayMode();s.addKeyListener([10,13],function(){if(u.isVisible()&&b&&b.buttons){if(b.buttons.ok){c("ok")}else{if(b.buttons.yes){c("yes")}}}});a=Ext.get(y.childNodes[2].childNodes[1]);a.enableDisplayMode();n=new Ext.ProgressBar({renderTo:h});h.createChild({cls:"x-clear"})}return u},updateText:function(A){if(!u.isVisible()&&!b.width){u.setSize(this.maxWidth,100)}l.update(A?A+" ":"&#160;");var y=d!=""?(j.getWidth()+j.getMargins("lr")):0,C=l.getWidth()+l.getMargins("lr"),z=u.getFrameWidth("lr"),B=u.body.getFrameWidth("lr"),x;x=Math.max(Math.min(b.width||y+C+z+B,b.maxWidth||this.maxWidth),Math.max(b.minWidth||this.minWidth,o||0));if(b.prompt===true){v.setWidth(x-y-z-B)}if(b.progress===true||b.wait===true){n.setSize(x-y-z-B)}if(Ext.isIE&&x==o){x+=4}l.update(A||"&#160;");u.setSize(x,"auto").center();return this},updateProgress:function(y,x,z){n.updateProgress(y,x);if(z){this.updateText(z)}return this},isVisible:function(){return u&&u.isVisible()},hide:function(){var x=u?u.activeGhost:null;if(this.isVisible()||x){u.hide();w();if(x){u.unghost(false,false)}}return this},show:function(A){if(this.isVisible()){this.hide()}b=A;var B=this.getDialog(b.title||"&#160;");B.setTitle(b.title||"&#160;");var x=(b.closable!==false&&b.progress!==true&&b.wait!==true);B.tools.close.setDisplayed(x);v=s;b.prompt=b.prompt||(b.multiline?true:false);if(b.prompt){if(b.multiline){s.hide();a.show();a.setHeight(Ext.isNumber(b.multiline)?b.multiline:this.defaultTextHeight);v=a}else{s.show();a.hide()}}else{s.hide();a.hide()}v.dom.value=b.value||"";if(b.prompt){B.focusEl=v}else{var z=b.buttons;var y=null;if(z&&z.ok){y=r.ok}else{if(z&&z.yes){y=r.yes}}if(y){B.focusEl=y}}if(Ext.isDefined(b.iconCls)){B.setIconClass(b.iconCls)}this.setIcon(Ext.isDefined(b.icon)?b.icon:i);o=k(b.buttons);n.setVisible(b.progress===true||b.wait===true);this.updateProgress(0,b.progressText);this.updateText(b.msg);if(b.cls){B.el.addClass(b.cls)}B.proxyDrag=b.proxyDrag===true;B.modal=b.modal!==false;B.mask=b.modal!==false?q:false;if(!B.isVisible()){document.body.appendChild(u.el.dom);B.setAnimateTarget(b.animEl);B.on("show",function(){if(x===true){B.keyMap.enable()}else{B.keyMap.disable()}},this,{single:true});B.show(b.animEl)}if(b.wait===true){n.wait(b.waitConfig)}return this},setIcon:function(x){if(!u){i=x;return}i=undefined;if(x&&x!=""){j.removeClass("x-hidden");j.replaceClass(d,x);h.addClass("x-dlg-icon");d=x}else{j.replaceClass(d,"x-hidden");h.removeClass("x-dlg-icon");d=""}return this},progress:function(z,y,x){this.show({title:z,msg:y,buttons:false,progress:true,closable:false,minWidth:this.minProgressWidth,progressText:x});return this},wait:function(z,y,x){this.show({title:y,msg:z,buttons:false,closable:false,wait:true,modal:true,minWidth:this.minProgressWidth,waitConfig:x});return this},alert:function(A,z,y,x){this.show({title:A,msg:z,buttons:this.OK,fn:y,scope:x,minWidth:this.minWidth});return this},confirm:function(A,z,y,x){this.show({title:A,msg:z,buttons:this.YESNO,fn:y,scope:x,icon:this.QUESTION,minWidth:this.minWidth});return this},prompt:function(C,B,z,y,x,A){this.show({title:C,msg:B,buttons:this.OKCANCEL,fn:z,minWidth:this.minPromptWidth,scope:y,prompt:true,multiline:x,value:A});return this},OK:{ok:true},CANCEL:{cancel:true},OKCANCEL:{ok:true,cancel:true},YESNO:{yes:true,no:true},YESNOCANCEL:{yes:true,no:true,cancel:true},INFO:"ext-mb-info",WARNING:"ext-mb-warning",QUESTION:"ext-mb-question",ERROR:"ext-mb-error",defaultTextHeight:75,maxWidth:600,minWidth:100,minProgressWidth:250,minPromptWidth:250,buttonText:{ok:"OK",cancel:"Cancel",yes:"Yes",no:"No"}}}();Ext.Msg=Ext.MessageBox;Ext.dd.PanelProxy=Ext.extend(Object,{constructor:function(a,b){this.panel=a;this.id=this.panel.id+"-ddproxy";Ext.apply(this,b)},insertProxy:true,setStatus:Ext.emptyFn,reset:Ext.emptyFn,update:Ext.emptyFn,stop:Ext.emptyFn,sync:Ext.emptyFn,getEl:function(){return this.ghost},getGhost:function(){return this.ghost},getProxy:function(){return this.proxy},hide:function(){if(this.ghost){if(this.proxy){this.proxy.remove();delete this.proxy}this.panel.el.dom.style.display="";this.ghost.remove();delete this.ghost}},show:function(){if(!this.ghost){this.ghost=this.panel.createGhost(this.panel.initialConfig.cls,undefined,Ext.getBody());this.ghost.setXY(this.panel.el.getXY());if(this.insertProxy){this.proxy=this.panel.el.insertSibling({cls:"x-panel-dd-spacer"});this.proxy.setSize(this.panel.getSize())}this.panel.el.dom.style.display="none"}},repair:function(b,c,a){this.hide();if(typeof c=="function"){c.call(a||this)}},moveProxy:function(a,b){if(this.proxy){a.insertBefore(this.proxy.dom,b)}}});Ext.Panel.DD=Ext.extend(Ext.dd.DragSource,{constructor:function(b,a){this.panel=b;this.dragData={panel:b};this.proxy=new Ext.dd.PanelProxy(b,a);Ext.Panel.DD.superclass.constructor.call(this,b.el,a);var d=b.header,c=b.body;if(d){this.setHandleElId(d.id);c=b.header}c.setStyle("cursor","move");this.scroll=false},showFrame:Ext.emptyFn,startDrag:Ext.emptyFn,b4StartDrag:function(a,b){this.proxy.show()},b4MouseDown:function(b){var a=b.getPageX(),c=b.getPageY();this.autoOffset(a,c)},onInitDrag:function(a,b){this.onStartDrag(a,b);return true},createFrame:Ext.emptyFn,getDragEl:function(a){return this.proxy.ghost.dom},endDrag:function(a){this.proxy.hide();this.panel.saveState()},autoOffset:function(a,b){a-=this.startPageX;b-=this.startPageY;this.setDelta(a,b)}});Ext.state.Provider=Ext.extend(Ext.util.Observable,{constructor:function(){this.addEvents("statechange");this.state={};Ext.state.Provider.superclass.constructor.call(this)},get:function(b,a){return typeof this.state[b]=="undefined"?a:this.state[b]},clear:function(a){delete this.state[a];this.fireEvent("statechange",this,a,null)},set:function(a,b){this.state[a]=b;this.fireEvent("statechange",this,a,b)},decodeValue:function(b){var e=/^(a|n|d|b|s|o|e)\:(.*)$/,h=e.exec(unescape(b)),d,c,a,g;if(!h||!h[1]){return}c=h[1];a=h[2];switch(c){case"e":return null;case"n":return parseFloat(a);case"d":return new Date(Date.parse(a));case"b":return(a=="1");case"a":d=[];if(a!=""){Ext.each(a.split("^"),function(i){d.push(this.decodeValue(i))},this)}return d;case"o":d={};if(a!=""){Ext.each(a.split("^"),function(i){g=i.split("=");d[g[0]]=this.decodeValue(g[1])},this)}return d;default:return a}},encodeValue:function(c){var b,g="",e=0,a,d;if(c==null){return"e:1"}else{if(typeof c=="number"){b="n:"+c}else{if(typeof c=="boolean"){b="b:"+(c?"1":"0")}else{if(Ext.isDate(c)){b="d:"+c.toGMTString()}else{if(Ext.isArray(c)){for(a=c.length;e<a;e++){g+=this.encodeValue(c[e]);if(e!=a-1){g+="^"}}b="a:"+g}else{if(typeof c=="object"){for(d in c){if(typeof c[d]!="function"&&c[d]!==undefined){g+=d+"="+this.encodeValue(c[d])+"^"}}b="o:"+g.substring(0,g.length-1)}else{b="s:"+c}}}}}}return escape(b)}});Ext.state.Manager=function(){var a=new Ext.state.Provider();return{setProvider:function(b){a=b},get:function(c,b){return a.get(c,b)},set:function(b,c){a.set(b,c)},clear:function(b){a.clear(b)},getProvider:function(){return a}}}();Ext.state.CookieProvider=Ext.extend(Ext.state.Provider,{constructor:function(a){Ext.state.CookieProvider.superclass.constructor.call(this);this.path="/";this.expires=new Date(new Date().getTime()+(1000*60*60*24*7));this.domain=null;this.secure=false;Ext.apply(this,a);this.state=this.readCookies()},set:function(a,b){if(typeof b=="undefined"||b===null){this.clear(a);return}this.setCookie(a,b);Ext.state.CookieProvider.superclass.set.call(this,a,b)},clear:function(a){this.clearCookie(a);Ext.state.CookieProvider.superclass.clear.call(this,a)},readCookies:function(){var d={},h=document.cookie+";",b=/\s?(.*?)=(.*?);/g,g,a,e;while((g=b.exec(h))!=null){a=g[1];e=g[2];if(a&&a.substring(0,3)=="ys-"){d[a.substr(3)]=this.decodeValue(e)}}return d},setCookie:function(a,b){document.cookie="ys-"+a+"="+this.encodeValue(b)+((this.expires==null)?"":("; expires="+this.expires.toGMTString()))+((this.path==null)?"":("; path="+this.path))+((this.domain==null)?"":("; domain="+this.domain))+((this.secure==true)?"; secure":"")},clearCookie:function(a){document.cookie="ys-"+a+"=null; expires=Thu, 01-Jan-70 00:00:01 GMT"+((this.path==null)?"":("; path="+this.path))+((this.domain==null)?"":("; domain="+this.domain))+((this.secure==true)?"; secure":"")}});Ext.DataView=Ext.extend(Ext.BoxComponent,{selectedClass:"x-view-selected",emptyText:"",deferEmptyText:true,trackOver:false,blockRefresh:false,last:false,initComponent:function(){Ext.DataView.superclass.initComponent.call(this);if(Ext.isString(this.tpl)||Ext.isArray(this.tpl)){this.tpl=new Ext.XTemplate(this.tpl)}this.addEvents("beforeclick","click","mouseenter","mouseleave","containerclick","dblclick","contextmenu","containercontextmenu","selectionchange","beforeselect");this.store=Ext.StoreMgr.lookup(this.store);this.all=new Ext.CompositeElementLite();this.selected=new Ext.CompositeElementLite()},afterRender:function(){Ext.DataView.superclass.afterRender.call(this);this.mon(this.getTemplateTarget(),{click:this.onClick,dblclick:this.onDblClick,contextmenu:this.onContextMenu,scope:this});if(this.overClass||this.trackOver){this.mon(this.getTemplateTarget(),{mouseover:this.onMouseOver,mouseout:this.onMouseOut,scope:this})}if(this.store){this.bindStore(this.store,true)}},refresh:function(){this.clearSelections(false,true);var b=this.getTemplateTarget(),a=this.store.getRange();b.update("");if(a.length<1){if(!this.deferEmptyText||this.hasSkippedEmptyText){b.update(this.emptyText)}this.all.clear()}else{this.tpl.overwrite(b,this.collectData(a,0));this.all.fill(Ext.query(this.itemSelector,b.dom));this.updateIndexes(0)}this.hasSkippedEmptyText=true},getTemplateTarget:function(){return this.el},prepareData:function(a){return a},collectData:function(b,e){var d=[],c=0,a=b.length;for(;c<a;c++){d[d.length]=this.prepareData(b[c].data,e+c,b[c])}return d},bufferRender:function(a,b){var c=document.createElement("div");this.tpl.overwrite(c,this.collectData(a,b));return Ext.query(this.itemSelector,c)},onUpdate:function(g,a){var b=this.store.indexOf(a);if(b>-1){var e=this.isSelected(b),c=this.all.elements[b],d=this.bufferRender([a],b)[0];this.all.replaceElement(b,d,true);if(e){this.selected.replaceElement(c,d);this.all.item(b).addClass(this.selectedClass)}this.updateIndexes(b,b)}},onAdd:function(g,d,e){if(this.all.getCount()===0){this.refresh();return}var c=this.bufferRender(d,e),h,b=this.all.elements;if(e<this.all.getCount()){h=this.all.item(e).insertSibling(c,"before",true);b.splice.apply(b,[e,0].concat(c))}else{h=this.all.last().insertSibling(c,"after",true);b.push.apply(b,c)}this.updateIndexes(e)},onRemove:function(c,a,b){this.deselect(b);this.all.removeElement(b,true);this.updateIndexes(b);if(this.store.getCount()===0){this.refresh()}},refreshNode:function(a){this.onUpdate(this.store,this.store.getAt(a))},updateIndexes:function(d,c){var b=this.all.elements;d=d||0;c=c||((c===0)?0:(b.length-1));for(var a=d;a<=c;a++){b[a].viewIndex=a}},getStore:function(){return this.store},bindStore:function(a,b){if(!b&&this.store){if(a!==this.store&&this.store.autoDestroy){this.store.destroy()}else{this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("datachanged",this.onDataChanged,this);this.store.un("add",this.onAdd,this);this.store.un("remove",this.onRemove,this);this.store.un("update",this.onUpdate,this);this.store.un("clear",this.refresh,this)}if(!a){this.store=null}}if(a){a=Ext.StoreMgr.lookup(a);a.on({scope:this,beforeload:this.onBeforeLoad,datachanged:this.onDataChanged,add:this.onAdd,remove:this.onRemove,update:this.onUpdate,clear:this.refresh})}this.store=a;if(a){this.refresh()}},onDataChanged:function(){if(this.blockRefresh!==true){this.refresh.apply(this,arguments)}},findItemFromChild:function(a){return Ext.fly(a).findParent(this.itemSelector,this.getTemplateTarget())},onClick:function(c){var b=c.getTarget(this.itemSelector,this.getTemplateTarget()),a;if(b){a=this.indexOf(b);if(this.onItemClick(b,a,c)!==false){this.fireEvent("click",this,a,b,c)}}else{if(this.fireEvent("containerclick",this,c)!==false){this.onContainerClick(c)}}},onContainerClick:function(a){this.clearSelections()},onContextMenu:function(b){var a=b.getTarget(this.itemSelector,this.getTemplateTarget());if(a){this.fireEvent("contextmenu",this,this.indexOf(a),a,b)}else{this.fireEvent("containercontextmenu",this,b)}},onDblClick:function(b){var a=b.getTarget(this.itemSelector,this.getTemplateTarget());if(a){this.fireEvent("dblclick",this,this.indexOf(a),a,b)}},onMouseOver:function(b){var a=b.getTarget(this.itemSelector,this.getTemplateTarget());if(a&&a!==this.lastItem){this.lastItem=a;Ext.fly(a).addClass(this.overClass);this.fireEvent("mouseenter",this,this.indexOf(a),a,b)}},onMouseOut:function(a){if(this.lastItem){if(!a.within(this.lastItem,true,true)){Ext.fly(this.lastItem).removeClass(this.overClass);this.fireEvent("mouseleave",this,this.indexOf(this.lastItem),this.lastItem,a);delete this.lastItem}}},onItemClick:function(b,a,c){if(this.fireEvent("beforeclick",this,a,b,c)===false){return false}if(this.multiSelect){this.doMultiSelection(b,a,c);c.preventDefault()}else{if(this.singleSelect){this.doSingleSelection(b,a,c);c.preventDefault()}}return true},doSingleSelection:function(b,a,c){if(c.ctrlKey&&this.isSelected(a)){this.deselect(a)}else{this.select(a,false)}},doMultiSelection:function(c,a,d){if(d.shiftKey&&this.last!==false){var b=this.last;this.selectRange(b,a,d.ctrlKey);this.last=b}else{if((d.ctrlKey||this.simpleSelect)&&this.isSelected(a)){this.deselect(a)}else{this.select(a,d.ctrlKey||d.shiftKey||this.simpleSelect)}}},getSelectionCount:function(){return this.selected.getCount()},getSelectedNodes:function(){return this.selected.elements},getSelectedIndexes:function(){var b=[],d=this.selected.elements,c=0,a=d.length;for(;c<a;c++){b.push(d[c].viewIndex)}return b},getSelectedRecords:function(){return this.getRecords(this.selected.elements)},getRecords:function(c){var b=[],d=0,a=c.length;for(;d<a;d++){b[b.length]=this.store.getAt(c[d].viewIndex)}return b},getRecord:function(a){return this.store.getAt(a.viewIndex)},clearSelections:function(a,b){if((this.multiSelect||this.singleSelect)&&this.selected.getCount()>0){if(!b){this.selected.removeClass(this.selectedClass)}this.selected.clear();this.last=false;if(!a){this.fireEvent("selectionchange",this,this.selected.elements)}}},isSelected:function(a){return this.selected.contains(this.getNode(a))},deselect:function(a){if(this.isSelected(a)){a=this.getNode(a);this.selected.removeElement(a);if(this.last==a.viewIndex){this.last=false}Ext.fly(a).removeClass(this.selectedClass);this.fireEvent("selectionchange",this,this.selected.elements)}},select:function(d,g,b){if(Ext.isArray(d)){if(!g){this.clearSelections(true)}for(var c=0,a=d.length;c<a;c++){this.select(d[c],true,true)}if(!b){this.fireEvent("selectionchange",this,this.selected.elements)}}else{var e=this.getNode(d);if(!g){this.clearSelections(true)}if(e&&!this.isSelected(e)){if(this.fireEvent("beforeselect",this,e,this.selected.elements)!==false){Ext.fly(e).addClass(this.selectedClass);this.selected.add(e);this.last=e.viewIndex;if(!b){this.fireEvent("selectionchange",this,this.selected.elements)}}}}},selectRange:function(c,a,b){if(!b){this.clearSelections(true)}this.select(this.getNodes(c,a),true)},getNode:function(b){if(Ext.isString(b)){return document.getElementById(b)}else{if(Ext.isNumber(b)){return this.all.elements[b]}else{if(b instanceof Ext.data.Record){var a=this.store.indexOf(b);return this.all.elements[a]}}}return b},getNodes:function(e,a){var d=this.all.elements,b=[],c;e=e||0;a=!Ext.isDefined(a)?Math.max(d.length-1,0):a;if(e<=a){for(c=e;c<=a&&d[c];c++){b.push(d[c])}}else{for(c=e;c>=a&&d[c];c--){b.push(d[c])}}return b},indexOf:function(a){a=this.getNode(a);if(Ext.isNumber(a.viewIndex)){return a.viewIndex}return this.all.indexOf(a)},onBeforeLoad:function(){if(this.loadingText){this.clearSelections(false,true);this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+"</div>");this.all.clear()}},onDestroy:function(){this.all.clear();this.selected.clear();Ext.DataView.superclass.onDestroy.call(this);this.bindStore(null)}});Ext.DataView.prototype.setStore=Ext.DataView.prototype.bindStore;Ext.reg("dataview",Ext.DataView);Ext.list.ListView=Ext.extend(Ext.DataView,{itemSelector:"dl",selectedClass:"x-list-selected",overClass:"x-list-over",scrollOffset:undefined,columnResize:true,columnSort:true,maxColumnWidth:Ext.isIE?99:100,initComponent:function(){if(this.columnResize){this.colResizer=new Ext.list.ColumnResizer(this.colResizer);this.colResizer.init(this)}if(this.columnSort){this.colSorter=new Ext.list.Sorter(this.columnSort);this.colSorter.init(this)}if(!this.internalTpl){this.internalTpl=new Ext.XTemplate('<div class="x-list-header"><div class="x-list-header-inner">','<tpl for="columns">','<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id,'-xlhd-{#}">',"{header}","</em></div>","</tpl>",'<div class="x-clear"></div>',"</div></div>",'<div class="x-list-body"><div class="x-list-body-inner">',"</div></div>")}if(!this.tpl){this.tpl=new Ext.XTemplate('<tpl for="rows">',"<dl>",'<tpl for="parent.columns">','<dt style="width:{[values.width*100]}%;text-align:{align};">','<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',"{[values.tpl.apply(parent)]}","</em></dt>","</tpl>",'<div class="x-clear"></div>',"</dl>","</tpl>")}var l=this.columns,h=0,k=0,m=l.length,b=[];for(var g=0;g<m;g++){var n=l[g];if(!n.isColumn){n.xtype=n.xtype?(/^lv/.test(n.xtype)?n.xtype:"lv"+n.xtype):"lvcolumn";n=Ext.create(n)}if(n.width){h+=n.width*100;if(h>this.maxColumnWidth){n.width-=(h-this.maxColumnWidth)/100}k++}b.push(n)}l=this.columns=b;if(k<m){var d=m-k;if(h<this.maxColumnWidth){var a=((this.maxColumnWidth-h)/d)/100;for(var e=0;e<m;e++){var n=l[e];if(!n.width){n.width=a}}}}Ext.list.ListView.superclass.initComponent.call(this)},onRender:function(){this.autoEl={cls:"x-list-wrap"};Ext.list.ListView.superclass.onRender.apply(this,arguments);this.internalTpl.overwrite(this.el,{columns:this.columns});this.innerBody=Ext.get(this.el.dom.childNodes[1].firstChild);this.innerHd=Ext.get(this.el.dom.firstChild.firstChild);if(this.hideHeaders){this.el.dom.firstChild.style.display="none"}},getTemplateTarget:function(){return this.innerBody},collectData:function(){var a=Ext.list.ListView.superclass.collectData.apply(this,arguments);return{columns:this.columns,rows:a}},verifyInternalSize:function(){if(this.lastSize){this.onResize(this.lastSize.width,this.lastSize.height)}},onResize:function(c,e){var b=this.innerBody.dom,g=this.innerHd.dom,d=c-Ext.num(this.scrollOffset,Ext.getScrollBarWidth())+"px",a;if(!b){return}a=b.parentNode;if(Ext.isNumber(c)){if(this.reserveScrollOffset||((a.offsetWidth-a.clientWidth)>10)){b.style.width=d;g.style.width=d}else{b.style.width=c+"px";g.style.width=c+"px";setTimeout(function(){if((a.offsetWidth-a.clientWidth)>10){b.style.width=d;g.style.width=d}},10)}}if(Ext.isNumber(e)){a.style.height=Math.max(0,e-g.parentNode.offsetHeight)+"px"}},updateIndexes:function(){Ext.list.ListView.superclass.updateIndexes.apply(this,arguments);this.verifyInternalSize()},findHeaderIndex:function(g){g=g.dom||g;var a=g.parentNode,d=a.parentNode.childNodes,b=0,e;for(;e=d[b];b++){if(e==a){return b}}return -1},setHdWidths:function(){var d=this.innerHd.dom.getElementsByTagName("div"),c=0,b=this.columns,a=b.length;for(;c<a;c++){d[c].style.width=(b[c].width*100)+"%"}}});Ext.reg("listview",Ext.list.ListView);Ext.ListView=Ext.list.ListView;Ext.list.Column=Ext.extend(Object,{isColumn:true,align:"left",header:"",width:null,cls:"",constructor:function(a){if(!a.tpl){a.tpl=new Ext.XTemplate("{"+a.dataIndex+"}")}else{if(Ext.isString(a.tpl)){a.tpl=new Ext.XTemplate(a.tpl)}}Ext.apply(this,a)}});Ext.reg("lvcolumn",Ext.list.Column);Ext.list.NumberColumn=Ext.extend(Ext.list.Column,{format:"0,000.00",constructor:function(a){a.tpl=a.tpl||new Ext.XTemplate("{"+a.dataIndex+':number("'+(a.format||this.format)+'")}');Ext.list.NumberColumn.superclass.constructor.call(this,a)}});Ext.reg("lvnumbercolumn",Ext.list.NumberColumn);Ext.list.DateColumn=Ext.extend(Ext.list.Column,{format:"m/d/Y",constructor:function(a){a.tpl=a.tpl||new Ext.XTemplate("{"+a.dataIndex+':date("'+(a.format||this.format)+'")}');Ext.list.DateColumn.superclass.constructor.call(this,a)}});Ext.reg("lvdatecolumn",Ext.list.DateColumn);Ext.list.BooleanColumn=Ext.extend(Ext.list.Column,{trueText:"true",falseText:"false",undefinedText:"&#160;",constructor:function(e){e.tpl=e.tpl||new Ext.XTemplate("{"+e.dataIndex+":this.format}");var b=this.trueText,d=this.falseText,a=this.undefinedText;e.tpl.format=function(c){if(c===undefined){return a}if(!c||c==="false"){return d}return b};Ext.list.DateColumn.superclass.constructor.call(this,e)}});Ext.reg("lvbooleancolumn",Ext.list.BooleanColumn);Ext.list.ColumnResizer=Ext.extend(Ext.util.Observable,{minPct:0.05,constructor:function(a){Ext.apply(this,a);Ext.list.ColumnResizer.superclass.constructor.call(this)},init:function(a){this.view=a;a.on("render",this.initEvents,this)},initEvents:function(a){a.mon(a.innerHd,"mousemove",this.handleHdMove,this);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeStart.createDelegate(this),onStart:this.onStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(a.innerHd);a.on("beforedestroy",this.tracker.destroy,this.tracker)},handleHdMove:function(i,d){var c=5,b=i.getPageX(),j=i.getTarget("em",3,true);if(j){var h=j.getRegion(),g=j.dom.style,a=j.dom.parentNode;if(b-h.left<=c&&a!=a.parentNode.firstChild){this.activeHd=Ext.get(a.previousSibling.firstChild);g.cursor=Ext.isWebKit?"e-resize":"col-resize"}else{if(h.right-b<=c&&a!=a.parentNode.lastChild.previousSibling){this.activeHd=j;g.cursor=Ext.isWebKit?"w-resize":"col-resize"}else{delete this.activeHd;g.cursor=""}}}},onBeforeStart:function(a){this.dragHd=this.activeHd;return !!this.dragHd},onStart:function(g){var d=this,b=d.view,c=d.dragHd,a=d.tracker.getXY()[0];d.proxy=b.el.createChild({cls:"x-list-resizer"});d.dragX=c.getX();d.headerIndex=b.findHeaderIndex(c);d.headersDisabled=b.disableHeaders;b.disableHeaders=true;d.proxy.setHeight(b.el.getHeight());d.proxy.setX(d.dragX);d.proxy.setWidth(a-d.dragX);this.setBoundaries()},setBoundaries:function(j){var k=this.view,h=this.headerIndex,c=k.innerHd.getWidth(),j=k.innerHd.getX(),b=Math.ceil(c*this.minPct),l=c-b,e=k.columns.length,d=k.innerHd.select("em",true),g=b+j,a=l+j,i;if(e==2){this.minX=g;this.maxX=a}else{i=d.item(h+2);this.minX=d.item(h).getX()+b;this.maxX=i?i.getX()-b:a;if(h==0){this.minX=g}else{if(h==e-2){this.maxX=a}}}},onDrag:function(c){var b=this,a=b.tracker.getXY()[0].constrain(b.minX,b.maxX);b.proxy.setWidth(a-this.dragX)},onEnd:function(i){var g=this.proxy.getWidth(),h=this.headerIndex,l=this.view,c=l.columns,b=l.innerHd.getWidth(),k=Math.ceil(g*l.maxColumnWidth/b)/100,d=this.headersDisabled,m=c[h],j=c[h+1],a=m.width+j.width;this.proxy.remove();m.width=k;j.width=a-k;delete this.dragHd;l.setHdWidths();l.refresh();setTimeout(function(){l.disableHeaders=d},100)}});Ext.ListView.ColumnResizer=Ext.list.ColumnResizer;Ext.list.Sorter=Ext.extend(Ext.util.Observable,{sortClasses:["sort-asc","sort-desc"],constructor:function(a){Ext.apply(this,a);Ext.list.Sorter.superclass.constructor.call(this)},init:function(a){this.view=a;a.on("render",this.initEvents,this)},initEvents:function(a){a.mon(a.innerHd,"click",this.onHdClick,this);a.innerHd.setStyle("cursor","pointer");a.mon(a.store,"datachanged",this.updateSortState,this);this.updateSortState.defer(10,this,[a.store])},updateSortState:function(c){var g=c.getSortState();if(!g){return}this.sortState=g;var e=this.view.columns,h=-1;for(var d=0,a=e.length;d<a;d++){if(e[d].dataIndex==g.field){h=d;break}}if(h!=-1){var b=g.direction;this.updateSortIcon(h,b)}},updateSortIcon:function(b,a){var d=this.sortClasses;var c=this.view.innerHd.select("em").removeClass(d);c.item(b).addClass(d[a=="DESC"?1:0])},onHdClick:function(c){var b=c.getTarget("em",3);if(b&&!this.view.disableHeaders){var a=this.view.findHeaderIndex(b);this.view.store.sort(this.view.columns[a].dataIndex)}}});Ext.ListView.Sorter=Ext.list.Sorter;Ext.TabPanel=Ext.extend(Ext.Panel,{deferredRender:true,tabWidth:120,minTabWidth:30,resizeTabs:false,enableTabScroll:false,scrollIncrement:0,scrollRepeatInterval:400,scrollDuration:0.35,animScroll:true,tabPosition:"top",baseCls:"x-tab-panel",autoTabs:false,autoTabSelector:"div.x-tab",activeTab:undefined,tabMargin:2,plain:false,wheelIncrement:20,idDelimiter:"__",itemCls:"x-tab-item",elements:"body",headerAsText:false,frame:false,hideBorders:true,initComponent:function(){this.frame=false;Ext.TabPanel.superclass.initComponent.call(this);this.addEvents("beforetabchange","tabchange","contextmenu");this.setLayout(new Ext.layout.CardLayout(Ext.apply({layoutOnCardChange:this.layoutOnTabChange,deferredRender:this.deferredRender},this.layoutConfig)));if(this.tabPosition=="top"){this.elements+=",header";this.stripTarget="header"}else{this.elements+=",footer";this.stripTarget="footer"}if(!this.stack){this.stack=Ext.TabPanel.AccessStack()}this.initItems()},onRender:function(c,a){Ext.TabPanel.superclass.onRender.call(this,c,a);if(this.plain){var g=this.tabPosition=="top"?"header":"footer";this[g].addClass("x-tab-panel-"+g+"-plain")}var b=this[this.stripTarget];this.stripWrap=b.createChild({cls:"x-tab-strip-wrap",cn:{tag:"ul",cls:"x-tab-strip x-tab-strip-"+this.tabPosition}});var e=(this.tabPosition=="bottom"?this.stripWrap:null);b.createChild({cls:"x-tab-strip-spacer"},e);this.strip=new Ext.Element(this.stripWrap.dom.firstChild);this.edge=this.strip.createChild({tag:"li",cls:"x-tab-edge",cn:[{tag:"span",cls:"x-tab-strip-text",cn:"&#160;"}]});this.strip.createChild({cls:"x-clear"});this.body.addClass("x-tab-panel-body-"+this.tabPosition);if(!this.itemTpl){var d=new Ext.Template('<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>','<a class="x-tab-right" href="#"><em class="x-tab-left">','<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',"</em></a></li>");d.disableFormats=true;d.compile();Ext.TabPanel.prototype.itemTpl=d}this.items.each(this.initTab,this)},afterRender:function(){Ext.TabPanel.superclass.afterRender.call(this);if(this.autoTabs){this.readTabs(false)}if(this.activeTab!==undefined){var a=Ext.isObject(this.activeTab)?this.activeTab:this.items.get(this.activeTab);delete this.activeTab;this.setActiveTab(a)}},initEvents:function(){Ext.TabPanel.superclass.initEvents.call(this);this.mon(this.strip,{scope:this,mousedown:this.onStripMouseDown,contextmenu:this.onStripContextMenu});if(this.enableTabScroll){this.mon(this.strip,"mousewheel",this.onWheel,this)}},findTargets:function(c){var b=null,a=c.getTarget("li:not(.x-tab-edge)",this.strip);if(a){b=this.getComponent(a.id.split(this.idDelimiter)[1]);if(b.disabled){return{close:null,item:null,el:null}}}return{close:c.getTarget(".x-tab-strip-close",this.strip),item:b,el:a}},onStripMouseDown:function(b){if(b.button!==0){return}b.preventDefault();var a=this.findTargets(b);if(a.close){if(a.item.fireEvent("beforeclose",a.item)!==false){a.item.fireEvent("close",a.item);this.remove(a.item)}return}if(a.item&&a.item!=this.activeTab){this.setActiveTab(a.item)}},onStripContextMenu:function(b){b.preventDefault();var a=this.findTargets(b);if(a.item){this.fireEvent("contextmenu",this,a.item,b)}},readTabs:function(d){if(d===true){this.items.each(function(h){this.remove(h)},this)}var c=this.el.query(this.autoTabSelector);for(var b=0,a=c.length;b<a;b++){var e=c[b],g=e.getAttribute("title");e.removeAttribute("title");this.add({title:g,contentEl:e})}},initTab:function(d,b){var e=this.strip.dom.childNodes[b],g=this.getTemplateArgs(d),c=e?this.itemTpl.insertBefore(e,g):this.itemTpl.append(this.strip,g),a="x-tab-strip-over",h=Ext.get(c);h.hover(function(){if(!d.disabled){h.addClass(a)}},function(){h.removeClass(a)});if(d.tabTip){h.child("span.x-tab-strip-text",true).qtip=d.tabTip}d.tabEl=c;h.select("a").on("click",function(i){if(!i.getPageX()){this.onStripMouseDown(i)}},this,{preventDefault:true});d.on({scope:this,disable:this.onItemDisabled,enable:this.onItemEnabled,titlechange:this.onItemTitleChanged,iconchange:this.onItemIconChanged,beforeshow:this.onBeforeShowItem})},getTemplateArgs:function(b){var a=b.closable?"x-tab-strip-closable":"";if(b.disabled){a+=" x-item-disabled"}if(b.iconCls){a+=" x-tab-with-icon"}if(b.tabCls){a+=" "+b.tabCls}return{id:this.id+this.idDelimiter+b.getItemId(),text:b.title,cls:a,iconCls:b.iconCls||""}},onAdd:function(b){Ext.TabPanel.superclass.onAdd.call(this,b);if(this.rendered){var a=this.items;this.initTab(b,a.indexOf(b));this.delegateUpdates()}},onBeforeAdd:function(b){var a=b.events?(this.items.containsKey(b.getItemId())?b:null):this.items.get(b);if(a){this.setActiveTab(b);return false}Ext.TabPanel.superclass.onBeforeAdd.apply(this,arguments);var c=b.elements;b.elements=c?c.replace(",header",""):c;b.border=(b.border===true)},onRemove:function(d){var b=Ext.get(d.tabEl);if(b){b.select("a").removeAllListeners();Ext.destroy(b)}Ext.TabPanel.superclass.onRemove.call(this,d);this.stack.remove(d);delete d.tabEl;d.un("disable",this.onItemDisabled,this);d.un("enable",this.onItemEnabled,this);d.un("titlechange",this.onItemTitleChanged,this);d.un("iconchange",this.onItemIconChanged,this);d.un("beforeshow",this.onBeforeShowItem,this);if(d==this.activeTab){var a=this.stack.next();if(a){this.setActiveTab(a)}else{if(this.items.getCount()>0){this.setActiveTab(0)}else{this.setActiveTab(null)}}}if(!this.destroying){this.delegateUpdates()}},onBeforeShowItem:function(a){if(a!=this.activeTab){this.setActiveTab(a);return false}},onItemDisabled:function(b){var a=this.getTabEl(b);if(a){Ext.fly(a).addClass("x-item-disabled")}this.stack.remove(b)},onItemEnabled:function(b){var a=this.getTabEl(b);if(a){Ext.fly(a).removeClass("x-item-disabled")}},onItemTitleChanged:function(b){var a=this.getTabEl(b);if(a){Ext.fly(a).child("span.x-tab-strip-text",true).innerHTML=b.title}},onItemIconChanged:function(d,a,c){var b=this.getTabEl(d);if(b){b=Ext.get(b);b.child("span.x-tab-strip-text").replaceClass(c,a);b[Ext.isEmpty(a)?"removeClass":"addClass"]("x-tab-with-icon")}},getTabEl:function(a){var b=this.getComponent(a);return b?b.tabEl:null},onResize:function(){Ext.TabPanel.superclass.onResize.apply(this,arguments);this.delegateUpdates()},beginUpdate:function(){this.suspendUpdates=true},endUpdate:function(){this.suspendUpdates=false;this.delegateUpdates()},hideTabStripItem:function(b){b=this.getComponent(b);var a=this.getTabEl(b);if(a){a.style.display="none";this.delegateUpdates()}this.stack.remove(b)},unhideTabStripItem:function(b){b=this.getComponent(b);var a=this.getTabEl(b);if(a){a.style.display="";this.delegateUpdates()}},delegateUpdates:function(){var a=this.rendered;if(this.suspendUpdates){return}if(this.resizeTabs&&a){this.autoSizeTabs()}if(this.enableTabScroll&&a){this.autoScrollTabs()}},autoSizeTabs:function(){var h=this.items.length,b=this.tabPosition!="bottom"?"header":"footer",c=this[b].dom.offsetWidth,a=this[b].dom.clientWidth;if(!this.resizeTabs||h<1||!a){return}var k=Math.max(Math.min(Math.floor((a-4)/h)-this.tabMargin,this.tabWidth),this.minTabWidth);this.lastTabWidth=k;var m=this.strip.query("li:not(.x-tab-edge)");for(var e=0,j=m.length;e<j;e++){var l=m[e],n=Ext.fly(l).child(".x-tab-strip-inner",true),g=l.offsetWidth,d=n.offsetWidth;n.style.width=(k-(g-d))+"px"}},adjustBodyWidth:function(a){if(this.header){this.header.setWidth(a)}if(this.footer){this.footer.setWidth(a)}return a},setActiveTab:function(c){c=this.getComponent(c);if(this.fireEvent("beforetabchange",this,c,this.activeTab)===false){return}if(!this.rendered){this.activeTab=c;return}if(this.activeTab!=c){if(this.activeTab){var a=this.getTabEl(this.activeTab);if(a){Ext.fly(a).removeClass("x-tab-strip-active")}}this.activeTab=c;if(c){var b=this.getTabEl(c);Ext.fly(b).addClass("x-tab-strip-active");this.stack.add(c);this.layout.setActiveItem(c);this.delegateUpdates();if(this.scrolling){this.scrollToTab(c,this.animScroll)}}this.fireEvent("tabchange",this,c)}},getActiveTab:function(){return this.activeTab||null},getItem:function(a){return this.getComponent(a)},autoScrollTabs:function(){this.pos=this.tabPosition=="bottom"?this.footer:this.header;var h=this.items.length,d=this.pos.dom.offsetWidth,c=this.pos.dom.clientWidth,g=this.stripWrap,e=g.dom,b=e.offsetWidth,i=this.getScrollPos(),a=this.edge.getOffsetsTo(this.stripWrap)[0]+i;if(!this.enableTabScroll||b<20){return}if(h==0||a<=c){e.scrollLeft=0;g.setWidth(c);if(this.scrolling){this.scrolling=false;this.pos.removeClass("x-tab-scrolling");this.scrollLeft.hide();this.scrollRight.hide();if(Ext.isAir||Ext.isWebKit){e.style.marginLeft="";e.style.marginRight=""}}}else{if(!this.scrolling){this.pos.addClass("x-tab-scrolling");if(Ext.isAir||Ext.isWebKit){e.style.marginLeft="18px";e.style.marginRight="18px"}}c-=g.getMargins("lr");g.setWidth(c>20?c:20);if(!this.scrolling){if(!this.scrollLeft){this.createScrollers()}else{this.scrollLeft.show();this.scrollRight.show()}}this.scrolling=true;if(i>(a-c)){e.scrollLeft=a-c}else{this.scrollToTab(this.activeTab,false)}this.updateScrollButtons()}},createScrollers:function(){this.pos.addClass("x-tab-scrolling-"+this.tabPosition);var c=this.stripWrap.dom.offsetHeight;var a=this.pos.insertFirst({cls:"x-tab-scroller-left"});a.setHeight(c);a.addClassOnOver("x-tab-scroller-left-over");this.leftRepeater=new Ext.util.ClickRepeater(a,{interval:this.scrollRepeatInterval,handler:this.onScrollLeft,scope:this});this.scrollLeft=a;var b=this.pos.insertFirst({cls:"x-tab-scroller-right"});b.setHeight(c);b.addClassOnOver("x-tab-scroller-right-over");this.rightRepeater=new Ext.util.ClickRepeater(b,{interval:this.scrollRepeatInterval,handler:this.onScrollRight,scope:this});this.scrollRight=b},getScrollWidth:function(){return this.edge.getOffsetsTo(this.stripWrap)[0]+this.getScrollPos()},getScrollPos:function(){return parseInt(this.stripWrap.dom.scrollLeft,10)||0},getScrollArea:function(){return parseInt(this.stripWrap.dom.clientWidth,10)||0},getScrollAnim:function(){return{duration:this.scrollDuration,callback:this.updateScrollButtons,scope:this}},getScrollIncrement:function(){return this.scrollIncrement||(this.resizeTabs?this.lastTabWidth+2:100)},scrollToTab:function(e,a){if(!e){return}var c=this.getTabEl(e),h=this.getScrollPos(),d=this.getScrollArea(),g=Ext.fly(c).getOffsetsTo(this.stripWrap)[0]+h,b=g+c.offsetWidth;if(g<h){this.scrollTo(g,a)}else{if(b>(h+d)){this.scrollTo(b-d,a)}}},scrollTo:function(b,a){this.stripWrap.scrollTo("left",b,a?this.getScrollAnim():false);if(!a){this.updateScrollButtons()}},onWheel:function(g){var h=g.getWheelDelta()*this.wheelIncrement*-1;g.stopEvent();var i=this.getScrollPos(),c=i+h,a=this.getScrollWidth()-this.getScrollArea();var b=Math.max(0,Math.min(a,c));if(b!=i){this.scrollTo(b,false)}},onScrollRight:function(){var a=this.getScrollWidth()-this.getScrollArea(),c=this.getScrollPos(),b=Math.min(a,c+this.getScrollIncrement());if(b!=c){this.scrollTo(b,this.animScroll)}},onScrollLeft:function(){var b=this.getScrollPos(),a=Math.max(0,b-this.getScrollIncrement());if(a!=b){this.scrollTo(a,this.animScroll)}},updateScrollButtons:function(){var a=this.getScrollPos();this.scrollLeft[a===0?"addClass":"removeClass"]("x-tab-scroller-left-disabled");this.scrollRight[a>=(this.getScrollWidth()-this.getScrollArea())?"addClass":"removeClass"]("x-tab-scroller-right-disabled")},beforeDestroy:function(){Ext.destroy(this.leftRepeater,this.rightRepeater);this.deleteMembers("strip","edge","scrollLeft","scrollRight","stripWrap");this.activeTab=null;Ext.TabPanel.superclass.beforeDestroy.apply(this)}});Ext.reg("tabpanel",Ext.TabPanel);Ext.TabPanel.prototype.activate=Ext.TabPanel.prototype.setActiveTab;Ext.TabPanel.AccessStack=function(){var a=[];return{add:function(b){a.push(b);if(a.length>10){a.shift()}},remove:function(e){var d=[];for(var c=0,b=a.length;c<b;c++){if(a[c]!=e){d.push(a[c])}}a=d},next:function(){return a.pop()}}};Ext.Button=Ext.extend(Ext.BoxComponent,{hidden:false,disabled:false,pressed:false,enableToggle:false,menuAlign:"tl-bl?",type:"button",menuClassTarget:"tr:nth(2)",clickEvent:"click",handleMouseEvents:true,tooltipType:"qtip",buttonSelector:"button:first-child",scale:"small",iconAlign:"left",arrowAlign:"right",initComponent:function(){if(this.menu){if(Ext.isArray(this.menu)){this.menu={items:this.menu}}if(Ext.isObject(this.menu)){this.menu.ownerCt=this}this.menu=Ext.menu.MenuMgr.get(this.menu);this.menu.ownerCt=undefined}Ext.Button.superclass.initComponent.call(this);this.addEvents("click","toggle","mouseover","mouseout","menushow","menuhide","menutriggerover","menutriggerout");if(Ext.isString(this.toggleGroup)){this.enableToggle=true}},getTemplateArgs:function(){return[this.type,"x-btn-"+this.scale+" x-btn-icon-"+this.scale+"-"+this.iconAlign,this.getMenuClass(),this.cls,this.id]},setButtonClass:function(){if(this.useSetClass){if(!Ext.isEmpty(this.oldCls)){this.el.removeClass([this.oldCls,"x-btn-pressed"])}this.oldCls=(this.iconCls||this.icon)?(this.text?"x-btn-text-icon":"x-btn-icon"):"x-btn-noicon";this.el.addClass([this.oldCls,this.pressed?"x-btn-pressed":null])}},getMenuClass:function(){return this.menu?(this.arrowAlign!="bottom"?"x-btn-arrow":"x-btn-arrow-bottom"):""},onRender:function(c,a){if(!this.template){if(!Ext.Button.buttonTemplate){Ext.Button.buttonTemplate=new Ext.Template('<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">','<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>','<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>','<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',"</tbody></table>");Ext.Button.buttonTemplate.compile()}this.template=Ext.Button.buttonTemplate}var b,d=this.getTemplateArgs();if(a){b=this.template.insertBefore(a,d,true)}else{b=this.template.append(c,d,true)}this.btnEl=b.child(this.buttonSelector);this.mon(this.btnEl,{scope:this,focus:this.onFocus,blur:this.onBlur});this.initButtonEl(b,this.btnEl);Ext.ButtonToggleMgr.register(this)},initButtonEl:function(b,c){this.el=b;this.setIcon(this.icon);this.setText(this.text);this.setIconClass(this.iconCls);if(Ext.isDefined(this.tabIndex)){c.dom.tabIndex=this.tabIndex}if(this.tooltip){this.setTooltip(this.tooltip,true)}if(this.handleMouseEvents){this.mon(b,{scope:this,mouseover:this.onMouseOver,mousedown:this.onMouseDown})}if(this.menu){this.mon(this.menu,{scope:this,show:this.onMenuShow,hide:this.onMenuHide})}if(this.repeat){var a=new Ext.util.ClickRepeater(b,Ext.isObject(this.repeat)?this.repeat:{});this.mon(a,"click",this.onRepeatClick,this)}else{this.mon(b,this.clickEvent,this.onClick,this)}},afterRender:function(){Ext.Button.superclass.afterRender.call(this);this.useSetClass=true;this.setButtonClass();this.doc=Ext.getDoc();this.doAutoWidth()},setIconClass:function(a){this.iconCls=a;if(this.el){this.btnEl.dom.className="";this.btnEl.addClass(["x-btn-text",a||""]);this.setButtonClass()}return this},setTooltip:function(b,a){if(this.rendered){if(!a){this.clearTip()}if(Ext.isObject(b)){Ext.QuickTips.register(Ext.apply({target:this.btnEl.id},b));this.tooltip=b}else{this.btnEl.dom[this.tooltipType]=b}}else{this.tooltip=b}return this},clearTip:function(){if(Ext.isObject(this.tooltip)){Ext.QuickTips.unregister(this.btnEl)}},beforeDestroy:function(){if(this.rendered){this.clearTip()}if(this.menu&&this.destroyMenu!==false){Ext.destroy(this.btnEl,this.menu)}Ext.destroy(this.repeater)},onDestroy:function(){if(this.rendered){this.doc.un("mouseover",this.monitorMouseOver,this);this.doc.un("mouseup",this.onMouseUp,this);delete this.doc;delete this.btnEl;Ext.ButtonToggleMgr.unregister(this)}Ext.Button.superclass.onDestroy.call(this)},doAutoWidth:function(){if(this.autoWidth!==false&&this.el&&this.text&&this.width===undefined){this.el.setWidth("auto");if(Ext.isIE7&&Ext.isStrict){var a=this.btnEl;if(a&&a.getWidth()>20){a.clip();a.setWidth(Ext.util.TextMetrics.measure(a,this.text).width+a.getFrameWidth("lr"))}}if(this.minWidth){if(this.el.getWidth()<this.minWidth){this.el.setWidth(this.minWidth)}}}},setHandler:function(b,a){this.handler=b;this.scope=a;return this},setText:function(a){this.text=a;if(this.el){this.btnEl.update(a||"&#160;");this.setButtonClass()}this.doAutoWidth();return this},setIcon:function(a){this.icon=a;if(this.el){this.btnEl.setStyle("background-image",a?"url("+a+")":"");this.setButtonClass()}return this},getText:function(){return this.text},toggle:function(b,a){b=b===undefined?!this.pressed:!!b;if(b!=this.pressed){if(this.rendered){this.el[b?"addClass":"removeClass"]("x-btn-pressed")}this.pressed=b;if(!a){this.fireEvent("toggle",this,b);if(this.toggleHandler){this.toggleHandler.call(this.scope||this,this,b)}}}return this},onDisable:function(){this.onDisableChange(true)},onEnable:function(){this.onDisableChange(false)},onDisableChange:function(a){if(this.el){if(!Ext.isIE6||!this.text){this.el[a?"addClass":"removeClass"](this.disabledClass)}this.el.dom.disabled=a}this.disabled=a},showMenu:function(){if(this.rendered&&this.menu){if(this.tooltip){Ext.QuickTips.getQuickTip().cancelShow(this.btnEl)}if(this.menu.isVisible()){this.menu.hide()}this.menu.ownerCt=this;this.menu.show(this.el,this.menuAlign)}return this},hideMenu:function(){if(this.hasVisibleMenu()){this.menu.hide()}return this},hasVisibleMenu:function(){return this.menu&&this.menu.ownerCt==this&&this.menu.isVisible()},onRepeatClick:function(a,b){this.onClick(b)},onClick:function(a){if(a){a.preventDefault()}if(a.button!==0){return}if(!this.disabled){this.doToggle();if(this.menu&&!this.hasVisibleMenu()&&!this.ignoreNextClick){this.showMenu()}this.fireEvent("click",this,a);if(this.handler){this.handler.call(this.scope||this,this,a)}}},doToggle:function(){if(this.enableToggle&&(this.allowDepress!==false||!this.pressed)){this.toggle()}},isMenuTriggerOver:function(b,a){return this.menu&&!a},isMenuTriggerOut:function(b,a){return this.menu&&!a},onMouseOver:function(b){if(!this.disabled){var a=b.within(this.el,true);if(!a){this.el.addClass("x-btn-over");if(!this.monitoringMouseOver){this.doc.on("mouseover",this.monitorMouseOver,this);this.monitoringMouseOver=true}this.fireEvent("mouseover",this,b)}if(this.isMenuTriggerOver(b,a)){this.fireEvent("menutriggerover",this,this.menu,b)}}},monitorMouseOver:function(a){if(a.target!=this.el.dom&&!a.within(this.el)){if(this.monitoringMouseOver){this.doc.un("mouseover",this.monitorMouseOver,this);this.monitoringMouseOver=false}this.onMouseOut(a)}},onMouseOut:function(b){var a=b.within(this.el)&&b.target!=this.el.dom;this.el.removeClass("x-btn-over");this.fireEvent("mouseout",this,b);if(this.isMenuTriggerOut(b,a)){this.fireEvent("menutriggerout",this,this.menu,b)}},focus:function(){this.btnEl.focus()},blur:function(){this.btnEl.blur()},onFocus:function(a){if(!this.disabled){this.el.addClass("x-btn-focus")}},onBlur:function(a){this.el.removeClass("x-btn-focus")},getClickEl:function(b,a){return this.el},onMouseDown:function(a){if(!this.disabled&&a.button===0){this.getClickEl(a).addClass("x-btn-click");this.doc.on("mouseup",this.onMouseUp,this)}},onMouseUp:function(a){if(a.button===0){this.getClickEl(a,true).removeClass("x-btn-click");this.doc.un("mouseup",this.onMouseUp,this)}},onMenuShow:function(a){if(this.menu.ownerCt==this){this.menu.ownerCt=this;this.ignoreNextClick=0;this.el.addClass("x-btn-menu-active");this.fireEvent("menushow",this,this.menu)}},onMenuHide:function(a){if(this.menu.ownerCt==this){this.el.removeClass("x-btn-menu-active");this.ignoreNextClick=this.restoreClick.defer(250,this);this.fireEvent("menuhide",this,this.menu);delete this.menu.ownerCt}},restoreClick:function(){this.ignoreNextClick=0}});Ext.reg("button",Ext.Button);Ext.ButtonToggleMgr=function(){var a={};function b(e,j){if(j){var h=a[e.toggleGroup];for(var d=0,c=h.length;d<c;d++){if(h[d]!=e){h[d].toggle(false)}}}}return{register:function(c){if(!c.toggleGroup){return}var d=a[c.toggleGroup];if(!d){d=a[c.toggleGroup]=[]}d.push(c);c.on("toggle",b)},unregister:function(c){if(!c.toggleGroup){return}var d=a[c.toggleGroup];if(d){d.remove(c);c.un("toggle",b)}},getPressed:function(h){var e=a[h];if(e){for(var d=0,c=e.length;d<c;d++){if(e[d].pressed===true){return e[d]}}}return null}}}();Ext.SplitButton=Ext.extend(Ext.Button,{arrowSelector:"em",split:true,initComponent:function(){Ext.SplitButton.superclass.initComponent.call(this);this.addEvents("arrowclick")},onRender:function(){Ext.SplitButton.superclass.onRender.apply(this,arguments);if(this.arrowTooltip){this.el.child(this.arrowSelector).dom[this.tooltipType]=this.arrowTooltip}},setArrowHandler:function(b,a){this.arrowHandler=b;this.scope=a},getMenuClass:function(){return"x-btn-split"+(this.arrowAlign=="bottom"?"-bottom":"")},isClickOnArrow:function(c){if(this.arrowAlign!="bottom"){var b=this.el.child("em.x-btn-split");var a=b.getRegion().right-b.getPadding("r");return c.getPageX()>a}else{return c.getPageY()>this.btnEl.getRegion().bottom}},onClick:function(b,a){b.preventDefault();if(!this.disabled){if(this.isClickOnArrow(b)){if(this.menu&&!this.menu.isVisible()&&!this.ignoreNextClick){this.showMenu()}this.fireEvent("arrowclick",this,b);if(this.arrowHandler){this.arrowHandler.call(this.scope||this,this,b)}}else{this.doToggle();this.fireEvent("click",this,b);if(this.handler){this.handler.call(this.scope||this,this,b)}}}},isMenuTriggerOver:function(a){return this.menu&&a.target.tagName==this.arrowSelector},isMenuTriggerOut:function(b,a){return this.menu&&b.target.tagName!=this.arrowSelector}});Ext.reg("splitbutton",Ext.SplitButton);Ext.CycleButton=Ext.extend(Ext.SplitButton,{getItemText:function(a){if(a&&this.showText===true){var b="";if(this.prependText){b+=this.prependText}b+=a.text;return b}return undefined},setActiveItem:function(c,a){if(!Ext.isObject(c)){c=this.menu.getComponent(c)}if(c){if(!this.rendered){this.text=this.getItemText(c);this.iconCls=c.iconCls}else{var b=this.getItemText(c);if(b){this.setText(b)}this.setIconClass(c.iconCls)}this.activeItem=c;if(!c.checked){c.setChecked(true,a)}if(this.forceIcon){this.setIconClass(this.forceIcon)}if(!a){this.fireEvent("change",this,c)}}},getActiveItem:function(){return this.activeItem},initComponent:function(){this.addEvents("change");if(this.changeHandler){this.on("change",this.changeHandler,this.scope||this);delete this.changeHandler}this.itemCount=this.items.length;this.menu={cls:"x-cycle-menu",items:[]};var a=0;Ext.each(this.items,function(c,b){Ext.apply(c,{group:c.group||this.id,itemIndex:b,checkHandler:this.checkHandler,scope:this,checked:c.checked||false});this.menu.items.push(c);if(c.checked){a=b}},this);Ext.CycleButton.superclass.initComponent.call(this);this.on("click",this.toggleSelected,this);this.setActiveItem(a,true)},checkHandler:function(a,b){if(b){this.setActiveItem(a)}},toggleSelected:function(){var a=this.menu;a.render();if(!a.hasLayout){a.doLayout()}var d,b;for(var c=1;c<this.itemCount;c++){d=(this.activeItem.itemIndex+c)%this.itemCount;b=a.items.itemAt(d);if(!b.disabled){b.setChecked(true);break}}}});Ext.reg("cycle",Ext.CycleButton);Ext.Toolbar=function(a){if(Ext.isArray(a)){a={items:a,layout:"toolbar"}}else{a=Ext.apply({layout:"toolbar"},a);if(a.buttons){a.items=a.buttons}}Ext.Toolbar.superclass.constructor.call(this,a)};(function(){var a=Ext.Toolbar;Ext.extend(a,Ext.Container,{defaultType:"button",enableOverflow:false,trackMenus:true,internalDefaults:{removeMode:"container",hideParent:true},toolbarCls:"x-toolbar",initComponent:function(){a.superclass.initComponent.call(this);this.addEvents("overflowchange")},onRender:function(c,b){if(!this.el){if(!this.autoCreate){this.autoCreate={cls:this.toolbarCls+" x-small-editor"}}this.el=c.createChild(Ext.apply({id:this.id},this.autoCreate),b);Ext.Toolbar.superclass.onRender.apply(this,arguments)}},lookupComponent:function(b){if(Ext.isString(b)){if(b=="-"){b=new a.Separator()}else{if(b==" "){b=new a.Spacer()}else{if(b=="->"){b=new a.Fill()}else{b=new a.TextItem(b)}}}this.applyDefaults(b)}else{if(b.isFormField||b.render){b=this.createComponent(b)}else{if(b.tag){b=new a.Item({autoEl:b})}else{if(b.tagName){b=new a.Item({el:b})}else{if(Ext.isObject(b)){b=b.xtype?this.createComponent(b):this.constructButton(b)}}}}}return b},applyDefaults:function(e){if(!Ext.isString(e)){e=Ext.Toolbar.superclass.applyDefaults.call(this,e);var b=this.internalDefaults;if(e.events){Ext.applyIf(e.initialConfig,b);Ext.apply(e,b)}else{Ext.applyIf(e,b)}}return e},addSeparator:function(){return this.add(new a.Separator())},addSpacer:function(){return this.add(new a.Spacer())},addFill:function(){this.add(new a.Fill())},addElement:function(b){return this.addItem(new a.Item({el:b}))},addItem:function(b){return this.add.apply(this,arguments)},addButton:function(c){if(Ext.isArray(c)){var e=[];for(var d=0,b=c.length;d<b;d++){e.push(this.addButton(c[d]))}return e}return this.add(this.constructButton(c))},addText:function(b){return this.addItem(new a.TextItem(b))},addDom:function(b){return this.add(new a.Item({autoEl:b}))},addField:function(b){return this.add(b)},insertButton:function(c,g){if(Ext.isArray(g)){var e=[];for(var d=0,b=g.length;d<b;d++){e.push(this.insertButton(c+d,g[d]))}return e}return Ext.Toolbar.superclass.insert.call(this,c,g)},trackMenu:function(c,b){if(this.trackMenus&&c.menu){var d=b?"mun":"mon";this[d](c,"menutriggerover",this.onButtonTriggerOver,this);this[d](c,"menushow",this.onButtonMenuShow,this);this[d](c,"menuhide",this.onButtonMenuHide,this)}},constructButton:function(d){var c=d.events?d:this.createComponent(d,d.split?"splitbutton":this.defaultType);return c},onAdd:function(b){Ext.Toolbar.superclass.onAdd.call(this);this.trackMenu(b);if(this.disabled){b.disable()}},onRemove:function(b){Ext.Toolbar.superclass.onRemove.call(this);if(b==this.activeMenuBtn){delete this.activeMenuBtn}this.trackMenu(b,true)},onDisable:function(){this.items.each(function(b){if(b.disable){b.disable()}})},onEnable:function(){this.items.each(function(b){if(b.enable){b.enable()}})},onButtonTriggerOver:function(b){if(this.activeMenuBtn&&this.activeMenuBtn!=b){this.activeMenuBtn.hideMenu();b.showMenu();this.activeMenuBtn=b}},onButtonMenuShow:function(b){this.activeMenuBtn=b},onButtonMenuHide:function(b){delete this.activeMenuBtn}});Ext.reg("toolbar",Ext.Toolbar);a.Item=Ext.extend(Ext.BoxComponent,{hideParent:true,enable:Ext.emptyFn,disable:Ext.emptyFn,focus:Ext.emptyFn});Ext.reg("tbitem",a.Item);a.Separator=Ext.extend(a.Item,{onRender:function(c,b){this.el=c.createChild({tag:"span",cls:"xtb-sep"},b)}});Ext.reg("tbseparator",a.Separator);a.Spacer=Ext.extend(a.Item,{onRender:function(c,b){this.el=c.createChild({tag:"div",cls:"xtb-spacer",style:this.width?"width:"+this.width+"px":""},b)}});Ext.reg("tbspacer",a.Spacer);a.Fill=Ext.extend(a.Item,{render:Ext.emptyFn,isFill:true});Ext.reg("tbfill",a.Fill);a.TextItem=Ext.extend(a.Item,{constructor:function(b){a.TextItem.superclass.constructor.call(this,Ext.isString(b)?{text:b}:b)},onRender:function(c,b){this.autoEl={cls:"xtb-text",html:this.text||""};a.TextItem.superclass.onRender.call(this,c,b)},setText:function(b){if(this.rendered){this.el.update(b)}else{this.text=b}}});Ext.reg("tbtext",a.TextItem);a.Button=Ext.extend(Ext.Button,{});a.SplitButton=Ext.extend(Ext.SplitButton,{});Ext.reg("tbbutton",a.Button);Ext.reg("tbsplit",a.SplitButton)})();Ext.ButtonGroup=Ext.extend(Ext.Panel,{baseCls:"x-btn-group",layout:"table",defaultType:"button",frame:true,internalDefaults:{removeMode:"container",hideParent:true},initComponent:function(){this.layoutConfig=this.layoutConfig||{};Ext.applyIf(this.layoutConfig,{columns:this.columns});if(!this.title){this.addClass("x-btn-group-notitle")}this.on("afterlayout",this.onAfterLayout,this);Ext.ButtonGroup.superclass.initComponent.call(this)},applyDefaults:function(b){b=Ext.ButtonGroup.superclass.applyDefaults.call(this,b);var a=this.internalDefaults;if(b.events){Ext.applyIf(b.initialConfig,a);Ext.apply(b,a)}else{Ext.applyIf(b,a)}return b},onAfterLayout:function(){var a=this.body.getFrameWidth("lr")+this.body.dom.firstChild.offsetWidth;this.body.setWidth(a);this.el.setWidth(a+this.getFrameWidth())}});Ext.reg("buttongroup",Ext.ButtonGroup);(function(){var a=Ext.Toolbar;Ext.PagingToolbar=Ext.extend(Ext.Toolbar,{pageSize:20,displayMsg:"Displaying {0} - {1} of {2}",emptyMsg:"No data to display",beforePageText:"Page",afterPageText:"of {0}",firstText:"First Page",prevText:"Previous Page",nextText:"Next Page",lastText:"Last Page",refreshText:"Refresh",initComponent:function(){var c=[this.first=new a.Button({tooltip:this.firstText,overflowText:this.firstText,iconCls:"x-tbar-page-first",disabled:true,handler:this.moveFirst,scope:this}),this.prev=new a.Button({tooltip:this.prevText,overflowText:this.prevText,iconCls:"x-tbar-page-prev",disabled:true,handler:this.movePrevious,scope:this}),"-",this.beforePageText,this.inputItem=new Ext.form.NumberField({cls:"x-tbar-page-number",allowDecimals:false,allowNegative:false,enableKeyEvents:true,selectOnFocus:true,submitValue:false,listeners:{scope:this,keydown:this.onPagingKeyDown,blur:this.onPagingBlur}}),this.afterTextItem=new a.TextItem({text:String.format(this.afterPageText,1)}),"-",this.next=new a.Button({tooltip:this.nextText,overflowText:this.nextText,iconCls:"x-tbar-page-next",disabled:true,handler:this.moveNext,scope:this}),this.last=new a.Button({tooltip:this.lastText,overflowText:this.lastText,iconCls:"x-tbar-page-last",disabled:true,handler:this.moveLast,scope:this}),"-",this.refresh=new a.Button({tooltip:this.refreshText,overflowText:this.refreshText,iconCls:"x-tbar-loading",handler:this.doRefresh,scope:this})];var b=this.items||this.buttons||[];if(this.prependButtons){this.items=b.concat(c)}else{this.items=c.concat(b)}delete this.buttons;if(this.displayInfo){this.items.push("->");this.items.push(this.displayItem=new a.TextItem({}))}Ext.PagingToolbar.superclass.initComponent.call(this);this.addEvents("change","beforechange");this.on("afterlayout",this.onFirstLayout,this,{single:true});this.cursor=0;this.bindStore(this.store,true)},onFirstLayout:function(){if(this.dsLoaded){this.onLoad.apply(this,this.dsLoaded)}},updateInfo:function(){if(this.displayItem){var b=this.store.getCount();var c=b==0?this.emptyMsg:String.format(this.displayMsg,this.cursor+1,this.cursor+b,this.store.getTotalCount());this.displayItem.setText(c)}},onLoad:function(b,e,j){if(!this.rendered){this.dsLoaded=[b,e,j];return}var g=this.getParams();this.cursor=(j.params&&j.params[g.start])?j.params[g.start]:0;var i=this.getPageData(),c=i.activePage,h=i.pages;this.afterTextItem.setText(String.format(this.afterPageText,i.pages));this.inputItem.setValue(c);this.first.setDisabled(c==1);this.prev.setDisabled(c==1);this.next.setDisabled(c==h);this.last.setDisabled(c==h);this.refresh.enable();this.updateInfo();this.fireEvent("change",this,i)},getPageData:function(){var b=this.store.getTotalCount();return{total:b,activePage:Math.ceil((this.cursor+this.pageSize)/this.pageSize),pages:b<this.pageSize?1:Math.ceil(b/this.pageSize)}},changePage:function(b){this.doLoad(((b-1)*this.pageSize).constrain(0,this.store.getTotalCount()))},onLoadError:function(){if(!this.rendered){return}this.refresh.enable()},readPage:function(e){var b=this.inputItem.getValue(),c;if(!b||isNaN(c=parseInt(b,10))){this.inputItem.setValue(e.activePage);return false}return c},onPagingFocus:function(){this.inputItem.select()},onPagingBlur:function(b){this.inputItem.setValue(this.getPageData().activePage)},onPagingKeyDown:function(i,h){var c=h.getKey(),j=this.getPageData(),g;if(c==h.RETURN){h.stopEvent();g=this.readPage(j);if(g!==false){g=Math.min(Math.max(1,g),j.pages)-1;this.doLoad(g*this.pageSize)}}else{if(c==h.HOME||c==h.END){h.stopEvent();g=c==h.HOME?1:j.pages;i.setValue(g)}else{if(c==h.UP||c==h.PAGEUP||c==h.DOWN||c==h.PAGEDOWN){h.stopEvent();if((g=this.readPage(j))){var b=h.shiftKey?10:1;if(c==h.DOWN||c==h.PAGEDOWN){b*=-1}g+=b;if(g>=1&g<=j.pages){i.setValue(g)}}}}}},getParams:function(){return this.paramNames||this.store.paramNames},beforeLoad:function(){if(this.rendered&&this.refresh){this.refresh.disable()}},doLoad:function(d){var c={},b=this.getParams();c[b.start]=d;c[b.limit]=this.pageSize;if(this.fireEvent("beforechange",this,c)!==false){this.store.load({params:c})}},moveFirst:function(){this.doLoad(0)},movePrevious:function(){this.doLoad(Math.max(0,this.cursor-this.pageSize))},moveNext:function(){this.doLoad(this.cursor+this.pageSize)},moveLast:function(){var c=this.store.getTotalCount(),b=c%this.pageSize;this.doLoad(b?(c-b):c-this.pageSize)},doRefresh:function(){this.doLoad(this.cursor)},bindStore:function(c,d){var b;if(!d&&this.store){if(c!==this.store&&this.store.autoDestroy){this.store.destroy()}else{this.store.un("beforeload",this.beforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.onLoadError,this)}if(!c){this.store=null}}if(c){c=Ext.StoreMgr.lookup(c);c.on({scope:this,beforeload:this.beforeLoad,load:this.onLoad,exception:this.onLoadError});b=true}this.store=c;if(b){this.onLoad(c,null,{})}},unbind:function(b){this.bindStore(null)},bind:function(b){this.bindStore(b)},onDestroy:function(){this.bindStore(null);Ext.PagingToolbar.superclass.onDestroy.call(this)}})})();Ext.reg("paging",Ext.PagingToolbar);Ext.History=(function(){var e,c;var k=false;var d;function g(){var l=location.href,m=l.indexOf("#"),n=m>=0?l.substr(m+1):null;if(Ext.isGecko){n=decodeURIComponent(n)}return n}function a(){c.value=d}function h(l){d=l;Ext.History.fireEvent("change",l)}function i(m){var l=['<html><body><div id="state">',Ext.util.Format.htmlEncode(m),"</div></body></html>"].join("");try{var o=e.contentWindow.document;o.open();o.write(l);o.close();return true}catch(n){return false}}function b(){if(!e.contentWindow||!e.contentWindow.document){setTimeout(b,10);return}var o=e.contentWindow.document;var m=o.getElementById("state");var l=m?m.innerText:null;var n=g();setInterval(function(){o=e.contentWindow.document;m=o.getElementById("state");var q=m?m.innerText:null;var p=g();if(q!==l){l=q;h(l);location.hash=l;n=l;a()}else{if(p!==n){n=p;i(p)}}},50);k=true;Ext.History.fireEvent("ready",Ext.History)}function j(){d=c.value?c.value:g();if(Ext.isIE){b()}else{var l=g();setInterval(function(){var m=g();if(m!==l){l=m;h(l);a()}},50);k=true;Ext.History.fireEvent("ready",Ext.History)}}return{fieldId:"x-history-field",iframeId:"x-history-frame",events:{},init:function(m,l){if(k){Ext.callback(m,l,[this]);return}if(!Ext.isReady){Ext.onReady(function(){Ext.History.init(m,l)});return}c=Ext.getDom(Ext.History.fieldId);if(Ext.isIE){e=Ext.getDom(Ext.History.iframeId)}this.addEvents("ready","change");if(m){this.on("ready",m,l,{single:true})}j()},add:function(l,m){if(m!==false){if(this.getToken()==l){return true}}if(Ext.isIE){return i(l)}else{location.hash=l;return true}},back:function(){history.go(-1)},forward:function(){history.go(1)},getToken:function(){return k?d:g()}}})();Ext.apply(Ext.History,new Ext.util.Observable());Ext.Tip=Ext.extend(Ext.Panel,{minWidth:40,maxWidth:300,shadow:"sides",defaultAlign:"tl-bl?",autoRender:true,quickShowInterval:250,frame:true,hidden:true,baseCls:"x-tip",floating:{shadow:true,shim:true,useDisplay:true,constrain:false},autoHeight:true,closeAction:"hide",initComponent:function(){Ext.Tip.superclass.initComponent.call(this);if(this.closable&&!this.title){this.elements+=",header"}},afterRender:function(){Ext.Tip.superclass.afterRender.call(this);if(this.closable){this.addTool({id:"close",handler:this[this.closeAction],scope:this})}},showAt:function(a){Ext.Tip.superclass.show.call(this);if(this.measureWidth!==false&&(!this.initialConfig||typeof this.initialConfig.width!="number")){this.doAutoWidth()}if(this.constrainPosition){a=this.el.adjustForConstraints(a)}this.setPagePosition(a[0],a[1])},doAutoWidth:function(a){a=a||0;var b=this.body.getTextWidth();if(this.title){b=Math.max(b,this.header.child("span").getTextWidth(this.title))}b+=this.getFrameWidth()+(this.closable?20:0)+this.body.getPadding("lr")+a;this.setWidth(b.constrain(this.minWidth,this.maxWidth));if(Ext.isIE7&&!this.repainted){this.el.repaint();this.repainted=true}},showBy:function(a,b){if(!this.rendered){this.render(Ext.getBody())}this.showAt(this.el.getAlignToXY(a,b||this.defaultAlign))},initDraggable:function(){this.dd=new Ext.Tip.DD(this,typeof this.draggable=="boolean"?null:this.draggable);this.header.addClass("x-tip-draggable")}});Ext.reg("tip",Ext.Tip);Ext.Tip.DD=function(b,a){Ext.apply(this,a);this.tip=b;Ext.Tip.DD.superclass.constructor.call(this,b.el.id,"WindowDD-"+b.id);this.setHandleElId(b.header.id);this.scroll=false};Ext.extend(Ext.Tip.DD,Ext.dd.DD,{moveOnly:true,scroll:false,headerOffsets:[100,25],startDrag:function(){this.tip.el.disableShadow()},endDrag:function(a){this.tip.el.enableShadow(true)}});Ext.ToolTip=Ext.extend(Ext.Tip,{showDelay:500,hideDelay:200,dismissDelay:5000,trackMouse:false,anchorToTarget:true,anchorOffset:0,targetCounter:0,constrainPosition:false,initComponent:function(){Ext.ToolTip.superclass.initComponent.call(this);this.lastActive=new Date();this.initTarget(this.target);this.origAnchor=this.anchor},onRender:function(b,a){Ext.ToolTip.superclass.onRender.call(this,b,a);this.anchorCls="x-tip-anchor-"+this.getAnchorPosition();this.anchorEl=this.el.createChild({cls:"x-tip-anchor "+this.anchorCls})},afterRender:function(){Ext.ToolTip.superclass.afterRender.call(this);this.anchorEl.setStyle("z-index",this.el.getZIndex()+1).setVisibilityMode(Ext.Element.DISPLAY)},initTarget:function(c){var a;if((a=Ext.get(c))){if(this.target){var b=Ext.get(this.target);this.mun(b,"mouseover",this.onTargetOver,this);this.mun(b,"mouseout",this.onTargetOut,this);this.mun(b,"mousemove",this.onMouseMove,this)}this.mon(a,{mouseover:this.onTargetOver,mouseout:this.onTargetOut,mousemove:this.onMouseMove,scope:this});this.target=a}if(this.anchor){this.anchorTarget=this.target}},onMouseMove:function(b){var a=this.delegate?b.getTarget(this.delegate):this.triggerElement=true;if(a){this.targetXY=b.getXY();if(a===this.triggerElement){if(!this.hidden&&this.trackMouse){this.setPagePosition(this.getTargetXY())}}else{this.hide();this.lastActive=new Date(0);this.onTargetOver(b)}}else{if(!this.closable&&this.isVisible()){this.hide()}}},getTargetXY:function(){if(this.delegate){this.anchorTarget=this.triggerElement}if(this.anchor){this.targetCounter++;var c=this.getOffsets(),l=(this.anchorToTarget&&!this.trackMouse)?this.el.getAlignToXY(this.anchorTarget,this.getAnchorAlign()):this.targetXY,a=Ext.lib.Dom.getViewWidth()-5,h=Ext.lib.Dom.getViewHeight()-5,i=document.documentElement,e=document.body,k=(i.scrollLeft||e.scrollLeft||0)+5,j=(i.scrollTop||e.scrollTop||0)+5,b=[l[0]+c[0],l[1]+c[1]],g=this.getSize();this.anchorEl.removeClass(this.anchorCls);if(this.targetCounter<2){if(b[0]<k){if(this.anchorToTarget){this.defaultAlign="l-r";if(this.mouseOffset){this.mouseOffset[0]*=-1}}this.anchor="left";return this.getTargetXY()}if(b[0]+g.width>a){if(this.anchorToTarget){this.defaultAlign="r-l";if(this.mouseOffset){this.mouseOffset[0]*=-1}}this.anchor="right";return this.getTargetXY()}if(b[1]<j){if(this.anchorToTarget){this.defaultAlign="t-b";if(this.mouseOffset){this.mouseOffset[1]*=-1}}this.anchor="top";return this.getTargetXY()}if(b[1]+g.height>h){if(this.anchorToTarget){this.defaultAlign="b-t";if(this.mouseOffset){this.mouseOffset[1]*=-1}}this.anchor="bottom";return this.getTargetXY()}}this.anchorCls="x-tip-anchor-"+this.getAnchorPosition();this.anchorEl.addClass(this.anchorCls);this.targetCounter=0;return b}else{var d=this.getMouseOffset();return[this.targetXY[0]+d[0],this.targetXY[1]+d[1]]}},getMouseOffset:function(){var a=this.anchor?[0,0]:[15,18];if(this.mouseOffset){a[0]+=this.mouseOffset[0];a[1]+=this.mouseOffset[1]}return a},getAnchorPosition:function(){if(this.anchor){this.tipAnchor=this.anchor.charAt(0)}else{var a=this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);if(!a){throw"AnchorTip.defaultAlign is invalid"}this.tipAnchor=a[1].charAt(0)}switch(this.tipAnchor){case"t":return"top";case"b":return"bottom";case"r":return"right"}return"left"},getAnchorAlign:function(){switch(this.anchor){case"top":return"tl-bl";case"left":return"tl-tr";case"right":return"tr-tl";default:return"bl-tl"}},getOffsets:function(){var b,a=this.getAnchorPosition().charAt(0);if(this.anchorToTarget&&!this.trackMouse){switch(a){case"t":b=[0,9];break;case"b":b=[0,-13];break;case"r":b=[-13,0];break;default:b=[9,0];break}}else{switch(a){case"t":b=[-15-this.anchorOffset,30];break;case"b":b=[-19-this.anchorOffset,-13-this.el.dom.offsetHeight];break;case"r":b=[-15-this.el.dom.offsetWidth,-13-this.anchorOffset];break;default:b=[25,-13-this.anchorOffset];break}}var c=this.getMouseOffset();b[0]+=c[0];b[1]+=c[1];return b},onTargetOver:function(b){if(this.disabled||b.within(this.target.dom,true)){return}var a=b.getTarget(this.delegate);if(a){this.triggerElement=a;this.clearTimer("hide");this.targetXY=b.getXY();this.delayShow()}},delayShow:function(){if(this.hidden&&!this.showTimer){if(this.lastActive.getElapsed()<this.quickShowInterval){this.show()}else{this.showTimer=this.show.defer(this.showDelay,this)}}else{if(!this.hidden&&this.autoHide!==false){this.show()}}},onTargetOut:function(a){if(this.disabled||a.within(this.target.dom,true)){return}this.clearTimer("show");if(this.autoHide!==false){this.delayHide()}},delayHide:function(){if(!this.hidden&&!this.hideTimer){this.hideTimer=this.hide.defer(this.hideDelay,this)}},hide:function(){this.clearTimer("dismiss");this.lastActive=new Date();if(this.anchorEl){this.anchorEl.hide()}Ext.ToolTip.superclass.hide.call(this);delete this.triggerElement},show:function(){if(this.anchor){this.showAt([-1000,-1000]);this.origConstrainPosition=this.constrainPosition;this.constrainPosition=false;this.anchor=this.origAnchor}this.showAt(this.getTargetXY());if(this.anchor){this.anchorEl.show();this.syncAnchor();this.constrainPosition=this.origConstrainPosition}else{this.anchorEl.hide()}},showAt:function(a){this.lastActive=new Date();this.clearTimers();Ext.ToolTip.superclass.showAt.call(this,a);if(this.dismissDelay&&this.autoHide!==false){this.dismissTimer=this.hide.defer(this.dismissDelay,this)}if(this.anchor&&!this.anchorEl.isVisible()){this.syncAnchor();this.anchorEl.show()}else{this.anchorEl.hide()}},syncAnchor:function(){var a,b,c;switch(this.tipAnchor.charAt(0)){case"t":a="b";b="tl";c=[20+this.anchorOffset,2];break;case"r":a="l";b="tr";c=[-2,11+this.anchorOffset];break;case"b":a="t";b="bl";c=[20+this.anchorOffset,-2];break;default:a="r";b="tl";c=[2,11+this.anchorOffset];break}this.anchorEl.alignTo(this.el,a+"-"+b,c)},setPagePosition:function(a,b){Ext.ToolTip.superclass.setPagePosition.call(this,a,b);if(this.anchor){this.syncAnchor()}},clearTimer:function(a){a=a+"Timer";clearTimeout(this[a]);delete this[a]},clearTimers:function(){this.clearTimer("show");this.clearTimer("dismiss");this.clearTimer("hide")},onShow:function(){Ext.ToolTip.superclass.onShow.call(this);Ext.getDoc().on("mousedown",this.onDocMouseDown,this)},onHide:function(){Ext.ToolTip.superclass.onHide.call(this);Ext.getDoc().un("mousedown",this.onDocMouseDown,this)},onDocMouseDown:function(a){if(this.autoHide!==true&&!this.closable&&!a.within(this.el.dom)){this.disable();this.doEnable.defer(100,this)}},doEnable:function(){if(!this.isDestroyed){this.enable()}},onDisable:function(){this.clearTimers();this.hide()},adjustPosition:function(a,d){if(this.constrainPosition){var c=this.targetXY[1],b=this.getSize().height;if(d<=c&&(d+b)>=c){d=c-b-5}}return{x:a,y:d}},beforeDestroy:function(){this.clearTimers();Ext.destroy(this.anchorEl);delete this.anchorEl;delete this.target;delete this.anchorTarget;delete this.triggerElement;Ext.ToolTip.superclass.beforeDestroy.call(this)},onDestroy:function(){Ext.getDoc().un("mousedown",this.onDocMouseDown,this);Ext.ToolTip.superclass.onDestroy.call(this)}});Ext.reg("tooltip",Ext.ToolTip);Ext.QuickTip=Ext.extend(Ext.ToolTip,{interceptTitles:false,tagConfig:{namespace:"ext",attribute:"qtip",width:"qwidth",target:"target",title:"qtitle",hide:"hide",cls:"qclass",align:"qalign",anchor:"anchor"},initComponent:function(){this.target=this.target||Ext.getDoc();this.targets=this.targets||{};Ext.QuickTip.superclass.initComponent.call(this)},register:function(e){var h=Ext.isArray(e)?e:arguments;for(var g=0,a=h.length;g<a;g++){var l=h[g];var k=l.target;if(k){if(Ext.isArray(k)){for(var d=0,b=k.length;d<b;d++){this.targets[Ext.id(k[d])]=l}}else{this.targets[Ext.id(k)]=l}}}},unregister:function(a){delete this.targets[Ext.id(a)]},cancelShow:function(b){var a=this.activeTarget;b=Ext.get(b).dom;if(this.isVisible()){if(a&&a.el==b){this.hide()}}else{if(a&&a.el==b){this.clearTimer("show")}}},getTipCfg:function(d){var b=d.getTarget(),c,a;if(this.interceptTitles&&b.title&&Ext.isString(b.title)){c=b.title;b.qtip=c;b.removeAttribute("title");d.preventDefault()}else{a=this.tagConfig;c=b.qtip||Ext.fly(b).getAttribute(a.attribute,a.namespace)}return c},onTargetOver:function(i){if(this.disabled){return}this.targetXY=i.getXY();var c=i.getTarget();if(!c||c.nodeType!==1||c==document||c==document.body){return}if(this.activeTarget&&((c==this.activeTarget.el)||Ext.fly(this.activeTarget.el).contains(c))){this.clearTimer("hide");this.show();return}if(c&&this.targets[c.id]){this.activeTarget=this.targets[c.id];this.activeTarget.el=c;this.anchor=this.activeTarget.anchor;if(this.anchor){this.anchorTarget=c}this.delayShow();return}var g,h=Ext.fly(c),b=this.tagConfig,d=b.namespace;if(g=this.getTipCfg(i)){var a=h.getAttribute(b.hide,d);this.activeTarget={el:c,text:g,width:h.getAttribute(b.width,d),autoHide:a!="user"&&a!=="false",title:h.getAttribute(b.title,d),cls:h.getAttribute(b.cls,d),align:h.getAttribute(b.align,d)};this.anchor=h.getAttribute(b.anchor,d);if(this.anchor){this.anchorTarget=c}this.delayShow()}},onTargetOut:function(a){if(this.activeTarget&&a.within(this.activeTarget.el)&&!this.getTipCfg(a)){return}this.clearTimer("show");if(this.autoHide!==false){this.delayHide()}},showAt:function(b){var a=this.activeTarget;if(a){if(!this.rendered){this.render(Ext.getBody());this.activeTarget=a}if(a.width){this.setWidth(a.width);this.body.setWidth(this.adjustBodyWidth(a.width-this.getFrameWidth()));this.measureWidth=false}else{this.measureWidth=true}this.setTitle(a.title||"");this.body.update(a.text);this.autoHide=a.autoHide;this.dismissDelay=a.dismissDelay||this.dismissDelay;if(this.lastCls){this.el.removeClass(this.lastCls);delete this.lastCls}if(a.cls){this.el.addClass(a.cls);this.lastCls=a.cls}if(this.anchor){this.constrainPosition=false}else{if(a.align){b=this.el.getAlignToXY(a.el,a.align);this.constrainPosition=false}else{this.constrainPosition=true}}}Ext.QuickTip.superclass.showAt.call(this,b)},hide:function(){delete this.activeTarget;Ext.QuickTip.superclass.hide.call(this)}});Ext.reg("quicktip",Ext.QuickTip);Ext.QuickTips=function(){var b,a=false;return{init:function(c){if(!b){if(!Ext.isReady){Ext.onReady(function(){Ext.QuickTips.init(c)});return}b=new Ext.QuickTip({elements:"header,body",disabled:a});if(c!==false){b.render(Ext.getBody())}}},ddDisable:function(){if(b&&!a){b.disable()}},ddEnable:function(){if(b&&!a){b.enable()}},enable:function(){if(b){b.enable()}a=false},disable:function(){if(b){b.disable()}a=true},isEnabled:function(){return b!==undefined&&!b.disabled},getQuickTip:function(){return b},register:function(){b.register.apply(b,arguments)},unregister:function(){b.unregister.apply(b,arguments)},tips:function(){b.register.apply(b,arguments)}}}();Ext.slider.Tip=Ext.extend(Ext.Tip,{minWidth:10,offsets:[0,-10],init:function(a){a.on({scope:this,dragstart:this.onSlide,drag:this.onSlide,dragend:this.hide,destroy:this.destroy})},onSlide:function(b,c,a){this.show();this.body.update(this.getText(a));this.doAutoWidth();this.el.alignTo(a.el,"b-t?",this.offsets)},getText:function(a){return String(a.value)}});Ext.ux.SliderTip=Ext.slider.Tip;Ext.tree.TreePanel=Ext.extend(Ext.Panel,{rootVisible:true,animate:Ext.enableFx,lines:true,enableDD:false,hlDrop:Ext.enableFx,pathSeparator:"/",bubbleEvents:[],initComponent:function(){Ext.tree.TreePanel.superclass.initComponent.call(this);if(!this.eventModel){this.eventModel=new Ext.tree.TreeEventModel(this)}var a=this.loader;if(!a){a=new Ext.tree.TreeLoader({dataUrl:this.dataUrl,requestMethod:this.requestMethod})}else{if(Ext.isObject(a)&&!a.load){a=new Ext.tree.TreeLoader(a)}}this.loader=a;this.nodeHash={};if(this.root){var b=this.root;delete this.root;this.setRootNode(b)}this.addEvents("append","remove","movenode","insert","beforeappend","beforeremove","beforemovenode","beforeinsert","beforeload","load","textchange","beforeexpandnode","beforecollapsenode","expandnode","disabledchange","collapsenode","beforeclick","click","containerclick","checkchange","beforedblclick","dblclick","containerdblclick","contextmenu","containercontextmenu","beforechildrenrendered","startdrag","enddrag","dragdrop","beforenodedrop","nodedrop","nodedragover");if(this.singleExpand){this.on("beforeexpandnode",this.restrictExpand,this)}},proxyNodeEvent:function(c,b,a,h,g,e,d){if(c=="collapse"||c=="expand"||c=="beforecollapse"||c=="beforeexpand"||c=="move"||c=="beforemove"){c=c+"node"}return this.fireEvent(c,b,a,h,g,e,d)},getRootNode:function(){return this.root},setRootNode:function(b){this.destroyRoot();if(!b.render){b=this.loader.createNode(b)}this.root=b;b.ownerTree=this;b.isRoot=true;this.registerNode(b);if(!this.rootVisible){var a=b.attributes.uiProvider;b.ui=a?new a(b):new Ext.tree.RootTreeNodeUI(b)}if(this.innerCt){this.clearInnerCt();this.renderRoot()}return b},clearInnerCt:function(){this.innerCt.update("")},renderRoot:function(){this.root.render();if(!this.rootVisible){this.root.renderChildren()}},getNodeById:function(a){return this.nodeHash[a]},registerNode:function(a){this.nodeHash[a.id]=a},unregisterNode:function(a){delete this.nodeHash[a.id]},toString:function(){return"[Tree"+(this.id?" "+this.id:"")+"]"},restrictExpand:function(a){var b=a.parentNode;if(b){if(b.expandedChild&&b.expandedChild.parentNode==b){b.expandedChild.collapse()}b.expandedChild=a}},getChecked:function(b,c){c=c||this.root;var d=[];var e=function(){if(this.attributes.checked){d.push(!b?this:(b=="id"?this.id:this.attributes[b]))}};c.cascade(e);return d},getLoader:function(){return this.loader},expandAll:function(){this.root.expand(true)},collapseAll:function(){this.root.collapse(true)},getSelectionModel:function(){if(!this.selModel){this.selModel=new Ext.tree.DefaultSelectionModel()}return this.selModel},expandPath:function(g,a,h){if(Ext.isEmpty(g)){if(h){h(false,undefined)}return}a=a||"id";var d=g.split(this.pathSeparator);var c=this.root;if(c.attributes[a]!=d[1]){if(h){h(false,null)}return}var b=1;var e=function(){if(++b==d.length){if(h){h(true,c)}return}var i=c.findChild(a,d[b]);if(!i){if(h){h(false,c)}return}c=i;i.expand(false,false,e)};c.expand(false,false,e)},selectPath:function(e,a,g){if(Ext.isEmpty(e)){if(g){g(false,undefined)}return}a=a||"id";var c=e.split(this.pathSeparator),b=c.pop();if(c.length>1){var d=function(i,h){if(i&&h){var j=h.findChild(a,b);if(j){j.select();if(g){g(true,j)}}else{if(g){g(false,j)}}}else{if(g){g(false,j)}}};this.expandPath(c.join(this.pathSeparator),a,d)}else{this.root.select();if(g){g(true,this.root)}}},getTreeEl:function(){return this.body},onRender:function(b,a){Ext.tree.TreePanel.superclass.onRender.call(this,b,a);this.el.addClass("x-tree");this.innerCt=this.body.createChild({tag:"ul",cls:"x-tree-root-ct "+(this.useArrows?"x-tree-arrows":this.lines?"x-tree-lines":"x-tree-no-lines")})},initEvents:function(){Ext.tree.TreePanel.superclass.initEvents.call(this);if(this.containerScroll){Ext.dd.ScrollManager.register(this.body)}if((this.enableDD||this.enableDrop)&&!this.dropZone){this.dropZone=new Ext.tree.TreeDropZone(this,this.dropConfig||{ddGroup:this.ddGroup||"TreeDD",appendOnly:this.ddAppendOnly===true})}if((this.enableDD||this.enableDrag)&&!this.dragZone){this.dragZone=new Ext.tree.TreeDragZone(this,this.dragConfig||{ddGroup:this.ddGroup||"TreeDD",scroll:this.ddScroll})}this.getSelectionModel().init(this)},afterRender:function(){Ext.tree.TreePanel.superclass.afterRender.call(this);this.renderRoot()},beforeDestroy:function(){if(this.rendered){Ext.dd.ScrollManager.unregister(this.body);Ext.destroy(this.dropZone,this.dragZone)}this.destroyRoot();Ext.destroy(this.loader);this.nodeHash=this.root=this.loader=null;Ext.tree.TreePanel.superclass.beforeDestroy.call(this)},destroyRoot:function(){if(this.root&&this.root.destroy){this.root.destroy(true)}}});Ext.tree.TreePanel.nodeTypes={};Ext.reg("treepanel",Ext.tree.TreePanel);Ext.tree.TreeEventModel=function(a){this.tree=a;this.tree.on("render",this.initEvents,this)};Ext.tree.TreeEventModel.prototype={initEvents:function(){var a=this.tree;if(a.trackMouseOver!==false){a.mon(a.innerCt,{scope:this,mouseover:this.delegateOver,mouseout:this.delegateOut})}a.mon(a.getTreeEl(),{scope:this,click:this.delegateClick,dblclick:this.delegateDblClick,contextmenu:this.delegateContextMenu})},getNode:function(b){var a;if(a=b.getTarget(".x-tree-node-el",10)){var c=Ext.fly(a,"_treeEvents").getAttribute("tree-node-id","ext");if(c){return this.tree.getNodeById(c)}}return null},getNodeTarget:function(b){var a=b.getTarget(".x-tree-node-icon",1);if(!a){a=b.getTarget(".x-tree-node-el",6)}return a},delegateOut:function(b,a){if(!this.beforeEvent(b)){return}if(b.getTarget(".x-tree-ec-icon",1)){var c=this.getNode(b);this.onIconOut(b,c);if(c==this.lastEcOver){delete this.lastEcOver}}if((a=this.getNodeTarget(b))&&!b.within(a,true)){this.onNodeOut(b,this.getNode(b))}},delegateOver:function(b,a){if(!this.beforeEvent(b)){return}if(Ext.isGecko&&!this.trackingDoc){Ext.getBody().on("mouseover",this.trackExit,this);this.trackingDoc=true}if(this.lastEcOver){this.onIconOut(b,this.lastEcOver);delete this.lastEcOver}if(b.getTarget(".x-tree-ec-icon",1)){this.lastEcOver=this.getNode(b);this.onIconOver(b,this.lastEcOver)}if(a=this.getNodeTarget(b)){this.onNodeOver(b,this.getNode(b))}},trackExit:function(a){if(this.lastOverNode){if(this.lastOverNode.ui&&!a.within(this.lastOverNode.ui.getEl())){this.onNodeOut(a,this.lastOverNode)}delete this.lastOverNode;Ext.getBody().un("mouseover",this.trackExit,this);this.trackingDoc=false}},delegateClick:function(b,a){if(this.beforeEvent(b)){if(b.getTarget("input[type=checkbox]",1)){this.onCheckboxClick(b,this.getNode(b))}else{if(b.getTarget(".x-tree-ec-icon",1)){this.onIconClick(b,this.getNode(b))}else{if(this.getNodeTarget(b)){this.onNodeClick(b,this.getNode(b))}}}}else{this.checkContainerEvent(b,"click")}},delegateDblClick:function(b,a){if(this.beforeEvent(b)){if(this.getNodeTarget(b)){this.onNodeDblClick(b,this.getNode(b))}}else{this.checkContainerEvent(b,"dblclick")}},delegateContextMenu:function(b,a){if(this.beforeEvent(b)){if(this.getNodeTarget(b)){this.onNodeContextMenu(b,this.getNode(b))}}else{this.checkContainerEvent(b,"contextmenu")}},checkContainerEvent:function(b,a){if(this.disabled){b.stopEvent();return false}this.onContainerEvent(b,a)},onContainerEvent:function(b,a){this.tree.fireEvent("container"+a,this.tree,b)},onNodeClick:function(b,a){a.ui.onClick(b)},onNodeOver:function(b,a){this.lastOverNode=a;a.ui.onOver(b)},onNodeOut:function(b,a){a.ui.onOut(b)},onIconOver:function(b,a){a.ui.addClass("x-tree-ec-over")},onIconOut:function(b,a){a.ui.removeClass("x-tree-ec-over")},onIconClick:function(b,a){a.ui.ecClick(b)},onCheckboxClick:function(b,a){a.ui.onCheckChange(b)},onNodeDblClick:function(b,a){a.ui.onDblClick(b)},onNodeContextMenu:function(b,a){a.ui.onContextMenu(b)},beforeEvent:function(b){var a=this.getNode(b);if(this.disabled||!a||!a.ui){b.stopEvent();return false}return true},disable:function(){this.disabled=true},enable:function(){this.disabled=false}};Ext.tree.DefaultSelectionModel=Ext.extend(Ext.util.Observable,{constructor:function(a){this.selNode=null;this.addEvents("selectionchange","beforeselect");Ext.apply(this,a);Ext.tree.DefaultSelectionModel.superclass.constructor.call(this)},init:function(a){this.tree=a;a.mon(a.getTreeEl(),"keydown",this.onKeyDown,this);a.on("click",this.onNodeClick,this)},onNodeClick:function(a,b){this.select(a)},select:function(c,a){if(!Ext.fly(c.ui.wrap).isVisible()&&a){return a.call(this,c)}var b=this.selNode;if(c==b){c.ui.onSelectedChange(true)}else{if(this.fireEvent("beforeselect",this,c,b)!==false){if(b&&b.ui){b.ui.onSelectedChange(false)}this.selNode=c;c.ui.onSelectedChange(true);this.fireEvent("selectionchange",this,c,b)}}return c},unselect:function(b,a){if(this.selNode==b){this.clearSelections(a)}},clearSelections:function(a){var b=this.selNode;if(b){b.ui.onSelectedChange(false);this.selNode=null;if(a!==true){this.fireEvent("selectionchange",this,null)}}return b},getSelectedNode:function(){return this.selNode},isSelected:function(a){return this.selNode==a},selectPrevious:function(a){if(!(a=a||this.selNode||this.lastSelNode)){return null}var c=a.previousSibling;if(c){if(!c.isExpanded()||c.childNodes.length<1){return this.select(c,this.selectPrevious)}else{var b=c.lastChild;while(b&&b.isExpanded()&&Ext.fly(b.ui.wrap).isVisible()&&b.childNodes.length>0){b=b.lastChild}return this.select(b,this.selectPrevious)}}else{if(a.parentNode&&(this.tree.rootVisible||!a.parentNode.isRoot)){return this.select(a.parentNode,this.selectPrevious)}}return null},selectNext:function(b){if(!(b=b||this.selNode||this.lastSelNode)){return null}if(b.firstChild&&b.isExpanded()&&Ext.fly(b.ui.wrap).isVisible()){return this.select(b.firstChild,this.selectNext)}else{if(b.nextSibling){return this.select(b.nextSibling,this.selectNext)}else{if(b.parentNode){var a=null;b.parentNode.bubble(function(){if(this.nextSibling){a=this.getOwnerTree().selModel.select(this.nextSibling,this.selectNext);return false}});return a}}}return null},onKeyDown:function(c){var b=this.selNode||this.lastSelNode;var d=this;if(!b){return}var a=c.getKey();switch(a){case c.DOWN:c.stopEvent();this.selectNext();break;case c.UP:c.stopEvent();this.selectPrevious();break;case c.RIGHT:c.preventDefault();if(b.hasChildNodes()){if(!b.isExpanded()){b.expand()}else{if(b.firstChild){this.select(b.firstChild,c)}}}break;case c.LEFT:c.preventDefault();if(b.hasChildNodes()&&b.isExpanded()){b.collapse()}else{if(b.parentNode&&(this.tree.rootVisible||b.parentNode!=this.tree.getRootNode())){this.select(b.parentNode,c)}}break}}});Ext.tree.MultiSelectionModel=Ext.extend(Ext.util.Observable,{constructor:function(a){this.selNodes=[];this.selMap={};this.addEvents("selectionchange");Ext.apply(this,a);Ext.tree.MultiSelectionModel.superclass.constructor.call(this)},init:function(a){this.tree=a;a.mon(a.getTreeEl(),"keydown",this.onKeyDown,this);a.on("click",this.onNodeClick,this)},onNodeClick:function(a,b){if(b.ctrlKey&&this.isSelected(a)){this.unselect(a)}else{this.select(a,b,b.ctrlKey)}},select:function(a,c,b){if(b!==true){this.clearSelections(true)}if(this.isSelected(a)){this.lastSelNode=a;return a}this.selNodes.push(a);this.selMap[a.id]=a;this.lastSelNode=a;a.ui.onSelectedChange(true);this.fireEvent("selectionchange",this,this.selNodes);return a},unselect:function(b){if(this.selMap[b.id]){b.ui.onSelectedChange(false);var c=this.selNodes;var a=c.indexOf(b);if(a!=-1){this.selNodes.splice(a,1)}delete this.selMap[b.id];this.fireEvent("selectionchange",this,this.selNodes)}},clearSelections:function(b){var d=this.selNodes;if(d.length>0){for(var c=0,a=d.length;c<a;c++){d[c].ui.onSelectedChange(false)}this.selNodes=[];this.selMap={};if(b!==true){this.fireEvent("selectionchange",this,this.selNodes)}}},isSelected:function(a){return this.selMap[a.id]?true:false},getSelectedNodes:function(){return this.selNodes.concat([])},onKeyDown:Ext.tree.DefaultSelectionModel.prototype.onKeyDown,selectNext:Ext.tree.DefaultSelectionModel.prototype.selectNext,selectPrevious:Ext.tree.DefaultSelectionModel.prototype.selectPrevious});Ext.data.Tree=Ext.extend(Ext.util.Observable,{constructor:function(a){this.nodeHash={};this.root=null;if(a){this.setRootNode(a)}this.addEvents("append","remove","move","insert","beforeappend","beforeremove","beforemove","beforeinsert");Ext.data.Tree.superclass.constructor.call(this)},pathSeparator:"/",proxyNodeEvent:function(){return this.fireEvent.apply(this,arguments)},getRootNode:function(){return this.root},setRootNode:function(a){this.root=a;a.ownerTree=this;a.isRoot=true;this.registerNode(a);return a},getNodeById:function(a){return this.nodeHash[a]},registerNode:function(a){this.nodeHash[a.id]=a},unregisterNode:function(a){delete this.nodeHash[a.id]},toString:function(){return"[Tree"+(this.id?" "+this.id:"")+"]"}});Ext.data.Node=Ext.extend(Ext.util.Observable,{constructor:function(a){this.attributes=a||{};this.leaf=this.attributes.leaf;this.id=this.attributes.id;if(!this.id){this.id=Ext.id(null,"xnode-");this.attributes.id=this.id}this.childNodes=[];this.parentNode=null;this.firstChild=null;this.lastChild=null;this.previousSibling=null;this.nextSibling=null;this.addEvents({append:true,remove:true,move:true,insert:true,beforeappend:true,beforeremove:true,beforemove:true,beforeinsert:true});this.listeners=this.attributes.listeners;Ext.data.Node.superclass.constructor.call(this)},fireEvent:function(b){if(Ext.data.Node.superclass.fireEvent.apply(this,arguments)===false){return false}var a=this.getOwnerTree();if(a){if(a.proxyNodeEvent.apply(a,arguments)===false){return false}}return true},isLeaf:function(){return this.leaf===true},setFirstChild:function(a){this.firstChild=a},setLastChild:function(a){this.lastChild=a},isLast:function(){return(!this.parentNode?true:this.parentNode.lastChild==this)},isFirst:function(){return(!this.parentNode?true:this.parentNode.firstChild==this)},hasChildNodes:function(){return !this.isLeaf()&&this.childNodes.length>0},isExpandable:function(){return this.attributes.expandable||this.hasChildNodes()},appendChild:function(e){var g=false;if(Ext.isArray(e)){g=e}else{if(arguments.length>1){g=arguments}}if(g){for(var d=0,a=g.length;d<a;d++){this.appendChild(g[d])}}else{if(this.fireEvent("beforeappend",this.ownerTree,this,e)===false){return false}var b=this.childNodes.length;var c=e.parentNode;if(c){if(e.fireEvent("beforemove",e.getOwnerTree(),e,c,this,b)===false){return false}c.removeChild(e)}b=this.childNodes.length;if(b===0){this.setFirstChild(e)}this.childNodes.push(e);e.parentNode=this;var h=this.childNodes[b-1];if(h){e.previousSibling=h;h.nextSibling=e}else{e.previousSibling=null}e.nextSibling=null;this.setLastChild(e);e.setOwnerTree(this.getOwnerTree());this.fireEvent("append",this.ownerTree,this,e,b);if(c){e.fireEvent("move",this.ownerTree,e,c,this,b)}return e}},removeChild:function(c,b){var a=this.childNodes.indexOf(c);if(a==-1){return false}if(this.fireEvent("beforeremove",this.ownerTree,this,c)===false){return false}this.childNodes.splice(a,1);if(c.previousSibling){c.previousSibling.nextSibling=c.nextSibling}if(c.nextSibling){c.nextSibling.previousSibling=c.previousSibling}if(this.firstChild==c){this.setFirstChild(c.nextSibling)}if(this.lastChild==c){this.setLastChild(c.previousSibling)}this.fireEvent("remove",this.ownerTree,this,c);if(b){c.destroy(true)}else{c.clear()}return c},clear:function(a){this.setOwnerTree(null,a);this.parentNode=this.previousSibling=this.nextSibling=null;if(a){this.firstChild=this.lastChild=null}},destroy:function(a){if(a===true){this.purgeListeners();this.clear(true);Ext.each(this.childNodes,function(b){b.destroy(true)});this.childNodes=null}else{this.remove(true)}},insertBefore:function(d,a){if(!a){return this.appendChild(d)}if(d==a){return false}if(this.fireEvent("beforeinsert",this.ownerTree,this,d,a)===false){return false}var b=this.childNodes.indexOf(a);var c=d.parentNode;var e=b;if(c==this&&this.childNodes.indexOf(d)<b){e--}if(c){if(d.fireEvent("beforemove",d.getOwnerTree(),d,c,this,b,a)===false){return false}c.removeChild(d)}if(e===0){this.setFirstChild(d)}this.childNodes.splice(e,0,d);d.parentNode=this;var g=this.childNodes[e-1];if(g){d.previousSibling=g;g.nextSibling=d}else{d.previousSibling=null}d.nextSibling=a;a.previousSibling=d;d.setOwnerTree(this.getOwnerTree());this.fireEvent("insert",this.ownerTree,this,d,a);if(c){d.fireEvent("move",this.ownerTree,d,c,this,e,a)}return d},remove:function(a){if(this.parentNode){this.parentNode.removeChild(this,a)}return this},removeAll:function(a){var c=this.childNodes,b;while((b=c[0])){this.removeChild(b,a)}return this},item:function(a){return this.childNodes[a]},replaceChild:function(a,c){var b=c?c.nextSibling:null;this.removeChild(c);this.insertBefore(a,b);return c},indexOf:function(a){return this.childNodes.indexOf(a)},getOwnerTree:function(){if(!this.ownerTree){var a=this;while(a){if(a.ownerTree){this.ownerTree=a.ownerTree;break}a=a.parentNode}}return this.ownerTree},getDepth:function(){var b=0;var a=this;while(a.parentNode){++b;a=a.parentNode}return b},setOwnerTree:function(a,b){if(a!=this.ownerTree){if(this.ownerTree){this.ownerTree.unregisterNode(this)}this.ownerTree=a;if(b!==true){Ext.each(this.childNodes,function(c){c.setOwnerTree(a)})}if(a){a.registerNode(this)}}},setId:function(b){if(b!==this.id){var a=this.ownerTree;if(a){a.unregisterNode(this)}this.id=this.attributes.id=b;if(a){a.registerNode(this)}this.onIdChange(b)}},onIdChange:Ext.emptyFn,getPath:function(c){c=c||"id";var e=this.parentNode;var a=[this.attributes[c]];while(e){a.unshift(e.attributes[c]);e=e.parentNode}var d=this.getOwnerTree().pathSeparator;return d+a.join(d)},bubble:function(c,b,a){var d=this;while(d){if(c.apply(b||d,a||[d])===false){break}d=d.parentNode}},cascade:function(g,e,b){if(g.apply(e||this,b||[this])!==false){var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){d[c].cascade(g,e,b)}}},eachChild:function(g,e,b){var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){if(g.apply(e||d[c],b||[d[c]])===false){break}}},findChild:function(b,c,a){return this.findChildBy(function(){return this.attributes[b]==c},null,a)},findChildBy:function(h,g,b){var e=this.childNodes,a=e.length,d=0,j,c;for(;d<a;d++){j=e[d];if(h.call(g||j,j)===true){return j}else{if(b){c=j.findChildBy(h,g,b);if(c!=null){return c}}}}return null},sort:function(e,d){var c=this.childNodes;var a=c.length;if(a>0){var g=d?function(){e.apply(d,arguments)}:e;c.sort(g);for(var b=0;b<a;b++){var h=c[b];h.previousSibling=c[b-1];h.nextSibling=c[b+1];if(b===0){this.setFirstChild(h)}if(b==a-1){this.setLastChild(h)}}}},contains:function(a){return a.isAncestor(this)},isAncestor:function(a){var b=this.parentNode;while(b){if(b==a){return true}b=b.parentNode}return false},toString:function(){return"[Node"+(this.id?" "+this.id:"")+"]"}});Ext.tree.TreeNode=Ext.extend(Ext.data.Node,{constructor:function(a){a=a||{};if(Ext.isString(a)){a={text:a}}this.childrenRendered=false;this.rendered=false;Ext.tree.TreeNode.superclass.constructor.call(this,a);this.expanded=a.expanded===true;this.isTarget=a.isTarget!==false;this.draggable=a.draggable!==false&&a.allowDrag!==false;this.allowChildren=a.allowChildren!==false&&a.allowDrop!==false;this.text=a.text;this.disabled=a.disabled===true;this.hidden=a.hidden===true;this.addEvents("textchange","beforeexpand","beforecollapse","expand","disabledchange","collapse","beforeclick","click","checkchange","beforedblclick","dblclick","contextmenu","beforechildrenrendered");var b=this.attributes.uiProvider||this.defaultUI||Ext.tree.TreeNodeUI;this.ui=new b(this)},preventHScroll:true,isExpanded:function(){return this.expanded},getUI:function(){return this.ui},getLoader:function(){var a;return this.loader||((a=this.getOwnerTree())&&a.loader?a.loader:(this.loader=new Ext.tree.TreeLoader()))},setFirstChild:function(a){var b=this.firstChild;Ext.tree.TreeNode.superclass.setFirstChild.call(this,a);if(this.childrenRendered&&b&&a!=b){b.renderIndent(true,true)}if(this.rendered){this.renderIndent(true,true)}},setLastChild:function(b){var a=this.lastChild;Ext.tree.TreeNode.superclass.setLastChild.call(this,b);if(this.childrenRendered&&a&&b!=a){a.renderIndent(true,true)}if(this.rendered){this.renderIndent(true,true)}},appendChild:function(b){if(!b.render&&!Ext.isArray(b)){b=this.getLoader().createNode(b)}var a=Ext.tree.TreeNode.superclass.appendChild.call(this,b);if(a&&this.childrenRendered){a.render()}this.ui.updateExpandIcon();return a},removeChild:function(b,a){this.ownerTree.getSelectionModel().unselect(b);Ext.tree.TreeNode.superclass.removeChild.apply(this,arguments);if(!a){var c=b.ui.rendered;if(c){b.ui.remove()}if(c&&this.childNodes.length<1){this.collapse(false,false)}else{this.ui.updateExpandIcon()}if(!this.firstChild&&!this.isHiddenRoot()){this.childrenRendered=false}}return b},insertBefore:function(c,a){if(!c.render){c=this.getLoader().createNode(c)}var b=Ext.tree.TreeNode.superclass.insertBefore.call(this,c,a);if(b&&a&&this.childrenRendered){c.render()}this.ui.updateExpandIcon();return b},setText:function(b){var a=this.text;this.text=this.attributes.text=b;if(this.rendered){this.ui.onTextChange(this,b,a)}this.fireEvent("textchange",this,b,a)},setIconCls:function(b){var a=this.attributes.iconCls;this.attributes.iconCls=b;if(this.rendered){this.ui.onIconClsChange(this,b,a)}},setTooltip:function(a,b){this.attributes.qtip=a;this.attributes.qtipTitle=b;if(this.rendered){this.ui.onTipChange(this,a,b)}},setIcon:function(a){this.attributes.icon=a;if(this.rendered){this.ui.onIconChange(this,a)}},setHref:function(a,b){this.attributes.href=a;this.attributes.hrefTarget=b;if(this.rendered){this.ui.onHrefChange(this,a,b)}},setCls:function(b){var a=this.attributes.cls;this.attributes.cls=b;if(this.rendered){this.ui.onClsChange(this,b,a)}},select:function(){var a=this.getOwnerTree();if(a){a.getSelectionModel().select(this)}},unselect:function(a){var b=this.getOwnerTree();if(b){b.getSelectionModel().unselect(this,a)}},isSelected:function(){var a=this.getOwnerTree();return a?a.getSelectionModel().isSelected(this):false},expand:function(a,c,d,b){if(!this.expanded){if(this.fireEvent("beforeexpand",this,a,c)===false){return}if(!this.childrenRendered){this.renderChildren()}this.expanded=true;if(!this.isHiddenRoot()&&(this.getOwnerTree().animate&&c!==false)||c){this.ui.animExpand(function(){this.fireEvent("expand",this);this.runCallback(d,b||this,[this]);if(a===true){this.expandChildNodes(true,true)}}.createDelegate(this));return}else{this.ui.expand();this.fireEvent("expand",this);this.runCallback(d,b||this,[this])}}else{this.runCallback(d,b||this,[this])}if(a===true){this.expandChildNodes(true)}},runCallback:function(a,c,b){if(Ext.isFunction(a)){a.apply(c,b)}},isHiddenRoot:function(){return this.isRoot&&!this.getOwnerTree().rootVisible},collapse:function(b,g,h,e){if(this.expanded&&!this.isHiddenRoot()){if(this.fireEvent("beforecollapse",this,b,g)===false){return}this.expanded=false;if((this.getOwnerTree().animate&&g!==false)||g){this.ui.animCollapse(function(){this.fireEvent("collapse",this);this.runCallback(h,e||this,[this]);if(b===true){this.collapseChildNodes(true)}}.createDelegate(this));return}else{this.ui.collapse();this.fireEvent("collapse",this);this.runCallback(h,e||this,[this])}}else{if(!this.expanded){this.runCallback(h,e||this,[this])}}if(b===true){var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){d[c].collapse(true,false)}}},delayedExpand:function(a){if(!this.expandProcId){this.expandProcId=this.expand.defer(a,this)}},cancelExpand:function(){if(this.expandProcId){clearTimeout(this.expandProcId)}this.expandProcId=false},toggle:function(){if(this.expanded){this.collapse()}else{this.expand()}},ensureVisible:function(c,b){var a=this.getOwnerTree();a.expandPath(this.parentNode?this.parentNode.getPath():this.getPath(),false,function(){var d=a.getNodeById(this.id);a.getTreeEl().scrollChildIntoView(d.ui.anchor);this.runCallback(c,b||this,[this])}.createDelegate(this))},expandChildNodes:function(b,e){var d=this.childNodes,c,a=d.length;for(c=0;c<a;c++){d[c].expand(b,e)}},collapseChildNodes:function(b){var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){d[c].collapse(b)}},disable:function(){this.disabled=true;this.unselect();if(this.rendered&&this.ui.onDisableChange){this.ui.onDisableChange(this,true)}this.fireEvent("disabledchange",this,true)},enable:function(){this.disabled=false;if(this.rendered&&this.ui.onDisableChange){this.ui.onDisableChange(this,false)}this.fireEvent("disabledchange",this,false)},renderChildren:function(b){if(b!==false){this.fireEvent("beforechildrenrendered",this)}var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){d[c].render(true)}this.childrenRendered=true},sort:function(e,d){Ext.tree.TreeNode.superclass.sort.apply(this,arguments);if(this.childrenRendered){var c=this.childNodes;for(var b=0,a=c.length;b<a;b++){c[b].render(true)}}},render:function(a){this.ui.render(a);if(!this.rendered){this.getOwnerTree().registerNode(this);this.rendered=true;if(this.expanded){this.expanded=false;this.expand(false,false)}}},renderIndent:function(b,e){if(e){this.ui.childIndent=null}this.ui.renderIndent();if(b===true&&this.childrenRendered){var d=this.childNodes;for(var c=0,a=d.length;c<a;c++){d[c].renderIndent(true,e)}}},beginUpdate:function(){this.childrenRendered=false},endUpdate:function(){if(this.expanded&&this.rendered){this.renderChildren()}},destroy:function(a){if(a===true){this.unselect(true)}Ext.tree.TreeNode.superclass.destroy.call(this,a);Ext.destroy(this.ui,this.loader);this.ui=this.loader=null},onIdChange:function(a){this.ui.onIdChange(a)}});Ext.tree.TreePanel.nodeTypes.node=Ext.tree.TreeNode;Ext.tree.AsyncTreeNode=function(a){this.loaded=a&&a.loaded===true;this.loading=false;Ext.tree.AsyncTreeNode.superclass.constructor.apply(this,arguments);this.addEvents("beforeload","load")};Ext.extend(Ext.tree.AsyncTreeNode,Ext.tree.TreeNode,{expand:function(b,e,h,c){if(this.loading){var g;var d=function(){if(!this.loading){clearInterval(g);this.expand(b,e,h,c)}}.createDelegate(this);g=setInterval(d,200);return}if(!this.loaded){if(this.fireEvent("beforeload",this)===false){return}this.loading=true;this.ui.beforeLoad(this);var a=this.loader||this.attributes.loader||this.getOwnerTree().getLoader();if(a){a.load(this,this.loadComplete.createDelegate(this,[b,e,h,c]),this);return}}Ext.tree.AsyncTreeNode.superclass.expand.call(this,b,e,h,c)},isLoading:function(){return this.loading},loadComplete:function(a,c,d,b){this.loading=false;this.loaded=true;this.ui.afterLoad(this);this.fireEvent("load",this);this.expand(a,c,d,b)},isLoaded:function(){return this.loaded},hasChildNodes:function(){if(!this.isLeaf()&&!this.loaded){return true}else{return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this)}},reload:function(b,a){this.collapse(false,false);while(this.firstChild){this.removeChild(this.firstChild).destroy()}this.childrenRendered=false;this.loaded=false;if(this.isHiddenRoot()){this.expanded=false}this.expand(false,false,b,a)}});Ext.tree.TreePanel.nodeTypes.async=Ext.tree.AsyncTreeNode;Ext.tree.TreeNodeUI=Ext.extend(Object,{constructor:function(a){Ext.apply(this,{node:a,rendered:false,animating:false,wasLeaf:true,ecc:"x-tree-ec-icon x-tree-elbow",emptyIcon:Ext.BLANK_IMAGE_URL})},removeChild:function(a){if(this.rendered){this.ctNode.removeChild(a.ui.getEl())}},beforeLoad:function(){this.addClass("x-tree-node-loading")},afterLoad:function(){this.removeClass("x-tree-node-loading")},onTextChange:function(b,c,a){if(this.rendered){this.textNode.innerHTML=c}},onIconClsChange:function(c,a,b){if(this.rendered){Ext.fly(this.iconNode).replaceClass(b,a)}},onIconChange:function(b,a){if(this.rendered){var c=Ext.isEmpty(a);this.iconNode.src=c?this.emptyIcon:a;Ext.fly(this.iconNode)[c?"removeClass":"addClass"]("x-tree-node-inline-icon")}},onTipChange:function(b,c,d){if(this.rendered){var a=Ext.isDefined(d);if(this.textNode.setAttributeNS){this.textNode.setAttributeNS("ext","qtip",c);if(a){this.textNode.setAttributeNS("ext","qtitle",d)}}else{this.textNode.setAttribute("ext:qtip",c);if(a){this.textNode.setAttribute("ext:qtitle",d)}}}},onHrefChange:function(b,a,c){if(this.rendered){this.anchor.href=this.getHref(a);if(Ext.isDefined(c)){this.anchor.target=c}}},onClsChange:function(c,a,b){if(this.rendered){Ext.fly(this.elNode).replaceClass(b,a)}},onDisableChange:function(a,b){this.disabled=b;if(this.checkbox){this.checkbox.disabled=b}this[b?"addClass":"removeClass"]("x-tree-node-disabled")},onSelectedChange:function(a){if(a){this.focus();this.addClass("x-tree-selected")}else{this.removeClass("x-tree-selected")}},onMove:function(a,h,e,g,d,b){this.childIndent=null;if(this.rendered){var i=g.ui.getContainer();if(!i){this.holder=document.createElement("div");this.holder.appendChild(this.wrap);return}var c=b?b.ui.getEl():null;if(c){i.insertBefore(this.wrap,c)}else{i.appendChild(this.wrap)}this.node.renderIndent(true,e!=g)}},addClass:function(a){if(this.elNode){Ext.fly(this.elNode).addClass(a)}},removeClass:function(a){if(this.elNode){Ext.fly(this.elNode).removeClass(a)}},remove:function(){if(this.rendered){this.holder=document.createElement("div");this.holder.appendChild(this.wrap)}},fireEvent:function(){return this.node.fireEvent.apply(this.node,arguments)},initEvents:function(){this.node.on("move",this.onMove,this);if(this.node.disabled){this.onDisableChange(this.node,true)}if(this.node.hidden){this.hide()}var b=this.node.getOwnerTree();var a=b.enableDD||b.enableDrag||b.enableDrop;if(a&&(!this.node.isRoot||b.rootVisible)){Ext.dd.Registry.register(this.elNode,{node:this.node,handles:this.getDDHandles(),isHandle:false})}},getDDHandles:function(){return[this.iconNode,this.textNode,this.elNode]},hide:function(){this.node.hidden=true;if(this.wrap){this.wrap.style.display="none"}},show:function(){this.node.hidden=false;if(this.wrap){this.wrap.style.display=""}},onContextMenu:function(a){if(this.node.hasListener("contextmenu")||this.node.getOwnerTree().hasListener("contextmenu")){a.preventDefault();this.focus();this.fireEvent("contextmenu",this.node,a)}},onClick:function(c){if(this.dropping){c.stopEvent();return}if(this.fireEvent("beforeclick",this.node,c)!==false){var b=c.getTarget("a");if(!this.disabled&&this.node.attributes.href&&b){this.fireEvent("click",this.node,c);return}else{if(b&&c.ctrlKey){c.stopEvent()}}c.preventDefault();if(this.disabled){return}if(this.node.attributes.singleClickExpand&&!this.animating&&this.node.isExpandable()){this.node.toggle()}this.fireEvent("click",this.node,c)}else{c.stopEvent()}},onDblClick:function(a){a.preventDefault();if(this.disabled){return}if(this.fireEvent("beforedblclick",this.node,a)!==false){if(this.checkbox){this.toggleCheck()}if(!this.animating&&this.node.isExpandable()){this.node.toggle()}this.fireEvent("dblclick",this.node,a)}},onOver:function(a){this.addClass("x-tree-node-over")},onOut:function(a){this.removeClass("x-tree-node-over")},onCheckChange:function(){var a=this.checkbox.checked;this.checkbox.defaultChecked=a;this.node.attributes.checked=a;this.fireEvent("checkchange",this.node,a)},ecClick:function(a){if(!this.animating&&this.node.isExpandable()){this.node.toggle()}},startDrop:function(){this.dropping=true},endDrop:function(){setTimeout(function(){this.dropping=false}.createDelegate(this),50)},expand:function(){this.updateExpandIcon();this.ctNode.style.display=""},focus:function(){if(!this.node.preventHScroll){try{this.anchor.focus()}catch(c){}}else{try{var b=this.node.getOwnerTree().getTreeEl().dom;var a=b.scrollLeft;this.anchor.focus();b.scrollLeft=a}catch(c){}}},toggleCheck:function(b){var a=this.checkbox;if(a){a.checked=(b===undefined?!a.checked:b);this.onCheckChange()}},blur:function(){try{this.anchor.blur()}catch(a){}},animExpand:function(b){var a=Ext.get(this.ctNode);a.stopFx();if(!this.node.isExpandable()){this.updateExpandIcon();this.ctNode.style.display="";Ext.callback(b);return}this.animating=true;this.updateExpandIcon();a.slideIn("t",{callback:function(){this.animating=false;Ext.callback(b)},scope:this,duration:this.node.ownerTree.duration||0.25})},highlight:function(){var a=this.node.getOwnerTree();Ext.fly(this.wrap).highlight(a.hlColor||"C3DAF9",{endColor:a.hlBaseColor})},collapse:function(){this.updateExpandIcon();this.ctNode.style.display="none"},animCollapse:function(b){var a=Ext.get(this.ctNode);a.enableDisplayMode("block");a.stopFx();this.animating=true;this.updateExpandIcon();a.slideOut("t",{callback:function(){this.animating=false;Ext.callback(b)},scope:this,duration:this.node.ownerTree.duration||0.25})},getContainer:function(){return this.ctNode},getEl:function(){return this.wrap},appendDDGhost:function(a){a.appendChild(this.elNode.cloneNode(true))},getDDRepairXY:function(){return Ext.lib.Dom.getXY(this.iconNode)},onRender:function(){this.render()},render:function(c){var e=this.node,b=e.attributes;var d=e.parentNode?e.parentNode.ui.getContainer():e.ownerTree.innerCt.dom;if(!this.rendered){this.rendered=true;this.renderElements(e,b,d,c);if(b.qtip){this.onTipChange(e,b.qtip,b.qtipTitle)}else{if(b.qtipCfg){b.qtipCfg.target=Ext.id(this.textNode);Ext.QuickTips.register(b.qtipCfg)}}this.initEvents();if(!this.node.expanded){this.updateExpandIcon(true)}}else{if(c===true){d.appendChild(this.wrap)}}},renderElements:function(e,k,j,l){this.indentMarkup=e.parentNode?e.parentNode.ui.getChildIndent():"";var g=Ext.isBoolean(k.checked),b,c=this.getHref(k.href),d=['<li class="x-tree-node"><div ext:tree-node-id="',e.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ',k.cls,'" unselectable="on">','<span class="x-tree-node-indent">',this.indentMarkup,"</span>",'<img alt="" src="',this.emptyIcon,'" class="x-tree-ec-icon x-tree-elbow" />','<img alt="" src="',k.icon||this.emptyIcon,'" class="x-tree-node-icon',(k.icon?" x-tree-node-inline-icon":""),(k.iconCls?" "+k.iconCls:""),'" unselectable="on" />',g?('<input class="x-tree-node-cb" type="checkbox" '+(k.checked?'checked="checked" />':"/>")):"",'<a hidefocus="on" class="x-tree-node-anchor" href="',c,'" tabIndex="1" ',k.hrefTarget?' target="'+k.hrefTarget+'"':"",'><span unselectable="on">',e.text,"</span></a></div>",'<ul class="x-tree-node-ct" style="display:none;"></ul>',"</li>"].join("");if(l!==true&&e.nextSibling&&(b=e.nextSibling.ui.getEl())){this.wrap=Ext.DomHelper.insertHtml("beforeBegin",b,d)}else{this.wrap=Ext.DomHelper.insertHtml("beforeEnd",j,d)}this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1];var i=this.elNode.childNodes;this.indentNode=i[0];this.ecNode=i[1];this.iconNode=i[2];var h=3;if(g){this.checkbox=i[3];this.checkbox.defaultChecked=this.checkbox.checked;h++}this.anchor=i[h];this.textNode=i[h].firstChild},getHref:function(a){return Ext.isEmpty(a)?(Ext.isGecko?"":"#"):a},getAnchor:function(){return this.anchor},getTextEl:function(){return this.textNode},getIconEl:function(){return this.iconNode},isChecked:function(){return this.checkbox?this.checkbox.checked:false},updateExpandIcon:function(){if(this.rendered){var g=this.node,d,c,a=g.isLast()?"x-tree-elbow-end":"x-tree-elbow",e=g.hasChildNodes();if(e||g.attributes.expandable){if(g.expanded){a+="-minus";d="x-tree-node-collapsed";c="x-tree-node-expanded"}else{a+="-plus";d="x-tree-node-expanded";c="x-tree-node-collapsed"}if(this.wasLeaf){this.removeClass("x-tree-node-leaf");this.wasLeaf=false}if(this.c1!=d||this.c2!=c){Ext.fly(this.elNode).replaceClass(d,c);this.c1=d;this.c2=c}}else{if(!this.wasLeaf){Ext.fly(this.elNode).replaceClass("x-tree-node-expanded","x-tree-node-collapsed");delete this.c1;delete this.c2;this.wasLeaf=true}}var b="x-tree-ec-icon "+a;if(this.ecc!=b){this.ecNode.className=b;this.ecc=b}}},onIdChange:function(a){if(this.rendered){this.elNode.setAttribute("ext:tree-node-id",a)}},getChildIndent:function(){if(!this.childIndent){var a=[],b=this.node;while(b){if(!b.isRoot||(b.isRoot&&b.ownerTree.rootVisible)){if(!b.isLast()){a.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-elbow-line" />')}else{a.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-icon" />')}}b=b.parentNode}this.childIndent=a.join("")}return this.childIndent},renderIndent:function(){if(this.rendered){var a="",b=this.node.parentNode;if(b){a=b.ui.getChildIndent()}if(this.indentMarkup!=a){this.indentNode.innerHTML=a;this.indentMarkup=a}this.updateExpandIcon()}},destroy:function(){if(this.elNode){Ext.dd.Registry.unregister(this.elNode.id)}Ext.each(["textnode","anchor","checkbox","indentNode","ecNode","iconNode","elNode","ctNode","wrap","holder"],function(a){if(this[a]){Ext.fly(this[a]).remove();delete this[a]}},this);delete this.node}});Ext.tree.RootTreeNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{render:function(){if(!this.rendered){var a=this.node.ownerTree.innerCt.dom;this.node.expanded=true;a.innerHTML='<div class="x-tree-root-node"></div>';this.wrap=this.ctNode=a.firstChild}},collapse:Ext.emptyFn,expand:Ext.emptyFn});Ext.tree.TreeLoader=function(a){this.baseParams={};Ext.apply(this,a);this.addEvents("beforeload","load","loadexception");Ext.tree.TreeLoader.superclass.constructor.call(this);if(Ext.isString(this.paramOrder)){this.paramOrder=this.paramOrder.split(/[\s,|]/)}};Ext.extend(Ext.tree.TreeLoader,Ext.util.Observable,{uiProviders:{},clearOnLoad:true,paramOrder:undefined,paramsAsHash:false,nodeParameter:"node",directFn:undefined,load:function(b,c,a){if(this.clearOnLoad){while(b.firstChild){b.removeChild(b.firstChild)}}if(this.doPreload(b)){this.runCallback(c,a||b,[b])}else{if(this.directFn||this.dataUrl||this.url){this.requestData(b,c,a||b)}}},doPreload:function(d){if(d.attributes.children){if(d.childNodes.length<1){var c=d.attributes.children;d.beginUpdate();for(var b=0,a=c.length;b<a;b++){var e=d.appendChild(this.createNode(c[b]));if(this.preloadChildren){this.doPreload(e)}}d.endUpdate()}return true}return false},getParams:function(g){var e=Ext.apply({},this.baseParams),h=this.nodeParameter,b=this.paramOrder;h&&(e[h]=g.id);if(this.directFn){var c=[g.id];if(b){if(h&&b.indexOf(h)>-1){c=[]}for(var d=0,a=b.length;d<a;d++){c.push(e[b[d]])}}else{if(this.paramsAsHash){c=[e]}}return c}else{return e}},requestData:function(c,d,b){if(this.fireEvent("beforeload",this,c,d)!==false){if(this.directFn){var a=this.getParams(c);a.push(this.processDirectResponse.createDelegate(this,[{callback:d,node:c,scope:b}],true));this.directFn.apply(window,a)}else{this.transId=Ext.Ajax.request({method:this.requestMethod,url:this.dataUrl||this.url,success:this.handleResponse,failure:this.handleFailure,scope:this,argument:{callback:d,node:c,scope:b},params:this.getParams(c)})}}else{this.runCallback(d,b||c,[])}},processDirectResponse:function(a,b,c){if(b.status){this.handleResponse({responseData:Ext.isArray(a)?a:null,responseText:a,argument:c})}else{this.handleFailure({argument:c})}},runCallback:function(a,c,b){if(Ext.isFunction(a)){a.apply(c,b)}},isLoading:function(){return !!this.transId},abort:function(){if(this.isLoading()){Ext.Ajax.abort(this.transId)}},createNode:function(attr){if(this.baseAttrs){Ext.applyIf(attr,this.baseAttrs)}if(this.applyLoader!==false&&!attr.loader){attr.loader=this}if(Ext.isString(attr.uiProvider)){attr.uiProvider=this.uiProviders[attr.uiProvider]||eval(attr.uiProvider)}if(attr.nodeType){return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr)}else{return attr.leaf?new Ext.tree.TreeNode(attr):new Ext.tree.AsyncTreeNode(attr)}},processResponse:function(d,c,k,l){var m=d.responseText;try{var a=d.responseData||Ext.decode(m);c.beginUpdate();for(var g=0,h=a.length;g<h;g++){var b=this.createNode(a[g]);if(b){c.appendChild(b)}}c.endUpdate();this.runCallback(k,l||c,[c])}catch(j){this.handleFailure(d)}},handleResponse:function(c){this.transId=false;var b=c.argument;this.processResponse(c,b.node,b.callback,b.scope);this.fireEvent("load",this,b.node,c)},handleFailure:function(c){this.transId=false;var b=c.argument;this.fireEvent("loadexception",this,b.node,c);this.runCallback(b.callback,b.scope||b.node,[b.node])},destroy:function(){this.abort();this.purgeListeners()}});Ext.tree.TreeFilter=function(a,b){this.tree=a;this.filtered={};Ext.apply(this,b)};Ext.tree.TreeFilter.prototype={clearBlank:false,reverse:false,autoClear:false,remove:false,filter:function(d,a,b){a=a||"text";var c;if(typeof d=="string"){var e=d.length;if(e==0&&this.clearBlank){this.clear();return}d=d.toLowerCase();c=function(g){return g.attributes[a].substr(0,e).toLowerCase()==d}}else{if(d.exec){c=function(g){return d.test(g.attributes[a])}}else{throw"Illegal filter type, must be string or regex"}}this.filterBy(c,null,b)},filterBy:function(d,c,b){b=b||this.tree.root;if(this.autoClear){this.clear()}var a=this.filtered,i=this.reverse;var e=function(k){if(k==b){return true}if(a[k.id]){return false}var j=d.call(c||k,k);if(!j||i){a[k.id]=k;k.ui.hide();return false}return true};b.cascade(e);if(this.remove){for(var h in a){if(typeof h!="function"){var g=a[h];if(g&&g.parentNode){g.parentNode.removeChild(g)}}}}},clear:function(){var b=this.tree;var a=this.filtered;for(var d in a){if(typeof d!="function"){var c=a[d];if(c){c.ui.show()}}}this.filtered={}}};Ext.tree.TreeSorter=Ext.extend(Object,{constructor:function(a,c){Ext.apply(this,c);a.on({scope:this,beforechildrenrendered:this.doSort,append:this.updateSort,insert:this.updateSort,textchange:this.updateSortParent});var e=this.dir&&this.dir.toLowerCase()=="desc",i=this.property||"text",d=this.sortType,h=this.folderSort,b=this.caseSensitive===true,g=this.leafAttr||"leaf";if(Ext.isString(d)){d=Ext.data.SortTypes[d]}this.sortFn=function(o,m){var k=o.attributes,j=m.attributes;if(h){if(k[g]&&!j[g]){return 1}if(!k[g]&&j[g]){return -1}}var n=k[i],l=j[i],q=d?d(n):(b?n:n.toUpperCase()),p=d?d(l):(b?l:l.toUpperCase());if(q<p){return e?1:-1}else{if(q>p){return e?-1:1}}return 0}},doSort:function(a){a.sort(this.sortFn)},updateSort:function(a,b){if(b.childrenRendered){this.doSort.defer(1,this,[b])}},updateSortParent:function(a){var b=a.parentNode;if(b&&b.childrenRendered){this.doSort.defer(1,this,[b])}}});if(Ext.dd.DropZone){Ext.tree.TreeDropZone=function(a,b){this.allowParentInsert=b.allowParentInsert||false;this.allowContainerDrop=b.allowContainerDrop||false;this.appendOnly=b.appendOnly||false;Ext.tree.TreeDropZone.superclass.constructor.call(this,a.getTreeEl(),b);this.tree=a;this.dragOverData={};this.lastInsertClass="x-tree-no-status"};Ext.extend(Ext.tree.TreeDropZone,Ext.dd.DropZone,{ddGroup:"TreeDD",expandDelay:1000,expandNode:function(a){if(a.hasChildNodes()&&!a.isExpanded()){a.expand(false,null,this.triggerCacheRefresh.createDelegate(this))}},queueExpand:function(a){this.expandProcId=this.expandNode.defer(this.expandDelay,this,[a])},cancelExpand:function(){if(this.expandProcId){clearTimeout(this.expandProcId);this.expandProcId=false}},isValidDropPoint:function(a,k,i,d,c){if(!a||!c){return false}var g=a.node;var h=c.node;if(!(g&&g.isTarget&&k)){return false}if(k=="append"&&g.allowChildren===false){return false}if((k=="above"||k=="below")&&(g.parentNode&&g.parentNode.allowChildren===false)){return false}if(h&&(g==h||h.contains(g))){return false}var b=this.dragOverData;b.tree=this.tree;b.target=g;b.data=c;b.point=k;b.source=i;b.rawEvent=d;b.dropNode=h;b.cancel=false;var j=this.tree.fireEvent("nodedragover",b);return b.cancel===false&&j!==false},getDropPoint:function(h,g,l){var m=g.node;if(m.isRoot){return m.allowChildren!==false?"append":false}var c=g.ddel;var o=Ext.lib.Dom.getY(c),j=o+c.offsetHeight;var i=Ext.lib.Event.getPageY(h);var k=m.allowChildren===false||m.isLeaf();if(this.appendOnly||m.parentNode.allowChildren===false){return k?false:"append"}var d=false;if(!this.allowParentInsert){d=m.hasChildNodes()&&m.isExpanded()}var a=(j-o)/(k?2:3);if(i>=o&&i<(o+a)){return"above"}else{if(!d&&(k||i>=j-a&&i<=j)){return"below"}else{return"append"}}},onNodeEnter:function(d,a,c,b){this.cancelExpand()},onContainerOver:function(a,c,b){if(this.allowContainerDrop&&this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode,node:this.tree.getRootNode()},"append",a,c,b)){return this.dropAllowed}return this.dropNotAllowed},onNodeOver:function(b,i,h,g){var k=this.getDropPoint(h,b,i);var c=b.node;if(!this.expandProcId&&k=="append"&&c.hasChildNodes()&&!b.node.isExpanded()){this.queueExpand(c)}else{if(k!="append"){this.cancelExpand()}}var d=this.dropNotAllowed;if(this.isValidDropPoint(b,k,i,h,g)){if(k){var a=b.ddel;var j;if(k=="above"){d=b.node.isFirst()?"x-tree-drop-ok-above":"x-tree-drop-ok-between";j="x-tree-drag-insert-above"}else{if(k=="below"){d=b.node.isLast()?"x-tree-drop-ok-below":"x-tree-drop-ok-between";j="x-tree-drag-insert-below"}else{d="x-tree-drop-ok-append";j="x-tree-drag-append"}}if(this.lastInsertClass!=j){Ext.fly(a).replaceClass(this.lastInsertClass,j);this.lastInsertClass=j}}}return d},onNodeOut:function(d,a,c,b){this.cancelExpand();this.removeDropIndicators(d)},onNodeDrop:function(i,b,h,d){var a=this.getDropPoint(h,i,b);var g=i.node;g.ui.startDrop();if(!this.isValidDropPoint(i,a,b,h,d)){g.ui.endDrop();return false}var c=d.node||(b.getTreeNode?b.getTreeNode(d,g,a,h):null);return this.processDrop(g,d,a,b,h,c)},onContainerDrop:function(a,g,c){if(this.allowContainerDrop&&this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode,node:this.tree.getRootNode()},"append",a,g,c)){var d=this.tree.getRootNode();d.ui.startDrop();var b=c.node||(a.getTreeNode?a.getTreeNode(c,d,"append",g):null);return this.processDrop(d,c,"append",a,g,b)}return false},processDrop:function(j,h,b,a,i,d){var g={tree:this.tree,target:j,data:h,point:b,source:a,rawEvent:i,dropNode:d,cancel:!d,dropStatus:false};var c=this.tree.fireEvent("beforenodedrop",g);if(c===false||g.cancel===true||!g.dropNode){j.ui.endDrop();return g.dropStatus}j=g.target;if(b=="append"&&!j.isExpanded()){j.expand(false,null,function(){this.completeDrop(g)}.createDelegate(this))}else{this.completeDrop(g)}return true},completeDrop:function(h){var d=h.dropNode,e=h.point,c=h.target;if(!Ext.isArray(d)){d=[d]}var g;for(var b=0,a=d.length;b<a;b++){g=d[b];if(e=="above"){c.parentNode.insertBefore(g,c)}else{if(e=="below"){c.parentNode.insertBefore(g,c.nextSibling)}else{c.appendChild(g)}}}g.ui.focus();if(Ext.enableFx&&this.tree.hlDrop){g.ui.highlight()}c.ui.endDrop();this.tree.fireEvent("nodedrop",h)},afterNodeMoved:function(a,c,g,d,b){if(Ext.enableFx&&this.tree.hlDrop){b.ui.focus();b.ui.highlight()}this.tree.fireEvent("nodedrop",this.tree,d,c,a,g)},getTree:function(){return this.tree},removeDropIndicators:function(b){if(b&&b.ddel){var a=b.ddel;Ext.fly(a).removeClass(["x-tree-drag-insert-above","x-tree-drag-insert-below","x-tree-drag-append"]);this.lastInsertClass="_noclass"}},beforeDragDrop:function(b,a,c){this.cancelExpand();return true},afterRepair:function(a){if(a&&Ext.enableFx){a.node.ui.highlight()}this.hideProxy()}})}if(Ext.dd.DragZone){Ext.tree.TreeDragZone=function(a,b){Ext.tree.TreeDragZone.superclass.constructor.call(this,a.innerCt,b);this.tree=a};Ext.extend(Ext.tree.TreeDragZone,Ext.dd.DragZone,{ddGroup:"TreeDD",onBeforeDrag:function(a,b){var c=a.node;return c&&c.draggable&&!c.disabled},onInitDrag:function(b){var a=this.dragData;this.tree.getSelectionModel().select(a.node);this.tree.eventModel.disable();this.proxy.update("");a.node.ui.appendDDGhost(this.proxy.ghost.dom);this.tree.fireEvent("startdrag",this.tree,a.node,b)},getRepairXY:function(b,a){return a.node.ui.getDDRepairXY()},onEndDrag:function(a,b){this.tree.eventModel.enable.defer(100,this.tree.eventModel);this.tree.fireEvent("enddrag",this.tree,a.node,b)},onValidDrop:function(a,b,c){this.tree.fireEvent("dragdrop",this.tree,this.dragData.node,a,b);this.hideProxy()},beforeInvalidDrop:function(a,c){var b=this.tree.getSelectionModel();b.clearSelections();b.select(this.dragData.node)},afterRepair:function(){if(Ext.enableFx&&this.tree.hlDrop){Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor||"c3daf9")}this.dragging=false}})}Ext.tree.TreeEditor=function(a,c,b){c=c||{};var d=c.events?c:new Ext.form.TextField(c);Ext.tree.TreeEditor.superclass.constructor.call(this,d,b);this.tree=a;if(!a.rendered){a.on("render",this.initEditor,this)}else{this.initEditor(a)}};Ext.extend(Ext.tree.TreeEditor,Ext.Editor,{alignment:"l-l",autoSize:false,hideEl:false,cls:"x-small-editor x-tree-editor",shim:false,shadow:"frame",maxWidth:250,editDelay:350,initEditor:function(a){a.on({scope:this,beforeclick:this.beforeNodeClick,dblclick:this.onNodeDblClick});this.on({scope:this,complete:this.updateNode,beforestartedit:this.fitToTree,specialkey:this.onSpecialKey});this.on("startedit",this.bindScroll,this,{delay:10})},fitToTree:function(b,c){var e=this.tree.getTreeEl().dom,d=c.dom;if(e.scrollLeft>d.offsetLeft){e.scrollLeft=d.offsetLeft}var a=Math.min(this.maxWidth,(e.clientWidth>20?e.clientWidth:e.offsetWidth)-Math.max(0,d.offsetLeft-e.scrollLeft)-5);this.setSize(a,"")},triggerEdit:function(a,c){this.completeEdit();if(a.attributes.editable!==false){this.editNode=a;if(this.tree.autoScroll){Ext.fly(a.ui.getEl()).scrollIntoView(this.tree.body)}var b=a.text||"";if(!Ext.isGecko&&Ext.isEmpty(a.text)){a.setText("&#160;")}this.autoEditTimer=this.startEdit.defer(this.editDelay,this,[a.ui.textNode,b]);return false}},bindScroll:function(){this.tree.getTreeEl().on("scroll",this.cancelEdit,this)},beforeNodeClick:function(a,b){clearTimeout(this.autoEditTimer);if(this.tree.getSelectionModel().isSelected(a)){b.stopEvent();return this.triggerEdit(a)}},onNodeDblClick:function(a,b){clearTimeout(this.autoEditTimer)},updateNode:function(a,b){this.tree.getTreeEl().un("scroll",this.cancelEdit,this);this.editNode.setText(b)},onHide:function(){Ext.tree.TreeEditor.superclass.onHide.call(this);if(this.editNode){this.editNode.ui.focus.defer(50,this.editNode.ui)}},onSpecialKey:function(c,b){var a=b.getKey();if(a==b.ESC){b.stopEvent();this.cancelEdit()}else{if(a==b.ENTER&&!b.hasModifier()){b.stopEvent();this.completeEdit()}}},onDestroy:function(){clearTimeout(this.autoEditTimer);Ext.tree.TreeEditor.superclass.onDestroy.call(this);var a=this.tree;a.un("beforeclick",this.beforeNodeClick,this);a.un("dblclick",this.onNodeDblClick,this)}});
+/* SWFObject v2.2 <http://code.google.com/p/swfobject/> 
+    is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
+*/
+var swfobject=function(){var E="undefined",s="object",T="Shockwave Flash",X="ShockwaveFlash.ShockwaveFlash",r="application/x-shockwave-flash",S="SWFObjectExprInst",y="onreadystatechange",P=window,k=document,u=navigator,U=false,V=[i],p=[],O=[],J=[],m,R,F,C,K=false,a=false,o,H,n=true,N=function(){var ab=typeof k.getElementById!=E&&typeof k.getElementsByTagName!=E&&typeof k.createElement!=E,ai=u.userAgent.toLowerCase(),Z=u.platform.toLowerCase(),af=Z?(/win/).test(Z):/win/.test(ai),ad=Z?(/mac/).test(Z):/mac/.test(ai),ag=/webkit/.test(ai)?parseFloat(ai.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,Y=!+"\v1",ah=[0,0,0],ac=null;if(typeof u.plugins!=E&&typeof u.plugins[T]==s){ac=u.plugins[T].description;if(ac&&!(typeof u.mimeTypes!=E&&u.mimeTypes[r]&&!u.mimeTypes[r].enabledPlugin)){U=true;Y=false;ac=ac.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ah[0]=parseInt(ac.replace(/^(.*)\..*$/,"$1"),10);ah[1]=parseInt(ac.replace(/^.*\.(.*)\s.*$/,"$1"),10);ah[2]=/[a-zA-Z]/.test(ac)?parseInt(ac.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof P.ActiveXObject!=E){try{var ae=new ActiveXObject(X);if(ae){ac=ae.GetVariable("$version");if(ac){Y=true;ac=ac.split(" ")[1].split(",");ah=[parseInt(ac[0],10),parseInt(ac[1],10),parseInt(ac[2],10)]}}}catch(aa){}}}return{w3:ab,pv:ah,wk:ag,ie:Y,win:af,mac:ad}}(),l=function(){if(!N.w3){return}if((typeof k.readyState!=E&&k.readyState=="complete")||(typeof k.readyState==E&&(k.getElementsByTagName("body")[0]||k.body))){g()}if(!K){if(typeof k.addEventListener!=E){k.addEventListener("DOMContentLoaded",g,false)}if(N.ie&&N.win){k.attachEvent(y,function(){if(k.readyState=="complete"){k.detachEvent(y,arguments.callee);g()}});if(P==top){(function(){if(K){return}try{k.documentElement.doScroll("left")}catch(Y){setTimeout(arguments.callee,0);return}g()})()}}if(N.wk){(function(){if(K){return}if(!(/loaded|complete/).test(k.readyState)){setTimeout(arguments.callee,0);return}g()})()}t(g)}}();function g(){if(K){return}try{var aa=k.getElementsByTagName("body")[0].appendChild(D("span"));aa.parentNode.removeChild(aa)}catch(ab){return}K=true;var Y=V.length;for(var Z=0;Z<Y;Z++){V[Z]()}}function L(Y){if(K){Y()}else{V[V.length]=Y}}function t(Z){if(typeof P.addEventListener!=E){P.addEventListener("load",Z,false)}else{if(typeof k.addEventListener!=E){k.addEventListener("load",Z,false)}else{if(typeof P.attachEvent!=E){j(P,"onload",Z)}else{if(typeof P.onload=="function"){var Y=P.onload;P.onload=function(){Y();Z()}}else{P.onload=Z}}}}}function i(){if(U){W()}else{I()}}function W(){var Y=k.getElementsByTagName("body")[0];var ab=D(s);ab.setAttribute("type",r);var aa=Y.appendChild(ab);if(aa){var Z=0;(function(){if(typeof aa.GetVariable!=E){var ac=aa.GetVariable("$version");if(ac){ac=ac.split(" ")[1].split(",");N.pv=[parseInt(ac[0],10),parseInt(ac[1],10),parseInt(ac[2],10)]}}else{if(Z<10){Z++;setTimeout(arguments.callee,10);return}}Y.removeChild(ab);aa=null;I()})()}else{I()}}function I(){var ah=p.length;if(ah>0){for(var ag=0;ag<ah;ag++){var Z=p[ag].id;var ac=p[ag].callbackFn;var ab={success:false,id:Z};if(N.pv[0]>0){var af=c(Z);if(af){if(G(p[ag].swfVersion)&&!(N.wk&&N.wk<312)){x(Z,true);if(ac){ab.success=true;ab.ref=A(Z);ac(ab)}}else{if(p[ag].expressInstall&&B()){var aj={};aj.data=p[ag].expressInstall;aj.width=af.getAttribute("width")||"0";aj.height=af.getAttribute("height")||"0";if(af.getAttribute("class")){aj.styleclass=af.getAttribute("class")}if(af.getAttribute("align")){aj.align=af.getAttribute("align")}var ai={};var Y=af.getElementsByTagName("param");var ad=Y.length;for(var ae=0;ae<ad;ae++){if(Y[ae].getAttribute("name").toLowerCase()!="movie"){ai[Y[ae].getAttribute("name")]=Y[ae].getAttribute("value")}}Q(aj,ai,Z,ac)}else{q(af);if(ac){ac(ab)}}}}}else{x(Z,true);if(ac){var aa=A(Z);if(aa&&typeof aa.SetVariable!=E){ab.success=true;ab.ref=aa}ac(ab)}}}}}function A(ab){var Y=null;var Z=c(ab);if(Z&&Z.nodeName=="OBJECT"){if(typeof Z.SetVariable!=E){Y=Z}else{var aa=Z.getElementsByTagName(s)[0];if(aa){Y=aa}}}return Y}function B(){return !a&&G("6.0.65")&&(N.win||N.mac)&&!(N.wk&&N.wk<312)}function Q(ab,ac,Y,aa){a=true;F=aa||null;C={success:false,id:Y};var af=c(Y);if(af){if(af.nodeName=="OBJECT"){m=h(af);R=null}else{m=af;R=Y}ab.id=S;if(typeof ab.width==E||(!(/%$/).test(ab.width)&&parseInt(ab.width,10)<310)){ab.width="310"}if(typeof ab.height==E||(!(/%$/).test(ab.height)&&parseInt(ab.height,10)<137)){ab.height="137"}k.title=k.title.slice(0,47)+" - Flash Player Installation";var ae=N.ie&&N.win?"ActiveX":"PlugIn",ad="MMredirectURL="+P.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ae+"&MMdoctitle="+k.title;if(typeof ac.flashvars!=E){ac.flashvars+="&"+ad}else{ac.flashvars=ad}if(N.ie&&N.win&&af.readyState!=4){var Z=D("div");Y+="SWFObjectNew";Z.setAttribute("id",Y);af.parentNode.insertBefore(Z,af);af.style.display="none";(function(){if(af.readyState==4){af.parentNode.removeChild(af)}else{setTimeout(arguments.callee,10)}})()}v(ab,ac,Y)}}function q(Z){if(N.ie&&N.win&&Z.readyState!=4){var Y=D("div");Z.parentNode.insertBefore(Y,Z);Y.parentNode.replaceChild(h(Z),Y);Z.style.display="none";(function(){if(Z.readyState==4){Z.parentNode.removeChild(Z)}else{setTimeout(arguments.callee,10)}})()}else{Z.parentNode.replaceChild(h(Z),Z)}}function h(ad){var ab=D("div");if(N.win&&N.ie){ab.innerHTML=ad.innerHTML}else{var Z=ad.getElementsByTagName(s)[0];if(Z){var ae=Z.childNodes;if(ae){var Y=ae.length;for(var aa=0;aa<Y;aa++){if(!(ae[aa].nodeType==1&&ae[aa].nodeName=="PARAM")&&!(ae[aa].nodeType==8)){ab.appendChild(ae[aa].cloneNode(true))}}}}}return ab}function v(aj,ah,Z){var Y,ab=c(Z);if(N.wk&&N.wk<312){return Y}if(ab){if(typeof aj.id==E){aj.id=Z}if(N.ie&&N.win){var ai="";for(var af in aj){if(aj[af]!=Object.prototype[af]){if(af.toLowerCase()=="data"){ah.movie=aj[af]}else{if(af.toLowerCase()=="styleclass"){ai+=' class="'+aj[af]+'"'}else{if(af.toLowerCase()!="classid"){ai+=" "+af+'="'+aj[af]+'"'}}}}}var ag="";for(var ae in ah){if(ah[ae]!=Object.prototype[ae]){ag+='<param name="'+ae+'" value="'+ah[ae]+'" />'}}ab.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ai+">"+ag+"</object>";O[O.length]=aj.id;Y=c(aj.id)}else{var aa=D(s);aa.setAttribute("type",r);for(var ad in aj){if(aj[ad]!=Object.prototype[ad]){if(ad.toLowerCase()=="styleclass"){aa.setAttribute("class",aj[ad])}else{if(ad.toLowerCase()!="classid"){aa.setAttribute(ad,aj[ad])}}}}for(var ac in ah){if(ah[ac]!=Object.prototype[ac]&&ac.toLowerCase()!="movie"){e(aa,ac,ah[ac])}}ab.parentNode.replaceChild(aa,ab);Y=aa}}return Y}function e(aa,Y,Z){var ab=D("param");ab.setAttribute("name",Y);ab.setAttribute("value",Z);aa.appendChild(ab)}function z(Z){var Y=c(Z);if(Y&&Y.nodeName=="OBJECT"){if(N.ie&&N.win){Y.style.display="none";(function(){if(Y.readyState==4){b(Z)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.removeChild(Y)}}}function b(aa){var Z=c(aa);if(Z){for(var Y in Z){if(typeof Z[Y]=="function"){Z[Y]=null}}Z.parentNode.removeChild(Z)}}function c(aa){var Y=null;try{Y=k.getElementById(aa)}catch(Z){}return Y}function D(Y){return k.createElement(Y)}function j(aa,Y,Z){aa.attachEvent(Y,Z);J[J.length]=[aa,Y,Z]}function G(aa){var Z=N.pv,Y=aa.split(".");Y[0]=parseInt(Y[0],10);Y[1]=parseInt(Y[1],10)||0;Y[2]=parseInt(Y[2],10)||0;return(Z[0]>Y[0]||(Z[0]==Y[0]&&Z[1]>Y[1])||(Z[0]==Y[0]&&Z[1]==Y[1]&&Z[2]>=Y[2]))?true:false}function w(ad,Z,ae,ac){if(N.ie&&N.mac){return}var ab=k.getElementsByTagName("head")[0];if(!ab){return}var Y=(ae&&typeof ae=="string")?ae:"screen";if(ac){o=null;H=null}if(!o||H!=Y){var aa=D("style");aa.setAttribute("type","text/css");aa.setAttribute("media",Y);o=ab.appendChild(aa);if(N.ie&&N.win&&typeof k.styleSheets!=E&&k.styleSheets.length>0){o=k.styleSheets[k.styleSheets.length-1]}H=Y}if(N.ie&&N.win){if(o&&typeof o.addRule==s){o.addRule(ad,Z)}}else{if(o&&typeof k.createTextNode!=E){o.appendChild(k.createTextNode(ad+" {"+Z+"}"))}}}function x(aa,Y){if(!n){return}var Z=Y?"visible":"hidden";if(K&&c(aa)){c(aa).style.visibility=Z}else{w("#"+aa,"visibility:"+Z)}}function M(Z){var aa=/[\\\"<>\.;]/;var Y=aa.exec(Z)!=null;return Y&&typeof encodeURIComponent!=E?encodeURIComponent(Z):Z}var d=function(){if(N.ie&&N.win){window.attachEvent("onunload",function(){var ad=J.length;for(var ac=0;ac<ad;ac++){J[ac][0].detachEvent(J[ac][1],J[ac][2])}var aa=O.length;for(var ab=0;ab<aa;ab++){z(O[ab])}for(var Z in N){N[Z]=null}N=null;for(var Y in swfobject){swfobject[Y]=null}swfobject=null;window.detachEvent("onunload",arguments.callee)})}}();return{registerObject:function(ac,Y,ab,aa){if(N.w3&&ac&&Y){var Z={};Z.id=ac;Z.swfVersion=Y;Z.expressInstall=ab;Z.callbackFn=aa;p[p.length]=Z;x(ac,false)}else{if(aa){aa({success:false,id:ac})}}},getObjectById:function(Y){if(N.w3){return A(Y)}},embedSWF:function(ac,ai,af,ah,Z,ab,aa,ae,ag,ad){var Y={success:false,id:ai};if(N.w3&&!(N.wk&&N.wk<312)&&ac&&ai&&af&&ah&&Z){x(ai,false);L(function(){af+="";ah+="";var ak={};if(ag&&typeof ag===s){for(var am in ag){ak[am]=ag[am]}}ak.data=ac;ak.width=af;ak.height=ah;var an={};if(ae&&typeof ae===s){for(var al in ae){an[al]=ae[al]}}if(aa&&typeof aa===s){for(var aj in aa){if(typeof an.flashvars!=E){an.flashvars+="&"+aj+"="+aa[aj]}else{an.flashvars=aj+"="+aa[aj]}}}if(G(Z)){var ao=v(ak,an,ai);if(ak.id==ai){x(ai,true)}Y.success=true;Y.ref=ao}else{if(ab&&B()){ak.data=ab;Q(ak,an,ai,ad);return}else{x(ai,true)}}if(ad){ad(Y)}})}else{if(ad){ad(Y)}}},switchOffAutoHideShow:function(){n=false},ua:N,getFlashPlayerVersion:function(){return{major:N.pv[0],minor:N.pv[1],release:N.pv[2]}},hasFlashPlayerVersion:G,createSWF:function(aa,Z,Y){if(N.w3){return v(aa,Z,Y)}else{return undefined}},showExpressInstall:function(aa,ab,Y,Z){if(N.w3&&B()){Q(aa,ab,Y,Z)}},removeSWF:function(Y){if(N.w3){z(Y)}},createCSS:function(ab,aa,Z,Y){if(N.w3){w(ab,aa,Z,Y)}},addDomLoadEvent:L,addLoadEvent:t,getQueryParamValue:function(ab){var aa=k.location.search||k.location.hash;if(aa){if(/\?/.test(aa)){aa=aa.split("?")[1]}if(ab==null){return M(aa)}var Z=aa.split("&");for(var Y=0;Y<Z.length;Y++){if(Z[Y].substring(0,Z[Y].indexOf("="))==ab){return M(Z[Y].substring((Z[Y].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var Y=c(S);if(Y&&m){Y.parentNode.replaceChild(m,Y);if(R){x(R,true);if(N.ie&&N.win){m.style.display="block"}}if(F){F(C)}}a=false}}}}();Ext.FlashComponent=Ext.extend(Ext.BoxComponent,{flashVersion:"9.0.115",backgroundColor:"#ffffff",wmode:"opaque",flashVars:undefined,flashParams:undefined,url:undefined,swfId:undefined,swfWidth:"100%",swfHeight:"100%",expressInstall:false,initComponent:function(){Ext.FlashComponent.superclass.initComponent.call(this);this.addEvents("initialize")},onRender:function(){Ext.FlashComponent.superclass.onRender.apply(this,arguments);var b=Ext.apply({allowScriptAccess:"always",bgcolor:this.backgroundColor,wmode:this.wmode},this.flashParams),a=Ext.apply({allowedDomain:document.location.hostname,YUISwfId:this.getId(),YUIBridgeCallback:"Ext.FlashEventProxy.onEvent"},this.flashVars);new swfobject.embedSWF(this.url,this.id,this.swfWidth,this.swfHeight,this.flashVersion,this.expressInstall?Ext.FlashComponent.EXPRESS_INSTALL_URL:undefined,a,b);this.swf=Ext.getDom(this.id);this.el=Ext.get(this.swf)},getSwfId:function(){return this.swfId||(this.swfId="extswf"+(++Ext.Component.AUTO_ID))},getId:function(){return this.id||(this.id="extflashcmp"+(++Ext.Component.AUTO_ID))},onFlashEvent:function(a){switch(a.type){case"swfReady":this.initSwf();return;case"log":return}a.component=this;this.fireEvent(a.type.toLowerCase().replace(/event$/,""),a)},initSwf:function(){this.onSwfReady(!!this.isInitialized);this.isInitialized=true;this.fireEvent("initialize",this)},beforeDestroy:function(){if(this.rendered){swfobject.removeSWF(this.swf.id)}Ext.FlashComponent.superclass.beforeDestroy.call(this)},onSwfReady:Ext.emptyFn});Ext.FlashComponent.EXPRESS_INSTALL_URL="http://swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf";Ext.reg("flash",Ext.FlashComponent);Ext.FlashEventProxy={onEvent:function(c,b){var a=Ext.getCmp(c);if(a){a.onFlashEvent(b)}else{arguments.callee.defer(10,this,[c,b])}}};Ext.chart.Chart=Ext.extend(Ext.FlashComponent,{refreshBuffer:100,chartStyle:{padding:10,animationEnabled:true,font:{name:"Tahoma",color:4473924,size:11},dataTip:{padding:5,border:{color:10075112,size:1},background:{color:14346230,alpha:0.9},font:{name:"Tahoma",color:1393291,size:10,bold:true}}},extraStyle:null,seriesStyles:null,disableCaching:Ext.isIE||Ext.isOpera,disableCacheParam:"_dc",initComponent:function(){Ext.chart.Chart.superclass.initComponent.call(this);if(!this.url){this.url=Ext.chart.Chart.CHART_URL}if(this.disableCaching){this.url=Ext.urlAppend(this.url,String.format("{0}={1}",this.disableCacheParam,new Date().getTime()))}this.addEvents("itemmouseover","itemmouseout","itemclick","itemdoubleclick","itemdragstart","itemdrag","itemdragend","beforerefresh","refresh");this.store=Ext.StoreMgr.lookup(this.store)},setStyle:function(a,b){this.swf.setStyle(a,Ext.encode(b))},setStyles:function(a){this.swf.setStyles(Ext.encode(a))},setSeriesStyles:function(b){this.seriesStyles=b;var a=[];Ext.each(b,function(c){a.push(Ext.encode(c))});this.swf.setSeriesStyles(a)},setCategoryNames:function(a){this.swf.setCategoryNames(a)},setLegendRenderer:function(c,b){var a=this;b=b||a;a.removeFnProxy(a.legendFnName);a.legendFnName=a.createFnProxy(function(d){return c.call(b,d)});a.swf.setLegendLabelFunction(a.legendFnName)},setTipRenderer:function(c,b){var a=this;b=b||a;a.removeFnProxy(a.tipFnName);a.tipFnName=a.createFnProxy(function(h,e,g){var d=a.store.getAt(e);return c.call(b,a,d,e,g)});a.swf.setDataTipFunction(a.tipFnName)},setSeries:function(a){this.series=a;this.refresh()},bindStore:function(a,b){if(!b&&this.store){if(a!==this.store&&this.store.autoDestroy){this.store.destroy()}else{this.store.un("datachanged",this.refresh,this);this.store.un("add",this.delayRefresh,this);this.store.un("remove",this.delayRefresh,this);this.store.un("update",this.delayRefresh,this);this.store.un("clear",this.refresh,this)}}if(a){a=Ext.StoreMgr.lookup(a);a.on({scope:this,datachanged:this.refresh,add:this.delayRefresh,remove:this.delayRefresh,update:this.delayRefresh,clear:this.refresh})}this.store=a;if(a&&!b){this.refresh()}},onSwfReady:function(b){Ext.chart.Chart.superclass.onSwfReady.call(this,b);var a;this.swf.setType(this.type);if(this.chartStyle){this.setStyles(Ext.apply({},this.extraStyle,this.chartStyle))}if(this.categoryNames){this.setCategoryNames(this.categoryNames)}if(this.tipRenderer){a=this.getFunctionRef(this.tipRenderer);this.setTipRenderer(a.fn,a.scope)}if(this.legendRenderer){a=this.getFunctionRef(this.legendRenderer);this.setLegendRenderer(a.fn,a.scope)}if(!b){this.bindStore(this.store,true)}this.refresh.defer(10,this)},delayRefresh:function(){if(!this.refreshTask){this.refreshTask=new Ext.util.DelayedTask(this.refresh,this)}this.refreshTask.delay(this.refreshBuffer)},refresh:function(){if(this.fireEvent("beforerefresh",this)!==false){var m=false;var k=[],c=this.store.data.items;for(var g=0,l=c.length;g<l;g++){k[g]=c[g].data}var e=[];var d=0;var n=null;var h=0;if(this.series){d=this.series.length;for(h=0;h<d;h++){n=this.series[h];var b={};for(var a in n){if(a=="style"&&n.style!==null){b.style=Ext.encode(n.style);m=true}else{b[a]=n[a]}}e.push(b)}}if(d>0){for(h=0;h<d;h++){n=e[h];if(!n.type){n.type=this.type}n.dataProvider=k}}else{e.push({type:this.type,dataProvider:k})}this.swf.setDataProvider(e);if(this.seriesStyles){this.setSeriesStyles(this.seriesStyles)}this.fireEvent("refresh",this)}},createFnProxy:function(a){var b="extFnProxy"+(++Ext.chart.Chart.PROXY_FN_ID);Ext.chart.Chart.proxyFunction[b]=a;return"Ext.chart.Chart.proxyFunction."+b},removeFnProxy:function(a){if(!Ext.isEmpty(a)){a=a.replace("Ext.chart.Chart.proxyFunction.","");delete Ext.chart.Chart.proxyFunction[a]}},getFunctionRef:function(a){if(Ext.isFunction(a)){return{fn:a,scope:this}}else{return{fn:a.fn,scope:a.scope||this}}},onDestroy:function(){if(this.refreshTask&&this.refreshTask.cancel){this.refreshTask.cancel()}Ext.chart.Chart.superclass.onDestroy.call(this);this.bindStore(null);this.removeFnProxy(this.tipFnName);this.removeFnProxy(this.legendFnName)}});Ext.reg("chart",Ext.chart.Chart);Ext.chart.Chart.PROXY_FN_ID=0;Ext.chart.Chart.proxyFunction={};Ext.chart.Chart.CHART_URL="http://yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf";Ext.chart.PieChart=Ext.extend(Ext.chart.Chart,{type:"pie",onSwfReady:function(a){Ext.chart.PieChart.superclass.onSwfReady.call(this,a);this.setDataField(this.dataField);this.setCategoryField(this.categoryField)},setDataField:function(a){this.dataField=a;this.swf.setDataField(a)},setCategoryField:function(a){this.categoryField=a;this.swf.setCategoryField(a)}});Ext.reg("piechart",Ext.chart.PieChart);Ext.chart.CartesianChart=Ext.extend(Ext.chart.Chart,{onSwfReady:function(a){Ext.chart.CartesianChart.superclass.onSwfReady.call(this,a);this.labelFn=[];if(this.xField){this.setXField(this.xField)}if(this.yField){this.setYField(this.yField)}if(this.xAxis){this.setXAxis(this.xAxis)}if(this.xAxes){this.setXAxes(this.xAxes)}if(this.yAxis){this.setYAxis(this.yAxis)}if(this.yAxes){this.setYAxes(this.yAxes)}if(Ext.isDefined(this.constrainViewport)){this.swf.setConstrainViewport(this.constrainViewport)}},setXField:function(a){this.xField=a;this.swf.setHorizontalField(a)},setYField:function(a){this.yField=a;this.swf.setVerticalField(a)},setXAxis:function(a){this.xAxis=this.createAxis("xAxis",a);this.swf.setHorizontalAxis(this.xAxis)},setXAxes:function(c){var b;for(var a=0;a<c.length;a++){b=this.createAxis("xAxis"+a,c[a]);this.swf.setHorizontalAxis(b)}},setYAxis:function(a){this.yAxis=this.createAxis("yAxis",a);this.swf.setVerticalAxis(this.yAxis)},setYAxes:function(c){var b;for(var a=0;a<c.length;a++){b=this.createAxis("yAxis"+a,c[a]);this.swf.setVerticalAxis(b)}},createAxis:function(b,d){var e=Ext.apply({},d),c,a;if(this[b]){a=this[b].labelFunction;this.removeFnProxy(a);this.labelFn.remove(a)}if(e.labelRenderer){c=this.getFunctionRef(e.labelRenderer);e.labelFunction=this.createFnProxy(function(g){return c.fn.call(c.scope,g)});delete e.labelRenderer;this.labelFn.push(e.labelFunction)}if(b.indexOf("xAxis")>-1&&e.position=="left"){e.position="bottom"}return e},onDestroy:function(){Ext.chart.CartesianChart.superclass.onDestroy.call(this);Ext.each(this.labelFn,function(a){this.removeFnProxy(a)},this)}});Ext.reg("cartesianchart",Ext.chart.CartesianChart);Ext.chart.LineChart=Ext.extend(Ext.chart.CartesianChart,{type:"line"});Ext.reg("linechart",Ext.chart.LineChart);Ext.chart.ColumnChart=Ext.extend(Ext.chart.CartesianChart,{type:"column"});Ext.reg("columnchart",Ext.chart.ColumnChart);Ext.chart.StackedColumnChart=Ext.extend(Ext.chart.CartesianChart,{type:"stackcolumn"});Ext.reg("stackedcolumnchart",Ext.chart.StackedColumnChart);Ext.chart.BarChart=Ext.extend(Ext.chart.CartesianChart,{type:"bar"});Ext.reg("barchart",Ext.chart.BarChart);Ext.chart.StackedBarChart=Ext.extend(Ext.chart.CartesianChart,{type:"stackbar"});Ext.reg("stackedbarchart",Ext.chart.StackedBarChart);Ext.chart.Axis=function(a){Ext.apply(this,a)};Ext.chart.Axis.prototype={type:null,orientation:"horizontal",reverse:false,labelFunction:null,hideOverlappingLabels:true,labelSpacing:2};Ext.chart.NumericAxis=Ext.extend(Ext.chart.Axis,{type:"numeric",minimum:NaN,maximum:NaN,majorUnit:NaN,minorUnit:NaN,snapToUnits:true,alwaysShowZero:true,scale:"linear",roundMajorUnit:true,calculateByLabelSize:true,position:"left",adjustMaximumByMajorUnit:true,adjustMinimumByMajorUnit:true});Ext.chart.TimeAxis=Ext.extend(Ext.chart.Axis,{type:"time",minimum:null,maximum:null,majorUnit:NaN,majorTimeUnit:null,minorUnit:NaN,minorTimeUnit:null,snapToUnits:true,stackingEnabled:false,calculateByLabelSize:true});Ext.chart.CategoryAxis=Ext.extend(Ext.chart.Axis,{type:"category",categoryNames:null,calculateCategoryCount:false});Ext.chart.Series=function(a){Ext.apply(this,a)};Ext.chart.Series.prototype={type:null,displayName:null};Ext.chart.CartesianSeries=Ext.extend(Ext.chart.Series,{xField:null,yField:null,showInLegend:true,axis:"primary"});Ext.chart.ColumnSeries=Ext.extend(Ext.chart.CartesianSeries,{type:"column"});Ext.chart.LineSeries=Ext.extend(Ext.chart.CartesianSeries,{type:"line"});Ext.chart.BarSeries=Ext.extend(Ext.chart.CartesianSeries,{type:"bar"});Ext.chart.PieSeries=Ext.extend(Ext.chart.Series,{type:"pie",dataField:null,categoryField:null});Ext.menu.Menu=Ext.extend(Ext.Container,{minWidth:120,shadow:"sides",subMenuAlign:"tl-tr?",defaultAlign:"tl-bl?",allowOtherMenus:false,ignoreParentClicks:false,enableScrolling:true,maxHeight:null,scrollIncrement:24,showSeparator:true,defaultOffsets:[0,0],plain:false,floating:true,zIndex:15000,hidden:true,layout:"menu",hideMode:"offsets",scrollerHeight:8,autoLayout:true,defaultType:"menuitem",bufferResize:false,initComponent:function(){if(Ext.isArray(this.initialConfig)){Ext.apply(this,{items:this.initialConfig})}this.addEvents("click","mouseover","mouseout","itemclick");Ext.menu.MenuMgr.register(this);if(this.floating){Ext.EventManager.onWindowResize(this.hide,this)}else{if(this.initialConfig.hidden!==false){this.hidden=false}this.internalDefaults={hideOnClick:false}}Ext.menu.Menu.superclass.initComponent.call(this);if(this.autoLayout){var a=this.doLayout.createDelegate(this,[]);this.on({add:a,remove:a})}},getLayoutTarget:function(){return this.ul},onRender:function(b,a){if(!b){b=Ext.getBody()}var c={id:this.getId(),cls:"x-menu "+((this.floating)?"x-menu-floating x-layer ":"")+(this.cls||"")+(this.plain?" x-menu-plain":"")+(this.showSeparator?"":" x-menu-nosep"),style:this.style,cn:[{tag:"a",cls:"x-menu-focus",href:"#",onclick:"return false;",tabIndex:"-1"},{tag:"ul",cls:"x-menu-list"}]};if(this.floating){this.el=new Ext.Layer({shadow:this.shadow,dh:c,constrain:false,parentEl:b,zindex:this.zIndex})}else{this.el=b.createChild(c)}Ext.menu.Menu.superclass.onRender.call(this,b,a);if(!this.keyNav){this.keyNav=new Ext.menu.MenuNav(this)}this.focusEl=this.el.child("a.x-menu-focus");this.ul=this.el.child("ul.x-menu-list");this.mon(this.ul,{scope:this,click:this.onClick,mouseover:this.onMouseOver,mouseout:this.onMouseOut});if(this.enableScrolling){this.mon(this.el,{scope:this,delegate:".x-menu-scroller",click:this.onScroll,mouseover:this.deactivateActive})}},findTargetItem:function(b){var a=b.getTarget(".x-menu-list-item",this.ul,true);if(a&&a.menuItemId){return this.items.get(a.menuItemId)}},onClick:function(b){var a=this.findTargetItem(b);if(a){if(a.isFormField){this.setActiveItem(a)}else{if(a instanceof Ext.menu.BaseItem){if(a.menu&&this.ignoreParentClicks){a.expandMenu();b.preventDefault()}else{if(a.onClick){a.onClick(b);this.fireEvent("click",this,a,b)}}}}}},setActiveItem:function(a,b){if(a!=this.activeItem){this.deactivateActive();if((this.activeItem=a).isFormField){a.focus()}else{a.activate(b)}}else{if(b){a.expandMenu()}}},deactivateActive:function(){var b=this.activeItem;if(b){if(b.isFormField){if(b.collapse){b.collapse()}}else{b.deactivate()}delete this.activeItem}},tryActivate:function(g,e){var b=this.items;for(var c=g,a=b.length;c>=0&&c<a;c+=e){var d=b.get(c);if(d.isVisible()&&!d.disabled&&(d.canActivate||d.isFormField)){this.setActiveItem(d,false);return d}}return false},onMouseOver:function(b){var a=this.findTargetItem(b);if(a){if(a.canActivate&&!a.disabled){this.setActiveItem(a,true)}}this.over=true;this.fireEvent("mouseover",this,b,a)},onMouseOut:function(b){var a=this.findTargetItem(b);if(a){if(a==this.activeItem&&a.shouldDeactivate&&a.shouldDeactivate(b)){this.activeItem.deactivate();delete this.activeItem}}this.over=false;this.fireEvent("mouseout",this,b,a)},onScroll:function(d,b){if(d){d.stopEvent()}var a=this.ul.dom,c=Ext.fly(b).is(".x-menu-scroller-top");a.scrollTop+=this.scrollIncrement*(c?-1:1);if(c?a.scrollTop<=0:a.scrollTop+this.activeMax>=a.scrollHeight){this.onScrollerOut(null,b)}},onScrollerIn:function(d,b){var a=this.ul.dom,c=Ext.fly(b).is(".x-menu-scroller-top");if(c?a.scrollTop>0:a.scrollTop+this.activeMax<a.scrollHeight){Ext.fly(b).addClass(["x-menu-item-active","x-menu-scroller-active"])}},onScrollerOut:function(b,a){Ext.fly(a).removeClass(["x-menu-item-active","x-menu-scroller-active"])},show:function(b,c,a){if(this.floating){this.parentMenu=a;if(!this.el){this.render();this.doLayout(false,true)}this.showAt(this.el.getAlignToXY(b,c||this.defaultAlign,this.defaultOffsets),a)}else{Ext.menu.Menu.superclass.show.call(this)}},showAt:function(b,a){if(this.fireEvent("beforeshow",this)!==false){this.parentMenu=a;if(!this.el){this.render()}if(this.enableScrolling){this.el.setXY(b);b[1]=this.constrainScroll(b[1]);b=[this.el.adjustForConstraints(b)[0],b[1]]}else{b=this.el.adjustForConstraints(b)}this.el.setXY(b);this.el.show();Ext.menu.Menu.superclass.onShow.call(this);if(Ext.isIE){this.fireEvent("autosize",this);if(!Ext.isIE8){this.el.repaint()}}this.hidden=false;this.focus();this.fireEvent("show",this)}},constrainScroll:function(i){var b,d=this.ul.setHeight("auto").getHeight(),a=i,h,e,g,c;if(this.floating){e=Ext.fly(this.el.dom.parentNode);g=e.getScroll().top;c=e.getViewSize().height;h=i-g;b=this.maxHeight?this.maxHeight:c-h;if(d>c){b=c;a=i-h}else{if(b<d){a=i-(d-b);b=d}}}else{b=this.getHeight()}if(this.maxHeight){b=Math.min(this.maxHeight,b)}if(d>b&&b>0){this.activeMax=b-this.scrollerHeight*2-this.el.getFrameWidth("tb")-Ext.num(this.el.shadowOffset,0);this.ul.setHeight(this.activeMax);this.createScrollers();this.el.select(".x-menu-scroller").setDisplayed("")}else{this.ul.setHeight(d);this.el.select(".x-menu-scroller").setDisplayed("none")}this.ul.dom.scrollTop=0;return a},createScrollers:function(){if(!this.scroller){this.scroller={pos:0,top:this.el.insertFirst({tag:"div",cls:"x-menu-scroller x-menu-scroller-top",html:"&#160;"}),bottom:this.el.createChild({tag:"div",cls:"x-menu-scroller x-menu-scroller-bottom",html:"&#160;"})};this.scroller.top.hover(this.onScrollerIn,this.onScrollerOut,this);this.scroller.topRepeater=new Ext.util.ClickRepeater(this.scroller.top,{listeners:{click:this.onScroll.createDelegate(this,[null,this.scroller.top],false)}});this.scroller.bottom.hover(this.onScrollerIn,this.onScrollerOut,this);this.scroller.bottomRepeater=new Ext.util.ClickRepeater(this.scroller.bottom,{listeners:{click:this.onScroll.createDelegate(this,[null,this.scroller.bottom],false)}})}},onLayout:function(){if(this.isVisible()){if(this.enableScrolling){this.constrainScroll(this.el.getTop())}if(this.floating){this.el.sync()}}},focus:function(){if(!this.hidden){this.doFocus.defer(50,this)}},doFocus:function(){if(!this.hidden){this.focusEl.focus()}},hide:function(a){if(!this.isDestroyed){this.deepHide=a;Ext.menu.Menu.superclass.hide.call(this);delete this.deepHide}},onHide:function(){Ext.menu.Menu.superclass.onHide.call(this);this.deactivateActive();if(this.el&&this.floating){this.el.hide()}var a=this.parentMenu;if(this.deepHide===true&&a){if(a.floating){a.hide(true)}else{a.deactivateActive()}}},lookupComponent:function(a){if(Ext.isString(a)){a=(a=="separator"||a=="-")?new Ext.menu.Separator():new Ext.menu.TextItem(a);this.applyDefaults(a)}else{if(Ext.isObject(a)){a=this.getMenuItem(a)}else{if(a.tagName||a.el){a=new Ext.BoxComponent({el:a})}}}return a},applyDefaults:function(b){if(!Ext.isString(b)){b=Ext.menu.Menu.superclass.applyDefaults.call(this,b);var a=this.internalDefaults;if(a){if(b.events){Ext.applyIf(b.initialConfig,a);Ext.apply(b,a)}else{Ext.applyIf(b,a)}}}return b},getMenuItem:function(a){a.ownerCt=this;if(!a.isXType){if(!a.xtype&&Ext.isBoolean(a.checked)){return new Ext.menu.CheckItem(a)}return Ext.create(a,this.defaultType)}return a},addSeparator:function(){return this.add(new Ext.menu.Separator())},addElement:function(a){return this.add(new Ext.menu.BaseItem({el:a}))},addItem:function(a){return this.add(a)},addMenuItem:function(a){return this.add(this.getMenuItem(a))},addText:function(a){return this.add(new Ext.menu.TextItem(a))},onDestroy:function(){Ext.EventManager.removeResizeListener(this.hide,this);var a=this.parentMenu;if(a&&a.activeChild==this){delete a.activeChild}delete this.parentMenu;Ext.menu.Menu.superclass.onDestroy.call(this);Ext.menu.MenuMgr.unregister(this);if(this.keyNav){this.keyNav.disable()}var b=this.scroller;if(b){Ext.destroy(b.topRepeater,b.bottomRepeater,b.top,b.bottom)}Ext.destroy(this.el,this.focusEl,this.ul)}});Ext.reg("menu",Ext.menu.Menu);Ext.menu.MenuNav=Ext.extend(Ext.KeyNav,function(){function a(d,c){if(!c.tryActivate(c.items.indexOf(c.activeItem)-1,-1)){c.tryActivate(c.items.length-1,-1)}}function b(d,c){if(!c.tryActivate(c.items.indexOf(c.activeItem)+1,1)){c.tryActivate(0,1)}}return{constructor:function(c){Ext.menu.MenuNav.superclass.constructor.call(this,c.el);this.scope=this.menu=c},doRelay:function(g,d){var c=g.getKey();if(this.menu.activeItem&&this.menu.activeItem.isFormField&&c!=g.TAB){return false}if(!this.menu.activeItem&&g.isNavKeyPress()&&c!=g.SPACE&&c!=g.RETURN){this.menu.tryActivate(0,1);return false}return d.call(this.scope||this,g,this.menu)},tab:function(d,c){d.stopEvent();if(d.shiftKey){a(d,c)}else{b(d,c)}},up:a,down:b,right:function(d,c){if(c.activeItem){c.activeItem.expandMenu(true)}},left:function(d,c){c.hide();if(c.parentMenu&&c.parentMenu.activeItem){c.parentMenu.activeItem.activate()}},enter:function(d,c){if(c.activeItem){d.stopPropagation();c.activeItem.onClick(d);c.fireEvent("click",this,c.activeItem);return true}}}}());Ext.menu.MenuMgr=function(){var h,e,b,d={},a=false,l=new Date();function n(){h={};e=new Ext.util.MixedCollection();b=Ext.getDoc().addKeyListener(27,j);b.disable()}function j(){if(e&&e.length>0){var o=e.clone();o.each(function(p){p.hide()});return true}return false}function g(o){e.remove(o);if(e.length<1){b.disable();Ext.getDoc().un("mousedown",m);a=false}}function k(o){var p=e.last();l=new Date();e.add(o);if(!a){b.enable();Ext.getDoc().on("mousedown",m);a=true}if(o.parentMenu){o.getEl().setZIndex(parseInt(o.parentMenu.getEl().getStyle("z-index"),10)+3);o.parentMenu.activeChild=o}else{if(p&&!p.isDestroyed&&p.isVisible()){o.getEl().setZIndex(parseInt(p.getEl().getStyle("z-index"),10)+3)}}}function c(o){if(o.activeChild){o.activeChild.hide()}if(o.autoHideTimer){clearTimeout(o.autoHideTimer);delete o.autoHideTimer}}function i(o){var p=o.parentMenu;if(!p&&!o.allowOtherMenus){j()}else{if(p&&p.activeChild){p.activeChild.hide()}}}function m(o){if(l.getElapsed()>50&&e.length>0&&!o.getTarget(".x-menu")){j()}}return{hideAll:function(){return j()},register:function(o){if(!h){n()}h[o.id]=o;o.on({beforehide:c,hide:g,beforeshow:i,show:k})},get:function(o){if(typeof o=="string"){if(!h){return null}return h[o]}else{if(o.events){return o}else{if(typeof o.length=="number"){return new Ext.menu.Menu({items:o})}else{return Ext.create(o,"menu")}}}},unregister:function(o){delete h[o.id];o.un("beforehide",c);o.un("hide",g);o.un("beforeshow",i);o.un("show",k)},registerCheckable:function(o){var p=o.group;if(p){if(!d[p]){d[p]=[]}d[p].push(o)}},unregisterCheckable:function(o){var p=o.group;if(p){d[p].remove(o)}},onCheckChange:function(q,r){if(q.group&&r){var t=d[q.group],p=0,o=t.length,s;for(;p<o;p++){s=t[p];if(s!=q){s.setChecked(false)}}}},getCheckedItem:function(q){var r=d[q];if(r){for(var p=0,o=r.length;p<o;p++){if(r[p].checked){return r[p]}}}return null},setCheckedItem:function(q,s){var r=d[q];if(r){for(var p=0,o=r.length;p<o;p++){if(r[p].id==s){r[p].setChecked(true)}}}return null}}}();Ext.menu.BaseItem=Ext.extend(Ext.Component,{canActivate:false,activeClass:"x-menu-item-active",hideOnClick:true,clickHideDelay:1,ctype:"Ext.menu.BaseItem",actionMode:"container",initComponent:function(){Ext.menu.BaseItem.superclass.initComponent.call(this);this.addEvents("click","activate","deactivate");if(this.handler){this.on("click",this.handler,this.scope)}},onRender:function(b,a){Ext.menu.BaseItem.superclass.onRender.apply(this,arguments);if(this.ownerCt&&this.ownerCt instanceof Ext.menu.Menu){this.parentMenu=this.ownerCt}else{this.container.addClass("x-menu-list-item");this.mon(this.el,{scope:this,click:this.onClick,mouseenter:this.activate,mouseleave:this.deactivate})}},setHandler:function(b,a){if(this.handler){this.un("click",this.handler,this.scope)}this.on("click",this.handler=b,this.scope=a)},onClick:function(a){if(!this.disabled&&this.fireEvent("click",this,a)!==false&&(this.parentMenu&&this.parentMenu.fireEvent("itemclick",this,a)!==false)){this.handleClick(a)}else{a.stopEvent()}},activate:function(){if(this.disabled){return false}var a=this.container;a.addClass(this.activeClass);this.region=a.getRegion().adjust(2,2,-2,-2);this.fireEvent("activate",this);return true},deactivate:function(){this.container.removeClass(this.activeClass);this.fireEvent("deactivate",this)},shouldDeactivate:function(a){return !this.region||!this.region.contains(a.getPoint())},handleClick:function(b){var a=this.parentMenu;if(this.hideOnClick){if(a.floating){this.clickHideDelayTimer=a.hide.defer(this.clickHideDelay,a,[true])}else{a.deactivateActive()}}},beforeDestroy:function(){clearTimeout(this.clickHideDelayTimer);Ext.menu.BaseItem.superclass.beforeDestroy.call(this)},expandMenu:Ext.emptyFn,hideMenu:Ext.emptyFn});Ext.reg("menubaseitem",Ext.menu.BaseItem);Ext.menu.TextItem=Ext.extend(Ext.menu.BaseItem,{hideOnClick:false,itemCls:"x-menu-text",constructor:function(a){if(typeof a=="string"){a={text:a}}Ext.menu.TextItem.superclass.constructor.call(this,a)},onRender:function(){var a=document.createElement("span");a.className=this.itemCls;a.innerHTML=this.text;this.el=a;Ext.menu.TextItem.superclass.onRender.apply(this,arguments)}});Ext.reg("menutextitem",Ext.menu.TextItem);Ext.menu.Separator=Ext.extend(Ext.menu.BaseItem,{itemCls:"x-menu-sep",hideOnClick:false,activeClass:"",onRender:function(a){var b=document.createElement("span");b.className=this.itemCls;b.innerHTML="&#160;";this.el=b;a.addClass("x-menu-sep-li");Ext.menu.Separator.superclass.onRender.apply(this,arguments)}});Ext.reg("menuseparator",Ext.menu.Separator);Ext.menu.Item=Ext.extend(Ext.menu.BaseItem,{itemCls:"x-menu-item",canActivate:true,showDelay:200,altText:"",hideDelay:200,ctype:"Ext.menu.Item",initComponent:function(){Ext.menu.Item.superclass.initComponent.call(this);if(this.menu){if(Ext.isArray(this.menu)){this.menu={items:this.menu}}if(Ext.isObject(this.menu)){this.menu.ownerCt=this}this.menu=Ext.menu.MenuMgr.get(this.menu);this.menu.ownerCt=undefined}},onRender:function(d,b){if(!this.itemTpl){this.itemTpl=Ext.menu.Item.prototype.itemTpl=new Ext.XTemplate('<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"','<tpl if="hrefTarget">',' target="{hrefTarget}"',"</tpl>",">",'<img alt="{altText}" src="{icon}" class="x-menu-item-icon {iconCls}"/>','<span class="x-menu-item-text">{text}</span>',"</a>")}var c=this.getTemplateArgs();this.el=b?this.itemTpl.insertBefore(b,c,true):this.itemTpl.append(d,c,true);this.iconEl=this.el.child("img.x-menu-item-icon");this.textEl=this.el.child(".x-menu-item-text");if(!this.href){this.mon(this.el,"click",Ext.emptyFn,null,{preventDefault:true})}Ext.menu.Item.superclass.onRender.call(this,d,b)},getTemplateArgs:function(){return{id:this.id,cls:this.itemCls+(this.menu?" x-menu-item-arrow":"")+(this.cls?" "+this.cls:""),href:this.href||"#",hrefTarget:this.hrefTarget,icon:this.icon||Ext.BLANK_IMAGE_URL,iconCls:this.iconCls||"",text:this.itemText||this.text||"&#160;",altText:this.altText||""}},setText:function(a){this.text=a||"&#160;";if(this.rendered){this.textEl.update(this.text);this.parentMenu.layout.doAutoSize()}},setIconClass:function(a){var b=this.iconCls;this.iconCls=a;if(this.rendered){this.iconEl.replaceClass(b,this.iconCls)}},beforeDestroy:function(){clearTimeout(this.showTimer);clearTimeout(this.hideTimer);if(this.menu){delete this.menu.ownerCt;this.menu.destroy()}Ext.menu.Item.superclass.beforeDestroy.call(this)},handleClick:function(a){if(!this.href){a.stopEvent()}Ext.menu.Item.superclass.handleClick.apply(this,arguments)},activate:function(a){if(Ext.menu.Item.superclass.activate.apply(this,arguments)){this.focus();if(a){this.expandMenu()}}return true},shouldDeactivate:function(a){if(Ext.menu.Item.superclass.shouldDeactivate.call(this,a)){if(this.menu&&this.menu.isVisible()){return !this.menu.getEl().getRegion().contains(a.getPoint())}return true}return false},deactivate:function(){Ext.menu.Item.superclass.deactivate.apply(this,arguments);this.hideMenu()},expandMenu:function(a){if(!this.disabled&&this.menu){clearTimeout(this.hideTimer);delete this.hideTimer;if(!this.menu.isVisible()&&!this.showTimer){this.showTimer=this.deferExpand.defer(this.showDelay,this,[a])}else{if(this.menu.isVisible()&&a){this.menu.tryActivate(0,1)}}}},deferExpand:function(a){delete this.showTimer;this.menu.show(this.container,this.parentMenu.subMenuAlign||"tl-tr?",this.parentMenu);if(a){this.menu.tryActivate(0,1)}},hideMenu:function(){clearTimeout(this.showTimer);delete this.showTimer;if(!this.hideTimer&&this.menu&&this.menu.isVisible()){this.hideTimer=this.deferHide.defer(this.hideDelay,this)}},deferHide:function(){delete this.hideTimer;if(this.menu.over){this.parentMenu.setActiveItem(this,false)}else{this.menu.hide()}}});Ext.reg("menuitem",Ext.menu.Item);Ext.menu.CheckItem=Ext.extend(Ext.menu.Item,{itemCls:"x-menu-item x-menu-check-item",groupClass:"x-menu-group-item",checked:false,ctype:"Ext.menu.CheckItem",initComponent:function(){Ext.menu.CheckItem.superclass.initComponent.call(this);this.addEvents("beforecheckchange","checkchange");if(this.checkHandler){this.on("checkchange",this.checkHandler,this.scope)}Ext.menu.MenuMgr.registerCheckable(this)},onRender:function(a){Ext.menu.CheckItem.superclass.onRender.apply(this,arguments);if(this.group){this.el.addClass(this.groupClass)}if(this.checked){this.checked=false;this.setChecked(true,true)}},destroy:function(){Ext.menu.MenuMgr.unregisterCheckable(this);Ext.menu.CheckItem.superclass.destroy.apply(this,arguments)},setChecked:function(b,a){var c=a===true;if(this.checked!=b&&(c||this.fireEvent("beforecheckchange",this,b)!==false)){Ext.menu.MenuMgr.onCheckChange(this,b);if(this.container){this.container[b?"addClass":"removeClass"]("x-menu-item-checked")}this.checked=b;if(!c){this.fireEvent("checkchange",this,b)}}},handleClick:function(a){if(!this.disabled&&!(this.checked&&this.group)){this.setChecked(!this.checked)}Ext.menu.CheckItem.superclass.handleClick.apply(this,arguments)}});Ext.reg("menucheckitem",Ext.menu.CheckItem);Ext.menu.DateMenu=Ext.extend(Ext.menu.Menu,{enableScrolling:false,hideOnClick:true,pickerId:null,cls:"x-date-menu",initComponent:function(){this.on("beforeshow",this.onBeforeShow,this);if(this.strict=(Ext.isIE7&&Ext.isStrict)){this.on("show",this.onShow,this,{single:true,delay:20})}Ext.apply(this,{plain:true,showSeparator:false,items:this.picker=new Ext.DatePicker(Ext.applyIf({internalRender:this.strict||!Ext.isIE,ctCls:"x-menu-date-item",id:this.pickerId},this.initialConfig))});this.picker.purgeListeners();Ext.menu.DateMenu.superclass.initComponent.call(this);this.relayEvents(this.picker,["select"]);this.on("show",this.picker.focus,this.picker);this.on("select",this.menuHide,this);if(this.handler){this.on("select",this.handler,this.scope||this)}},menuHide:function(){if(this.hideOnClick){this.hide(true)}},onBeforeShow:function(){if(this.picker){this.picker.hideMonthPicker(true)}},onShow:function(){var a=this.picker.getEl();a.setWidth(a.getWidth())}});Ext.reg("datemenu",Ext.menu.DateMenu);Ext.menu.ColorMenu=Ext.extend(Ext.menu.Menu,{enableScrolling:false,hideOnClick:true,cls:"x-color-menu",paletteId:null,initComponent:function(){Ext.apply(this,{plain:true,showSeparator:false,items:this.palette=new Ext.ColorPalette(Ext.applyIf({id:this.paletteId},this.initialConfig))});this.palette.purgeListeners();Ext.menu.ColorMenu.superclass.initComponent.call(this);this.relayEvents(this.palette,["select"]);this.on("select",this.menuHide,this);if(this.handler){this.on("select",this.handler,this.scope||this)}},menuHide:function(){if(this.hideOnClick){this.hide(true)}}});Ext.reg("colormenu",Ext.menu.ColorMenu);Ext.form.Field=Ext.extend(Ext.BoxComponent,{invalidClass:"x-form-invalid",invalidText:"The value in this field is invalid",focusClass:"x-form-focus",validationEvent:"keyup",validateOnBlur:true,validationDelay:250,defaultAutoCreate:{tag:"input",type:"text",size:"20",autocomplete:"off"},fieldClass:"x-form-field",msgTarget:"qtip",msgFx:"normal",readOnly:false,disabled:false,submitValue:true,isFormField:true,msgDisplay:"",hasFocus:false,initComponent:function(){Ext.form.Field.superclass.initComponent.call(this);this.addEvents("focus","blur","specialkey","change","invalid","valid")},getName:function(){return this.rendered&&this.el.dom.name?this.el.dom.name:this.name||this.id||""},onRender:function(c,a){if(!this.el){var b=this.getAutoCreate();if(!b.name){b.name=this.name||this.id}if(this.inputType){b.type=this.inputType}this.autoEl=b}Ext.form.Field.superclass.onRender.call(this,c,a);if(this.submitValue===false){this.el.dom.removeAttribute("name")}var d=this.el.dom.type;if(d){if(d=="password"){d="text"}this.el.addClass("x-form-"+d)}if(this.readOnly){this.setReadOnly(true)}if(this.tabIndex!==undefined){this.el.dom.setAttribute("tabIndex",this.tabIndex)}this.el.addClass([this.fieldClass,this.cls])},getItemCt:function(){return this.itemCt},initValue:function(){if(this.value!==undefined){this.setValue(this.value)}else{if(!Ext.isEmpty(this.el.dom.value)&&this.el.dom.value!=this.emptyText){this.setValue(this.el.dom.value)}}this.originalValue=this.getValue()},isDirty:function(){if(this.disabled||!this.rendered){return false}return String(this.getValue())!==String(this.originalValue)},setReadOnly:function(a){if(this.rendered){this.el.dom.readOnly=a}this.readOnly=a},afterRender:function(){Ext.form.Field.superclass.afterRender.call(this);this.initEvents();this.initValue()},fireKey:function(a){if(a.isSpecialKey()){this.fireEvent("specialkey",this,a)}},reset:function(){this.setValue(this.originalValue);this.clearInvalid()},initEvents:function(){this.mon(this.el,Ext.EventManager.getKeyEvent(),this.fireKey,this);this.mon(this.el,"focus",this.onFocus,this);this.mon(this.el,"blur",this.onBlur,this,this.inEditor?{buffer:10}:null)},preFocus:Ext.emptyFn,onFocus:function(){this.preFocus();if(this.focusClass){this.el.addClass(this.focusClass)}if(!this.hasFocus){this.hasFocus=true;this.startValue=this.getValue();this.fireEvent("focus",this)}},beforeBlur:Ext.emptyFn,onBlur:function(){this.beforeBlur();if(this.focusClass){this.el.removeClass(this.focusClass)}this.hasFocus=false;if(this.validationEvent!==false&&(this.validateOnBlur||this.validationEvent=="blur")){this.validate()}var a=this.getValue();if(String(a)!==String(this.startValue)){this.fireEvent("change",this,a,this.startValue)}this.fireEvent("blur",this);this.postBlur()},postBlur:Ext.emptyFn,isValid:function(a){if(this.disabled){return true}var c=this.preventMark;this.preventMark=a===true;var b=this.validateValue(this.processValue(this.getRawValue()),a);this.preventMark=c;return b},validate:function(){if(this.disabled||this.validateValue(this.processValue(this.getRawValue()))){this.clearInvalid();return true}return false},processValue:function(a){return a},validateValue:function(b){var a=this.getErrors(b)[0];if(a==undefined){return true}else{this.markInvalid(a);return false}},getErrors:function(){return[]},getActiveError:function(){return this.activeError||""},markInvalid:function(c){if(this.rendered&&!this.preventMark){c=c||this.invalidText;var a=this.getMessageHandler();if(a){a.mark(this,c)}else{if(this.msgTarget){this.el.addClass(this.invalidClass);var b=Ext.getDom(this.msgTarget);if(b){b.innerHTML=c;b.style.display=this.msgDisplay}}}}this.setActiveError(c)},clearInvalid:function(){if(this.rendered&&!this.preventMark){this.el.removeClass(this.invalidClass);var a=this.getMessageHandler();if(a){a.clear(this)}else{if(this.msgTarget){this.el.removeClass(this.invalidClass);var b=Ext.getDom(this.msgTarget);if(b){b.innerHTML="";b.style.display="none"}}}}this.unsetActiveError()},setActiveError:function(b,a){this.activeError=b;if(a!==true){this.fireEvent("invalid",this,b)}},unsetActiveError:function(a){delete this.activeError;if(a!==true){this.fireEvent("valid",this)}},getMessageHandler:function(){return Ext.form.MessageTargets[this.msgTarget]},getErrorCt:function(){return this.el.findParent(".x-form-element",5,true)||this.el.findParent(".x-form-field-wrap",5,true)},alignErrorEl:function(){this.errorEl.setWidth(this.getErrorCt().getWidth(true)-20)},alignErrorIcon:function(){this.errorIcon.alignTo(this.el,"tl-tr",[2,0])},getRawValue:function(){var a=this.rendered?this.el.getValue():Ext.value(this.value,"");if(a===this.emptyText){a=""}return a},getValue:function(){if(!this.rendered){return this.value}var a=this.el.getValue();if(a===this.emptyText||a===undefined){a=""}return a},setRawValue:function(a){return this.rendered?(this.el.dom.value=(Ext.isEmpty(a)?"":a)):""},setValue:function(a){this.value=a;if(this.rendered){this.el.dom.value=(Ext.isEmpty(a)?"":a);this.validate()}return this},append:function(a){this.setValue([this.getValue(),a].join(""))}});Ext.form.MessageTargets={qtip:{mark:function(a,b){a.el.addClass(a.invalidClass);a.el.dom.qtip=b;a.el.dom.qclass="x-form-invalid-tip";if(Ext.QuickTips){Ext.QuickTips.enable()}},clear:function(a){a.el.removeClass(a.invalidClass);a.el.dom.qtip=""}},title:{mark:function(a,b){a.el.addClass(a.invalidClass);a.el.dom.title=b},clear:function(a){a.el.dom.title=""}},under:{mark:function(b,c){b.el.addClass(b.invalidClass);if(!b.errorEl){var a=b.getErrorCt();if(!a){b.el.dom.title=c;return}b.errorEl=a.createChild({cls:"x-form-invalid-msg"});b.on("resize",b.alignErrorEl,b);b.on("destroy",function(){Ext.destroy(this.errorEl)},b)}b.alignErrorEl();b.errorEl.update(c);Ext.form.Field.msgFx[b.msgFx].show(b.errorEl,b)},clear:function(a){a.el.removeClass(a.invalidClass);if(a.errorEl){Ext.form.Field.msgFx[a.msgFx].hide(a.errorEl,a)}else{a.el.dom.title=""}}},side:{mark:function(b,c){b.el.addClass(b.invalidClass);if(!b.errorIcon){var a=b.getErrorCt();if(!a){b.el.dom.title=c;return}b.errorIcon=a.createChild({cls:"x-form-invalid-icon"});if(b.ownerCt){b.ownerCt.on("afterlayout",b.alignErrorIcon,b);b.ownerCt.on("expand",b.alignErrorIcon,b)}b.on("resize",b.alignErrorIcon,b);b.on("destroy",function(){Ext.destroy(this.errorIcon)},b)}b.alignErrorIcon();b.errorIcon.dom.qtip=c;b.errorIcon.dom.qclass="x-form-invalid-tip";b.errorIcon.show()},clear:function(a){a.el.removeClass(a.invalidClass);if(a.errorIcon){a.errorIcon.dom.qtip="";a.errorIcon.hide()}else{a.el.dom.title=""}}}};Ext.form.Field.msgFx={normal:{show:function(a,b){a.setDisplayed("block")},hide:function(a,b){a.setDisplayed(false).update("")}},slide:{show:function(a,b){a.slideIn("t",{stopFx:true})},hide:function(a,b){a.slideOut("t",{stopFx:true,useDisplay:true})}},slideRight:{show:function(a,b){a.fixDisplay();a.alignTo(b.el,"tl-tr");a.slideIn("l",{stopFx:true})},hide:function(a,b){a.slideOut("l",{stopFx:true,useDisplay:true})}}};Ext.reg("field",Ext.form.Field);Ext.form.TextField=Ext.extend(Ext.form.Field,{grow:false,growMin:30,growMax:800,vtype:null,maskRe:null,disableKeyFilter:false,allowBlank:true,minLength:0,maxLength:Number.MAX_VALUE,minLengthText:"The minimum length for this field is {0}",maxLengthText:"The maximum length for this field is {0}",selectOnFocus:false,blankText:"This field is required",validator:null,regex:null,regexText:"",emptyText:null,emptyClass:"x-form-empty-field",initComponent:function(){Ext.form.TextField.superclass.initComponent.call(this);this.addEvents("autosize","keydown","keyup","keypress")},initEvents:function(){Ext.form.TextField.superclass.initEvents.call(this);if(this.validationEvent=="keyup"){this.validationTask=new Ext.util.DelayedTask(this.validate,this);this.mon(this.el,"keyup",this.filterValidation,this)}else{if(this.validationEvent!==false&&this.validationEvent!="blur"){this.mon(this.el,this.validationEvent,this.validate,this,{buffer:this.validationDelay})}}if(this.selectOnFocus||this.emptyText){this.mon(this.el,"mousedown",this.onMouseDown,this);if(this.emptyText){this.applyEmptyText()}}if(this.maskRe||(this.vtype&&this.disableKeyFilter!==true&&(this.maskRe=Ext.form.VTypes[this.vtype+"Mask"]))){this.mon(this.el,"keypress",this.filterKeys,this)}if(this.grow){this.mon(this.el,"keyup",this.onKeyUpBuffered,this,{buffer:50});this.mon(this.el,"click",this.autoSize,this)}if(this.enableKeyEvents){this.mon(this.el,{scope:this,keyup:this.onKeyUp,keydown:this.onKeyDown,keypress:this.onKeyPress})}},onMouseDown:function(a){if(!this.hasFocus){this.mon(this.el,"mouseup",Ext.emptyFn,this,{single:true,preventDefault:true})}},processValue:function(a){if(this.stripCharsRe){var b=a.replace(this.stripCharsRe,"");if(b!==a){this.setRawValue(b);return b}}return a},filterValidation:function(a){if(!a.isNavKeyPress()){this.validationTask.delay(this.validationDelay)}},onDisable:function(){Ext.form.TextField.superclass.onDisable.call(this);if(Ext.isIE){this.el.dom.unselectable="on"}},onEnable:function(){Ext.form.TextField.superclass.onEnable.call(this);if(Ext.isIE){this.el.dom.unselectable=""}},onKeyUpBuffered:function(a){if(this.doAutoSize(a)){this.autoSize()}},doAutoSize:function(a){return !a.isNavKeyPress()},onKeyUp:function(a){this.fireEvent("keyup",this,a)},onKeyDown:function(a){this.fireEvent("keydown",this,a)},onKeyPress:function(a){this.fireEvent("keypress",this,a)},reset:function(){Ext.form.TextField.superclass.reset.call(this);this.applyEmptyText()},applyEmptyText:function(){if(this.rendered&&this.emptyText&&this.getRawValue().length<1&&!this.hasFocus){this.setRawValue(this.emptyText);this.el.addClass(this.emptyClass)}},preFocus:function(){var a=this.el,b;if(this.emptyText){if(a.dom.value==this.emptyText){this.setRawValue("");b=true}a.removeClass(this.emptyClass)}if(this.selectOnFocus||b){a.dom.select()}},postBlur:function(){this.applyEmptyText()},filterKeys:function(b){if(b.ctrlKey){return}var a=b.getKey();if(Ext.isGecko&&(b.isNavKeyPress()||a==b.BACKSPACE||(a==b.DELETE&&b.button==-1))){return}var c=String.fromCharCode(b.getCharCode());if(!Ext.isGecko&&b.isSpecialKey()&&!c){return}if(!this.maskRe.test(c)){b.stopEvent()}},setValue:function(a){if(this.emptyText&&this.el&&!Ext.isEmpty(a)){this.el.removeClass(this.emptyClass)}Ext.form.TextField.superclass.setValue.apply(this,arguments);this.applyEmptyText();this.autoSize();return this},getErrors:function(a){var d=Ext.form.TextField.superclass.getErrors.apply(this,arguments);a=Ext.isDefined(a)?a:this.processValue(this.getRawValue());if(Ext.isFunction(this.validator)){var c=this.validator(a);if(c!==true){d.push(c)}}if(a.length<1||a===this.emptyText){if(this.allowBlank){return d}else{d.push(this.blankText)}}if(!this.allowBlank&&(a.length<1||a===this.emptyText)){d.push(this.blankText)}if(a.length<this.minLength){d.push(String.format(this.minLengthText,this.minLength))}if(a.length>this.maxLength){d.push(String.format(this.maxLengthText,this.maxLength))}if(this.vtype){var b=Ext.form.VTypes;if(!b[this.vtype](a,this)){d.push(this.vtypeText||b[this.vtype+"Text"])}}if(this.regex&&!this.regex.test(a)){d.push(this.regexText)}return d},selectText:function(h,a){var c=this.getRawValue();var e=false;if(c.length>0){h=h===undefined?0:h;a=a===undefined?c.length:a;var g=this.el.dom;if(g.setSelectionRange){g.setSelectionRange(h,a)}else{if(g.createTextRange){var b=g.createTextRange();b.moveStart("character",h);b.moveEnd("character",a-c.length);b.select()}}e=Ext.isGecko||Ext.isOpera}else{e=true}if(e){this.focus()}},autoSize:function(){if(!this.grow||!this.rendered){return}if(!this.metrics){this.metrics=Ext.util.TextMetrics.createInstance(this.el)}var c=this.el;var b=c.dom.value;var e=document.createElement("div");e.appendChild(document.createTextNode(b));b=e.innerHTML;Ext.removeNode(e);e=null;b+="&#160;";var a=Math.min(this.growMax,Math.max(this.metrics.getWidth(b)+10,this.growMin));this.el.setWidth(a);this.fireEvent("autosize",this,a)},onDestroy:function(){if(this.validationTask){this.validationTask.cancel();this.validationTask=null}Ext.form.TextField.superclass.onDestroy.call(this)}});Ext.reg("textfield",Ext.form.TextField);Ext.form.TriggerField=Ext.extend(Ext.form.TextField,{defaultAutoCreate:{tag:"input",type:"text",size:"16",autocomplete:"off"},hideTrigger:false,editable:true,readOnly:false,wrapFocusClass:"x-trigger-wrap-focus",autoSize:Ext.emptyFn,monitorTab:true,deferHeight:true,mimicing:false,actionMode:"wrap",defaultTriggerWidth:17,onResize:function(a,c){Ext.form.TriggerField.superclass.onResize.call(this,a,c);var b=this.getTriggerWidth();if(Ext.isNumber(a)){this.el.setWidth(a-b)}this.wrap.setWidth(this.el.getWidth()+b)},getTriggerWidth:function(){var a=this.trigger.getWidth();if(!this.hideTrigger&&!this.readOnly&&a===0){a=this.defaultTriggerWidth}return a},alignErrorIcon:function(){if(this.wrap){this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])}},onRender:function(b,a){this.doc=Ext.isIE?Ext.getBody():Ext.getDoc();Ext.form.TriggerField.superclass.onRender.call(this,b,a);this.wrap=this.el.wrap({cls:"x-form-field-wrap x-form-field-trigger-wrap"});this.trigger=this.wrap.createChild(this.triggerConfig||{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.triggerClass});this.initTrigger();if(!this.width){this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth())}this.resizeEl=this.positionEl=this.wrap},getWidth:function(){return(this.el.getWidth()+this.trigger.getWidth())},updateEditState:function(){if(this.rendered){if(this.readOnly){this.el.dom.readOnly=true;this.el.addClass("x-trigger-noedit");this.mun(this.el,"click",this.onTriggerClick,this);this.trigger.setDisplayed(false)}else{if(!this.editable){this.el.dom.readOnly=true;this.el.addClass("x-trigger-noedit");this.mon(this.el,"click",this.onTriggerClick,this)}else{this.el.dom.readOnly=false;this.el.removeClass("x-trigger-noedit");this.mun(this.el,"click",this.onTriggerClick,this)}this.trigger.setDisplayed(!this.hideTrigger)}this.onResize(this.width||this.wrap.getWidth())}},setHideTrigger:function(a){if(a!=this.hideTrigger){this.hideTrigger=a;this.updateEditState()}},setEditable:function(a){if(a!=this.editable){this.editable=a;this.updateEditState()}},setReadOnly:function(a){if(a!=this.readOnly){this.readOnly=a;this.updateEditState()}},afterRender:function(){Ext.form.TriggerField.superclass.afterRender.call(this);this.updateEditState()},initTrigger:function(){this.mon(this.trigger,"click",this.onTriggerClick,this,{preventDefault:true});this.trigger.addClassOnOver("x-form-trigger-over");this.trigger.addClassOnClick("x-form-trigger-click")},onDestroy:function(){Ext.destroy(this.trigger,this.wrap);if(this.mimicing){this.doc.un("mousedown",this.mimicBlur,this)}delete this.doc;Ext.form.TriggerField.superclass.onDestroy.call(this)},onFocus:function(){Ext.form.TriggerField.superclass.onFocus.call(this);if(!this.mimicing){this.wrap.addClass(this.wrapFocusClass);this.mimicing=true;this.doc.on("mousedown",this.mimicBlur,this,{delay:10});if(this.monitorTab){this.on("specialkey",this.checkTab,this)}}},checkTab:function(a,b){if(b.getKey()==b.TAB){this.triggerBlur()}},onBlur:Ext.emptyFn,mimicBlur:function(a){if(!this.isDestroyed&&!this.wrap.contains(a.target)&&this.validateBlur(a)){this.triggerBlur()}},triggerBlur:function(){this.mimicing=false;this.doc.un("mousedown",this.mimicBlur,this);if(this.monitorTab&&this.el){this.un("specialkey",this.checkTab,this)}Ext.form.TriggerField.superclass.onBlur.call(this);if(this.wrap){this.wrap.removeClass(this.wrapFocusClass)}},beforeBlur:Ext.emptyFn,validateBlur:function(a){return true},onTriggerClick:Ext.emptyFn});Ext.form.TwinTriggerField=Ext.extend(Ext.form.TriggerField,{initComponent:function(){Ext.form.TwinTriggerField.superclass.initComponent.call(this);this.triggerConfig={tag:"span",cls:"x-form-twin-triggers",cn:[{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.trigger1Class},{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.trigger2Class}]}},getTrigger:function(a){return this.triggers[a]},afterRender:function(){Ext.form.TwinTriggerField.superclass.afterRender.call(this);var c=this.triggers,b=0,a=c.length;for(;b<a;++b){if(this["hideTrigger"+(b+1)]){c[b].hide()}}},initTrigger:function(){var a=this.trigger.select(".x-form-trigger",true),b=this;a.each(function(d,g,c){var e="Trigger"+(c+1);d.hide=function(){var h=b.wrap.getWidth();this.dom.style.display="none";b.el.setWidth(h-b.trigger.getWidth());b["hidden"+e]=true};d.show=function(){var h=b.wrap.getWidth();this.dom.style.display="";b.el.setWidth(h-b.trigger.getWidth());b["hidden"+e]=false};this.mon(d,"click",this["on"+e+"Click"],this,{preventDefault:true});d.addClassOnOver("x-form-trigger-over");d.addClassOnClick("x-form-trigger-click")},this);this.triggers=a.elements},getTriggerWidth:function(){var a=0;Ext.each(this.triggers,function(d,c){var e="Trigger"+(c+1),b=d.getWidth();if(b===0&&!this["hidden"+e]){a+=this.defaultTriggerWidth}else{a+=b}},this);return a},onDestroy:function(){Ext.destroy(this.triggers);Ext.form.TwinTriggerField.superclass.onDestroy.call(this)},onTrigger1Click:Ext.emptyFn,onTrigger2Click:Ext.emptyFn});Ext.reg("trigger",Ext.form.TriggerField);Ext.form.TextArea=Ext.extend(Ext.form.TextField,{growMin:60,growMax:1000,growAppend:"&#160;\n&#160;",enterIsSpecial:false,preventScrollbars:false,onRender:function(b,a){if(!this.el){this.defaultAutoCreate={tag:"textarea",style:"width:100px;height:60px;",autocomplete:"off"}}Ext.form.TextArea.superclass.onRender.call(this,b,a);if(this.grow){this.textSizeEl=Ext.DomHelper.append(document.body,{tag:"pre",cls:"x-form-grow-sizer"});if(this.preventScrollbars){this.el.setStyle("overflow","hidden")}this.el.setHeight(this.growMin)}},onDestroy:function(){Ext.removeNode(this.textSizeEl);Ext.form.TextArea.superclass.onDestroy.call(this)},fireKey:function(a){if(a.isSpecialKey()&&(this.enterIsSpecial||(a.getKey()!=a.ENTER||a.hasModifier()))){this.fireEvent("specialkey",this,a)}},doAutoSize:function(a){return !a.isNavKeyPress()||a.getKey()==a.ENTER},filterValidation:function(a){if(!a.isNavKeyPress()||(!this.enterIsSpecial&&a.keyCode==a.ENTER)){this.validationTask.delay(this.validationDelay)}},autoSize:function(){if(!this.grow||!this.textSizeEl){return}var c=this.el,a=Ext.util.Format.htmlEncode(c.dom.value),d=this.textSizeEl,b;Ext.fly(d).setWidth(this.el.getWidth());if(a.length<1){a="&#160;&#160;"}else{a+=this.growAppend;if(Ext.isIE){a=a.replace(/\n/g,"&#160;<br />")}}d.innerHTML=a;b=Math.min(this.growMax,Math.max(d.offsetHeight,this.growMin));if(b!=this.lastHeight){this.lastHeight=b;this.el.setHeight(b);this.fireEvent("autosize",this,b)}}});Ext.reg("textarea",Ext.form.TextArea);Ext.form.NumberField=Ext.extend(Ext.form.TextField,{fieldClass:"x-form-field x-form-num-field",allowDecimals:true,decimalSeparator:".",decimalPrecision:2,allowNegative:true,minValue:Number.NEGATIVE_INFINITY,maxValue:Number.MAX_VALUE,minText:"The minimum value for this field is {0}",maxText:"The maximum value for this field is {0}",nanText:"{0} is not a valid number",baseChars:"0123456789",autoStripChars:false,initEvents:function(){var a=this.baseChars+"";if(this.allowDecimals){a+=this.decimalSeparator}if(this.allowNegative){a+="-"}a=Ext.escapeRe(a);this.maskRe=new RegExp("["+a+"]");if(this.autoStripChars){this.stripCharsRe=new RegExp("[^"+a+"]","gi")}Ext.form.NumberField.superclass.initEvents.call(this)},getErrors:function(b){var c=Ext.form.NumberField.superclass.getErrors.apply(this,arguments);b=Ext.isDefined(b)?b:this.processValue(this.getRawValue());if(b.length<1){return c}b=String(b).replace(this.decimalSeparator,".");if(isNaN(b)){c.push(String.format(this.nanText,b))}var a=this.parseValue(b);if(a<this.minValue){c.push(String.format(this.minText,this.minValue))}if(a>this.maxValue){c.push(String.format(this.maxText,this.maxValue))}return c},getValue:function(){return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)))},setValue:function(a){a=Ext.isNumber(a)?a:parseFloat(String(a).replace(this.decimalSeparator,"."));a=this.fixPrecision(a);a=isNaN(a)?"":String(a).replace(".",this.decimalSeparator);return Ext.form.NumberField.superclass.setValue.call(this,a)},setMinValue:function(a){this.minValue=Ext.num(a,Number.NEGATIVE_INFINITY)},setMaxValue:function(a){this.maxValue=Ext.num(a,Number.MAX_VALUE)},parseValue:function(a){a=parseFloat(String(a).replace(this.decimalSeparator,"."));return isNaN(a)?"":a},fixPrecision:function(b){var a=isNaN(b);if(!this.allowDecimals||this.decimalPrecision==-1||a||!b){return a?"":b}return parseFloat(parseFloat(b).toFixed(this.decimalPrecision))},beforeBlur:function(){var a=this.parseValue(this.getRawValue());if(!Ext.isEmpty(a)){this.setValue(a)}}});Ext.reg("numberfield",Ext.form.NumberField);Ext.form.DateField=Ext.extend(Ext.form.TriggerField,{format:"m/d/Y",altFormats:"m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",disabledDaysText:"Disabled",disabledDatesText:"Disabled",minText:"The date in this field must be equal to or after {0}",maxText:"The date in this field must be equal to or before {0}",invalidText:"{0} is not a valid date - it must be in the format {1}",triggerClass:"x-form-date-trigger",showToday:true,startDay:0,defaultAutoCreate:{tag:"input",type:"text",size:"10",autocomplete:"off"},initTime:"12",initTimeFormat:"H",safeParse:function(b,c){if(Date.formatContainsHourInfo(c)){return Date.parseDate(b,c)}else{var a=Date.parseDate(b+" "+this.initTime,c+" "+this.initTimeFormat);if(a){return a.clearTime()}}},initComponent:function(){Ext.form.DateField.superclass.initComponent.call(this);this.addEvents("select");if(Ext.isString(this.minValue)){this.minValue=this.parseDate(this.minValue)}if(Ext.isString(this.maxValue)){this.maxValue=this.parseDate(this.maxValue)}this.disabledDatesRE=null;this.initDisabledDays()},initEvents:function(){Ext.form.DateField.superclass.initEvents.call(this);this.keyNav=new Ext.KeyNav(this.el,{down:function(a){this.onTriggerClick()},scope:this,forceKeyDown:true})},initDisabledDays:function(){if(this.disabledDates){var b=this.disabledDates,a=b.length-1,c="(?:";Ext.each(b,function(g,e){c+=Ext.isDate(g)?"^"+Ext.escapeRe(g.dateFormat(this.format))+"$":b[e];if(e!=a){c+="|"}},this);this.disabledDatesRE=new RegExp(c+")")}},setDisabledDates:function(a){this.disabledDates=a;this.initDisabledDays();if(this.menu){this.menu.picker.setDisabledDates(this.disabledDatesRE)}},setDisabledDays:function(a){this.disabledDays=a;if(this.menu){this.menu.picker.setDisabledDays(a)}},setMinValue:function(a){this.minValue=(Ext.isString(a)?this.parseDate(a):a);if(this.menu){this.menu.picker.setMinDate(this.minValue)}},setMaxValue:function(a){this.maxValue=(Ext.isString(a)?this.parseDate(a):a);if(this.menu){this.menu.picker.setMaxDate(this.maxValue)}},getErrors:function(e){var h=Ext.form.DateField.superclass.getErrors.apply(this,arguments);e=this.formatDate(e||this.processValue(this.getRawValue()));if(e.length<1){return h}var c=e;e=this.parseDate(e);if(!e){h.push(String.format(this.invalidText,c,this.format));return h}var g=e.getTime();if(this.minValue&&g<this.minValue.clearTime().getTime()){h.push(String.format(this.minText,this.formatDate(this.minValue)))}if(this.maxValue&&g>this.maxValue.clearTime().getTime()){h.push(String.format(this.maxText,this.formatDate(this.maxValue)))}if(this.disabledDays){var a=e.getDay();for(var b=0;b<this.disabledDays.length;b++){if(a===this.disabledDays[b]){h.push(this.disabledDaysText);break}}}var d=this.formatDate(e);if(this.disabledDatesRE&&this.disabledDatesRE.test(d)){h.push(String.format(this.disabledDatesText,d))}return h},validateBlur:function(){return !this.menu||!this.menu.isVisible()},getValue:function(){return this.parseDate(Ext.form.DateField.superclass.getValue.call(this))||""},setValue:function(a){return Ext.form.DateField.superclass.setValue.call(this,this.formatDate(this.parseDate(a)))},parseDate:function(g){if(!g||Ext.isDate(g)){return g}var b=this.safeParse(g,this.format),c=this.altFormats,e=this.altFormatsArray;if(!b&&c){e=e||c.split("|");for(var d=0,a=e.length;d<a&&!b;d++){b=this.safeParse(g,e[d])}}return b},onDestroy:function(){Ext.destroy(this.menu,this.keyNav);Ext.form.DateField.superclass.onDestroy.call(this)},formatDate:function(a){return Ext.isDate(a)?a.dateFormat(this.format):a},onTriggerClick:function(){if(this.disabled){return}if(this.menu==null){this.menu=new Ext.menu.DateMenu({hideOnClick:false,focusOnSelect:false})}this.onFocus();Ext.apply(this.menu.picker,{minDate:this.minValue,maxDate:this.maxValue,disabledDatesRE:this.disabledDatesRE,disabledDatesText:this.disabledDatesText,disabledDays:this.disabledDays,disabledDaysText:this.disabledDaysText,format:this.format,showToday:this.showToday,startDay:this.startDay,minText:String.format(this.minText,this.formatDate(this.minValue)),maxText:String.format(this.maxText,this.formatDate(this.maxValue))});this.menu.picker.setValue(this.getValue()||new Date());this.menu.show(this.el,"tl-bl?");this.menuEvents("on")},menuEvents:function(a){this.menu[a]("select",this.onSelect,this);this.menu[a]("hide",this.onMenuHide,this);this.menu[a]("show",this.onFocus,this)},onSelect:function(a,b){this.setValue(b);this.fireEvent("select",this,b);this.menu.hide()},onMenuHide:function(){this.focus(false,60);this.menuEvents("un")},beforeBlur:function(){var a=this.parseDate(this.getRawValue());if(a){this.setValue(a)}}});Ext.reg("datefield",Ext.form.DateField);Ext.form.DisplayField=Ext.extend(Ext.form.Field,{validationEvent:false,validateOnBlur:false,defaultAutoCreate:{tag:"div"},fieldClass:"x-form-display-field",htmlEncode:false,initEvents:Ext.emptyFn,isValid:function(){return true},validate:function(){return true},getRawValue:function(){var a=this.rendered?this.el.dom.innerHTML:Ext.value(this.value,"");if(a===this.emptyText){a=""}if(this.htmlEncode){a=Ext.util.Format.htmlDecode(a)}return a},getValue:function(){return this.getRawValue()},getName:function(){return this.name},setRawValue:function(a){if(this.htmlEncode){a=Ext.util.Format.htmlEncode(a)}return this.rendered?(this.el.dom.innerHTML=(Ext.isEmpty(a)?"":a)):(this.value=a)},setValue:function(a){this.setRawValue(a);return this}});Ext.reg("displayfield",Ext.form.DisplayField);Ext.form.ComboBox=Ext.extend(Ext.form.TriggerField,{defaultAutoCreate:{tag:"input",type:"text",size:"24",autocomplete:"off"},listClass:"",selectedClass:"x-combo-selected",listEmptyText:"",triggerClass:"x-form-arrow-trigger",shadow:"sides",listAlign:"tl-bl?",maxHeight:300,minHeight:90,triggerAction:"query",minChars:4,autoSelect:true,typeAhead:false,queryDelay:500,pageSize:0,selectOnFocus:false,queryParam:"query",loadingText:"Loading...",resizable:false,handleHeight:8,allQuery:"",mode:"remote",minListWidth:70,forceSelection:false,typeAheadDelay:250,lazyInit:true,clearFilterOnReset:true,submitValue:undefined,initComponent:function(){Ext.form.ComboBox.superclass.initComponent.call(this);this.addEvents("expand","collapse","beforeselect","select","beforequery");if(this.transform){var c=Ext.getDom(this.transform);if(!this.hiddenName){this.hiddenName=c.name}if(!this.store){this.mode="local";var j=[],e=c.options;for(var b=0,a=e.length;b<a;b++){var h=e[b],g=(h.hasAttribute?h.hasAttribute("value"):h.getAttributeNode("value").specified)?h.value:h.text;if(h.selected&&Ext.isEmpty(this.value,true)){this.value=g}j.push([g,h.text])}this.store=new Ext.data.ArrayStore({idIndex:0,fields:["value","text"],data:j,autoDestroy:true});this.valueField="value";this.displayField="text"}c.name=Ext.id();if(!this.lazyRender){this.target=true;this.el=Ext.DomHelper.insertBefore(c,this.autoCreate||this.defaultAutoCreate);this.render(this.el.parentNode,c)}Ext.removeNode(c)}else{if(this.store){this.store=Ext.StoreMgr.lookup(this.store);if(this.store.autoCreated){this.displayField=this.valueField="field1";if(!this.store.expandData){this.displayField="field2"}this.mode="local"}}}this.selectedIndex=-1;if(this.mode=="local"){if(!Ext.isDefined(this.initialConfig.queryDelay)){this.queryDelay=10}if(!Ext.isDefined(this.initialConfig.minChars)){this.minChars=0}}},onRender:function(b,a){if(this.hiddenName&&!Ext.isDefined(this.submitValue)){this.submitValue=false}Ext.form.ComboBox.superclass.onRender.call(this,b,a);if(this.hiddenName){this.hiddenField=this.el.insertSibling({tag:"input",type:"hidden",name:this.hiddenName,id:(this.hiddenId||Ext.id())},"before",true)}if(Ext.isGecko){this.el.dom.setAttribute("autocomplete","off")}if(!this.lazyInit){this.initList()}else{this.on("focus",this.initList,this,{single:true})}},initValue:function(){Ext.form.ComboBox.superclass.initValue.call(this);if(this.hiddenField){this.hiddenField.value=Ext.value(Ext.isDefined(this.hiddenValue)?this.hiddenValue:this.value,"")}},getParentZIndex:function(){var a;if(this.ownerCt){this.findParentBy(function(b){a=parseInt(b.getPositionEl().getStyle("z-index"),10);return !!a})}return a},getZIndex:function(b){b=b||Ext.getDom(this.getListParent()||Ext.getBody());var a=parseInt(Ext.fly(b).getStyle("z-index"),10);if(!a){a=this.getParentZIndex()}return(a||12000)+5},initList:function(){if(!this.list){var a="x-combo-list",c=Ext.getDom(this.getListParent()||Ext.getBody());this.list=new Ext.Layer({parentEl:c,shadow:this.shadow,cls:[a,this.listClass].join(" "),constrain:false,zindex:this.getZIndex(c)});var b=this.listWidth||Math.max(this.wrap.getWidth(),this.minListWidth);this.list.setSize(b,0);this.list.swallowEvent("mousewheel");this.assetHeight=0;if(this.syncFont!==false){this.list.setStyle("font-size",this.el.getStyle("font-size"))}if(this.title){this.header=this.list.createChild({cls:a+"-hd",html:this.title});this.assetHeight+=this.header.getHeight()}this.innerList=this.list.createChild({cls:a+"-inner"});this.mon(this.innerList,"mouseover",this.onViewOver,this);this.mon(this.innerList,"mousemove",this.onViewMove,this);this.innerList.setWidth(b-this.list.getFrameWidth("lr"));if(this.pageSize){this.footer=this.list.createChild({cls:a+"-ft"});this.pageTb=new Ext.PagingToolbar({store:this.store,pageSize:this.pageSize,renderTo:this.footer});this.assetHeight+=this.footer.getHeight()}if(!this.tpl){this.tpl='<tpl for="."><div class="'+a+'-item">{'+this.displayField+"}</div></tpl>"}this.view=new Ext.DataView({applyTo:this.innerList,tpl:this.tpl,singleSelect:true,selectedClass:this.selectedClass,itemSelector:this.itemSelector||"."+a+"-item",emptyText:this.listEmptyText,deferEmptyText:false});this.mon(this.view,{containerclick:this.onViewClick,click:this.onViewClick,scope:this});this.bindStore(this.store,true);if(this.resizable){this.resizer=new Ext.Resizable(this.list,{pinned:true,handles:"se"});this.mon(this.resizer,"resize",function(g,d,e){this.maxHeight=e-this.handleHeight-this.list.getFrameWidth("tb")-this.assetHeight;this.listWidth=d;this.innerList.setWidth(d-this.list.getFrameWidth("lr"));this.restrictHeight()},this);this[this.pageSize?"footer":"innerList"].setStyle("margin-bottom",this.handleHeight+"px")}}},getListParent:function(){return document.body},getStore:function(){return this.store},bindStore:function(a,b){if(this.store&&!b){if(this.store!==a&&this.store.autoDestroy){this.store.destroy()}else{this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.collapse,this)}if(!a){this.store=null;if(this.view){this.view.bindStore(null)}if(this.pageTb){this.pageTb.bindStore(null)}}}if(a){if(!b){this.lastQuery=null;if(this.pageTb){this.pageTb.bindStore(a)}}this.store=Ext.StoreMgr.lookup(a);this.store.on({scope:this,beforeload:this.onBeforeLoad,load:this.onLoad,exception:this.collapse});if(this.view){this.view.bindStore(a)}}},reset:function(){if(this.clearFilterOnReset&&this.mode=="local"){this.store.clearFilter()}Ext.form.ComboBox.superclass.reset.call(this)},initEvents:function(){Ext.form.ComboBox.superclass.initEvents.call(this);this.keyNav=new Ext.KeyNav(this.el,{up:function(a){this.inKeyMode=true;this.selectPrev()},down:function(a){if(!this.isExpanded()){this.onTriggerClick()}else{this.inKeyMode=true;this.selectNext()}},enter:function(a){this.onViewClick()},esc:function(a){this.collapse()},tab:function(a){if(this.forceSelection===true){this.collapse()}else{this.onViewClick(false)}return true},scope:this,doRelay:function(c,b,a){if(a=="down"||this.scope.isExpanded()){var d=Ext.KeyNav.prototype.doRelay.apply(this,arguments);if(!Ext.isIE&&Ext.EventManager.useKeydown){this.scope.fireKey(c)}return d}return true},forceKeyDown:true,defaultEventAction:"stopEvent"});this.queryDelay=Math.max(this.queryDelay||10,this.mode=="local"?10:250);this.dqTask=new Ext.util.DelayedTask(this.initQuery,this);if(this.typeAhead){this.taTask=new Ext.util.DelayedTask(this.onTypeAhead,this)}if(!this.enableKeyEvents){this.mon(this.el,"keyup",this.onKeyUp,this)}},onDestroy:function(){if(this.dqTask){this.dqTask.cancel();this.dqTask=null}this.bindStore(null);Ext.destroy(this.resizer,this.view,this.pageTb,this.list);Ext.destroyMembers(this,"hiddenField");Ext.form.ComboBox.superclass.onDestroy.call(this)},fireKey:function(a){if(!this.isExpanded()){Ext.form.ComboBox.superclass.fireKey.call(this,a)}},onResize:function(a,b){Ext.form.ComboBox.superclass.onResize.apply(this,arguments);if(!isNaN(a)&&this.isVisible()&&this.list){this.doResize(a)}else{this.bufferSize=a}},doResize:function(a){if(!Ext.isDefined(this.listWidth)){var b=Math.max(a,this.minListWidth);this.list.setWidth(b);this.innerList.setWidth(b-this.list.getFrameWidth("lr"))}},onEnable:function(){Ext.form.ComboBox.superclass.onEnable.apply(this,arguments);if(this.hiddenField){this.hiddenField.disabled=false}},onDisable:function(){Ext.form.ComboBox.superclass.onDisable.apply(this,arguments);if(this.hiddenField){this.hiddenField.disabled=true}},onBeforeLoad:function(){if(!this.hasFocus){return}this.innerList.update(this.loadingText?'<div class="loading-indicator">'+this.loadingText+"</div>":"");this.restrictHeight();this.selectedIndex=-1},onLoad:function(){if(!this.hasFocus){return}if(this.store.getCount()>0||this.listEmptyText){this.expand();this.restrictHeight();if(this.lastQuery==this.allQuery){if(this.editable){this.el.dom.select()}if(this.autoSelect!==false&&!this.selectByValue(this.value,true)){this.select(0,true)}}else{if(this.autoSelect!==false){this.selectNext()}if(this.typeAhead&&this.lastKey!=Ext.EventObject.BACKSPACE&&this.lastKey!=Ext.EventObject.DELETE){this.taTask.delay(this.typeAheadDelay)}}}else{this.collapse()}},onTypeAhead:function(){if(this.store.getCount()>0){var b=this.store.getAt(0);var c=b.data[this.displayField];var a=c.length;var d=this.getRawValue().length;if(d!=a){this.setRawValue(c);this.selectText(d,c.length)}}},assertValue:function(){var b=this.getRawValue(),a;if(this.valueField&&Ext.isDefined(this.value)){a=this.findRecord(this.valueField,this.value)}if(!a||a.get(this.displayField)!=b){a=this.findRecord(this.displayField,b)}if(!a&&this.forceSelection){if(b.length>0&&b!=this.emptyText){this.el.dom.value=Ext.value(this.lastSelectionText,"");this.applyEmptyText()}else{this.clearValue()}}else{if(a&&this.valueField){if(this.value==b){return}b=a.get(this.valueField||this.displayField)}this.setValue(b)}},onSelect:function(a,b){if(this.fireEvent("beforeselect",this,a,b)!==false){this.setValue(a.data[this.valueField||this.displayField]);this.collapse();this.fireEvent("select",this,a,b)}},getName:function(){var a=this.hiddenField;return a&&a.name?a.name:this.hiddenName||Ext.form.ComboBox.superclass.getName.call(this)},getValue:function(){if(this.valueField){return Ext.isDefined(this.value)?this.value:""}else{return Ext.form.ComboBox.superclass.getValue.call(this)}},clearValue:function(){if(this.hiddenField){this.hiddenField.value=""}this.setRawValue("");this.lastSelectionText="";this.applyEmptyText();this.value=""},setValue:function(a){var c=a;if(this.valueField){var b=this.findRecord(this.valueField,a);if(b){c=b.data[this.displayField]}else{if(Ext.isDefined(this.valueNotFoundText)){c=this.valueNotFoundText}}}this.lastSelectionText=c;if(this.hiddenField){this.hiddenField.value=Ext.value(a,"")}Ext.form.ComboBox.superclass.setValue.call(this,c);this.value=a;return this},findRecord:function(c,b){var a;if(this.store.getCount()>0){this.store.each(function(d){if(d.data[c]==b){a=d;return false}})}return a},onViewMove:function(b,a){this.inKeyMode=false},onViewOver:function(d,b){if(this.inKeyMode){return}var c=this.view.findItemFromChild(b);if(c){var a=this.view.indexOf(c);this.select(a,false)}},onViewClick:function(b){var a=this.view.getSelectedIndexes()[0],c=this.store,d=c.getAt(a);if(d){this.onSelect(d,a)}else{this.collapse()}if(b!==false){this.el.focus()}},restrictHeight:function(){this.innerList.dom.style.height="";var b=this.innerList.dom,e=this.list.getFrameWidth("tb")+(this.resizable?this.handleHeight:0)+this.assetHeight,c=Math.max(b.clientHeight,b.offsetHeight,b.scrollHeight),a=this.getPosition()[1]-Ext.getBody().getScroll().top,g=Ext.lib.Dom.getViewHeight()-a-this.getSize().height,d=Math.max(a,g,this.minHeight||0)-this.list.shadowOffset-e-5;c=Math.min(c,d,this.maxHeight);this.innerList.setHeight(c);this.list.beginUpdate();this.list.setHeight(c+e);this.list.alignTo.apply(this.list,[this.el].concat(this.listAlign));this.list.endUpdate()},isExpanded:function(){return this.list&&this.list.isVisible()},selectByValue:function(a,c){if(!Ext.isEmpty(a,true)){var b=this.findRecord(this.valueField||this.displayField,a);if(b){this.select(this.store.indexOf(b),c);return true}}return false},select:function(a,c){this.selectedIndex=a;this.view.select(a);if(c!==false){var b=this.view.getNode(a);if(b){this.innerList.scrollChildIntoView(b,false)}}},selectNext:function(){var a=this.store.getCount();if(a>0){if(this.selectedIndex==-1){this.select(0)}else{if(this.selectedIndex<a-1){this.select(this.selectedIndex+1)}}}},selectPrev:function(){var a=this.store.getCount();if(a>0){if(this.selectedIndex==-1){this.select(0)}else{if(this.selectedIndex!==0){this.select(this.selectedIndex-1)}}}},onKeyUp:function(b){var a=b.getKey();if(this.editable!==false&&this.readOnly!==true&&(a==b.BACKSPACE||!b.isSpecialKey())){this.lastKey=a;this.dqTask.delay(this.queryDelay)}Ext.form.ComboBox.superclass.onKeyUp.call(this,b)},validateBlur:function(){return !this.list||!this.list.isVisible()},initQuery:function(){this.doQuery(this.getRawValue())},beforeBlur:function(){this.assertValue()},postBlur:function(){Ext.form.ComboBox.superclass.postBlur.call(this);this.collapse();this.inKeyMode=false},doQuery:function(c,b){c=Ext.isEmpty(c)?"":c;var a={query:c,forceAll:b,combo:this,cancel:false};if(this.fireEvent("beforequery",a)===false||a.cancel){return false}c=a.query;b=a.forceAll;if(b===true||(c.length>=this.minChars)){if(this.lastQuery!==c){this.lastQuery=c;if(this.mode=="local"){this.selectedIndex=-1;if(b){this.store.clearFilter()}else{this.store.filter(this.displayField,c)}this.onLoad()}else{this.store.baseParams[this.queryParam]=c;this.store.load({params:this.getParams(c)});this.expand()}}else{this.selectedIndex=-1;this.onLoad()}}},getParams:function(a){var b={},c=this.store.paramNames;if(this.pageSize){b[c.start]=0;b[c.limit]=this.pageSize}return b},collapse:function(){if(!this.isExpanded()){return}this.list.hide();Ext.getDoc().un("mousewheel",this.collapseIf,this);Ext.getDoc().un("mousedown",this.collapseIf,this);this.fireEvent("collapse",this)},collapseIf:function(a){if(!this.isDestroyed&&!a.within(this.wrap)&&!a.within(this.list)){this.collapse()}},expand:function(){if(this.isExpanded()||!this.hasFocus){return}if(this.title||this.pageSize){this.assetHeight=0;if(this.title){this.assetHeight+=this.header.getHeight()}if(this.pageSize){this.assetHeight+=this.footer.getHeight()}}if(this.bufferSize){this.doResize(this.bufferSize);delete this.bufferSize}this.list.alignTo.apply(this.list,[this.el].concat(this.listAlign));this.list.setZIndex(this.getZIndex());this.list.show();if(Ext.isGecko2){this.innerList.setOverflow("auto")}this.mon(Ext.getDoc(),{scope:this,mousewheel:this.collapseIf,mousedown:this.collapseIf});this.fireEvent("expand",this)},onTriggerClick:function(){if(this.readOnly||this.disabled){return}if(this.isExpanded()){this.collapse();this.el.focus()}else{this.onFocus({});if(this.triggerAction=="all"){this.doQuery(this.allQuery,true)}else{this.doQuery(this.getRawValue())}this.el.focus()}}});Ext.reg("combo",Ext.form.ComboBox);Ext.form.Checkbox=Ext.extend(Ext.form.Field,{focusClass:undefined,fieldClass:"x-form-field",checked:false,boxLabel:"&#160;",defaultAutoCreate:{tag:"input",type:"checkbox",autocomplete:"off"},actionMode:"wrap",initComponent:function(){Ext.form.Checkbox.superclass.initComponent.call(this);this.addEvents("check")},onResize:function(){Ext.form.Checkbox.superclass.onResize.apply(this,arguments);if(!this.boxLabel&&!this.fieldLabel){this.el.alignTo(this.wrap,"c-c")}},initEvents:function(){Ext.form.Checkbox.superclass.initEvents.call(this);this.mon(this.el,{scope:this,click:this.onClick,change:this.onClick})},markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,onRender:function(b,a){Ext.form.Checkbox.superclass.onRender.call(this,b,a);if(this.inputValue!==undefined){this.el.dom.value=this.inputValue}this.wrap=this.el.wrap({cls:"x-form-check-wrap"});if(this.boxLabel){this.wrap.createChild({tag:"label",htmlFor:this.el.id,cls:"x-form-cb-label",html:this.boxLabel})}if(this.checked){this.setValue(true)}else{this.checked=this.el.dom.checked}if(Ext.isIE&&!Ext.isStrict){this.wrap.repaint()}this.resizeEl=this.positionEl=this.wrap},onDestroy:function(){Ext.destroy(this.wrap);Ext.form.Checkbox.superclass.onDestroy.call(this)},initValue:function(){this.originalValue=this.getValue()},getValue:function(){if(this.rendered){return this.el.dom.checked}return this.checked},onClick:function(){if(this.el.dom.checked!=this.checked){this.setValue(this.el.dom.checked)}},setValue:function(a){var c=this.checked,b=this.inputValue;if(a===false){this.checked=false}else{this.checked=(a===true||a==="true"||a=="1"||(b?a==b:String(a).toLowerCase()=="on"))}if(this.rendered){this.el.dom.checked=this.checked;this.el.dom.defaultChecked=this.checked}if(c!=this.checked){this.fireEvent("check",this,this.checked);if(this.handler){this.handler.call(this.scope||this,this,this.checked)}}return this}});Ext.reg("checkbox",Ext.form.Checkbox);Ext.form.CheckboxGroup=Ext.extend(Ext.form.Field,{columns:"auto",vertical:false,allowBlank:true,blankText:"You must select at least one item in this group",defaultType:"checkbox",groupCls:"x-form-check-group",initComponent:function(){this.addEvents("change");this.on("change",this.validate,this);Ext.form.CheckboxGroup.superclass.initComponent.call(this)},onRender:function(j,g){if(!this.el){var p={autoEl:{id:this.id},cls:this.groupCls,layout:"column",renderTo:j,bufferResize:false};var a={xtype:"container",defaultType:this.defaultType,layout:"form",defaults:{hideLabel:true,anchor:"100%"}};if(this.items[0].items){Ext.apply(p,{layoutConfig:{columns:this.items.length},defaults:this.defaults,items:this.items});for(var e=0,m=this.items.length;e<m;e++){Ext.applyIf(this.items[e],a)}}else{var d,n=[];if(typeof this.columns=="string"){this.columns=this.items.length}if(!Ext.isArray(this.columns)){var k=[];for(var e=0;e<this.columns;e++){k.push((100/this.columns)*0.01)}this.columns=k}d=this.columns.length;for(var e=0;e<d;e++){var b=Ext.apply({items:[]},a);b[this.columns[e]<=1?"columnWidth":"width"]=this.columns[e];if(this.defaults){b.defaults=Ext.apply(b.defaults||{},this.defaults)}n.push(b)}if(this.vertical){var r=Math.ceil(this.items.length/d),o=0;for(var e=0,m=this.items.length;e<m;e++){if(e>0&&e%r==0){o++}if(this.items[e].fieldLabel){this.items[e].hideLabel=false}n[o].items.push(this.items[e])}}else{for(var e=0,m=this.items.length;e<m;e++){var q=e%d;if(this.items[e].fieldLabel){this.items[e].hideLabel=false}n[q].items.push(this.items[e])}}Ext.apply(p,{layoutConfig:{columns:d},items:n})}this.panel=new Ext.Container(p);this.panel.ownerCt=this;this.el=this.panel.getEl();if(this.forId&&this.itemCls){var c=this.el.up(this.itemCls).child("label",true);if(c){c.setAttribute("htmlFor",this.forId)}}var h=this.panel.findBy(function(i){return i.isFormField},this);this.items=new Ext.util.MixedCollection();this.items.addAll(h)}Ext.form.CheckboxGroup.superclass.onRender.call(this,j,g)},initValue:function(){if(this.value){this.setValue.apply(this,this.buffered?this.value:[this.value]);delete this.buffered;delete this.value}},afterRender:function(){Ext.form.CheckboxGroup.superclass.afterRender.call(this);this.eachItem(function(a){a.on("check",this.fireChecked,this);a.inGroup=true})},doLayout:function(){if(this.rendered){this.panel.forceLayout=this.ownerCt.forceLayout;this.panel.doLayout()}},fireChecked:function(){var a=[];this.eachItem(function(b){if(b.checked){a.push(b)}});this.fireEvent("change",this,a)},getErrors:function(){var b=Ext.form.CheckboxGroup.superclass.getErrors.apply(this,arguments);if(!this.allowBlank){var a=true;this.eachItem(function(c){if(c.checked){return(a=false)}});if(a){b.push(this.blankText)}}return b},isDirty:function(){if(this.disabled||!this.rendered){return false}var a=false;this.eachItem(function(b){if(b.isDirty()){a=true;return false}});return a},setReadOnly:function(a){if(this.rendered){this.eachItem(function(b){b.setReadOnly(a)})}this.readOnly=a},onDisable:function(){this.eachItem(function(a){a.disable()})},onEnable:function(){this.eachItem(function(a){a.enable()})},onResize:function(a,b){this.panel.setSize(a,b);this.panel.doLayout()},reset:function(){if(this.originalValue){this.eachItem(function(a){if(a.setValue){a.setValue(false);a.originalValue=a.getValue()}});this.resetOriginal=true;this.setValue(this.originalValue);delete this.resetOriginal}else{this.eachItem(function(a){if(a.reset){a.reset()}})}(function(){this.clearInvalid()}).defer(50,this)},setValue:function(){if(this.rendered){this.onSetValue.apply(this,arguments)}else{this.buffered=true;this.value=arguments}return this},onSetValue:function(d,c){if(arguments.length==1){if(Ext.isArray(d)){Ext.each(d,function(h,e){if(Ext.isObject(h)&&h.setValue){h.setValue(true);if(this.resetOriginal===true){h.originalValue=h.getValue()}}else{var g=this.items.itemAt(e);if(g){g.setValue(h)}}},this)}else{if(Ext.isObject(d)){for(var a in d){var b=this.getBox(a);if(b){b.setValue(d[a])}}}else{this.setValueForItem(d)}}}else{var b=this.getBox(d);if(b){b.setValue(c)}}},beforeDestroy:function(){Ext.destroy(this.panel);if(!this.rendered){Ext.destroy(this.items)}Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this)},setValueForItem:function(a){a=String(a).split(",");this.eachItem(function(b){if(a.indexOf(b.inputValue)>-1){b.setValue(true)}})},getBox:function(b){var a=null;this.eachItem(function(c){if(b==c||c.dataIndex==b||c.id==b||c.getName()==b){a=c;return false}});return a},getValue:function(){var a=[];this.eachItem(function(b){if(b.checked){a.push(b)}});return a},eachItem:function(b,a){if(this.items&&this.items.each){this.items.each(b,a||this)}},getRawValue:Ext.emptyFn,setRawValue:Ext.emptyFn});Ext.reg("checkboxgroup",Ext.form.CheckboxGroup);Ext.form.CompositeField=Ext.extend(Ext.form.Field,{defaultMargins:"0 5 0 0",skipLastItemMargin:true,isComposite:true,combineErrors:true,labelConnector:", ",initComponent:function(){var g=[],b=this.items,e;for(var d=0,c=b.length;d<c;d++){e=b[d];if(!Ext.isEmpty(e.ref)){e.ref="../"+e.ref}g.push(e.fieldLabel);Ext.applyIf(e,this.defaults);if(!(d==c-1&&this.skipLastItemMargin)){Ext.applyIf(e,{margins:this.defaultMargins})}}this.fieldLabel=this.fieldLabel||this.buildLabel(g);this.fieldErrors=new Ext.util.MixedCollection(true,function(h){return h.field});this.fieldErrors.on({scope:this,add:this.updateInvalidMark,remove:this.updateInvalidMark,replace:this.updateInvalidMark});Ext.form.CompositeField.superclass.initComponent.apply(this,arguments);this.innerCt=new Ext.Container({layout:"hbox",items:this.items,cls:"x-form-composite",defaultMargins:"0 3 0 0",ownerCt:this});this.innerCt.ownerCt=undefined;var a=this.innerCt.findBy(function(h){return h.isFormField},this);this.items=new Ext.util.MixedCollection();this.items.addAll(a)},onRender:function(c,a){if(!this.el){var d=this.innerCt;d.render(c);this.el=d.getEl();if(this.combineErrors){this.eachItem(function(e){Ext.apply(e,{markInvalid:this.onFieldMarkInvalid.createDelegate(this,[e],0),clearInvalid:this.onFieldClearInvalid.createDelegate(this,[e],0)})})}var b=this.el.parent().parent().child("label",true);if(b){b.setAttribute("for",this.items.items[0].id)}}Ext.form.CompositeField.superclass.onRender.apply(this,arguments)},onFieldMarkInvalid:function(d,c){var b=d.getName(),a={field:b,errorName:d.fieldLabel||b,error:c};this.fieldErrors.replace(b,a);if(!d.preventMark){d.el.addClass(d.invalidClass)}},onFieldClearInvalid:function(a){this.fieldErrors.removeKey(a.getName());a.el.removeClass(a.invalidClass)},updateInvalidMark:function(){var a=Ext.isIE6&&Ext.isStrict;if(this.fieldErrors.length==0){this.clearInvalid();if(a){this.clearInvalid.defer(50,this)}}else{var b=this.buildCombinedErrorMessage(this.fieldErrors.items);this.sortErrors();this.markInvalid(b);if(a){this.markInvalid(b)}}},validateValue:function(c,a){var b=true;this.eachItem(function(d){if(!d.isValid(a)){b=false}});return b},buildCombinedErrorMessage:function(e){var d=[],b;for(var c=0,a=e.length;c<a;c++){b=e[c];d.push(String.format("{0}: {1}",b.errorName,b.error))}return d.join("<br />")},sortErrors:function(){var a=this.items;this.fieldErrors.sort("ASC",function(g,d){var c=function(b){return function(i){return i.getName()==b}};var h=a.findIndexBy(c(g.field)),e=a.findIndexBy(c(d.field));return h<e?-1:1})},reset:function(){this.eachItem(function(a){a.reset()});(function(){this.clearInvalid()}).defer(50,this)},clearInvalidChildren:function(){this.eachItem(function(a){a.clearInvalid()})},buildLabel:function(a){return Ext.clean(a).join(this.labelConnector)},isDirty:function(){if(this.disabled||!this.rendered){return false}var a=false;this.eachItem(function(b){if(b.isDirty()){a=true;return false}});return a},eachItem:function(b,a){if(this.items&&this.items.each){this.items.each(b,a||this)}},onResize:function(e,c,a,d){var b=this.innerCt;if(this.rendered&&b.rendered){b.setSize(e,c)}Ext.form.CompositeField.superclass.onResize.apply(this,arguments)},doLayout:function(c,b){if(this.rendered){var a=this.innerCt;a.forceLayout=this.ownerCt.forceLayout;a.doLayout(c,b)}},beforeDestroy:function(){Ext.destroy(this.innerCt);Ext.form.CompositeField.superclass.beforeDestroy.call(this)},setReadOnly:function(a){if(a==undefined){a=true}a=!!a;if(this.rendered){this.eachItem(function(b){b.setReadOnly(a)})}this.readOnly=a},onShow:function(){Ext.form.CompositeField.superclass.onShow.call(this);this.doLayout()},onDisable:function(){this.eachItem(function(a){a.disable()})},onEnable:function(){this.eachItem(function(a){a.enable()})}});Ext.reg("compositefield",Ext.form.CompositeField);Ext.form.Radio=Ext.extend(Ext.form.Checkbox,{inputType:"radio",markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,getGroupValue:function(){var a=this.el.up("form")||Ext.getBody();var b=a.child('input[name="'+this.el.dom.name+'"]:checked',true);return b?b.value:null},setValue:function(b){var a,d,c;if(typeof b=="boolean"){Ext.form.Radio.superclass.setValue.call(this,b)}else{if(this.rendered){a=this.getCheckEl();c=a.child('input[name="'+this.el.dom.name+'"][value="'+b+'"]',true);if(c){Ext.getCmp(c.id).setValue(true)}}}if(this.rendered&&this.checked){a=a||this.getCheckEl();d=this.getCheckEl().select('input[name="'+this.el.dom.name+'"]');d.each(function(e){if(e.dom.id!=this.id){Ext.getCmp(e.dom.id).setValue(false)}},this)}return this},getCheckEl:function(){if(this.inGroup){return this.el.up(".x-form-radio-group")}return this.el.up("form")||Ext.getBody()}});Ext.reg("radio",Ext.form.Radio);Ext.form.RadioGroup=Ext.extend(Ext.form.CheckboxGroup,{allowBlank:true,blankText:"You must select one item in this group",defaultType:"radio",groupCls:"x-form-radio-group",getValue:function(){var a=null;this.eachItem(function(b){if(b.checked){a=b;return false}});return a},onSetValue:function(c,b){if(arguments.length>1){var a=this.getBox(c);if(a){a.setValue(b);if(a.checked){this.eachItem(function(d){if(d!==a){d.setValue(false)}})}}}else{this.setValueForItem(c)}},setValueForItem:function(a){a=String(a).split(",")[0];this.eachItem(function(b){b.setValue(a==b.inputValue)})},fireChecked:function(){if(!this.checkTask){this.checkTask=new Ext.util.DelayedTask(this.bufferChecked,this)}this.checkTask.delay(10)},bufferChecked:function(){var a=null;this.eachItem(function(b){if(b.checked){a=b;return false}});this.fireEvent("change",this,a)},onDestroy:function(){if(this.checkTask){this.checkTask.cancel();this.checkTask=null}Ext.form.RadioGroup.superclass.onDestroy.call(this)}});Ext.reg("radiogroup",Ext.form.RadioGroup);Ext.form.Hidden=Ext.extend(Ext.form.Field,{inputType:"hidden",shouldLayout:false,onRender:function(){Ext.form.Hidden.superclass.onRender.apply(this,arguments)},initEvents:function(){this.originalValue=this.getValue()},setSize:Ext.emptyFn,setWidth:Ext.emptyFn,setHeight:Ext.emptyFn,setPosition:Ext.emptyFn,setPagePosition:Ext.emptyFn,markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn});Ext.reg("hidden",Ext.form.Hidden);Ext.form.BasicForm=Ext.extend(Ext.util.Observable,{constructor:function(b,a){Ext.apply(this,a);if(Ext.isString(this.paramOrder)){this.paramOrder=this.paramOrder.split(/[\s,|]/)}this.items=new Ext.util.MixedCollection(false,function(c){return c.getItemId()});this.addEvents("beforeaction","actionfailed","actioncomplete");if(b){this.initEl(b)}Ext.form.BasicForm.superclass.constructor.call(this)},timeout:30,paramOrder:undefined,paramsAsHash:false,waitTitle:"Please Wait...",activeAction:null,trackResetOnLoad:false,initEl:function(a){this.el=Ext.get(a);this.id=this.el.id||Ext.id();if(!this.standardSubmit){this.el.on("submit",this.onSubmit,this)}this.el.addClass("x-form")},getEl:function(){return this.el},onSubmit:function(a){a.stopEvent()},destroy:function(a){if(a!==true){this.items.each(function(b){Ext.destroy(b)});Ext.destroy(this.el)}this.items.clear();this.purgeListeners()},isValid:function(){var a=true;this.items.each(function(b){if(!b.validate()){a=false}});return a},isDirty:function(){var a=false;this.items.each(function(b){if(b.isDirty()){a=true;return false}});return a},doAction:function(b,a){if(Ext.isString(b)){b=new Ext.form.Action.ACTION_TYPES[b](this,a)}if(this.fireEvent("beforeaction",this,b)!==false){this.beforeAction(b);b.run.defer(100,b)}return this},submit:function(b){b=b||{};if(this.standardSubmit){var a=b.clientValidation===false||this.isValid();if(a){var c=this.el.dom;if(this.url&&Ext.isEmpty(c.action)){c.action=this.url}c.submit()}return a}var d=String.format("{0}submit",this.api?"direct":"");this.doAction(d,b);return this},load:function(a){var b=String.format("{0}load",this.api?"direct":"");this.doAction(b,a);return this},updateRecord:function(b){b.beginEdit();var a=b.fields,d,c;a.each(function(e){d=this.findField(e.name);if(d){c=d.getValue();if(Ext.type(c)!==false&&c.getGroupValue){c=c.getGroupValue()}else{if(d.eachItem){c=[];d.eachItem(function(g){c.push(g.getValue())})}}b.set(e.name,c)}},this);b.endEdit();return this},loadRecord:function(a){this.setValues(a.data);return this},beforeAction:function(a){this.items.each(function(c){if(c.isFormField&&c.syncValue){c.syncValue()}});var b=a.options;if(b.waitMsg){if(this.waitMsgTarget===true){this.el.mask(b.waitMsg,"x-mask-loading")}else{if(this.waitMsgTarget){this.waitMsgTarget=Ext.get(this.waitMsgTarget);this.waitMsgTarget.mask(b.waitMsg,"x-mask-loading")}else{Ext.MessageBox.wait(b.waitMsg,b.waitTitle||this.waitTitle)}}}},afterAction:function(a,c){this.activeAction=null;var b=a.options;if(b.waitMsg){if(this.waitMsgTarget===true){this.el.unmask()}else{if(this.waitMsgTarget){this.waitMsgTarget.unmask()}else{Ext.MessageBox.updateProgress(1);Ext.MessageBox.hide()}}}if(c){if(b.reset){this.reset()}Ext.callback(b.success,b.scope,[this,a]);this.fireEvent("actioncomplete",this,a)}else{Ext.callback(b.failure,b.scope,[this,a]);this.fireEvent("actionfailed",this,a)}},findField:function(c){var b=this.items.get(c);if(!Ext.isObject(b)){var a=function(d){if(d.isFormField){if(d.dataIndex==c||d.id==c||d.getName()==c){b=d;return false}else{if(d.isComposite){return d.items.each(a)}else{if(d instanceof Ext.form.CheckboxGroup&&d.rendered){return d.eachItem(a)}}}}};this.items.each(a)}return b||null},markInvalid:function(h){if(Ext.isArray(h)){for(var c=0,a=h.length;c<a;c++){var b=h[c];var d=this.findField(b.id);if(d){d.markInvalid(b.msg)}}}else{var e,g;for(g in h){if(!Ext.isFunction(h[g])&&(e=this.findField(g))){e.markInvalid(h[g])}}}return this},setValues:function(c){if(Ext.isArray(c)){for(var d=0,a=c.length;d<a;d++){var b=c[d];var e=this.findField(b.id);if(e){e.setValue(b.value);if(this.trackResetOnLoad){e.originalValue=e.getValue()}}}}else{var g,h;for(h in c){if(!Ext.isFunction(c[h])&&(g=this.findField(h))){g.setValue(c[h]);if(this.trackResetOnLoad){g.originalValue=g.getValue()}}}}return this},getValues:function(b){var a=Ext.lib.Ajax.serializeForm(this.el.dom);if(b===true){return a}return Ext.urlDecode(a)},getFieldValues:function(a){var d={},e,b,c;this.items.each(function(g){if(!g.disabled&&(a!==true||g.isDirty())){e=g.getName();b=d[e];c=g.getValue();if(Ext.isDefined(b)){if(Ext.isArray(b)){d[e].push(c)}else{d[e]=[b,c]}}else{d[e]=c}}});return d},clearInvalid:function(){this.items.each(function(a){a.clearInvalid()});return this},reset:function(){this.items.each(function(a){a.reset()});return this},add:function(){this.items.addAll(Array.prototype.slice.call(arguments,0));return this},remove:function(a){this.items.remove(a);return this},cleanDestroyed:function(){this.items.filterBy(function(a){return !!a.isDestroyed}).each(this.remove,this)},render:function(){this.items.each(function(a){if(a.isFormField&&!a.rendered&&document.getElementById(a.id)){a.applyToMarkup(a.id)}});return this},applyToFields:function(a){this.items.each(function(b){Ext.apply(b,a)});return this},applyIfToFields:function(a){this.items.each(function(b){Ext.applyIf(b,a)});return this},callFieldMethod:function(b,a){a=a||[];this.items.each(function(c){if(Ext.isFunction(c[b])){c[b].apply(c,a)}});return this}});Ext.BasicForm=Ext.form.BasicForm;Ext.FormPanel=Ext.extend(Ext.Panel,{minButtonWidth:75,labelAlign:"left",monitorValid:false,monitorPoll:200,layout:"form",initComponent:function(){this.form=this.createForm();Ext.FormPanel.superclass.initComponent.call(this);this.bodyCfg={tag:"form",cls:this.baseCls+"-body",method:this.method||"POST",id:this.formId||Ext.id()};if(this.fileUpload){this.bodyCfg.enctype="multipart/form-data"}this.initItems();this.addEvents("clientvalidation");this.relayEvents(this.form,["beforeaction","actionfailed","actioncomplete"])},createForm:function(){var a=Ext.applyIf({listeners:{}},this.initialConfig);return new Ext.form.BasicForm(null,a)},initFields:function(){var c=this.form;var a=this;var b=function(d){if(a.isField(d)){c.add(d)}else{if(d.findBy&&d!=a){a.applySettings(d);if(d.items&&d.items.each){d.items.each(b,this)}}}};this.items.each(b,this)},applySettings:function(b){var a=b.ownerCt;Ext.applyIf(b,{labelAlign:a.labelAlign,labelWidth:a.labelWidth,itemCls:a.itemCls})},getLayoutTarget:function(){return this.form.el},getForm:function(){return this.form},onRender:function(b,a){this.initFields();Ext.FormPanel.superclass.onRender.call(this,b,a);this.form.initEl(this.body)},beforeDestroy:function(){this.stopMonitoring();this.form.destroy(true);Ext.FormPanel.superclass.beforeDestroy.call(this)},isField:function(a){return !!a.setValue&&!!a.getValue&&!!a.markInvalid&&!!a.clearInvalid},initEvents:function(){Ext.FormPanel.superclass.initEvents.call(this);this.on({scope:this,add:this.onAddEvent,remove:this.onRemoveEvent});if(this.monitorValid){this.startMonitoring()}},onAdd:function(a){Ext.FormPanel.superclass.onAdd.call(this,a);this.processAdd(a)},onAddEvent:function(a,b){if(a!==this){this.processAdd(b)}},processAdd:function(a){if(this.isField(a)){this.form.add(a)}else{if(a.findBy){this.applySettings(a);this.form.add.apply(this.form,a.findBy(this.isField))}}},onRemove:function(a){Ext.FormPanel.superclass.onRemove.call(this,a);this.processRemove(a)},onRemoveEvent:function(a,b){if(a!==this){this.processRemove(b)}},processRemove:function(a){if(!this.destroying){if(this.isField(a)){this.form.remove(a)}else{if(a.findBy){Ext.each(a.findBy(this.isField),this.form.remove,this.form);this.form.cleanDestroyed()}}}},startMonitoring:function(){if(!this.validTask){this.validTask=new Ext.util.TaskRunner();this.validTask.start({run:this.bindHandler,interval:this.monitorPoll||200,scope:this})}},stopMonitoring:function(){if(this.validTask){this.validTask.stopAll();this.validTask=null}},load:function(){this.form.load.apply(this.form,arguments)},onDisable:function(){Ext.FormPanel.superclass.onDisable.call(this);if(this.form){this.form.items.each(function(){this.disable()})}},onEnable:function(){Ext.FormPanel.superclass.onEnable.call(this);if(this.form){this.form.items.each(function(){this.enable()})}},bindHandler:function(){var e=true;this.form.items.each(function(g){if(!g.isValid(true)){e=false;return false}});if(this.fbar){var b=this.fbar.items.items;for(var d=0,a=b.length;d<a;d++){var c=b[d];if(c.formBind===true&&c.disabled===e){c.setDisabled(!e)}}}this.fireEvent("clientvalidation",this,e)}});Ext.reg("form",Ext.FormPanel);Ext.form.FormPanel=Ext.FormPanel;Ext.form.FieldSet=Ext.extend(Ext.Panel,{baseCls:"x-fieldset",layout:"form",animCollapse:false,onRender:function(b,a){if(!this.el){this.el=document.createElement("fieldset");this.el.id=this.id;if(this.title||this.header||this.checkboxToggle){this.el.appendChild(document.createElement("legend")).className=this.baseCls+"-header"}}Ext.form.FieldSet.superclass.onRender.call(this,b,a);if(this.checkboxToggle){var c=typeof this.checkboxToggle=="object"?this.checkboxToggle:{tag:"input",type:"checkbox",name:this.checkboxName||this.id+"-checkbox"};this.checkbox=this.header.insertFirst(c);this.checkbox.dom.checked=!this.collapsed;this.mon(this.checkbox,"click",this.onCheckClick,this)}},onCollapse:function(a,b){if(this.checkbox){this.checkbox.dom.checked=false}Ext.form.FieldSet.superclass.onCollapse.call(this,a,b)},onExpand:function(a,b){if(this.checkbox){this.checkbox.dom.checked=true}Ext.form.FieldSet.superclass.onExpand.call(this,a,b)},onCheckClick:function(){this[this.checkbox.dom.checked?"expand":"collapse"]()}});Ext.reg("fieldset",Ext.form.FieldSet);Ext.form.HtmlEditor=Ext.extend(Ext.form.Field,{enableFormat:true,enableFontSize:true,enableColors:true,enableAlignments:true,enableLists:true,enableSourceEdit:true,enableLinks:true,enableFont:true,createLinkText:"Please enter the URL for the link:",defaultLinkValue:"http://",fontFamilies:["Arial","Courier New","Tahoma","Times New Roman","Verdana"],defaultFont:"tahoma",defaultValue:(Ext.isOpera||Ext.isIE6)?"&#160;":"&#8203;",actionMode:"wrap",validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Ext.emptyFn,iframePad:3,hideMode:"offsets",defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"off"},initComponent:function(){this.addEvents("initialize","activate","beforesync","beforepush","sync","push","editmodechange");Ext.form.HtmlEditor.superclass.initComponent.call(this)},createFontOptions:function(){var d=[],b=this.fontFamilies,c,g;for(var e=0,a=b.length;e<a;e++){c=b[e];g=c.toLowerCase();d.push('<option value="',g,'" style="font-family:',c,';"',(this.defaultFont==g?' selected="true">':">"),c,"</option>")}return d.join("")},createToolbar:function(e){var c=[];var a=Ext.QuickTips&&Ext.QuickTips.isEnabled();function d(j,h,i){return{itemId:j,cls:"x-btn-icon",iconCls:"x-edit-"+j,enableToggle:h!==false,scope:e,handler:i||e.relayBtnCmd,clickEvent:"mousedown",tooltip:a?e.buttonTips[j]||undefined:undefined,overflowText:e.buttonTips[j].title||undefined,tabIndex:-1}}if(this.enableFont&&!Ext.isSafari2){var g=new Ext.Toolbar.Item({autoEl:{tag:"select",cls:"x-font-select",html:this.createFontOptions()}});c.push(g,"-")}if(this.enableFormat){c.push(d("bold"),d("italic"),d("underline"))}if(this.enableFontSize){c.push("-",d("increasefontsize",false,this.adjustFont),d("decreasefontsize",false,this.adjustFont))}if(this.enableColors){c.push("-",{itemId:"forecolor",cls:"x-btn-icon",iconCls:"x-edit-forecolor",clickEvent:"mousedown",tooltip:a?e.buttonTips.forecolor||undefined:undefined,tabIndex:-1,menu:new Ext.menu.ColorMenu({allowReselect:true,focus:Ext.emptyFn,value:"000000",plain:true,listeners:{scope:this,select:function(i,h){this.execCmd("forecolor",Ext.isWebKit||Ext.isIE?"#"+h:h);this.deferFocus()}},clickEvent:"mousedown"})},{itemId:"backcolor",cls:"x-btn-icon",iconCls:"x-edit-backcolor",clickEvent:"mousedown",tooltip:a?e.buttonTips.backcolor||undefined:undefined,tabIndex:-1,menu:new Ext.menu.ColorMenu({focus:Ext.emptyFn,value:"FFFFFF",plain:true,allowReselect:true,listeners:{scope:this,select:function(i,h){if(Ext.isGecko){this.execCmd("useCSS",false);this.execCmd("hilitecolor",h);this.execCmd("useCSS",true);this.deferFocus()}else{this.execCmd(Ext.isOpera?"hilitecolor":"backcolor",Ext.isWebKit||Ext.isIE?"#"+h:h);this.deferFocus()}}},clickEvent:"mousedown"})})}if(this.enableAlignments){c.push("-",d("justifyleft"),d("justifycenter"),d("justifyright"))}if(!Ext.isSafari2){if(this.enableLinks){c.push("-",d("createlink",false,this.createLink))}if(this.enableLists){c.push("-",d("insertorderedlist"),d("insertunorderedlist"))}if(this.enableSourceEdit){c.push("-",d("sourceedit",true,function(h){this.toggleSourceEdit(!this.sourceEditMode)}))}}var b=new Ext.Toolbar({renderTo:this.wrap.dom.firstChild,items:c});if(g){this.fontSelect=g.el;this.mon(this.fontSelect,"change",function(){var h=this.fontSelect.dom.value;this.relayCmd("fontname",h);this.deferFocus()},this)}this.mon(b.el,"click",function(h){h.preventDefault()});this.tb=b;this.tb.doLayout()},onDisable:function(){this.wrap.mask();Ext.form.HtmlEditor.superclass.onDisable.call(this)},onEnable:function(){this.wrap.unmask();Ext.form.HtmlEditor.superclass.onEnable.call(this)},setReadOnly:function(b){Ext.form.HtmlEditor.superclass.setReadOnly.call(this,b);if(this.initialized){if(Ext.isIE){this.getEditorBody().contentEditable=!b}else{this.setDesignMode(!b)}var a=this.getEditorBody();if(a){a.style.cursor=this.readOnly?"default":"text"}this.disableItems(b)}},getDocMarkup:function(){var a=Ext.fly(this.iframe).getHeight()-this.iframePad*2;return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>',this.iframePad,a)},getEditorBody:function(){var a=this.getDoc();return a.body||a.documentElement},getDoc:function(){return Ext.isIE?this.getWin().document:(this.iframe.contentDocument||this.getWin().document)},getWin:function(){return Ext.isIE?this.iframe.contentWindow:window.frames[this.iframe.name]},onRender:function(b,a){Ext.form.HtmlEditor.superclass.onRender.call(this,b,a);this.el.dom.style.border="0 none";this.el.dom.setAttribute("tabIndex",-1);this.el.addClass("x-hidden");if(Ext.isIE){this.el.applyStyles("margin-top:-1px;margin-bottom:-1px;")}this.wrap=this.el.wrap({cls:"x-html-editor-wrap",cn:{cls:"x-html-editor-tb"}});this.createToolbar(this);this.disableItems(true);this.tb.doLayout();this.createIFrame();if(!this.width){var c=this.el.getSize();this.setSize(c.width,this.height||c.height)}this.resizeEl=this.positionEl=this.wrap},createIFrame:function(){var a=document.createElement("iframe");a.name=Ext.id();a.frameBorder="0";a.style.overflow="auto";a.src=Ext.SSL_SECURE_URL;this.wrap.dom.appendChild(a);this.iframe=a;this.monitorTask=Ext.TaskMgr.start({run:this.checkDesignMode,scope:this,interval:100})},initFrame:function(){Ext.TaskMgr.stop(this.monitorTask);var b=this.getDoc();this.win=this.getWin();b.open();b.write(this.getDocMarkup());b.close();var a={run:function(){var c=this.getDoc();if(c.body||c.readyState=="complete"){Ext.TaskMgr.stop(a);this.setDesignMode(true);this.initEditor.defer(10,this)}},interval:10,duration:10000,scope:this};Ext.TaskMgr.start(a)},checkDesignMode:function(){if(this.wrap&&this.wrap.dom.offsetWidth){var a=this.getDoc();if(!a){return}if(!a.editorInitialized||this.getDesignMode()!="on"){this.initFrame()}}},setDesignMode:function(b){var a=this.getDoc();if(a){if(this.readOnly){b=false}a.designMode=(/on|true/i).test(String(b).toLowerCase())?"on":"off"}},getDesignMode:function(){var a=this.getDoc();if(!a){return""}return String(a.designMode).toLowerCase()},disableItems:function(a){if(this.fontSelect){this.fontSelect.dom.disabled=a}this.tb.items.each(function(b){if(b.getItemId()!="sourceedit"){b.setDisabled(a)}})},onResize:function(b,c){Ext.form.HtmlEditor.superclass.onResize.apply(this,arguments);if(this.el&&this.iframe){if(Ext.isNumber(b)){var e=b-this.wrap.getFrameWidth("lr");this.el.setWidth(e);this.tb.setWidth(e);this.iframe.style.width=Math.max(e,0)+"px"}if(Ext.isNumber(c)){var a=c-this.wrap.getFrameWidth("tb")-this.tb.el.getHeight();this.el.setHeight(a);this.iframe.style.height=Math.max(a,0)+"px";var d=this.getEditorBody();if(d){d.style.height=Math.max((a-(this.iframePad*2)),0)+"px"}}}},toggleSourceEdit:function(b){var d,a;if(b===undefined){b=!this.sourceEditMode}this.sourceEditMode=b===true;var c=this.tb.getComponent("sourceedit");if(c.pressed!==this.sourceEditMode){c.toggle(this.sourceEditMode);if(!c.xtbHidden){return}}if(this.sourceEditMode){this.previousSize=this.getSize();d=Ext.get(this.iframe).getHeight();this.disableItems(true);this.syncValue();this.iframe.className="x-hidden";this.el.removeClass("x-hidden");this.el.dom.removeAttribute("tabIndex");this.el.focus();this.el.dom.style.height=d+"px"}else{a=parseInt(this.el.dom.style.height,10);if(this.initialized){this.disableItems(this.readOnly)}this.pushValue();this.iframe.className="";this.el.addClass("x-hidden");this.el.dom.setAttribute("tabIndex",-1);this.deferFocus();this.setSize(this.previousSize);delete this.previousSize;this.iframe.style.height=a+"px"}this.fireEvent("editmodechange",this,this.sourceEditMode)},createLink:function(){var a=prompt(this.createLinkText,this.defaultLinkValue);if(a&&a!="http://"){this.relayCmd("createlink",a)}},initEvents:function(){this.originalValue=this.getValue()},markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,setValue:function(a){Ext.form.HtmlEditor.superclass.setValue.call(this,a);this.pushValue();return this},cleanHtml:function(a){a=String(a);if(Ext.isWebKit){a=a.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi,"")}if(a.charCodeAt(0)==this.defaultValue.replace(/\D/g,"")){a=a.substring(1)}return a},syncValue:function(){if(this.initialized){var d=this.getEditorBody();var c=d.innerHTML;if(Ext.isWebKit){var b=d.getAttribute("style");var a=b.match(/text-align:(.*?);/i);if(a&&a[1]){c='<div style="'+a[0]+'">'+c+"</div>"}}c=this.cleanHtml(c);if(this.fireEvent("beforesync",this,c)!==false){this.el.dom.value=c;this.fireEvent("sync",this,c)}}},getValue:function(){this[this.sourceEditMode?"pushValue":"syncValue"]();return Ext.form.HtmlEditor.superclass.getValue.call(this)},pushValue:function(){if(this.initialized){var a=this.el.dom.value;if(!this.activated&&a.length<1){a=this.defaultValue}if(this.fireEvent("beforepush",this,a)!==false){this.getEditorBody().innerHTML=a;if(Ext.isGecko){this.setDesignMode(false);this.setDesignMode(true)}this.fireEvent("push",this,a)}}},deferFocus:function(){this.focus.defer(10,this)},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus()}else{this.el.focus()}},initEditor:function(){try{var c=this.getEditorBody(),a=this.el.getStyles("font-size","font-family","background-image","background-repeat","background-color","color"),g,b;a["background-attachment"]="fixed";c.bgProperties="fixed";Ext.DomHelper.applyStyles(c,a);g=this.getDoc();if(g){try{Ext.EventManager.removeAll(g)}catch(d){}}b=this.onEditorEvent.createDelegate(this);Ext.EventManager.on(g,{mousedown:b,dblclick:b,click:b,keyup:b,buffer:100});if(Ext.isGecko){Ext.EventManager.on(g,"keypress",this.applyCommand,this)}if(Ext.isIE||Ext.isWebKit||Ext.isOpera){Ext.EventManager.on(g,"keydown",this.fixKeys,this)}g.editorInitialized=true;this.initialized=true;this.pushValue();this.setReadOnly(this.readOnly);this.fireEvent("initialize",this)}catch(d){}},beforeDestroy:function(){if(this.monitorTask){Ext.TaskMgr.stop(this.monitorTask)}if(this.rendered){Ext.destroy(this.tb);var b=this.getDoc();if(b){try{Ext.EventManager.removeAll(b);for(var c in b){delete b[c]}}catch(a){}}if(this.wrap){this.wrap.dom.innerHTML="";this.wrap.remove()}}Ext.form.HtmlEditor.superclass.beforeDestroy.call(this)},onFirstFocus:function(){this.activated=true;this.disableItems(this.readOnly);if(Ext.isGecko){this.win.focus();var a=this.win.getSelection();if(!a.focusNode||a.focusNode.nodeType!=3){var b=a.getRangeAt(0);b.selectNodeContents(this.getEditorBody());b.collapse(true);this.deferFocus()}try{this.execCmd("useCSS",true);this.execCmd("styleWithCSS",false)}catch(c){}}this.fireEvent("activate",this)},adjustFont:function(b){var d=b.getItemId()=="increasefontsize"?1:-1,c=this.getDoc(),a=parseInt(c.queryCommandValue("FontSize")||2,10);if((Ext.isSafari&&!Ext.isSafari2)||Ext.isChrome||Ext.isAir){if(a<=10){a=1+d}else{if(a<=13){a=2+d}else{if(a<=16){a=3+d}else{if(a<=18){a=4+d}else{if(a<=24){a=5+d}else{a=6+d}}}}}a=a.constrain(1,6)}else{if(Ext.isSafari){d*=2}a=Math.max(1,a+d)+(Ext.isSafari?"px":0)}this.execCmd("FontSize",a)},onEditorEvent:function(a){this.updateToolbar()},updateToolbar:function(){if(this.readOnly){return}if(!this.activated){this.onFirstFocus();return}var b=this.tb.items.map,c=this.getDoc();if(this.enableFont&&!Ext.isSafari2){var a=(c.queryCommandValue("FontName")||this.defaultFont).toLowerCase();if(a!=this.fontSelect.dom.value){this.fontSelect.dom.value=a}}if(this.enableFormat){b.bold.toggle(c.queryCommandState("bold"));b.italic.toggle(c.queryCommandState("italic"));b.underline.toggle(c.queryCommandState("underline"))}if(this.enableAlignments){b.justifyleft.toggle(c.queryCommandState("justifyleft"));b.justifycenter.toggle(c.queryCommandState("justifycenter"));b.justifyright.toggle(c.queryCommandState("justifyright"))}if(!Ext.isSafari2&&this.enableLists){b.insertorderedlist.toggle(c.queryCommandState("insertorderedlist"));b.insertunorderedlist.toggle(c.queryCommandState("insertunorderedlist"))}Ext.menu.MenuMgr.hideAll();this.syncValue()},relayBtnCmd:function(a){this.relayCmd(a.getItemId())},relayCmd:function(b,a){(function(){this.focus();this.execCmd(b,a);this.updateToolbar()}).defer(10,this)},execCmd:function(b,a){var c=this.getDoc();c.execCommand(b,false,a===undefined?null:a);this.syncValue()},applyCommand:function(b){if(b.ctrlKey){var d=b.getCharCode(),a;if(d>0){d=String.fromCharCode(d);switch(d){case"b":a="bold";break;case"i":a="italic";break;case"u":a="underline";break}if(a){this.win.focus();this.execCmd(a);this.deferFocus();b.preventDefault()}}}},insertAtCursor:function(c){if(!this.activated){return}if(Ext.isIE){this.win.focus();var b=this.getDoc(),a=b.selection.createRange();if(a){a.pasteHTML(c);this.syncValue();this.deferFocus()}}else{this.win.focus();this.execCmd("InsertHTML",c);this.deferFocus()}},fixKeys:function(){if(Ext.isIE){return function(g){var a=g.getKey(),d=this.getDoc(),b;if(a==g.TAB){g.stopEvent();b=d.selection.createRange();if(b){b.collapse(true);b.pasteHTML("&nbsp;&nbsp;&nbsp;&nbsp;");this.deferFocus()}}else{if(a==g.ENTER){b=d.selection.createRange();if(b){var c=b.parentElement();if(!c||c.tagName.toLowerCase()!="li"){g.stopEvent();b.pasteHTML("<br />");b.collapse(false);b.select()}}}}}}else{if(Ext.isOpera){return function(b){var a=b.getKey();if(a==b.TAB){b.stopEvent();this.win.focus();this.execCmd("InsertHTML","&nbsp;&nbsp;&nbsp;&nbsp;");this.deferFocus()}}}else{if(Ext.isWebKit){return function(b){var a=b.getKey();if(a==b.TAB){b.stopEvent();this.execCmd("InsertText","\t");this.deferFocus()}else{if(a==b.ENTER){b.stopEvent();this.execCmd("InsertHtml","<br /><br />");this.deferFocus()}}}}}}}(),getToolbar:function(){return this.tb},buttonTips:{bold:{title:"Bold (Ctrl+B)",text:"Make the selected text bold.",cls:"x-html-editor-tip"},italic:{title:"Italic (Ctrl+I)",text:"Make the selected text italic.",cls:"x-html-editor-tip"},underline:{title:"Underline (Ctrl+U)",text:"Underline the selected text.",cls:"x-html-editor-tip"},increasefontsize:{title:"Grow Text",text:"Increase the font size.",cls:"x-html-editor-tip"},decreasefontsize:{title:"Shrink Text",text:"Decrease the font size.",cls:"x-html-editor-tip"},backcolor:{title:"Text Highlight Color",text:"Change the background color of the selected text.",cls:"x-html-editor-tip"},forecolor:{title:"Font Color",text:"Change the color of the selected text.",cls:"x-html-editor-tip"},justifyleft:{title:"Align Text Left",text:"Align text to the left.",cls:"x-html-editor-tip"},justifycenter:{title:"Center Text",text:"Center text in the editor.",cls:"x-html-editor-tip"},justifyright:{title:"Align Text Right",text:"Align text to the right.",cls:"x-html-editor-tip"},insertunorderedlist:{title:"Bullet List",text:"Start a bulleted list.",cls:"x-html-editor-tip"},insertorderedlist:{title:"Numbered List",text:"Start a numbered list.",cls:"x-html-editor-tip"},createlink:{title:"Hyperlink",text:"Make the selected text a hyperlink.",cls:"x-html-editor-tip"},sourceedit:{title:"Source Edit",text:"Switch to source editing mode.",cls:"x-html-editor-tip"}}});Ext.reg("htmleditor",Ext.form.HtmlEditor);Ext.form.TimeField=Ext.extend(Ext.form.ComboBox,{minValue:undefined,maxValue:undefined,minText:"The time in this field must be equal to or after {0}",maxText:"The time in this field must be equal to or before {0}",invalidText:"{0} is not a valid time",format:"g:i A",altFormats:"g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",increment:15,mode:"local",triggerAction:"all",typeAhead:false,initDate:"1/1/2008",initDateFormat:"j/n/Y",initComponent:function(){if(Ext.isDefined(this.minValue)){this.setMinValue(this.minValue,true)}if(Ext.isDefined(this.maxValue)){this.setMaxValue(this.maxValue,true)}if(!this.store){this.generateStore(true)}Ext.form.TimeField.superclass.initComponent.call(this)},setMinValue:function(b,a){this.setLimit(b,true,a);return this},setMaxValue:function(b,a){this.setLimit(b,false,a);return this},generateStore:function(b){var c=this.minValue||new Date(this.initDate).clearTime(),a=this.maxValue||new Date(this.initDate).clearTime().add("mi",(24*60)-1),d=[];while(c<=a){d.push(c.dateFormat(this.format));c=c.add("mi",this.increment)}this.bindStore(d,b)},setLimit:function(b,g,a){var e;if(Ext.isString(b)){e=this.parseDate(b)}else{if(Ext.isDate(b)){e=b}}if(e){var c=new Date(this.initDate).clearTime();c.setHours(e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds());this[g?"minValue":"maxValue"]=c;if(!a){this.generateStore()}}},getValue:function(){var a=Ext.form.TimeField.superclass.getValue.call(this);return this.formatDate(this.parseDate(a))||""},setValue:function(a){return Ext.form.TimeField.superclass.setValue.call(this,this.formatDate(this.parseDate(a)))},validateValue:Ext.form.DateField.prototype.validateValue,formatDate:Ext.form.DateField.prototype.formatDate,parseDate:function(h){if(!h||Ext.isDate(h)){return h}var j=this.initDate+" ",g=this.initDateFormat+" ",b=Date.parseDate(j+h,g+this.format),c=this.altFormats;if(!b&&c){if(!this.altFormatsArray){this.altFormatsArray=c.split("|")}for(var e=0,d=this.altFormatsArray,a=d.length;e<a&&!b;e++){b=Date.parseDate(j+h,g+d[e])}}return b}});Ext.reg("timefield",Ext.form.TimeField);Ext.form.SliderField=Ext.extend(Ext.form.Field,{useTips:true,tipText:null,actionMode:"wrap",initComponent:function(){var b=Ext.copyTo({id:this.id+"-slider"},this.initialConfig,["vertical","minValue","maxValue","decimalPrecision","keyIncrement","increment","clickToChange","animate"]);if(this.useTips){var a=this.tipText?{getText:this.tipText}:{};b.plugins=[new Ext.slider.Tip(a)]}this.slider=new Ext.Slider(b);Ext.form.SliderField.superclass.initComponent.call(this)},onRender:function(b,a){this.autoCreate={id:this.id,name:this.name,type:"hidden",tag:"input"};Ext.form.SliderField.superclass.onRender.call(this,b,a);this.wrap=this.el.wrap({cls:"x-form-field-wrap"});this.resizeEl=this.positionEl=this.wrap;this.slider.render(this.wrap)},onResize:function(b,c,d,a){Ext.form.SliderField.superclass.onResize.call(this,b,c,d,a);this.slider.setSize(b,c)},initEvents:function(){Ext.form.SliderField.superclass.initEvents.call(this);this.slider.on("change",this.onChange,this)},onChange:function(b,a){this.setValue(a,undefined,true)},onEnable:function(){Ext.form.SliderField.superclass.onEnable.call(this);this.slider.enable()},onDisable:function(){Ext.form.SliderField.superclass.onDisable.call(this);this.slider.disable()},beforeDestroy:function(){Ext.destroy(this.slider);Ext.form.SliderField.superclass.beforeDestroy.call(this)},alignErrorIcon:function(){this.errorIcon.alignTo(this.slider.el,"tl-tr",[2,0])},setMinValue:function(a){this.slider.setMinValue(a);return this},setMaxValue:function(a){this.slider.setMaxValue(a);return this},setValue:function(c,b,a){if(!a){this.slider.setValue(c,b)}return Ext.form.SliderField.superclass.setValue.call(this,this.slider.getValue())},getValue:function(){return this.slider.getValue()}});Ext.reg("sliderfield",Ext.form.SliderField);Ext.form.Label=Ext.extend(Ext.BoxComponent,{onRender:function(b,a){if(!this.el){this.el=document.createElement("label");this.el.id=this.getId();this.el.innerHTML=this.text?Ext.util.Format.htmlEncode(this.text):(this.html||"");if(this.forId){this.el.setAttribute("for",this.forId)}}Ext.form.Label.superclass.onRender.call(this,b,a)},setText:function(a,b){var c=b===false;this[!c?"text":"html"]=a;delete this[c?"text":"html"];if(this.rendered){this.el.dom.innerHTML=b!==false?Ext.util.Format.htmlEncode(a):a}return this}});Ext.reg("label",Ext.form.Label);Ext.form.Action=function(b,a){this.form=b;this.options=a||{}};Ext.form.Action.CLIENT_INVALID="client";Ext.form.Action.SERVER_INVALID="server";Ext.form.Action.CONNECT_FAILURE="connect";Ext.form.Action.LOAD_FAILURE="load";Ext.form.Action.prototype={type:"default",run:function(a){},success:function(a){},handleResponse:function(a){},failure:function(a){this.response=a;this.failureType=Ext.form.Action.CONNECT_FAILURE;this.form.afterAction(this,false)},processResponse:function(a){this.response=a;if(!a.responseText&&!a.responseXML){return true}this.result=this.handleResponse(a);return this.result},decodeResponse:function(a){try{return Ext.decode(a.responseText)}catch(b){return false}},getUrl:function(c){var a=this.options.url||this.form.url||this.form.el.dom.action;if(c){var b=this.getParams();if(b){a=Ext.urlAppend(a,b)}}return a},getMethod:function(){return(this.options.method||this.form.method||this.form.el.dom.method||"POST").toUpperCase()},getParams:function(){var a=this.form.baseParams;var b=this.options.params;if(b){if(typeof b=="object"){b=Ext.urlEncode(Ext.applyIf(b,a))}else{if(typeof b=="string"&&a){b+="&"+Ext.urlEncode(a)}}}else{if(a){b=Ext.urlEncode(a)}}return b},createCallback:function(a){var a=a||{};return{success:this.success,failure:this.failure,scope:this,timeout:(a.timeout*1000)||(this.form.timeout*1000),upload:this.form.fileUpload?this.success:undefined}}};Ext.form.Action.Submit=function(b,a){Ext.form.Action.Submit.superclass.constructor.call(this,b,a)};Ext.extend(Ext.form.Action.Submit,Ext.form.Action,{type:"submit",run:function(){var e=this.options,g=this.getMethod(),d=g=="GET";if(e.clientValidation===false||this.form.isValid()){if(e.submitEmptyText===false){var a=this.form.items,c=[],b=function(h){if(h.el.getValue()==h.emptyText){c.push(h);h.el.dom.value=""}if(h.isComposite&&h.rendered){h.items.each(b)}};a.each(b)}Ext.Ajax.request(Ext.apply(this.createCallback(e),{form:this.form.el.dom,url:this.getUrl(d),method:g,headers:e.headers,params:!d?this.getParams():null,isUpload:this.form.fileUpload}));if(e.submitEmptyText===false){Ext.each(c,function(h){if(h.applyEmptyText){h.applyEmptyText()}})}}else{if(e.clientValidation!==false){this.failureType=Ext.form.Action.CLIENT_INVALID;this.form.afterAction(this,false)}}},success:function(b){var a=this.processResponse(b);if(a===true||a.success){this.form.afterAction(this,true);return}if(a.errors){this.form.markInvalid(a.errors)}this.failureType=Ext.form.Action.SERVER_INVALID;this.form.afterAction(this,false)},handleResponse:function(c){if(this.form.errorReader){var b=this.form.errorReader.read(c);var g=[];if(b.records){for(var d=0,a=b.records.length;d<a;d++){var e=b.records[d];g[d]=e.data}}if(g.length<1){g=null}return{success:b.success,errors:g}}return this.decodeResponse(c)}});Ext.form.Action.Load=function(b,a){Ext.form.Action.Load.superclass.constructor.call(this,b,a);this.reader=this.form.reader};Ext.extend(Ext.form.Action.Load,Ext.form.Action,{type:"load",run:function(){Ext.Ajax.request(Ext.apply(this.createCallback(this.options),{method:this.getMethod(),url:this.getUrl(false),headers:this.options.headers,params:this.getParams()}))},success:function(b){var a=this.processResponse(b);if(a===true||!a.success||!a.data){this.failureType=Ext.form.Action.LOAD_FAILURE;this.form.afterAction(this,false);return}this.form.clearInvalid();this.form.setValues(a.data);this.form.afterAction(this,true)},handleResponse:function(b){if(this.form.reader){var a=this.form.reader.read(b);var c=a.records&&a.records[0]?a.records[0].data:null;return{success:a.success,data:c}}return this.decodeResponse(b)}});Ext.form.Action.DirectLoad=Ext.extend(Ext.form.Action.Load,{constructor:function(b,a){Ext.form.Action.DirectLoad.superclass.constructor.call(this,b,a)},type:"directload",run:function(){var a=this.getParams();a.push(this.success,this);this.form.api.load.apply(window,a)},getParams:function(){var c=[],h={};var e=this.form.baseParams;var g=this.options.params;Ext.apply(h,g,e);var b=this.form.paramOrder;if(b){for(var d=0,a=b.length;d<a;d++){c.push(h[b[d]])}}else{if(this.form.paramsAsHash){c.push(h)}}return c},processResponse:function(a){this.result=a;return a},success:function(a,b){if(b.type==Ext.Direct.exceptions.SERVER){a={}}Ext.form.Action.DirectLoad.superclass.success.call(this,a)}});Ext.form.Action.DirectSubmit=Ext.extend(Ext.form.Action.Submit,{constructor:function(b,a){Ext.form.Action.DirectSubmit.superclass.constructor.call(this,b,a)},type:"directsubmit",run:function(){var a=this.options;if(a.clientValidation===false||this.form.isValid()){this.success.params=this.getParams();this.form.api.submit(this.form.el.dom,this.success,this)}else{if(a.clientValidation!==false){this.failureType=Ext.form.Action.CLIENT_INVALID;this.form.afterAction(this,false)}}},getParams:function(){var c={};var a=this.form.baseParams;var b=this.options.params;Ext.apply(c,b,a);return c},processResponse:function(a){this.result=a;return a},success:function(a,b){if(b.type==Ext.Direct.exceptions.SERVER){a={}}Ext.form.Action.DirectSubmit.superclass.success.call(this,a)}});Ext.form.Action.ACTION_TYPES={load:Ext.form.Action.Load,submit:Ext.form.Action.Submit,directload:Ext.form.Action.DirectLoad,directsubmit:Ext.form.Action.DirectSubmit};Ext.form.VTypes=function(){var c=/^[a-zA-Z_]+$/,d=/^[a-zA-Z0-9_]+$/,b=/^(\w+)([\-+.\'][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,a=/(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;return{email:function(e){return b.test(e)},emailText:'This field should be an e-mail address in the format "user@example.com"',emailMask:/[a-z0-9_\.\-\+\'@]/i,url:function(e){return a.test(e)},urlText:'This field should be a URL in the format "http://www.example.com"',alpha:function(e){return c.test(e)},alphaText:"This field should only contain letters and _",alphaMask:/[a-z_]/i,alphanum:function(e){return d.test(e)},alphanumText:"This field should only contain letters, numbers and _",alphanumMask:/[a-z0-9_]/i}}();Ext.grid.GridPanel=Ext.extend(Ext.Panel,{autoExpandColumn:false,autoExpandMax:1000,autoExpandMin:50,columnLines:false,ddText:"{0} selected row{1}",deferRowRender:true,enableColumnHide:true,enableColumnMove:true,enableDragDrop:false,enableHdMenu:true,loadMask:false,minColumnWidth:25,stripeRows:false,trackMouseOver:true,stateEvents:["columnmove","columnresize","sortchange","groupchange"],view:null,bubbleEvents:[],rendered:false,viewReady:false,initComponent:function(){Ext.grid.GridPanel.superclass.initComponent.call(this);if(this.columnLines){this.cls=(this.cls||"")+" x-grid-with-col-lines"}this.autoScroll=false;this.autoWidth=false;if(Ext.isArray(this.columns)){this.colModel=new Ext.grid.ColumnModel(this.columns);delete this.columns}if(this.ds){this.store=this.ds;delete this.ds}if(this.cm){this.colModel=this.cm;delete this.cm}if(this.sm){this.selModel=this.sm;delete this.sm}this.store=Ext.StoreMgr.lookup(this.store);this.addEvents("click","dblclick","contextmenu","mousedown","mouseup","mouseover","mouseout","keypress","keydown","cellmousedown","rowmousedown","headermousedown","groupmousedown","rowbodymousedown","containermousedown","cellclick","celldblclick","rowclick","rowdblclick","headerclick","headerdblclick","groupclick","groupdblclick","containerclick","containerdblclick","rowbodyclick","rowbodydblclick","rowcontextmenu","cellcontextmenu","headercontextmenu","groupcontextmenu","containercontextmenu","rowbodycontextmenu","bodyscroll","columnresize","columnmove","sortchange","groupchange","reconfigure","viewready")},onRender:function(d,a){Ext.grid.GridPanel.superclass.onRender.apply(this,arguments);var e=this.getGridEl();this.el.addClass("x-grid-panel");this.mon(e,{scope:this,mousedown:this.onMouseDown,click:this.onClick,dblclick:this.onDblClick,contextmenu:this.onContextMenu});this.relayEvents(e,["mousedown","mouseup","mouseover","mouseout","keypress","keydown"]);var b=this.getView();b.init(this);b.render();this.getSelectionModel().init(this)},initEvents:function(){Ext.grid.GridPanel.superclass.initEvents.call(this);if(this.loadMask){this.loadMask=new Ext.LoadMask(this.bwrap,Ext.apply({store:this.store},this.loadMask))}},initStateEvents:function(){Ext.grid.GridPanel.superclass.initStateEvents.call(this);this.mon(this.colModel,"hiddenchange",this.saveState,this,{delay:100})},applyState:function(a){var k=this.colModel,g=a.columns,j=this.store,m,h,l;if(g){for(var d=0,e=g.length;d<e;d++){m=g[d];h=k.getColumnById(m.id);if(h){l=k.getIndexById(m.id);k.setState(l,{hidden:m.hidden,width:m.width,sortable:m.sortable});if(l!=d){k.moveColumn(l,d)}}}}if(j){m=a.sort;if(m){j[j.remoteSort?"setDefaultSort":"sort"](m.field,m.direction)}m=a.group;if(j.groupBy){if(m){j.groupBy(m)}else{j.clearGrouping()}}}var b=Ext.apply({},a);delete b.columns;delete b.sort;Ext.grid.GridPanel.superclass.applyState.call(this,b)},getState:function(){var g={columns:[]},b=this.store,e,a;for(var d=0,h;(h=this.colModel.config[d]);d++){g.columns[d]={id:h.id,width:h.width};if(h.hidden){g.columns[d].hidden=true}if(h.sortable){g.columns[d].sortable=true}}if(b){e=b.getSortState();if(e){g.sort=e}if(b.getGroupState){a=b.getGroupState();if(a){g.group=a}}}return g},afterRender:function(){Ext.grid.GridPanel.superclass.afterRender.call(this);var a=this.view;this.on("bodyresize",a.layout,a);a.layout(true);if(this.deferRowRender){if(!this.deferRowRenderTask){this.deferRowRenderTask=new Ext.util.DelayedTask(a.afterRender,this.view)}this.deferRowRenderTask.delay(10)}else{a.afterRender()}this.viewReady=true},reconfigure:function(a,b){var c=this.rendered;if(c){if(this.loadMask){this.loadMask.destroy();this.loadMask=new Ext.LoadMask(this.bwrap,Ext.apply({},{store:a},this.initialConfig.loadMask))}}if(this.view){this.view.initData(a,b)}this.store=a;this.colModel=b;if(c){this.view.refresh(true)}this.fireEvent("reconfigure",this,a,b)},onDestroy:function(){if(this.deferRowRenderTask&&this.deferRowRenderTask.cancel){this.deferRowRenderTask.cancel()}if(this.rendered){Ext.destroy(this.view,this.loadMask)}else{if(this.store&&this.store.autoDestroy){this.store.destroy()}}Ext.destroy(this.colModel,this.selModel);this.store=this.selModel=this.colModel=this.view=this.loadMask=null;Ext.grid.GridPanel.superclass.onDestroy.call(this)},processEvent:function(a,b){this.view.processEvent(a,b)},onClick:function(a){this.processEvent("click",a)},onMouseDown:function(a){this.processEvent("mousedown",a)},onContextMenu:function(b,a){this.processEvent("contextmenu",b)},onDblClick:function(a){this.processEvent("dblclick",a)},walkCells:function(k,c,b,e,j){var i=this.colModel,g=i.getColumnCount(),a=this.store,h=a.getCount(),d=true;if(b<0){if(c<0){k--;d=false}while(k>=0){if(!d){c=g-1}d=false;while(c>=0){if(e.call(j||this,k,c,i)===true){return[k,c]}c--}k--}}else{if(c>=g){k++;d=false}while(k<h){if(!d){c=0}d=false;while(c<g){if(e.call(j||this,k,c,i)===true){return[k,c]}c++}k++}}return null},getGridEl:function(){return this.body},stopEditing:Ext.emptyFn,getSelectionModel:function(){if(!this.selModel){this.selModel=new Ext.grid.RowSelectionModel(this.disableSelection?{selectRow:Ext.emptyFn}:null)}return this.selModel},getStore:function(){return this.store},getColumnModel:function(){return this.colModel},getView:function(){if(!this.view){this.view=new Ext.grid.GridView(this.viewConfig)}return this.view},getDragDropText:function(){var a=this.selModel.getCount();return String.format(this.ddText,a,a==1?"":"s")}});Ext.reg("grid",Ext.grid.GridPanel);Ext.grid.PivotGrid=Ext.extend(Ext.grid.GridPanel,{aggregator:"sum",renderer:undefined,initComponent:function(){Ext.grid.PivotGrid.superclass.initComponent.apply(this,arguments);this.initAxes();this.enableColumnResize=false;this.viewConfig=Ext.apply(this.viewConfig||{},{forceFit:true});this.colModel=new Ext.grid.ColumnModel({})},getAggregator:function(){if(typeof this.aggregator=="string"){return Ext.grid.PivotAggregatorMgr.types[this.aggregator]}else{return this.aggregator}},setAggregator:function(a){this.aggregator=a},setMeasure:function(a){this.measure=a},setLeftAxis:function(b,a){this.leftAxis=b;if(a){this.view.refresh()}},setTopAxis:function(b,a){this.topAxis=b;if(a){this.view.refresh()}},initAxes:function(){var a=Ext.grid.PivotAxis;if(!(this.leftAxis instanceof a)){this.setLeftAxis(new a({orientation:"vertical",dimensions:this.leftAxis||[],store:this.store}))}if(!(this.topAxis instanceof a)){this.setTopAxis(new a({orientation:"horizontal",dimensions:this.topAxis||[],store:this.store}))}},extractData:function(){var c=this.store.data.items,s=c.length,q=[],h,g,e,d;if(s==0){return[]}var l=this.leftAxis.getTuples(),o=l.length,m=this.topAxis.getTuples(),a=m.length,b=this.getAggregator();for(g=0;g<s;g++){h=c[g];for(e=0;e<o;e++){q[e]=q[e]||[];if(l[e].matcher(h)===true){for(d=0;d<a;d++){q[e][d]=q[e][d]||[];if(m[d].matcher(h)){q[e][d].push(h)}}}}}var n=q.length,p,r;for(g=0;g<n;g++){r=q[g];p=r.length;for(e=0;e<p;e++){q[g][e]=b(q[g][e],this.measure)}}return q},getView:function(){if(!this.view){this.view=new Ext.grid.PivotGridView(this.viewConfig)}return this.view}});Ext.reg("pivotgrid",Ext.grid.PivotGrid);Ext.grid.PivotAggregatorMgr=new Ext.AbstractManager();Ext.grid.PivotAggregatorMgr.registerType("sum",function(a,c){var e=a.length,d=0,b;for(b=0;b<e;b++){d+=a[b].get(c)}return d});Ext.grid.PivotAggregatorMgr.registerType("avg",function(a,c){var e=a.length,d=0,b;for(b=0;b<e;b++){d+=a[b].get(c)}return(d/e)||"n/a"});Ext.grid.PivotAggregatorMgr.registerType("min",function(a,c){var e=[],d=a.length,b;for(b=0;b<d;b++){e.push(a[b].get(c))}return Math.min.apply(this,e)||"n/a"});Ext.grid.PivotAggregatorMgr.registerType("max",function(a,c){var e=[],d=a.length,b;for(b=0;b<d;b++){e.push(a[b].get(c))}return Math.max.apply(this,e)||"n/a"});Ext.grid.PivotAggregatorMgr.registerType("count",function(a,b){return a.length});Ext.grid.GridView=Ext.extend(Ext.util.Observable,{deferEmptyText:true,scrollOffset:undefined,autoFill:false,forceFit:false,sortClasses:["sort-asc","sort-desc"],sortAscText:"Sort Ascending",sortDescText:"Sort Descending",columnsText:"Columns",selectedRowClass:"x-grid3-row-selected",borderWidth:2,tdClass:"x-grid3-cell",hdCls:"x-grid3-hd",markDirty:true,cellSelectorDepth:4,rowSelectorDepth:10,rowBodySelectorDepth:10,cellSelector:"td.x-grid3-cell",rowSelector:"div.x-grid3-row",rowBodySelector:"div.x-grid3-row-body",firstRowCls:"x-grid3-row-first",lastRowCls:"x-grid3-row-last",rowClsRe:/(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,headerMenuOpenCls:"x-grid3-hd-menu-open",rowOverCls:"x-grid3-row-over",constructor:function(a){Ext.apply(this,a);this.addEvents("beforerowremoved","beforerowsinserted","beforerefresh","rowremoved","rowsinserted","rowupdated","refresh");Ext.grid.GridView.superclass.constructor.call(this)},masterTpl:new Ext.Template('<div class="x-grid3" hidefocus="true">','<div class="x-grid3-viewport">','<div class="x-grid3-header">','<div class="x-grid3-header-inner">','<div class="x-grid3-header-offset" style="{ostyle}">{header}</div>',"</div>",'<div class="x-clear"></div>',"</div>",'<div class="x-grid3-scroller">','<div class="x-grid3-body" style="{bstyle}">{body}</div>','<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',"</div>","</div>",'<div class="x-grid3-resize-marker">&#160;</div>','<div class="x-grid3-resize-proxy">&#160;</div>',"</div>"),headerTpl:new Ext.Template('<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',"<thead>",'<tr class="x-grid3-hd-row">{cells}</tr>',"</thead>","</table>"),bodyTpl:new Ext.Template("{rows}"),cellTpl:new Ext.Template('<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>','<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',"</td>"),initTemplates:function(){var c=this.templates||{},d,b,g=new Ext.Template('<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}">','<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">',this.grid.enableHdMenu?'<a class="x-grid3-hd-btn" href="#"></a>':"","{value}",'<img alt="" class="x-grid3-sort-icon" src="',Ext.BLANK_IMAGE_URL,'" />',"</div>","</td>"),a=['<tr class="x-grid3-row-body-tr" style="{bodyStyle}">','<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">','<div class="x-grid3-row-body">{body}</div>',"</td>","</tr>"].join(""),e=['<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',"<tbody>","<tr>{cells}</tr>",this.enableRowBody?a:"","</tbody>","</table>"].join("");Ext.applyIf(c,{hcell:g,cell:this.cellTpl,body:this.bodyTpl,header:this.headerTpl,master:this.masterTpl,row:new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}">'+e+"</div>"),rowInner:new Ext.Template(e)});for(b in c){d=c[b];if(d&&Ext.isFunction(d.compile)&&!d.compiled){d.disableFormats=true;d.compile()}}this.templates=c;this.colRe=new RegExp("x-grid3-td-([^\\s]+)","")},fly:function(a){if(!this._flyweight){this._flyweight=new Ext.Element.Flyweight(document.body)}this._flyweight.dom=a;return this._flyweight},getEditorParent:function(){return this.scroller.dom},initElements:function(){var b=Ext.Element,d=Ext.get(this.grid.getGridEl().dom.firstChild),e=new b(d.child("div.x-grid3-viewport")),c=new b(e.child("div.x-grid3-header")),a=new b(e.child("div.x-grid3-scroller"));if(this.grid.hideHeaders){c.setDisplayed(false)}if(this.forceFit){a.setStyle("overflow-x","hidden")}Ext.apply(this,{el:d,mainWrap:e,scroller:a,mainHd:c,innerHd:c.child("div.x-grid3-header-inner").dom,mainBody:new b(b.fly(a).child("div.x-grid3-body")),focusEl:new b(b.fly(a).child("a")),resizeMarker:new b(d.child("div.x-grid3-resize-marker")),resizeProxy:new b(d.child("div.x-grid3-resize-proxy"))});this.focusEl.swallowEvent("click",true)},getRows:function(){return this.hasRows()?this.mainBody.dom.childNodes:[]},findCell:function(a){if(!a){return false}return this.fly(a).findParent(this.cellSelector,this.cellSelectorDepth)},findCellIndex:function(d,c){var b=this.findCell(d),a;if(b){a=this.fly(b).hasClass(c);if(!c||a){return this.getCellIndex(b)}}return false},getCellIndex:function(b){if(b){var a=b.className.match(this.colRe);if(a&&a[1]){return this.cm.getIndexById(a[1])}}return false},findHeaderCell:function(b){var a=this.findCell(b);return a&&this.fly(a).hasClass(this.hdCls)?a:null},findHeaderIndex:function(a){return this.findCellIndex(a,this.hdCls)},findRow:function(a){if(!a){return false}return this.fly(a).findParent(this.rowSelector,this.rowSelectorDepth)},findRowIndex:function(a){var b=this.findRow(a);return b?b.rowIndex:false},findRowBody:function(a){if(!a){return false}return this.fly(a).findParent(this.rowBodySelector,this.rowBodySelectorDepth)},getRow:function(a){return this.getRows()[a]},getCell:function(b,a){return Ext.fly(this.getRow(b)).query(this.cellSelector)[a]},getHeaderCell:function(a){return this.mainHd.dom.getElementsByTagName("td")[a]},addRowClass:function(b,a){var c=this.getRow(b);if(c){this.fly(c).addClass(a)}},removeRowClass:function(c,a){var b=this.getRow(c);if(b){this.fly(b).removeClass(a)}},removeRow:function(a){Ext.removeNode(this.getRow(a));this.syncFocusEl(a)},removeRows:function(c,a){var b=this.mainBody.dom,d;for(d=c;d<=a;d++){Ext.removeNode(b.childNodes[c])}this.syncFocusEl(c)},getScrollState:function(){var a=this.scroller.dom;return{left:a.scrollLeft,top:a.scrollTop}},restoreScroll:function(a){var b=this.scroller.dom;b.scrollLeft=a.left;b.scrollTop=a.top},scrollToTop:function(){var a=this.scroller.dom;a.scrollTop=0;a.scrollLeft=0},syncScroll:function(){this.syncHeaderScroll();var a=this.scroller.dom;this.grid.fireEvent("bodyscroll",a.scrollLeft,a.scrollTop)},syncHeaderScroll:function(){var a=this.innerHd,b=this.scroller.dom.scrollLeft;a.scrollLeft=b;a.scrollLeft=b},updateSortIcon:function(d,c){var a=this.sortClasses,b=a[c=="DESC"?1:0],e=this.mainHd.select("td").removeClass(a);e.item(d).addClass(b)},updateAllColumnWidths:function(){var e=this.getTotalWidth(),k=this.cm.getColumnCount(),m=this.getRows(),g=m.length,b=[],l,a,h,d,c;for(d=0;d<k;d++){b[d]=this.getColumnWidth(d);this.getHeaderCell(d).style.width=b[d]}this.updateHeaderWidth();for(d=0;d<g;d++){l=m[d];l.style.width=e;a=l.firstChild;if(a){a.style.width=e;h=a.rows[0];for(c=0;c<k;c++){h.childNodes[c].style.width=b[c]}}}this.onAllColumnWidthsUpdated(b,e)},updateColumnWidth:function(d,b){var c=this.getColumnWidth(d),j=this.getTotalWidth(),h=this.getHeaderCell(d),a=this.getRows(),e=a.length,l,g,k;this.updateHeaderWidth();h.style.width=c;for(g=0;g<e;g++){l=a[g];k=l.firstChild;l.style.width=j;if(k){k.style.width=j;k.rows[0].childNodes[d].style.width=c}}this.onColumnWidthUpdated(d,c,j)},updateColumnHidden:function(b,j){var h=this.getTotalWidth(),k=j?"none":"",g=this.getHeaderCell(b),a=this.getRows(),d=a.length,l,c,e;this.updateHeaderWidth();g.style.display=k;for(e=0;e<d;e++){l=a[e];l.style.width=h;c=l.firstChild;if(c){c.style.width=h;c.rows[0].childNodes[b].style.display=k}}this.onColumnHiddenUpdated(b,j,h);delete this.lastViewWidth;this.layout()},doRender:function(d,v,m,a,r,t){var h=this.templates,c=h.cell,y=h.row,o=r-1,b="width:"+this.getTotalWidth()+";",k=[],l=[],n={tstyle:b},q={},w=v.length,x,g,e,u,s,p;for(s=0;s<w;s++){e=v[s];l=[];p=s+a;for(u=0;u<r;u++){g=d[u];q.id=g.id;q.css=u===0?"x-grid3-cell-first ":(u==o?"x-grid3-cell-last ":"");q.attr=q.cellAttr="";q.style=g.style;q.value=g.renderer.call(g.scope,e.data[g.name],q,e,p,u,m);if(Ext.isEmpty(q.value)){q.value="&#160;"}if(this.markDirty&&e.dirty&&typeof e.modified[g.name]!="undefined"){q.css+=" x-grid3-dirty-cell"}l[l.length]=c.apply(q)}x=[];if(t&&((p+1)%2===0)){x[0]="x-grid3-row-alt"}if(e.dirty){x[1]=" x-grid3-dirty-row"}n.cols=r;if(this.getRowClass){x[2]=this.getRowClass(e,p,n,m)}n.alt=x.join(" ");n.cells=l.join("");k[k.length]=y.apply(n)}return k.join("")},processRows:function(a,g){if(!this.ds||this.ds.getCount()<1){return}var d=this.getRows(),c=d.length,e,b;g=g||!this.grid.stripeRows;a=a||0;for(b=0;b<c;b++){e=d[b];if(e){e.rowIndex=b;if(!g){e.className=e.className.replace(this.rowClsRe," ");if((b+1)%2===0){e.className+=" x-grid3-row-alt"}}}}if(a===0){Ext.fly(d[0]).addClass(this.firstRowCls)}Ext.fly(d[c-1]).addClass(this.lastRowCls)},afterRender:function(){if(!this.ds||!this.cm){return}this.mainBody.dom.innerHTML=this.renderBody()||"&#160;";this.processRows(0,true);if(this.deferEmptyText!==true){this.applyEmptyText()}this.grid.fireEvent("viewready",this.grid)},afterRenderUI:function(){var a=this.grid;this.initElements();Ext.fly(this.innerHd).on("click",this.handleHdDown,this);this.mainHd.on({scope:this,mouseover:this.handleHdOver,mouseout:this.handleHdOut,mousemove:this.handleHdMove});this.scroller.on("scroll",this.syncScroll,this);if(a.enableColumnResize!==false){this.splitZone=new Ext.grid.GridView.SplitDragZone(a,this.mainHd.dom)}if(a.enableColumnMove){this.columnDrag=new Ext.grid.GridView.ColumnDragZone(a,this.innerHd);this.columnDrop=new Ext.grid.HeaderDropZone(a,this.mainHd.dom)}if(a.enableHdMenu!==false){this.hmenu=new Ext.menu.Menu({id:a.id+"-hctx"});this.hmenu.add({itemId:"asc",text:this.sortAscText,cls:"xg-hmenu-sort-asc"},{itemId:"desc",text:this.sortDescText,cls:"xg-hmenu-sort-desc"});if(a.enableColumnHide!==false){this.colMenu=new Ext.menu.Menu({id:a.id+"-hcols-menu"});this.colMenu.on({scope:this,beforeshow:this.beforeColMenuShow,itemclick:this.handleHdMenuClick});this.hmenu.add("-",{itemId:"columns",hideOnClick:false,text:this.columnsText,menu:this.colMenu,iconCls:"x-cols-icon"})}this.hmenu.on("itemclick",this.handleHdMenuClick,this)}if(a.trackMouseOver){this.mainBody.on({scope:this,mouseover:this.onRowOver,mouseout:this.onRowOut})}if(a.enableDragDrop||a.enableDrag){this.dragZone=new Ext.grid.GridDragZone(a,{ddGroup:a.ddGroup||"GridDD"})}this.updateHeaderSortState()},renderUI:function(){var a=this.templates;return a.master.apply({body:a.body.apply({rows:"&#160;"}),header:this.renderHeaders(),ostyle:"width:"+this.getOffsetWidth()+";",bstyle:"width:"+this.getTotalWidth()+";"})},processEvent:function(b,h){var i=h.getTarget(),a=this.grid,d=this.findHeaderIndex(i),k,j,c,g;a.fireEvent(b,h);if(d!==false){a.fireEvent("header"+b,a,d,h)}else{k=this.findRowIndex(i);if(k!==false){j=this.findCellIndex(i);if(j!==false){c=a.colModel.getColumnAt(j);if(a.fireEvent("cell"+b,a,k,j,h)!==false){if(!c||(c.processEvent&&(c.processEvent(b,h,a,k,j)!==false))){a.fireEvent("row"+b,a,k,h)}}}else{if(a.fireEvent("row"+b,a,k,h)!==false){(g=this.findRowBody(i))&&a.fireEvent("rowbody"+b,a,k,h)}}}else{a.fireEvent("container"+b,a,h)}}},layout:function(j){if(!this.mainBody){return}var a=this.grid,d=a.getGridEl(),c=d.getSize(true),i=c.width,b=c.height,h=this.scroller,g,e,k;if(i<20||b<20){return}if(a.autoHeight){g=h.dom.style;g.overflow="visible";if(Ext.isWebKit){g.position="static"}}else{this.el.setSize(i,b);e=this.mainHd.getHeight();k=b-e;h.setSize(i,k);if(this.innerHd){this.innerHd.style.width=(i)+"px"}}if(this.forceFit||(j===true&&this.autoFill)){if(this.lastViewWidth!=i){this.fitColumns(false,false);this.lastViewWidth=i}}else{this.autoExpand();this.syncHeaderScroll()}this.onLayout(i,k)},onLayout:function(a,b){},onColumnWidthUpdated:function(c,a,b){},onAllColumnWidthsUpdated:function(a,b){},onColumnHiddenUpdated:function(b,c,a){},updateColumnText:function(a,b){},afterMove:function(a){},init:function(a){this.grid=a;this.initTemplates();this.initData(a.store,a.colModel);this.initUI(a)},getColumnId:function(a){return this.cm.getColumnId(a)},getOffsetWidth:function(){return(this.cm.getTotalWidth()+this.getScrollOffset())+"px"},getScrollOffset:function(){return Ext.num(this.scrollOffset,Ext.getScrollBarWidth())},renderHeaders:function(){var e=this.cm,g=this.templates,a=g.hcell,d={},h=e.getColumnCount(),j=h-1,k=[],c,b;for(c=0;c<h;c++){if(c==0){b="x-grid3-cell-first "}else{b=c==j?"x-grid3-cell-last ":""}d={id:e.getColumnId(c),value:e.getColumnHeader(c)||"",style:this.getColumnStyle(c,true),css:b,tooltip:this.getColumnTooltip(c)};if(e.config[c].align=="right"){d.istyle="padding-right: 16px;"}else{delete d.istyle}k[c]=a.apply(d)}return g.header.apply({cells:k.join(""),tstyle:String.format("width: {0};",this.getTotalWidth())})},getColumnTooltip:function(a){var b=this.cm.getColumnTooltip(a);if(b){if(Ext.QuickTips.isEnabled()){return'ext:qtip="'+b+'"'}else{return'title="'+b+'"'}}return""},beforeUpdate:function(){this.grid.stopEditing(true)},updateHeaders:function(){this.innerHd.firstChild.innerHTML=this.renderHeaders();this.updateHeaderWidth(false)},updateHeaderWidth:function(c){var b=this.innerHd.firstChild,a=this.getTotalWidth();b.style.width=this.getOffsetWidth();b.firstChild.style.width=a;if(c!==false){this.mainBody.dom.style.width=a}},focusRow:function(a){this.focusCell(a,0,false)},focusCell:function(d,b,c){this.syncFocusEl(this.ensureVisible(d,b,c));var a=this.focusEl;if(Ext.isGecko){a.focus()}else{a.focus.defer(1,a)}},resolveCell:function(h,d,g){if(!Ext.isNumber(h)){h=h.rowIndex}if(!this.ds){return null}if(h<0||h>=this.ds.getCount()){return null}d=(d!==undefined?d:0);var c=this.getRow(h),b=this.cm,e=b.getColumnCount(),a;if(!(g===false&&d===0)){while(d<e&&b.isHidden(d)){d++}a=this.getCell(h,d)}return{row:c,cell:a}},getResolvedXY:function(b){if(!b){return null}var a=b.cell,c=b.row;if(a){return Ext.fly(a).getXY()}else{return[this.el.getX(),Ext.fly(c).getY()]}},syncFocusEl:function(d,a,c){var b=d;if(!Ext.isArray(b)){d=Math.min(d,Math.max(0,this.getRows().length-1));if(isNaN(d)){return}b=this.getResolvedXY(this.resolveCell(d,a,c))}this.focusEl.setXY(b||this.scroller.getXY())},ensureVisible:function(t,g,e){var r=this.resolveCell(t,g,e);if(!r||!r.row){return null}var k=r.row,h=r.cell,n=this.scroller.dom,d=k,s=0,o=this.el.dom;while(d&&d!=o){s+=d.offsetTop;d=d.offsetParent}s-=this.mainHd.dom.offsetHeight;o=parseInt(n.scrollTop,10);var q=s+k.offsetHeight,a=n.clientHeight,m=o+a;if(s<o){n.scrollTop=s}else{if(q>m){n.scrollTop=q-a}}if(e!==false){var l=parseInt(h.offsetLeft,10),j=l+h.offsetWidth,i=parseInt(n.scrollLeft,10),b=i+n.clientWidth;if(l<i){n.scrollLeft=l}else{if(j>b){n.scrollLeft=j-n.clientWidth}}}return this.getResolvedXY(r)},insertRows:function(a,i,e,h){var d=a.getCount()-1;if(!h&&i===0&&e>=d){this.fireEvent("beforerowsinserted",this,i,e);this.refresh();this.fireEvent("rowsinserted",this,i,e)}else{if(!h){this.fireEvent("beforerowsinserted",this,i,e)}var b=this.renderRows(i,e),g=this.getRow(i);if(g){if(i===0){Ext.fly(this.getRow(0)).removeClass(this.firstRowCls)}Ext.DomHelper.insertHtml("beforeBegin",g,b)}else{var c=this.getRow(d-1);if(c){Ext.fly(c).removeClass(this.lastRowCls)}Ext.DomHelper.insertHtml("beforeEnd",this.mainBody.dom,b)}if(!h){this.processRows(i);this.fireEvent("rowsinserted",this,i,e)}else{if(i===0||i>=d){Ext.fly(this.getRow(i)).addClass(i===0?this.firstRowCls:this.lastRowCls)}}}this.syncFocusEl(i)},deleteRows:function(a,c,b){if(a.getRowCount()<1){this.refresh()}else{this.fireEvent("beforerowsdeleted",this,c,b);this.removeRows(c,b);this.processRows(c);this.fireEvent("rowsdeleted",this,c,b)}},getColumnStyle:function(b,d){var a=this.cm,g=a.config,c=d?"":g[b].css||"",e=g[b].align;c+=String.format("width: {0};",this.getColumnWidth(b));if(a.isHidden(b)){c+="display: none; "}if(e){c+=String.format("text-align: {0};",e)}return c},getColumnWidth:function(b){var c=this.cm.getColumnWidth(b),a=this.borderWidth;if(Ext.isNumber(c)){if(Ext.isBorderBox||(Ext.isWebKit&&!Ext.isSafari2)){return c+"px"}else{return Math.max(c-a,0)+"px"}}else{return c}},getTotalWidth:function(){return this.cm.getTotalWidth()+"px"},fitColumns:function(g,j,h){var a=this.grid,l=this.cm,s=l.getTotalWidth(false),q=this.getGridInnerWidth(),r=q-s,c=[],o=0,n=0,u,d,p;if(q<20||r===0){return false}var e=l.getColumnCount(true),m=l.getColumnCount(false),b=e-(Ext.isNumber(h)?1:0);if(b===0){b=1;h=undefined}for(p=0;p<m;p++){if(!l.isFixed(p)&&p!==h){u=l.getColumnWidth(p);c.push(p,u);if(!l.isHidden(p)){o=p;n+=u}}}d=(q-l.getTotalWidth())/n;while(c.length){u=c.pop();p=c.pop();l.setColumnWidth(p,Math.max(a.minColumnWidth,Math.floor(u+u*d)),true)}s=l.getTotalWidth(false);if(s>q){var t=(b==e)?o:h,k=Math.max(1,l.getColumnWidth(t)-(s-q));l.setColumnWidth(t,k,true)}if(g!==true){this.updateAllColumnWidths()}return true},autoExpand:function(k){var a=this.grid,i=this.cm,e=this.getGridInnerWidth(),c=i.getTotalWidth(false),g=a.autoExpandColumn;if(!this.userResized&&g){if(e!=c){var j=i.getIndexById(g),b=i.getColumnWidth(j),h=e-c+b,d=Math.min(Math.max(h,a.autoExpandMin),a.autoExpandMax);if(b!=d){i.setColumnWidth(j,d,true);if(k!==true){this.updateColumnWidth(j,d)}}}}},getGridInnerWidth:function(){return this.grid.getGridEl().getWidth(true)-this.getScrollOffset()},getColumnData:function(){var e=[],c=this.cm,g=c.getColumnCount(),a=this.ds.fields,d,b;for(d=0;d<g;d++){b=c.getDataIndex(d);e[d]={name:Ext.isDefined(b)?b:(a.get(d)?a.get(d).name:undefined),renderer:c.getRenderer(d),scope:c.getRendererScope(d),id:c.getColumnId(d),style:this.getColumnStyle(d)}}return e},renderRows:function(i,c){var a=this.grid,g=a.store,j=a.stripeRows,e=a.colModel,h=e.getColumnCount(),d=g.getCount(),b;if(d<1){return""}i=i||0;c=Ext.isDefined(c)?c:d-1;b=g.getRange(i,c);return this.doRender(this.getColumnData(),b,g,i,h,j)},renderBody:function(){var a=this.renderRows()||"&#160;";return this.templates.body.apply({rows:a})},refreshRow:function(g){var l=this.ds,m=this.cm.getColumnCount(),c=this.getColumnData(),n=m-1,p=["x-grid3-row"],e={tstyle:String.format("width: {0};",this.getTotalWidth())},a=[],k=this.templates.cell,j,q,b,o,h,d;if(Ext.isNumber(g)){j=g;g=l.getAt(j)}else{j=l.indexOf(g)}if(!g||j<0){return}for(d=0;d<m;d++){b=c[d];if(d==0){h="x-grid3-cell-first"}else{h=(d==n)?"x-grid3-cell-last ":""}o={id:b.id,style:b.style,css:h,attr:"",cellAttr:""};o.value=b.renderer.call(b.scope,g.data[b.name],o,g,j,d,l);if(Ext.isEmpty(o.value)){o.value="&#160;"}if(this.markDirty&&g.dirty&&typeof g.modified[b.name]!="undefined"){o.css+=" x-grid3-dirty-cell"}a[d]=k.apply(o)}q=this.getRow(j);q.className="";if(this.grid.stripeRows&&((j+1)%2===0)){p.push("x-grid3-row-alt")}if(this.getRowClass){e.cols=m;p.push(this.getRowClass(g,j,e,l))}this.fly(q).addClass(p).setStyle(e.tstyle);e.cells=a.join("");q.innerHTML=this.templates.rowInner.apply(e);this.fireEvent("rowupdated",this,j,g)},refresh:function(b){this.fireEvent("beforerefresh",this);this.grid.stopEditing(true);var a=this.renderBody();this.mainBody.update(a).setWidth(this.getTotalWidth());if(b===true){this.updateHeaders();this.updateHeaderSortState()}this.processRows(0,true);this.layout();this.applyEmptyText();this.fireEvent("refresh",this)},applyEmptyText:function(){if(this.emptyText&&!this.hasRows()){this.mainBody.update('<div class="x-grid-empty">'+this.emptyText+"</div>")}},updateHeaderSortState:function(){var b=this.ds.getSortState();if(!b){return}if(!this.sortState||(this.sortState.field!=b.field||this.sortState.direction!=b.direction)){this.grid.fireEvent("sortchange",this.grid,b)}this.sortState=b;var c=this.cm.findColumnIndex(b.field);if(c!=-1){var a=b.direction;this.updateSortIcon(c,a)}},clearHeaderSortState:function(){if(!this.sortState){return}this.grid.fireEvent("sortchange",this.grid,null);this.mainHd.select("td").removeClass(this.sortClasses);delete this.sortState},destroy:function(){var j=this,a=j.grid,d=a.getGridEl(),i=j.dragZone,g=j.splitZone,h=j.columnDrag,e=j.columnDrop,k=j.scrollToTopTask,c,b;if(k&&k.cancel){k.cancel()}Ext.destroyMembers(j,"colMenu","hmenu");j.initData(null,null);j.purgeListeners();Ext.fly(j.innerHd).un("click",j.handleHdDown,j);if(a.enableColumnMove){c=h.dragData;b=h.proxy;Ext.destroy(h.el,b.ghost,b.el,e.el,e.proxyTop,e.proxyBottom,c.ddel,c.header);if(b.anim){Ext.destroy(b.anim)}delete b.ghost;delete c.ddel;delete c.header;h.destroy();delete Ext.dd.DDM.locationCache[h.id];delete h._domRef;delete e.proxyTop;delete e.proxyBottom;e.destroy();delete Ext.dd.DDM.locationCache["gridHeader"+d.id];delete e._domRef;delete Ext.dd.DDM.ids[e.ddGroup]}if(g){g.destroy();delete g._domRef;delete Ext.dd.DDM.ids["gridSplitters"+d.id]}Ext.fly(j.innerHd).removeAllListeners();Ext.removeNode(j.innerHd);delete j.innerHd;Ext.destroy(j.el,j.mainWrap,j.mainHd,j.scroller,j.mainBody,j.focusEl,j.resizeMarker,j.resizeProxy,j.activeHdBtn,j._flyweight,i,g);delete a.container;if(i){i.destroy()}Ext.dd.DDM.currentTarget=null;delete Ext.dd.DDM.locationCache[d.id];Ext.EventManager.removeResizeListener(j.onWindowResize,j)},onDenyColumnHide:function(){},render:function(){if(this.autoFill){var a=this.grid.ownerCt;if(a&&a.getLayout()){a.on("afterlayout",function(){this.fitColumns(true,true);this.updateHeaders();this.updateHeaderSortState()},this,{single:true})}}else{if(this.forceFit){this.fitColumns(true,false)}else{if(this.grid.autoExpandColumn){this.autoExpand(true)}}}this.grid.getGridEl().dom.innerHTML=this.renderUI();this.afterRenderUI()},initData:function(a,e){var b=this;if(b.ds){var d=b.ds;d.un("add",b.onAdd,b);d.un("load",b.onLoad,b);d.un("clear",b.onClear,b);d.un("remove",b.onRemove,b);d.un("update",b.onUpdate,b);d.un("datachanged",b.onDataChange,b);if(d!==a&&d.autoDestroy){d.destroy()}}if(a){a.on({scope:b,load:b.onLoad,add:b.onAdd,remove:b.onRemove,update:b.onUpdate,clear:b.onClear,datachanged:b.onDataChange})}if(b.cm){var c=b.cm;c.un("configchange",b.onColConfigChange,b);c.un("widthchange",b.onColWidthChange,b);c.un("headerchange",b.onHeaderChange,b);c.un("hiddenchange",b.onHiddenChange,b);c.un("columnmoved",b.onColumnMove,b)}if(e){delete b.lastViewWidth;e.on({scope:b,configchange:b.onColConfigChange,widthchange:b.onColWidthChange,headerchange:b.onHeaderChange,hiddenchange:b.onHiddenChange,columnmoved:b.onColumnMove})}b.ds=a;b.cm=e},onDataChange:function(){this.refresh(true);this.updateHeaderSortState();this.syncFocusEl(0)},onClear:function(){this.refresh();this.syncFocusEl(0)},onUpdate:function(b,a){this.refreshRow(a)},onAdd:function(b,a,c){this.insertRows(b,c,c+(a.length-1))},onRemove:function(b,a,c,d){if(d!==true){this.fireEvent("beforerowremoved",this,c,a)}this.removeRow(c);if(d!==true){this.processRows(c);this.applyEmptyText();this.fireEvent("rowremoved",this,c,a)}},onLoad:function(){if(Ext.isGecko){if(!this.scrollToTopTask){this.scrollToTopTask=new Ext.util.DelayedTask(this.scrollToTop,this)}this.scrollToTopTask.delay(1)}else{this.scrollToTop()}},onColWidthChange:function(a,b,c){this.updateColumnWidth(b,c)},onHeaderChange:function(a,b,c){this.updateHeaders()},onHiddenChange:function(a,b,c){this.updateColumnHidden(b,c)},onColumnMove:function(a,c,b){this.indexMap=null;this.refresh(true);this.restoreScroll(this.getScrollState());this.afterMove(b);this.grid.fireEvent("columnmove",c,b)},onColConfigChange:function(){delete this.lastViewWidth;this.indexMap=null;this.refresh(true)},initUI:function(a){a.on("headerclick",this.onHeaderClick,this)},initEvents:Ext.emptyFn,onHeaderClick:function(b,a){if(this.headersDisabled||!this.cm.isSortable(a)){return}b.stopEditing(true);b.store.sort(this.cm.getDataIndex(a))},onRowOver:function(b,a){var c=this.findRowIndex(a);if(c!==false){this.addRowClass(c,this.rowOverCls)}},onRowOut:function(b,a){var c=this.findRowIndex(a);if(c!==false&&!b.within(this.getRow(c),true)){this.removeRowClass(c,this.rowOverCls)}},onRowSelect:function(a){this.addRowClass(a,this.selectedRowClass)},onRowDeselect:function(a){this.removeRowClass(a,this.selectedRowClass)},onCellSelect:function(c,b){var a=this.getCell(c,b);if(a){this.fly(a).addClass("x-grid3-cell-selected")}},onCellDeselect:function(c,b){var a=this.getCell(c,b);if(a){this.fly(a).removeClass("x-grid3-cell-selected")}},handleWheel:function(a){a.stopPropagation()},onColumnSplitterMoved:function(a,b){this.userResized=true;this.grid.colModel.setColumnWidth(a,b,true);if(this.forceFit){this.fitColumns(true,false,a);this.updateAllColumnWidths()}else{this.updateColumnWidth(a,b);this.syncHeaderScroll()}this.grid.fireEvent("columnresize",a,b)},beforeColMenuShow:function(){var b=this.cm,d=b.getColumnCount(),a=this.colMenu,c;a.removeAll();for(c=0;c<d;c++){if(b.config[c].hideable!==false){a.add(new Ext.menu.CheckItem({text:b.getColumnHeader(c),itemId:"col-"+b.getColumnId(c),checked:!b.isHidden(c),disabled:b.config[c].hideable===false,hideOnClick:false}))}}},handleHdMenuClick:function(c){var a=this.ds,b=this.cm.getDataIndex(this.hdCtxIndex);switch(c.getItemId()){case"asc":a.sort(b,"ASC");break;case"desc":a.sort(b,"DESC");break;default:this.handleHdMenuClickDefault(c)}return true},handleHdMenuClickDefault:function(c){var b=this.cm,d=c.getItemId(),a=b.getIndexById(d.substr(4));if(a!=-1){if(c.checked&&b.getColumnsBy(this.isHideableColumn,this).length<=1){this.onDenyColumnHide();return}b.setHidden(a,c.checked)}},handleHdDown:function(i,j){if(Ext.fly(j).hasClass("x-grid3-hd-btn")){i.stopEvent();var k=this.cm,g=this.findHeaderCell(j),h=this.getCellIndex(g),d=k.isSortable(h),c=this.hmenu,b=c.items,a=this.headerMenuOpenCls;this.hdCtxIndex=h;Ext.fly(g).addClass(a);b.get("asc").setDisabled(!d);b.get("desc").setDisabled(!d);c.on("hide",function(){Ext.fly(g).removeClass(a)},this,{single:true});c.show(j,"tl-bl?")}},handleHdMove:function(k){var i=this.findHeaderCell(this.activeHdRef);if(i&&!this.headersDisabled){var l=this.splitHandleWidth||5,j=this.activeHdRegion,p=i.style,m=this.cm,o="",g=k.getPageX();if(this.grid.enableColumnResize!==false){var a=this.activeHdIndex,b=this.getPreviousVisible(a),n=m.isResizable(a),c=b&&m.isResizable(b),d=g-j.left<=l,h=j.right-g<=(!this.activeHdBtn?l:2);if(d&&c){o=Ext.isAir?"move":Ext.isWebKit?"e-resize":"col-resize"}else{if(h&&n){o=Ext.isAir?"move":Ext.isWebKit?"w-resize":"col-resize"}}}p.cursor=o}},getPreviousVisible:function(a){while(a>0){if(!this.cm.isHidden(a-1)){return a}a--}return undefined},handleHdOver:function(c,b){var d=this.findHeaderCell(b);if(d&&!this.headersDisabled){var a=this.fly(d);this.activeHdRef=b;this.activeHdIndex=this.getCellIndex(d);this.activeHdRegion=a.getRegion();if(!this.isMenuDisabled(this.activeHdIndex,a)){a.addClass("x-grid3-hd-over");this.activeHdBtn=a.child(".x-grid3-hd-btn");if(this.activeHdBtn){this.activeHdBtn.dom.style.height=(d.firstChild.offsetHeight-1)+"px"}}}},handleHdOut:function(b,a){var c=this.findHeaderCell(a);if(c&&(!Ext.isIE||!b.within(c,true))){this.activeHdRef=null;this.fly(c).removeClass("x-grid3-hd-over");c.style.cursor=""}},isMenuDisabled:function(a,b){return this.cm.isMenuDisabled(a)},hasRows:function(){var a=this.mainBody.dom.firstChild;return a&&a.nodeType==1&&a.className!="x-grid-empty"},isHideableColumn:function(a){return !a.hidden},bind:function(a,b){this.initData(a,b)}});Ext.grid.GridView.SplitDragZone=Ext.extend(Ext.dd.DDProxy,{constructor:function(a,b){this.grid=a;this.view=a.getView();this.marker=this.view.resizeMarker;this.proxy=this.view.resizeProxy;Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this,b,"gridSplitters"+this.grid.getGridEl().id,{dragElId:Ext.id(this.proxy.dom),resizeFrame:false});this.scroll=false;this.hw=this.view.splitHandleWidth||5},b4StartDrag:function(a,e){this.dragHeadersDisabled=this.view.headersDisabled;this.view.headersDisabled=true;var d=this.view.mainWrap.getHeight();this.marker.setHeight(d);this.marker.show();this.marker.alignTo(this.view.getHeaderCell(this.cellIndex),"tl-tl",[-2,0]);this.proxy.setHeight(d);var b=this.cm.getColumnWidth(this.cellIndex),c=Math.max(b-this.grid.minColumnWidth,0);this.resetConstraints();this.setXConstraint(c,1000);this.setYConstraint(0,0);this.minX=a-c;this.maxX=a+1000;this.startPos=a;Ext.dd.DDProxy.prototype.b4StartDrag.call(this,a,e)},allowHeaderDrag:function(a){return true},handleMouseDown:function(a){var h=this.view.findHeaderCell(a.getTarget());if(h&&this.allowHeaderDrag(a)){var k=this.view.fly(h).getXY(),c=k[0],i=a.getXY(),b=i[0],g=h.offsetWidth,d=false;if((b-c)<=this.hw){d=-1}else{if((c+g)-b<=this.hw){d=0}}if(d!==false){this.cm=this.grid.colModel;var j=this.view.getCellIndex(h);if(d==-1){if(j+d<0){return}while(this.cm.isHidden(j+d)){--d;if(j+d<0){return}}}this.cellIndex=j+d;this.split=h.dom;if(this.cm.isResizable(this.cellIndex)&&!this.cm.isFixed(this.cellIndex)){Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this,arguments)}}else{if(this.view.columnDrag){this.view.columnDrag.callHandleMouseDown(a)}}}},endDrag:function(g){this.marker.hide();var a=this.view,c=Math.max(this.minX,g.getPageX()),d=c-this.startPos,b=this.dragHeadersDisabled;a.onColumnSplitterMoved(this.cellIndex,this.cm.getColumnWidth(this.cellIndex)+d);setTimeout(function(){a.headersDisabled=b},50)},autoOffset:function(){this.setDelta(0,0)}});Ext.grid.PivotGridView=Ext.extend(Ext.grid.GridView,{colHeaderCellCls:"grid-hd-group-cell",title:"",getColumnHeaders:function(){return this.grid.topAxis.buildHeaders()},getRowHeaders:function(){return this.grid.leftAxis.buildHeaders()},renderRows:function(a,t){var b=this.grid,o=b.extractData(),p=o.length,g=this.templates,s=b.renderer,h=typeof s=="function",w=this.getCellCls,n=typeof w=="function",d=g.cell,x=g.row,k=[],q={},c="width:"+this.getGridInnerWidth()+"px;",l,r,e,v,m;a=a||0;t=Ext.isDefined(t)?t:p-1;for(v=0;v<p;v++){m=o[v];r=m.length;l=[];for(var u=0;u<r;u++){q.id=v+"-"+u;q.css=u===0?"x-grid3-cell-first ":(u==(r-1)?"x-grid3-cell-last ":"");q.attr=q.cellAttr="";q.value=m[u];if(Ext.isEmpty(q.value)){q.value="&#160;"}if(h){q.value=s(q.value)}if(n){q.css+=w(q.value)+" "}l[l.length]=d.apply(q)}k[k.length]=x.apply({tstyle:c,cols:r,cells:l.join(""),alt:""})}return k.join("")},masterTpl:new Ext.Template('<div class="x-grid3 x-pivotgrid" hidefocus="true">','<div class="x-grid3-viewport">','<div class="x-grid3-header">','<div class="x-grid3-header-title"><span>{title}</span></div>','<div class="x-grid3-header-inner">','<div class="x-grid3-header-offset" style="{ostyle}"></div>',"</div>",'<div class="x-clear"></div>',"</div>",'<div class="x-grid3-scroller">','<div class="x-grid3-row-headers"></div>','<div class="x-grid3-body" style="{bstyle}">{body}</div>','<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',"</div>","</div>",'<div class="x-grid3-resize-marker">&#160;</div>','<div class="x-grid3-resize-proxy">&#160;</div>',"</div>"),initTemplates:function(){Ext.grid.PivotGridView.superclass.initTemplates.apply(this,arguments);var a=this.templates||{};if(!a.gcell){a.gcell=new Ext.XTemplate('<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} '+this.colHeaderCellCls+'" style="{style}">','<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">',this.grid.enableHdMenu?'<a class="x-grid3-hd-btn" href="#"></a>':"","{value}","</div>","</td>")}this.templates=a;this.hrowRe=new RegExp("ux-grid-hd-group-row-(\\d+)","")},initElements:function(){Ext.grid.PivotGridView.superclass.initElements.apply(this,arguments);this.rowHeadersEl=new Ext.Element(this.scroller.child("div.x-grid3-row-headers"));this.headerTitleEl=new Ext.Element(this.mainHd.child("div.x-grid3-header-title"))},getGridInnerWidth:function(){var a=Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this,arguments);return a-this.getTotalRowHeaderWidth()},getTotalRowHeaderWidth:function(){var d=this.getRowHeaders(),c=d.length,b=0,a;for(a=0;a<c;a++){b+=d[a].width}return b},getTotalColumnHeaderHeight:function(){return this.getColumnHeaders().length*21},getCellIndex:function(b){if(b){var a=b.className.match(this.colRe),c;if(a&&(c=a[1])){return parseInt(c.split("-")[1],10)}}return false},renderUI:function(){var b=this.templates,a=this.getGridInnerWidth();return b.master.apply({body:b.body.apply({rows:"&#160;"}),ostyle:"width:"+a+"px",bstyle:"width:"+a+"px"})},onLayout:function(b,a){Ext.grid.PivotGridView.superclass.onLayout.apply(this,arguments);var b=this.getGridInnerWidth();this.resizeColumnHeaders(b);this.resizeAllRows(b)},refresh:function(b){this.fireEvent("beforerefresh",this);this.grid.stopEditing(true);var a=this.renderBody();this.mainBody.update(a).setWidth(this.getGridInnerWidth());if(b===true){this.updateHeaders();this.updateHeaderSortState()}this.processRows(0,true);this.layout();this.applyEmptyText();this.fireEvent("refresh",this)},renderHeaders:Ext.emptyFn,fitColumns:Ext.emptyFn,resizeColumnHeaders:function(b){var a=this.grid.topAxis;if(a.rendered){a.el.setWidth(b)}},resizeRowHeaders:function(){var a=this.getTotalRowHeaderWidth(),b=String.format("margin-left: {0}px;",a);this.rowHeadersEl.setWidth(a);this.mainBody.applyStyles(b);Ext.fly(this.innerHd).applyStyles(b);this.headerTitleEl.setWidth(a);this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight())},resizeAllRows:function(b){var d=this.getRows(),c=d.length,a;for(a=0;a<c;a++){Ext.fly(d[a]).setWidth(b);Ext.fly(d[a]).child("table").setWidth(b)}},updateHeaders:function(){this.renderGroupRowHeaders();this.renderGroupColumnHeaders()},renderGroupRowHeaders:function(){var a=this.grid.leftAxis;this.resizeRowHeaders();a.rendered=false;a.render(this.rowHeadersEl);this.setTitle(this.title)},setTitle:function(a){this.headerTitleEl.child("span").dom.innerHTML=a},renderGroupColumnHeaders:function(){var a=this.grid.topAxis;a.rendered=false;a.render(this.innerHd.firstChild)},isMenuDisabled:function(a,b){return true}});Ext.grid.PivotAxis=Ext.extend(Ext.Component,{orientation:"horizontal",defaultHeaderWidth:80,paddingWidth:7,setDimensions:function(a){this.dimensions=a},onRender:function(b,a){var c=this.orientation=="horizontal"?this.renderHorizontalRows():this.renderVerticalRows();this.el=Ext.DomHelper.overwrite(b.dom,{tag:"table",cn:c},true)},renderHorizontalRows:function(){var k=this.buildHeaders(),a=k.length,g=[],c,h,e,d,b;for(d=0;d<a;d++){c=[];h=k[d].items;e=h.length;for(b=0;b<e;b++){c.push({tag:"td",html:h[b].header,colspan:h[b].span})}g[d]={tag:"tr",cn:c}}return g},renderVerticalRows:function(){var b=this.buildHeaders(),k=b.length,a=[],m=[],h,c,l,g,e,d;for(e=0;e<k;e++){c=b[e];g=c.width||80;h=c.items.length;for(d=0;d<h;d++){l=c.items[d];a[l.start]=a[l.start]||[];a[l.start].push({tag:"td",html:l.header,rowspan:l.span,width:Ext.isBorderBox?g:g-this.paddingWidth})}}h=a.length;for(e=0;e<h;e++){m[e]={tag:"tr",cn:a[e]}}return m},getTuples:function(){var b=new Ext.data.Store({});b.data=this.store.data.clone();b.fields=this.store.fields;var l=[],a=this.dimensions,c=a.length,j;for(j=0;j<c;j++){l.push({field:a[j].dataIndex,direction:a[j].direction||"ASC"})}b.sort(l);var e=b.data.items,n=[],k=[],o,h,d,g,m;c=e.length;for(j=0;j<c;j++){d=this.getRecordInfo(e[j]);g=d.data;h="";for(m in g){h+=g[m]+"---"}if(n.indexOf(h)==-1){n.push(h);k.push(d)}}b.destroy();return k},getRecordInfo:function(a){var e=this.dimensions,d=e.length,h={},j,c,b;for(b=0;b<d;b++){j=e[b];c=j.dataIndex;h[c]=a.get(c)}var g=function(i){return function(k){for(var l in i){if(k.get(l)!=i[l]){return false}}return true}};return{data:h,matcher:g(h)}},buildHeaders:function(){var l=this.getTuples(),m=l.length,a=this.dimensions,e,r=a.length,c=[],o,s,n,q,p,b,k,h,g,d;for(g=0;g<r;g++){e=a[g];s=[];p=0;b=0;for(d=0;d<m;d++){o=l[d];k=d==(m-1);n=o.data[e.dataIndex];h=q!=undefined&&q!=n;if(g>0&&d>0){h=h||o.data[a[g-1].dataIndex]!=l[d-1].data[a[g-1].dataIndex]}if(h){s.push({header:q,span:p,start:b});b+=p;p=0}if(k){s.push({header:n,span:p+1,start:b});b+=p;p=0}q=n;p++}c.push({items:s,width:e.width||this.defaultHeaderWidth});q=undefined}return c}});Ext.grid.HeaderDragZone=Ext.extend(Ext.dd.DragZone,{maxDragWidth:120,constructor:function(a,c,b){this.grid=a;this.view=a.getView();this.ddGroup="gridHeader"+this.grid.getGridEl().id;Ext.grid.HeaderDragZone.superclass.constructor.call(this,c);if(b){this.setHandleElId(Ext.id(c));this.setOuterHandleElId(Ext.id(b))}this.scroll=false},getDragData:function(c){var a=Ext.lib.Event.getTarget(c),b=this.view.findHeaderCell(a);if(b){return{ddel:b.firstChild,header:b}}return false},onInitDrag:function(a){this.dragHeadersDisabled=this.view.headersDisabled;this.view.headersDisabled=true;var b=this.dragData.ddel.cloneNode(true);b.id=Ext.id();b.style.width=Math.min(this.dragData.header.offsetWidth,this.maxDragWidth)+"px";this.proxy.update(b);return true},afterValidDrop:function(){this.completeDrop()},afterInvalidDrop:function(){this.completeDrop()},completeDrop:function(){var a=this.view,b=this.dragHeadersDisabled;setTimeout(function(){a.headersDisabled=b},50)}});Ext.grid.HeaderDropZone=Ext.extend(Ext.dd.DropZone,{proxyOffsets:[-4,-9],fly:Ext.Element.fly,constructor:function(a,c,b){this.grid=a;this.view=a.getView();this.proxyTop=Ext.DomHelper.append(document.body,{cls:"col-move-top",html:"&#160;"},true);this.proxyBottom=Ext.DomHelper.append(document.body,{cls:"col-move-bottom",html:"&#160;"},true);this.proxyTop.hide=this.proxyBottom.hide=function(){this.setLeftTop(-100,-100);this.setStyle("visibility","hidden")};this.ddGroup="gridHeader"+this.grid.getGridEl().id;Ext.grid.HeaderDropZone.superclass.constructor.call(this,a.getGridEl().dom)},getTargetFromEvent:function(c){var a=Ext.lib.Event.getTarget(c),b=this.view.findCellIndex(a);if(b!==false){return this.view.getHeaderCell(b)}},nextVisible:function(c){var b=this.view,a=this.grid.colModel;c=c.nextSibling;while(c){if(!a.isHidden(b.getCellIndex(c))){return c}c=c.nextSibling}return null},prevVisible:function(c){var b=this.view,a=this.grid.colModel;c=c.prevSibling;while(c){if(!a.isHidden(b.getCellIndex(c))){return c}c=c.prevSibling}return null},positionIndicator:function(d,k,j){var a=Ext.lib.Event.getPageX(j),g=Ext.lib.Dom.getRegion(k.firstChild),c,i,b=g.top+this.proxyOffsets[1];if((g.right-a)<=(g.right-g.left)/2){c=g.right+this.view.borderWidth;i="after"}else{c=g.left;i="before"}if(this.grid.colModel.isFixed(this.view.getCellIndex(k))){return false}c+=this.proxyOffsets[0];this.proxyTop.setLeftTop(c,b);this.proxyTop.show();if(!this.bottomOffset){this.bottomOffset=this.view.mainHd.getHeight()}this.proxyBottom.setLeftTop(c,b+this.proxyTop.dom.offsetHeight+this.bottomOffset);this.proxyBottom.show();return i},onNodeEnter:function(d,a,c,b){if(b.header!=d){this.positionIndicator(b.header,d,c)}},onNodeOver:function(g,b,d,c){var a=false;if(c.header!=g){a=this.positionIndicator(c.header,g,d)}if(!a){this.proxyTop.hide();this.proxyBottom.hide()}return a?this.dropAllowed:this.dropNotAllowed},onNodeOut:function(d,a,c,b){this.proxyTop.hide();this.proxyBottom.hide()},onNodeDrop:function(b,m,g,c){var d=c.header;if(d!=b){var k=this.grid.colModel,j=Ext.lib.Event.getPageX(g),a=Ext.lib.Dom.getRegion(b.firstChild),o=(a.right-j)<=((a.right-a.left)/2)?"after":"before",i=this.view.getCellIndex(d),l=this.view.getCellIndex(b);if(o=="after"){l++}if(i<l){l--}k.moveColumn(i,l);return true}return false}});Ext.grid.GridView.ColumnDragZone=Ext.extend(Ext.grid.HeaderDragZone,{constructor:function(a,b){Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this,a,b,null);this.proxy.el.addClass("x-grid3-col-dd")},handleMouseDown:function(a){},callHandleMouseDown:function(a){Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this,a)}});Ext.grid.SplitDragZone=Ext.extend(Ext.dd.DDProxy,{fly:Ext.Element.fly,constructor:function(a,c,b){this.grid=a;this.view=a.getView();this.proxy=this.view.resizeProxy;Ext.grid.SplitDragZone.superclass.constructor.call(this,c,"gridSplitters"+this.grid.getGridEl().id,{dragElId:Ext.id(this.proxy.dom),resizeFrame:false});this.setHandleElId(Ext.id(c));this.setOuterHandleElId(Ext.id(b));this.scroll=false},b4StartDrag:function(a,d){this.view.headersDisabled=true;this.proxy.setHeight(this.view.mainWrap.getHeight());var b=this.cm.getColumnWidth(this.cellIndex);var c=Math.max(b-this.grid.minColumnWidth,0);this.resetConstraints();this.setXConstraint(c,1000);this.setYConstraint(0,0);this.minX=a-c;this.maxX=a+1000;this.startPos=a;Ext.dd.DDProxy.prototype.b4StartDrag.call(this,a,d)},handleMouseDown:function(c){var b=Ext.EventObject.setEvent(c);var a=this.fly(b.getTarget());if(a.hasClass("x-grid-split")){this.cellIndex=this.view.getCellIndex(a.dom);this.split=a.dom;this.cm=this.grid.colModel;if(this.cm.isResizable(this.cellIndex)&&!this.cm.isFixed(this.cellIndex)){Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this,arguments)}}},endDrag:function(c){this.view.headersDisabled=false;var a=Math.max(this.minX,Ext.lib.Event.getPageX(c));var b=a-this.startPos;this.view.onColumnSplitterMoved(this.cellIndex,this.cm.getColumnWidth(this.cellIndex)+b)},autoOffset:function(){this.setDelta(0,0)}});Ext.grid.GridDragZone=function(b,a){this.view=b.getView();Ext.grid.GridDragZone.superclass.constructor.call(this,this.view.mainBody.dom,a);this.scroll=false;this.grid=b;this.ddel=document.createElement("div");this.ddel.className="x-grid-dd-wrap"};Ext.extend(Ext.grid.GridDragZone,Ext.dd.DragZone,{ddGroup:"GridDD",getDragData:function(b){var a=Ext.lib.Event.getTarget(b);var d=this.view.findRowIndex(a);if(d!==false){var c=this.grid.selModel;if(!c.isSelected(d)||b.hasModifier()){c.handleMouseDown(this.grid,d,b)}return{grid:this.grid,ddel:this.ddel,rowIndex:d,selections:c.getSelections()}}return false},onInitDrag:function(b){var a=this.dragData;this.ddel.innerHTML=this.grid.getDragDropText();this.proxy.update(this.ddel)},afterRepair:function(){this.dragging=false},getRepairXY:function(b,a){return false},onEndDrag:function(a,b){},onValidDrop:function(a,b,c){this.hideProxy()},beforeInvalidDrop:function(a,b){}});Ext.grid.ColumnModel=Ext.extend(Ext.util.Observable,{defaultWidth:100,defaultSortable:false,constructor:function(a){if(a.columns){Ext.apply(this,a);this.setConfig(a.columns,true)}else{this.setConfig(a,true)}this.addEvents("widthchange","headerchange","hiddenchange","columnmoved","configchange");Ext.grid.ColumnModel.superclass.constructor.call(this)},getColumnId:function(a){return this.config[a].id},getColumnAt:function(a){return this.config[a]},setConfig:function(d,b){var e,h,a;if(!b){delete this.totalWidth;for(e=0,a=this.config.length;e<a;e++){h=this.config[e];if(h.setEditor){h.setEditor(null)}}}this.defaults=Ext.apply({width:this.defaultWidth,sortable:this.defaultSortable},this.defaults);this.config=d;this.lookup={};for(e=0,a=d.length;e<a;e++){h=Ext.applyIf(d[e],this.defaults);if(Ext.isEmpty(h.id)){h.id=e}if(!h.isColumn){var g=Ext.grid.Column.types[h.xtype||"gridcolumn"];h=new g(h);d[e]=h}this.lookup[h.id]=h}if(!b){this.fireEvent("configchange",this)}},getColumnById:function(a){return this.lookup[a]},getIndexById:function(c){for(var b=0,a=this.config.length;b<a;b++){if(this.config[b].id==c){return b}}return -1},moveColumn:function(e,b){var a=this.config,d=a[e];a.splice(e,1);a.splice(b,0,d);this.dataMap=null;this.fireEvent("columnmoved",this,e,b)},getColumnCount:function(b){var d=this.config.length,e=0,a;if(b===true){for(a=0;a<d;a++){if(!this.isHidden(a)){e++}}return e}return d},getColumnsBy:function(g,e){var b=this.config,h=b.length,a=[],d,j;for(d=0;d<h;d++){j=b[d];if(g.call(e||this,j,d)===true){a[a.length]=j}}return a},isSortable:function(a){return !!this.config[a].sortable},isMenuDisabled:function(a){return !!this.config[a].menuDisabled},getRenderer:function(a){return this.config[a].renderer||Ext.grid.ColumnModel.defaultRenderer},getRendererScope:function(a){return this.config[a].scope},setRenderer:function(a,b){this.config[a].renderer=b},getColumnWidth:function(a){var b=this.config[a].width;if(typeof b!="number"){b=this.defaultWidth}return b},setColumnWidth:function(b,c,a){this.config[b].width=c;this.totalWidth=null;if(!a){this.fireEvent("widthchange",this,b,c)}},getTotalWidth:function(b){if(!this.totalWidth){this.totalWidth=0;for(var c=0,a=this.config.length;c<a;c++){if(b||!this.isHidden(c)){this.totalWidth+=this.getColumnWidth(c)}}}return this.totalWidth},getColumnHeader:function(a){return this.config[a].header},setColumnHeader:function(a,b){this.config[a].header=b;this.fireEvent("headerchange",this,a,b)},getColumnTooltip:function(a){return this.config[a].tooltip},setColumnTooltip:function(a,b){this.config[a].tooltip=b},getDataIndex:function(a){return this.config[a].dataIndex},setDataIndex:function(a,b){this.config[a].dataIndex=b},findColumnIndex:function(d){var e=this.config;for(var b=0,a=e.length;b<a;b++){if(e[b].dataIndex==d){return b}}return -1},isCellEditable:function(b,e){var d=this.config[b],a=d.editable;return !!(a||(!Ext.isDefined(a)&&d.editor))},getCellEditor:function(a,b){return this.config[a].getCellEditor(b)},setEditable:function(a,b){this.config[a].editable=b},isHidden:function(a){return !!this.config[a].hidden},isFixed:function(a){return !!this.config[a].fixed},isResizable:function(a){return a>=0&&this.config[a].resizable!==false&&this.config[a].fixed!==true},setHidden:function(a,b){var d=this.config[a];if(d.hidden!==b){d.hidden=b;this.totalWidth=null;this.fireEvent("hiddenchange",this,a,b)}},setEditor:function(a,b){this.config[a].setEditor(b)},destroy:function(){var b=this.config.length,a=0;for(;a<b;a++){this.config[a].destroy()}delete this.config;delete this.lookup;this.purgeListeners()},setState:function(a,b){b=Ext.applyIf(b,this.defaults);Ext.apply(this.config[a],b)}});Ext.grid.ColumnModel.defaultRenderer=function(a){if(typeof a=="string"&&a.length<1){return"&#160;"}return a};Ext.grid.AbstractSelectionModel=Ext.extend(Ext.util.Observable,{constructor:function(){this.locked=false;Ext.grid.AbstractSelectionModel.superclass.constructor.call(this)},init:function(a){this.grid=a;if(this.lockOnInit){delete this.lockOnInit;this.locked=false;this.lock()}this.initEvents()},lock:function(){if(!this.locked){this.locked=true;var a=this.grid;if(a){a.getView().on({scope:this,beforerefresh:this.sortUnLock,refresh:this.sortLock})}else{this.lockOnInit=true}}},sortLock:function(){this.locked=true},sortUnLock:function(){this.locked=false},unlock:function(){if(this.locked){this.locked=false;var a=this.grid,b;if(a){b=a.getView();b.un("beforerefresh",this.sortUnLock,this);b.un("refresh",this.sortLock,this)}else{delete this.lockOnInit}}},isLocked:function(){return this.locked},destroy:function(){this.unlock();this.purgeListeners()}});Ext.grid.RowSelectionModel=Ext.extend(Ext.grid.AbstractSelectionModel,{singleSelect:false,constructor:function(a){Ext.apply(this,a);this.selections=new Ext.util.MixedCollection(false,function(b){return b.id});this.last=false;this.lastActive=false;this.addEvents("selectionchange","beforerowselect","rowselect","rowdeselect");Ext.grid.RowSelectionModel.superclass.constructor.call(this)},initEvents:function(){if(!this.grid.enableDragDrop&&!this.grid.enableDrag){this.grid.on("rowmousedown",this.handleMouseDown,this)}this.rowNav=new Ext.KeyNav(this.grid.getGridEl(),{up:this.onKeyPress,down:this.onKeyPress,scope:this});this.grid.getView().on({scope:this,refresh:this.onRefresh,rowupdated:this.onRowUpdated,rowremoved:this.onRemove})},onKeyPress:function(g,b){var a=b=="up",h=a?"selectPrevious":"selectNext",d=a?-1:1,c;if(!g.shiftKey||this.singleSelect){this[h](false)}else{if(this.last!==false&&this.lastActive!==false){c=this.last;this.selectRange(this.last,this.lastActive+d);this.grid.getView().focusRow(this.lastActive);if(c!==false){this.last=c}}else{this.selectFirstRow()}}},onRefresh:function(){var g=this.grid.store,d=this.getSelections(),c=0,a=d.length,b,e;this.silent=true;this.clearSelections(true);for(;c<a;c++){e=d[c];if((b=g.indexOfId(e.id))!=-1){this.selectRow(b,true)}}if(d.length!=this.selections.getCount()){this.fireEvent("selectionchange",this)}this.silent=false},onRemove:function(a,b,c){if(this.selections.remove(c)!==false){this.fireEvent("selectionchange",this)}},onRowUpdated:function(a,b,c){if(this.isSelected(c)){a.onRowSelect(b)}},selectRecords:function(b,e){if(!e){this.clearSelections()}var d=this.grid.store,c=0,a=b.length;for(;c<a;c++){this.selectRow(d.indexOf(b[c]),true)}},getCount:function(){return this.selections.length},selectFirstRow:function(){this.selectRow(0)},selectLastRow:function(a){this.selectRow(this.grid.store.getCount()-1,a)},selectNext:function(a){if(this.hasNext()){this.selectRow(this.last+1,a);this.grid.getView().focusRow(this.last);return true}return false},selectPrevious:function(a){if(this.hasPrevious()){this.selectRow(this.last-1,a);this.grid.getView().focusRow(this.last);return true}return false},hasNext:function(){return this.last!==false&&(this.last+1)<this.grid.store.getCount()},hasPrevious:function(){return !!this.last},getSelections:function(){return[].concat(this.selections.items)},getSelected:function(){return this.selections.itemAt(0)},each:function(e,d){var c=this.getSelections(),b=0,a=c.length;for(;b<a;b++){if(e.call(d||this,c[b],b)===false){return false}}return true},clearSelections:function(a){if(this.isLocked()){return}if(a!==true){var c=this.grid.store,b=this.selections;b.each(function(d){this.deselectRow(c.indexOfId(d.id))},this);b.clear()}else{this.selections.clear()}this.last=false},selectAll:function(){if(this.isLocked()){return}this.selections.clear();for(var b=0,a=this.grid.store.getCount();b<a;b++){this.selectRow(b,true)}},hasSelection:function(){return this.selections.length>0},isSelected:function(a){var b=Ext.isNumber(a)?this.grid.store.getAt(a):a;return(b&&this.selections.key(b.id)?true:false)},isIdSelected:function(a){return(this.selections.key(a)?true:false)},handleMouseDown:function(d,i,h){if(h.button!==0||this.isLocked()){return}var a=this.grid.getView();if(h.shiftKey&&!this.singleSelect&&this.last!==false){var c=this.last;this.selectRange(c,i,h.ctrlKey);this.last=c;a.focusRow(i)}else{var b=this.isSelected(i);if(h.ctrlKey&&b){this.deselectRow(i)}else{if(!b||this.getCount()>1){this.selectRow(i,h.ctrlKey||h.shiftKey);a.focusRow(i)}}}},selectRows:function(c,d){if(!d){this.clearSelections()}for(var b=0,a=c.length;b<a;b++){this.selectRow(c[b],true)}},selectRange:function(b,a,d){var c;if(this.isLocked()){return}if(!d){this.clearSelections()}if(b<=a){for(c=b;c<=a;c++){this.selectRow(c,true)}}else{for(c=b;c>=a;c--){this.selectRow(c,true)}}},deselectRange:function(c,b,a){if(this.isLocked()){return}for(var d=c;d<=b;d++){this.deselectRow(d,a)}},selectRow:function(b,d,a){if(this.isLocked()||(b<0||b>=this.grid.store.getCount())||(d&&this.isSelected(b))){return}var c=this.grid.store.getAt(b);if(c&&this.fireEvent("beforerowselect",this,b,d,c)!==false){if(!d||this.singleSelect){this.clearSelections()}this.selections.add(c);this.last=this.lastActive=b;if(!a){this.grid.getView().onRowSelect(b)}if(!this.silent){this.fireEvent("rowselect",this,b,c);this.fireEvent("selectionchange",this)}}},deselectRow:function(b,a){if(this.isLocked()){return}if(this.last==b){this.last=false}if(this.lastActive==b){this.lastActive=false}var c=this.grid.store.getAt(b);if(c){this.selections.remove(c);if(!a){this.grid.getView().onRowDeselect(b)}this.fireEvent("rowdeselect",this,b,c);this.fireEvent("selectionchange",this)}},acceptsNav:function(c,b,a){return !a.isHidden(b)&&a.isCellEditable(b,c)},onEditorKey:function(n,l){var d=l.getKey(),h,i=this.grid,p=i.lastEdit,j=i.activeEditor,b=l.shiftKey,o,p,a,m;if(d==l.TAB){l.stopEvent();j.completeEdit();if(b){h=i.walkCells(j.row,j.col-1,-1,this.acceptsNav,this)}else{h=i.walkCells(j.row,j.col+1,1,this.acceptsNav,this)}}else{if(d==l.ENTER){if(this.moveEditorOnEnter!==false){if(b){h=i.walkCells(p.row-1,p.col,-1,this.acceptsNav,this)}else{h=i.walkCells(p.row+1,p.col,1,this.acceptsNav,this)}}}}if(h){a=h[0];m=h[1];this.onEditorSelect(a,p.row);if(i.isEditor&&i.editing){o=i.activeEditor;if(o&&o.field.triggerBlur){o.field.triggerBlur()}}i.startEditing(a,m)}},onEditorSelect:function(b,a){if(a!=b){this.selectRow(b)}},destroy:function(){Ext.destroy(this.rowNav);this.rowNav=null;Ext.grid.RowSelectionModel.superclass.destroy.call(this)}});Ext.grid.Column=Ext.extend(Ext.util.Observable,{isColumn:true,constructor:function(b){Ext.apply(this,b);if(Ext.isString(this.renderer)){this.renderer=Ext.util.Format[this.renderer]}else{if(Ext.isObject(this.renderer)){this.scope=this.renderer.scope;this.renderer=this.renderer.fn}}if(!this.scope){this.scope=this}var a=this.editor;delete this.editor;this.setEditor(a);this.addEvents("click","contextmenu","dblclick","mousedown");Ext.grid.Column.superclass.constructor.call(this)},processEvent:function(b,d,c,g,a){return this.fireEvent(b,this,c,g,d)},destroy:function(){if(this.setEditor){this.setEditor(null)}this.purgeListeners()},renderer:function(a){return a},getEditor:function(a){return this.editable!==false?this.editor:null},setEditor:function(b){var a=this.editor;if(a){if(a.gridEditor){a.gridEditor.destroy();delete a.gridEditor}else{a.destroy()}}this.editor=null;if(b){if(!b.isXType){b=Ext.create(b,"textfield")}this.editor=b}},getCellEditor:function(b){var a=this.getEditor(b);if(a){if(!a.startEdit){if(!a.gridEditor){a.gridEditor=new Ext.grid.GridEditor(a)}a=a.gridEditor}}return a}});Ext.grid.BooleanColumn=Ext.extend(Ext.grid.Column,{trueText:"true",falseText:"false",undefinedText:"&#160;",constructor:function(a){Ext.grid.BooleanColumn.superclass.constructor.call(this,a);var c=this.trueText,d=this.falseText,b=this.undefinedText;this.renderer=function(e){if(e===undefined){return b}if(!e||e==="false"){return d}return c}}});Ext.grid.NumberColumn=Ext.extend(Ext.grid.Column,{format:"0,000.00",constructor:function(a){Ext.grid.NumberColumn.superclass.constructor.call(this,a);this.renderer=Ext.util.Format.numberRenderer(this.format)}});Ext.grid.DateColumn=Ext.extend(Ext.grid.Column,{format:"m/d/Y",constructor:function(a){Ext.grid.DateColumn.superclass.constructor.call(this,a);this.renderer=Ext.util.Format.dateRenderer(this.format)}});Ext.grid.TemplateColumn=Ext.extend(Ext.grid.Column,{constructor:function(a){Ext.grid.TemplateColumn.superclass.constructor.call(this,a);var b=(!Ext.isPrimitive(this.tpl)&&this.tpl.compile)?this.tpl:new Ext.XTemplate(this.tpl);this.renderer=function(d,e,c){return b.apply(c.data)};this.tpl=b}});Ext.grid.ActionColumn=Ext.extend(Ext.grid.Column,{header:"&#160;",actionIdRe:/x-action-col-(\d+)/,altText:"",constructor:function(b){var g=this,c=b.items||(g.items=[g]),a=c.length,d,e;Ext.grid.ActionColumn.superclass.constructor.call(g,b);g.renderer=function(h,i){h=Ext.isFunction(b.renderer)?b.renderer.apply(this,arguments)||"":"";i.css+=" x-action-col-cell";for(d=0;d<a;d++){e=c[d];h+='<img alt="'+(e.altText||g.altText)+'" src="'+(e.icon||Ext.BLANK_IMAGE_URL)+'" class="x-action-col-icon x-action-col-'+String(d)+" "+(e.iconCls||"")+" "+(Ext.isFunction(e.getClass)?e.getClass.apply(e.scope||this.scope||this,arguments):"")+'"'+((e.tooltip)?' ext:qtip="'+e.tooltip+'"':"")+" />"}return h}},destroy:function(){delete this.items;delete this.renderer;return Ext.grid.ActionColumn.superclass.destroy.apply(this,arguments)},processEvent:function(c,i,d,j,b){var a=i.getTarget().className.match(this.actionIdRe),h,g;if(a&&(h=this.items[parseInt(a[1],10)])){if(c=="click"){(g=h.handler||this.handler)&&g.call(h.scope||this.scope||this,d,j,b,h,i)}else{if((c=="mousedown")&&(h.stopSelection!==false)){return false}}}return Ext.grid.ActionColumn.superclass.processEvent.apply(this,arguments)}});Ext.grid.Column.types={gridcolumn:Ext.grid.Column,booleancolumn:Ext.grid.BooleanColumn,numbercolumn:Ext.grid.NumberColumn,datecolumn:Ext.grid.DateColumn,templatecolumn:Ext.grid.TemplateColumn,actioncolumn:Ext.grid.ActionColumn};Ext.grid.RowNumberer=Ext.extend(Object,{header:"",width:23,sortable:false,constructor:function(a){Ext.apply(this,a);if(this.rowspan){this.renderer=this.renderer.createDelegate(this)}},fixed:true,hideable:false,menuDisabled:true,dataIndex:"",id:"numberer",rowspan:undefined,renderer:function(b,c,a,d){if(this.rowspan){c.cellAttr='rowspan="'+this.rowspan+'"'}return d+1}});Ext.grid.CheckboxSelectionModel=Ext.extend(Ext.grid.RowSelectionModel,{header:'<div class="x-grid3-hd-checker">&#160;</div>',width:20,sortable:false,menuDisabled:true,fixed:true,hideable:false,dataIndex:"",id:"checker",isColumn:true,constructor:function(){Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this,arguments);if(this.checkOnly){this.handleMouseDown=Ext.emptyFn}},initEvents:function(){Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);this.grid.on("render",function(){Ext.fly(this.grid.getView().innerHd).on("mousedown",this.onHdMouseDown,this)},this)},processEvent:function(b,d,c,g,a){if(b=="mousedown"){this.onMouseDown(d,d.getTarget());return false}else{return Ext.grid.Column.prototype.processEvent.apply(this,arguments)}},onMouseDown:function(c,b){if(c.button===0&&b.className=="x-grid3-row-checker"){c.stopEvent();var d=c.getTarget(".x-grid3-row");if(d){var a=d.rowIndex;if(this.isSelected(a)){this.deselectRow(a)}else{this.selectRow(a,true);this.grid.getView().focusRow(a)}}}},onHdMouseDown:function(c,a){if(a.className=="x-grid3-hd-checker"){c.stopEvent();var b=Ext.fly(a.parentNode);var d=b.hasClass("x-grid3-hd-checker-on");if(d){b.removeClass("x-grid3-hd-checker-on");this.clearSelections()}else{b.addClass("x-grid3-hd-checker-on");this.selectAll()}}},renderer:function(b,c,a){return'<div class="x-grid3-row-checker">&#160;</div>'},onEditorSelect:function(b,a){if(a!=b&&!this.checkOnly){this.selectRow(b)}}});Ext.grid.CellSelectionModel=Ext.extend(Ext.grid.AbstractSelectionModel,{constructor:function(a){Ext.apply(this,a);this.selection=null;this.addEvents("beforecellselect","cellselect","selectionchange");Ext.grid.CellSelectionModel.superclass.constructor.call(this)},initEvents:function(){this.grid.on("cellmousedown",this.handleMouseDown,this);this.grid.on(Ext.EventManager.getKeyEvent(),this.handleKeyDown,this);this.grid.getView().on({scope:this,refresh:this.onViewChange,rowupdated:this.onRowUpdated,beforerowremoved:this.clearSelections,beforerowsinserted:this.clearSelections});if(this.grid.isEditor){this.grid.on("beforeedit",this.beforeEdit,this)}},beforeEdit:function(a){this.select(a.row,a.column,false,true,a.record)},onRowUpdated:function(a,b,c){if(this.selection&&this.selection.record==c){a.onCellSelect(b,this.selection.cell[1])}},onViewChange:function(){this.clearSelections(true)},getSelectedCell:function(){return this.selection?this.selection.cell:null},clearSelections:function(b){var a=this.selection;if(a){if(b!==true){this.grid.view.onCellDeselect(a.cell[0],a.cell[1])}this.selection=null;this.fireEvent("selectionchange",this,null)}},hasSelection:function(){return this.selection?true:false},handleMouseDown:function(b,d,a,c){if(c.button!==0||this.isLocked()){return}this.select(d,a)},select:function(g,c,b,e,d){if(this.fireEvent("beforecellselect",this,g,c)!==false){this.clearSelections();d=d||this.grid.store.getAt(g);this.selection={record:d,cell:[g,c]};if(!b){var a=this.grid.getView();a.onCellSelect(g,c);if(e!==true){a.focusCell(g,c)}}this.fireEvent("cellselect",this,g,c);this.fireEvent("selectionchange",this,this.selection)}},isSelectable:function(c,b,a){return !a.isHidden(b)},onEditorKey:function(b,a){if(a.getKey()==a.TAB){this.handleKeyDown(a)}},handleKeyDown:function(j){if(!j.isNavKeyPress()){return}var d=j.getKey(),i=this.grid,p=this.selection,b=this,m=function(g,c,e){return i.walkCells(g,c,e,i.isEditor&&i.editing?b.acceptsNav:b.isSelectable,b)},o,h,a,l,n;switch(d){case j.ESC:case j.PAGE_UP:case j.PAGE_DOWN:break;default:j.stopEvent();break}if(!p){o=m(0,0,1);if(o){this.select(o[0],o[1])}return}o=p.cell;a=o[0];l=o[1];switch(d){case j.TAB:if(j.shiftKey){h=m(a,l-1,-1)}else{h=m(a,l+1,1)}break;case j.DOWN:h=m(a+1,l,1);break;case j.UP:h=m(a-1,l,-1);break;case j.RIGHT:h=m(a,l+1,1);break;case j.LEFT:h=m(a,l-1,-1);break;case j.ENTER:if(i.isEditor&&!i.editing){i.startEditing(a,l);return}break}if(h){a=h[0];l=h[1];this.select(a,l);if(i.isEditor&&i.editing){n=i.activeEditor;if(n&&n.field.triggerBlur){n.field.triggerBlur()}i.startEditing(a,l)}}},acceptsNav:function(c,b,a){return !a.isHidden(b)&&a.isCellEditable(b,c)}});Ext.grid.EditorGridPanel=Ext.extend(Ext.grid.GridPanel,{clicksToEdit:2,forceValidation:false,isEditor:true,detectEdit:false,autoEncode:false,trackMouseOver:false,initComponent:function(){Ext.grid.EditorGridPanel.superclass.initComponent.call(this);if(!this.selModel){this.selModel=new Ext.grid.CellSelectionModel()}this.activeEditor=null;this.addEvents("beforeedit","afteredit","validateedit")},initEvents:function(){Ext.grid.EditorGridPanel.superclass.initEvents.call(this);this.getGridEl().on("mousewheel",this.stopEditing.createDelegate(this,[true]),this);this.on("columnresize",this.stopEditing,this,[true]);if(this.clicksToEdit==1){this.on("cellclick",this.onCellDblClick,this)}else{var a=this.getView();if(this.clicksToEdit=="auto"&&a.mainBody){a.mainBody.on("mousedown",this.onAutoEditClick,this)}this.on("celldblclick",this.onCellDblClick,this)}},onResize:function(){Ext.grid.EditorGridPanel.superclass.onResize.apply(this,arguments);var a=this.activeEditor;if(this.editing&&a){a.realign(true)}},onCellDblClick:function(b,c,a){this.startEditing(c,a)},onAutoEditClick:function(c,b){if(c.button!==0){return}var g=this.view.findRowIndex(b),a=this.view.findCellIndex(b);if(g!==false&&a!==false){this.stopEditing();if(this.selModel.getSelectedCell){var d=this.selModel.getSelectedCell();if(d&&d[0]===g&&d[1]===a){this.startEditing(g,a)}}else{if(this.selModel.isSelected(g)){this.startEditing(g,a)}}}},onEditComplete:function(b,d,a){this.editing=false;this.lastActiveEditor=this.activeEditor;this.activeEditor=null;var c=b.record,h=this.colModel.getDataIndex(b.col);d=this.postEditValue(d,a,c,h);if(this.forceValidation===true||String(d)!==String(a)){var g={grid:this,record:c,field:h,originalValue:a,value:d,row:b.row,column:b.col,cancel:false};if(this.fireEvent("validateedit",g)!==false&&!g.cancel&&String(d)!==String(a)){c.set(h,g.value);delete g.cancel;this.fireEvent("afteredit",g)}}this.view.focusCell(b.row,b.col)},startEditing:function(i,c){this.stopEditing();if(this.colModel.isCellEditable(c,i)){this.view.ensureVisible(i,c,true);var d=this.store.getAt(i),h=this.colModel.getDataIndex(c),g={grid:this,record:d,field:h,value:d.data[h],row:i,column:c,cancel:false};if(this.fireEvent("beforeedit",g)!==false&&!g.cancel){this.editing=true;var b=this.colModel.getCellEditor(c,i);if(!b){return}if(!b.rendered){b.parentEl=this.view.getEditorParent(b);b.on({scope:this,render:{fn:function(e){e.field.focus(false,true)},single:true,scope:this},specialkey:function(k,j){this.getSelectionModel().onEditorKey(k,j)},complete:this.onEditComplete,canceledit:this.stopEditing.createDelegate(this,[true])})}Ext.apply(b,{row:i,col:c,record:d});this.lastEdit={row:i,col:c};this.activeEditor=b;b.selectSameEditor=(this.activeEditor==this.lastActiveEditor);var a=this.preEditValue(d,h);b.startEdit(this.view.getCell(i,c).firstChild,Ext.isDefined(a)?a:"");(function(){delete b.selectSameEditor}).defer(50)}}},preEditValue:function(a,c){var b=a.data[c];return this.autoEncode&&Ext.isString(b)?Ext.util.Format.htmlDecode(b):b},postEditValue:function(c,a,b,d){return this.autoEncode&&Ext.isString(c)?Ext.util.Format.htmlEncode(c):c},stopEditing:function(b){if(this.editing){var a=this.lastActiveEditor=this.activeEditor;if(a){a[b===true?"cancelEdit":"completeEdit"]();this.view.focusCell(a.row,a.col)}this.activeEditor=null}this.editing=false}});Ext.reg("editorgrid",Ext.grid.EditorGridPanel);Ext.grid.GridEditor=function(b,a){Ext.grid.GridEditor.superclass.constructor.call(this,b,a);b.monitorTab=false};Ext.extend(Ext.grid.GridEditor,Ext.Editor,{alignment:"tl-tl",autoSize:"width",hideEl:false,cls:"x-small-editor x-grid-editor",shim:false,shadow:false});Ext.grid.PropertyRecord=Ext.data.Record.create([{name:"name",type:"string"},"value"]);Ext.grid.PropertyStore=Ext.extend(Ext.util.Observable,{constructor:function(a,b){this.grid=a;this.store=new Ext.data.Store({recordType:Ext.grid.PropertyRecord});this.store.on("update",this.onUpdate,this);if(b){this.setSource(b)}Ext.grid.PropertyStore.superclass.constructor.call(this)},setSource:function(c){this.source=c;this.store.removeAll();var b=[];for(var a in c){if(this.isEditableValue(c[a])){b.push(new Ext.grid.PropertyRecord({name:a,value:c[a]},a))}}this.store.loadRecords({records:b},{},true)},onUpdate:function(e,a,d){if(d==Ext.data.Record.EDIT){var b=a.data.value;var c=a.modified.value;if(this.grid.fireEvent("beforepropertychange",this.source,a.id,b,c)!==false){this.source[a.id]=b;a.commit();this.grid.fireEvent("propertychange",this.source,a.id,b,c)}else{a.reject()}}},getProperty:function(a){return this.store.getAt(a)},isEditableValue:function(a){return Ext.isPrimitive(a)||Ext.isDate(a)},setValue:function(d,c,a){var b=this.getRec(d);if(b){b.set("value",c);this.source[d]=c}else{if(a){this.source[d]=c;b=new Ext.grid.PropertyRecord({name:d,value:c},d);this.store.add(b)}}},remove:function(b){var a=this.getRec(b);if(a){this.store.remove(a);delete this.source[b]}},getRec:function(a){return this.store.getById(a)},getSource:function(){return this.source}});Ext.grid.PropertyColumnModel=Ext.extend(Ext.grid.ColumnModel,{nameText:"Name",valueText:"Value",dateFormat:"m/j/Y",trueText:"true",falseText:"false",constructor:function(c,b){var d=Ext.grid,e=Ext.form;this.grid=c;d.PropertyColumnModel.superclass.constructor.call(this,[{header:this.nameText,width:50,sortable:true,dataIndex:"name",id:"name",menuDisabled:true},{header:this.valueText,width:50,resizable:false,dataIndex:"value",id:"value",menuDisabled:true}]);this.store=b;var a=new e.Field({autoCreate:{tag:"select",children:[{tag:"option",value:"true",html:this.trueText},{tag:"option",value:"false",html:this.falseText}]},getValue:function(){return this.el.dom.value=="true"}});this.editors={date:new d.GridEditor(new e.DateField({selectOnFocus:true})),string:new d.GridEditor(new e.TextField({selectOnFocus:true})),number:new d.GridEditor(new e.NumberField({selectOnFocus:true,style:"text-align:left;"})),"boolean":new d.GridEditor(a,{autoSize:"both"})};this.renderCellDelegate=this.renderCell.createDelegate(this);this.renderPropDelegate=this.renderProp.createDelegate(this)},renderDate:function(a){return a.dateFormat(this.dateFormat)},renderBool:function(a){return this[a?"trueText":"falseText"]},isCellEditable:function(a,b){return a==1},getRenderer:function(a){return a==1?this.renderCellDelegate:this.renderPropDelegate},renderProp:function(a){return this.getPropertyName(a)},renderCell:function(d,b,c){var a=this.grid.customRenderers[c.get("name")];if(a){return a.apply(this,arguments)}var e=d;if(Ext.isDate(d)){e=this.renderDate(d)}else{if(typeof d=="boolean"){e=this.renderBool(d)}}return Ext.util.Format.htmlEncode(e)},getPropertyName:function(b){var a=this.grid.propertyNames;return a&&a[b]?a[b]:b},getCellEditor:function(a,e){var b=this.store.getProperty(e),d=b.data.name,c=b.data.value;if(this.grid.customEditors[d]){return this.grid.customEditors[d]}if(Ext.isDate(c)){return this.editors.date}else{if(typeof c=="number"){return this.editors.number}else{if(typeof c=="boolean"){return this.editors["boolean"]}else{return this.editors.string}}}},destroy:function(){Ext.grid.PropertyColumnModel.superclass.destroy.call(this);this.destroyEditors(this.editors);this.destroyEditors(this.grid.customEditors)},destroyEditors:function(b){for(var a in b){Ext.destroy(b[a])}}});Ext.grid.PropertyGrid=Ext.extend(Ext.grid.EditorGridPanel,{enableColumnMove:false,stripeRows:false,trackMouseOver:false,clicksToEdit:1,enableHdMenu:false,viewConfig:{forceFit:true},initComponent:function(){this.customRenderers=this.customRenderers||{};this.customEditors=this.customEditors||{};this.lastEditRow=null;var b=new Ext.grid.PropertyStore(this);this.propStore=b;var a=new Ext.grid.PropertyColumnModel(this,b);b.store.sort("name","ASC");this.addEvents("beforepropertychange","propertychange");this.cm=a;this.ds=b.store;Ext.grid.PropertyGrid.superclass.initComponent.call(this);this.mon(this.selModel,"beforecellselect",function(e,d,c){if(c===0){this.startEditing.defer(200,this,[d,1]);return false}},this)},onRender:function(){Ext.grid.PropertyGrid.superclass.onRender.apply(this,arguments);this.getGridEl().addClass("x-props-grid")},afterRender:function(){Ext.grid.PropertyGrid.superclass.afterRender.apply(this,arguments);if(this.source){this.setSource(this.source)}},setSource:function(a){this.propStore.setSource(a)},getSource:function(){return this.propStore.getSource()},setProperty:function(c,b,a){this.propStore.setValue(c,b,a)},removeProperty:function(a){this.propStore.remove(a)}});Ext.reg("propertygrid",Ext.grid.PropertyGrid);Ext.grid.GroupingView=Ext.extend(Ext.grid.GridView,{groupByText:"Group By This Field",showGroupsText:"Show in Groups",hideGroupedColumn:false,showGroupName:true,startCollapsed:false,enableGrouping:true,enableGroupingMenu:true,enableNoGroups:true,emptyGroupText:"(None)",ignoreAdd:false,groupTextTpl:"{text}",groupMode:"value",cancelEditOnToggle:true,initTemplates:function(){Ext.grid.GroupingView.superclass.initTemplates.call(this);this.state={};var a=this.grid.getSelectionModel();a.on(a.selectRow?"beforerowselect":"beforecellselect",this.onBeforeRowSelect,this);if(!this.startGroup){this.startGroup=new Ext.XTemplate('<div id="{groupId}" class="x-grid-group {cls}">','<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">',this.groupTextTpl,"</div></div>",'<div id="{groupId}-bd" class="x-grid-group-body">')}this.startGroup.compile();if(!this.endGroup){this.endGroup="</div></div>"}},findGroup:function(a){return Ext.fly(a).up(".x-grid-group",this.mainBody.dom)},getGroups:function(){return this.hasRows()?this.mainBody.dom.childNodes:[]},onAdd:function(d,a,b){if(this.canGroup()&&!this.ignoreAdd){var c=this.getScrollState();this.fireEvent("beforerowsinserted",d,b,b+(a.length-1));this.refresh();this.restoreScroll(c);this.fireEvent("rowsinserted",d,b,b+(a.length-1))}else{if(!this.canGroup()){Ext.grid.GroupingView.superclass.onAdd.apply(this,arguments)}}},onRemove:function(e,a,b,d){Ext.grid.GroupingView.superclass.onRemove.apply(this,arguments);var c=document.getElementById(a._groupId);if(c&&c.childNodes[1].childNodes.length<1){Ext.removeNode(c)}this.applyEmptyText()},refreshRow:function(a){if(this.ds.getCount()==1){this.refresh()}else{this.isUpdating=true;Ext.grid.GroupingView.superclass.refreshRow.apply(this,arguments);this.isUpdating=false}},beforeMenuShow:function(){var c,a=this.hmenu.items,b=this.cm.config[this.hdCtxIndex].groupable===false;if((c=a.get("groupBy"))){c.setDisabled(b)}if((c=a.get("showGroups"))){c.setDisabled(b);c.setChecked(this.canGroup(),true)}},renderUI:function(){var a=Ext.grid.GroupingView.superclass.renderUI.call(this);if(this.enableGroupingMenu&&this.hmenu){this.hmenu.add("-",{itemId:"groupBy",text:this.groupByText,handler:this.onGroupByClick,scope:this,iconCls:"x-group-by-icon"});if(this.enableNoGroups){this.hmenu.add({itemId:"showGroups",text:this.showGroupsText,checked:true,checkHandler:this.onShowGroupsClick,scope:this})}this.hmenu.on("beforeshow",this.beforeMenuShow,this)}return a},processEvent:function(b,i){Ext.grid.GroupingView.superclass.processEvent.call(this,b,i);var h=i.getTarget(".x-grid-group-hd",this.mainBody);if(h){var g=this.getGroupField(),d=this.getPrefix(g),a=h.id.substring(d.length),c=new RegExp("gp-"+Ext.escapeRe(g)+"--hd");a=a.substr(0,a.length-3);if(a||c.test(h.id)){this.grid.fireEvent("group"+b,this.grid,g,a,i)}if(b=="mousedown"&&i.button==0){this.toggleGroup(h.parentNode)}}},onGroupByClick:function(){var a=this.grid;this.enableGrouping=true;a.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));a.fireEvent("groupchange",a,a.store.getGroupState());this.beforeMenuShow();this.refresh()},onShowGroupsClick:function(a,b){this.enableGrouping=b;if(b){this.onGroupByClick()}else{this.grid.store.clearGrouping();this.grid.fireEvent("groupchange",this,null)}},toggleRowIndex:function(c,a){if(!this.canGroup()){return}var b=this.getRow(c);if(b){this.toggleGroup(this.findGroup(b),a)}},toggleGroup:function(c,b){var a=Ext.get(c),d=Ext.util.Format.htmlEncode(a.id);b=Ext.isDefined(b)?b:a.hasClass("x-grid-group-collapsed");if(this.state[d]!==b){if(this.cancelEditOnToggle!==false){this.grid.stopEditing(true)}this.state[d]=b;a[b?"removeClass":"addClass"]("x-grid-group-collapsed")}},toggleAllGroups:function(c){var b=this.getGroups();for(var d=0,a=b.length;d<a;d++){this.toggleGroup(b[d],c)}},expandAllGroups:function(){this.toggleAllGroups(true)},collapseAllGroups:function(){this.toggleAllGroups(false)},getGroup:function(a,e,i,j,b,h){var c=this.cm.config[b],d=i?i.call(c.scope,a,{},e,j,b,h):String(a);if(d===""||d==="&#160;"){d=c.emptyGroupText||this.emptyGroupText}return d},getGroupField:function(){return this.grid.store.getGroupState()},afterRender:function(){if(!this.ds||!this.cm){return}Ext.grid.GroupingView.superclass.afterRender.call(this);if(this.grid.deferRowRender){this.updateGroupWidths()}},afterRenderUI:function(){Ext.grid.GroupingView.superclass.afterRenderUI.call(this);if(this.enableGroupingMenu&&this.hmenu){this.hmenu.add("-",{itemId:"groupBy",text:this.groupByText,handler:this.onGroupByClick,scope:this,iconCls:"x-group-by-icon"});if(this.enableNoGroups){this.hmenu.add({itemId:"showGroups",text:this.showGroupsText,checked:true,checkHandler:this.onShowGroupsClick,scope:this})}this.hmenu.on("beforeshow",this.beforeMenuShow,this)}},renderRows:function(){var a=this.getGroupField();var e=!!a;if(this.hideGroupedColumn){var b=this.cm.findColumnIndex(a),d=Ext.isDefined(this.lastGroupField);if(!e&&d){this.mainBody.update("");this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField),false);delete this.lastGroupField}else{if(e&&!d){this.lastGroupField=a;this.cm.setHidden(b,true)}else{if(e&&d&&a!==this.lastGroupField){this.mainBody.update("");var c=this.cm.findColumnIndex(this.lastGroupField);this.cm.setHidden(c,false);this.lastGroupField=a;this.cm.setHidden(b,true)}}}}return Ext.grid.GroupingView.superclass.renderRows.apply(this,arguments)},doRender:function(c,h,q,a,p,s){if(h.length<1){return""}if(!this.canGroup()||this.isUpdating){return Ext.grid.GroupingView.superclass.doRender.apply(this,arguments)}var z=this.getGroupField(),o=this.cm.findColumnIndex(z),w,j="width:"+this.getTotalWidth()+";",e=this.cm.config[o],b=e.groupRenderer||e.renderer,t=this.showGroupName?(e.groupName||e.header)+": ":"",y=[],l,u,v,n;for(u=0,v=h.length;u<v;u++){var k=a+u,m=h[u],d=m.data[z];w=this.getGroup(d,m,b,k,o,q);if(!l||l.group!=w){n=this.constructId(d,z,o);this.state[n]=!(Ext.isDefined(this.state[n])?!this.state[n]:this.startCollapsed);l={group:w,gvalue:d,text:t+w,groupId:n,startRow:k,rs:[m],cls:this.state[n]?"":"x-grid-group-collapsed",style:j};y.push(l)}else{l.rs.push(m)}m._groupId=n}var x=[];for(u=0,v=y.length;u<v;u++){w=y[u];this.doGroupStart(x,w,c,q,p);x[x.length]=Ext.grid.GroupingView.superclass.doRender.call(this,c,w.rs,q,w.startRow,p,s);this.doGroupEnd(x,w,c,q,p)}return x.join("")},getGroupId:function(a){var b=this.getGroupField();return this.constructId(a,b,this.cm.findColumnIndex(b))},constructId:function(c,e,a){var b=this.cm.config[a],d=b.groupRenderer||b.renderer,g=(this.groupMode=="value")?c:this.getGroup(c,{data:{}},d,0,a,this.ds);return this.getPrefix(e)+Ext.util.Format.htmlEncode(g)},canGroup:function(){return this.enableGrouping&&!!this.getGroupField()},getPrefix:function(a){return this.grid.getGridEl().id+"-gp-"+a+"-"},doGroupStart:function(a,d,b,e,c){a[a.length]=this.startGroup.apply(d)},doGroupEnd:function(a,d,b,e,c){a[a.length]=this.endGroup},getRows:function(){if(!this.canGroup()){return Ext.grid.GroupingView.superclass.getRows.call(this)}var k=[],c=this.getGroups(),h,e=0,a=c.length,d,b;for(;e<a;++e){h=c[e].childNodes[1];if(h){h=h.childNodes;for(d=0,b=h.length;d<b;++d){k[k.length]=h[d]}}}return k},updateGroupWidths:function(){if(!this.canGroup()||!this.hasRows()){return}var c=Math.max(this.cm.getTotalWidth(),this.el.dom.offsetWidth-this.getScrollOffset())+"px";var b=this.getGroups();for(var d=0,a=b.length;d<a;d++){b[d].firstChild.style.width=c}},onColumnWidthUpdated:function(c,a,b){Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this,c,a,b);this.updateGroupWidths()},onAllColumnWidthsUpdated:function(a,b){Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this,a,b);this.updateGroupWidths()},onColumnHiddenUpdated:function(b,c,a){Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this,b,c,a);this.updateGroupWidths()},onLayout:function(){this.updateGroupWidths()},onBeforeRowSelect:function(b,a){this.toggleRowIndex(a,true)}});Ext.grid.GroupingView.GROUP_ID=1000;
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/ext-base.js b/src/main/webapp/lib/ext-3.4.0/ext-base.js
new file mode 100644
index 0000000000000000000000000000000000000000..7362d51187b499271836eb789942a6073a6f2101
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/ext-base.js
@@ -0,0 +1,7 @@
+/*
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+window.undefined=window.undefined;Ext={version:"3.4.0",versionDetail:{major:3,minor:4,patch:0}};Ext.apply=function(d,e,b){if(b){Ext.apply(d,b)}if(d&&e&&typeof e=="object"){for(var a in e){d[a]=e[a]}}return d};(function(){var g=0,u=Object.prototype.toString,v=navigator.userAgent.toLowerCase(),A=function(e){return e.test(v)},i=document,n=i.documentMode,l=i.compatMode=="CSS1Compat",C=A(/opera/),h=A(/\bchrome\b/),w=A(/webkit/),z=!h&&A(/safari/),f=z&&A(/applewebkit\/4/),b=z&&A(/version\/3/),D=z&&A(/version\/4/),t=!C&&A(/msie/),r=t&&(A(/msie 7/)||n==7),q=t&&(A(/msie 8/)&&n!=7),p=t&&A(/msie 9/),s=t&&!r&&!q&&!p,o=!w&&A(/gecko/),d=o&&A(/rv:1\.8/),a=o&&A(/rv:1\.9/),x=t&&!l,B=A(/windows|win32/),k=A(/macintosh|mac os x/),j=A(/adobeair/),m=A(/linux/),c=/^https/i.test(window.location.protocol);if(s){try{i.execCommand("BackgroundImageCache",false,true)}catch(y){}}Ext.apply(Ext,{SSL_SECURE_URL:c&&t?'javascript:""':"about:blank",isStrict:l,isSecure:c,isReady:false,enableForcedBoxModel:false,enableGarbageCollector:true,enableListenerCollection:false,enableNestedListenerRemoval:false,USE_NATIVE_JSON:false,applyIf:function(E,F){if(E){for(var e in F){if(!Ext.isDefined(E[e])){E[e]=F[e]}}}return E},id:function(e,E){e=Ext.getDom(e,true)||{};if(!e.id){e.id=(E||"ext-gen")+(++g)}return e.id},extend:function(){var E=function(G){for(var F in G){this[F]=G[F]}};var e=Object.prototype.constructor;return function(L,I,K){if(typeof I=="object"){K=I;I=L;L=K.constructor!=e?K.constructor:function(){I.apply(this,arguments)}}var H=function(){},J,G=I.prototype;H.prototype=G;J=L.prototype=new H();J.constructor=L;L.superclass=G;if(G.constructor==e){G.constructor=I}L.override=function(F){Ext.override(L,F)};J.superclass=J.supr=(function(){return G});J.override=E;Ext.override(L,K);L.extend=function(F){return Ext.extend(L,F)};return L}}(),override:function(e,F){if(F){var E=e.prototype;Ext.apply(E,F);if(Ext.isIE&&F.hasOwnProperty("toString")){E.toString=F.toString}}},namespace:function(){var G=arguments.length,H=0,E,F,e,J,I,K;for(;H<G;++H){e=arguments[H];J=arguments[H].split(".");K=window[J[0]];if(K===undefined){K=window[J[0]]={}}I=J.slice(1);E=I.length;for(F=0;F<E;++F){K=K[I[F]]=K[I[F]]||{}}}return K},urlEncode:function(I,H){var F,E=[],G=encodeURIComponent;Ext.iterate(I,function(e,J){F=Ext.isEmpty(J);Ext.each(F?e:J,function(K){E.push("&",G(e),"=",(!Ext.isEmpty(K)&&(K!=e||!F))?(Ext.isDate(K)?Ext.encode(K).replace(/"/g,""):G(K)):"")})});if(!H){E.shift();H=""}return H+E.join("")},urlDecode:function(F,E){if(Ext.isEmpty(F)){return{}}var I={},H=F.split("&"),J=decodeURIComponent,e,G;Ext.each(H,function(K){K=K.split("=");e=J(K[0]);G=J(K[1]);I[e]=E||!I[e]?G:[].concat(I[e]).concat(G)});return I},urlAppend:function(e,E){if(!Ext.isEmpty(E)){return e+(e.indexOf("?")===-1?"?":"&")+E}return e},toArray:function(){return t?function(F,I,G,H){H=[];for(var E=0,e=F.length;E<e;E++){H.push(F[E])}return H.slice(I||0,G||H.length)}:function(e,F,E){return Array.prototype.slice.call(e,F||0,E||e.length)}}(),isIterable:function(e){if(Ext.isArray(e)||e.callee){return true}if(/NodeList|HTMLCollection/.test(u.call(e))){return true}return((typeof e.nextNode!="undefined"||e.item)&&Ext.isNumber(e.length))},each:function(H,G,F){if(Ext.isEmpty(H,true)){return}if(!Ext.isIterable(H)||Ext.isPrimitive(H)){H=[H]}for(var E=0,e=H.length;E<e;E++){if(G.call(F||H[E],H[E],E,H)===false){return E}}},iterate:function(F,E,e){if(Ext.isEmpty(F)){return}if(Ext.isIterable(F)){Ext.each(F,E,e);return}else{if(typeof F=="object"){for(var G in F){if(F.hasOwnProperty(G)){if(E.call(e||F,G,F[G],F)===false){return}}}}}},getDom:function(F,E){if(!F||!i){return null}if(F.dom){return F.dom}else{if(typeof F=="string"){var G=i.getElementById(F);if(G&&t&&E){if(F==G.getAttribute("id")){return G}else{return null}}return G}else{return F}}},getBody:function(){return Ext.get(i.body||i.documentElement)},getHead:function(){var e;return function(){if(e==undefined){e=Ext.get(i.getElementsByTagName("head")[0])}return e}}(),removeNode:t&&!q?function(){var e;return function(E){if(E&&E.tagName!="BODY"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(E,true):Ext.EventManager.removeAll(E);e=e||i.createElement("div");e.appendChild(E);e.innerHTML="";delete Ext.elCache[E.id]}}}():function(e){if(e&&e.parentNode&&e.tagName!="BODY"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(e,true):Ext.EventManager.removeAll(e);e.parentNode.removeChild(e);delete Ext.elCache[e.id]}},isEmpty:function(E,e){return E===null||E===undefined||((Ext.isArray(E)&&!E.length))||(!e?E==="":false)},isArray:function(e){return u.apply(e)==="[object Array]"},isDate:function(e){return u.apply(e)==="[object Date]"},isObject:function(e){return !!e&&Object.prototype.toString.call(e)==="[object Object]"},isPrimitive:function(e){return Ext.isString(e)||Ext.isNumber(e)||Ext.isBoolean(e)},isFunction:function(e){return u.apply(e)==="[object Function]"},isNumber:function(e){return typeof e==="number"&&isFinite(e)},isString:function(e){return typeof e==="string"},isBoolean:function(e){return typeof e==="boolean"},isElement:function(e){return e?!!e.tagName:false},isDefined:function(e){return typeof e!=="undefined"},isOpera:C,isWebKit:w,isChrome:h,isSafari:z,isSafari3:b,isSafari4:D,isSafari2:f,isIE:t,isIE6:s,isIE7:r,isIE8:q,isIE9:p,isGecko:o,isGecko2:d,isGecko3:a,isBorderBox:x,isLinux:m,isWindows:B,isMac:k,isAir:j});Ext.ns=Ext.namespace})();Ext.ns("Ext.util","Ext.lib","Ext.data","Ext.supports");Ext.elCache={};Ext.apply(Function.prototype,{createInterceptor:function(b,a){var c=this;return !Ext.isFunction(b)?this:function(){var e=this,d=arguments;b.target=e;b.method=c;return(b.apply(a||e||window,d)!==false)?c.apply(e||window,d):null}},createCallback:function(){var a=arguments,b=this;return function(){return b.apply(window,a)}},createDelegate:function(c,b,a){var d=this;return function(){var f=b||arguments;if(a===true){f=Array.prototype.slice.call(arguments,0);f=f.concat(b)}else{if(Ext.isNumber(a)){f=Array.prototype.slice.call(arguments,0);var e=[a,0].concat(b);Array.prototype.splice.apply(f,e)}}return d.apply(c||window,f)}},defer:function(c,e,b,a){var d=this.createDelegate(e,b,a);if(c>0){return setTimeout(d,c)}d();return 0}});Ext.applyIf(String,{format:function(b){var a=Ext.toArray(arguments,1);return b.replace(/\{(\d+)\}/g,function(c,d){return a[d]})}});Ext.applyIf(Array.prototype,{indexOf:function(b,c){var a=this.length;c=c||0;c+=(c<0)?a:0;for(;c<a;++c){if(this[c]===b){return c}}return -1},remove:function(b){var a=this.indexOf(b);if(a!=-1){this.splice(a,1)}return this}});Ext.util.TaskRunner=function(e){e=e||10;var f=[],a=[],b=0,g=false,d=function(){g=false;clearInterval(b);b=0},h=function(){if(!g){g=true;b=setInterval(i,e)}},c=function(j){a.push(j);if(j.onStop){j.onStop.apply(j.scope||j)}},i=function(){var l=a.length,n=new Date().getTime();if(l>0){for(var p=0;p<l;p++){f.remove(a[p])}a=[];if(f.length<1){d();return}}for(var p=0,o,k,m,j=f.length;p<j;++p){o=f[p];k=n-o.taskRunTime;if(o.interval<=k){m=o.run.apply(o.scope||o,o.args||[++o.taskRunCount]);o.taskRunTime=n;if(m===false||o.taskRunCount===o.repeat){c(o);return}}if(o.duration&&o.duration<=(n-o.taskStartTime)){c(o)}}};this.start=function(j){f.push(j);j.taskStartTime=new Date().getTime();j.taskRunTime=0;j.taskRunCount=0;h();return j};this.stop=function(j){c(j);return j};this.stopAll=function(){d();for(var k=0,j=f.length;k<j;k++){if(f[k].onStop){f[k].onStop()}}f=[];a=[]}};Ext.TaskMgr=new Ext.util.TaskRunner();(function(){var b;function c(d){if(!b){b=new Ext.Element.Flyweight()}b.dom=d;return b}(function(){var g=document,e=g.compatMode=="CSS1Compat",f=Math.max,d=Math.round,h=parseInt;Ext.lib.Dom={isAncestor:function(j,k){var i=false;j=Ext.getDom(j);k=Ext.getDom(k);if(j&&k){if(j.contains){return j.contains(k)}else{if(j.compareDocumentPosition){return !!(j.compareDocumentPosition(k)&16)}else{while(k=k.parentNode){i=k==j||i}}}}return i},getViewWidth:function(i){return i?this.getDocumentWidth():this.getViewportWidth()},getViewHeight:function(i){return i?this.getDocumentHeight():this.getViewportHeight()},getDocumentHeight:function(){return f(!e?g.body.scrollHeight:g.documentElement.scrollHeight,this.getViewportHeight())},getDocumentWidth:function(){return f(!e?g.body.scrollWidth:g.documentElement.scrollWidth,this.getViewportWidth())},getViewportHeight:function(){return Ext.isIE?(Ext.isStrict?g.documentElement.clientHeight:g.body.clientHeight):self.innerHeight},getViewportWidth:function(){return !Ext.isStrict&&!Ext.isOpera?g.body.clientWidth:Ext.isIE?g.documentElement.clientWidth:self.innerWidth},getY:function(i){return this.getXY(i)[1]},getX:function(i){return this.getXY(i)[0]},getXY:function(k){var j,q,s,v,l,m,u=0,r=0,t,i,n=(g.body||g.documentElement),o=[0,0];k=Ext.getDom(k);if(k!=n){if(k.getBoundingClientRect){s=k.getBoundingClientRect();t=c(document).getScroll();o=[d(s.left+t.left),d(s.top+t.top)]}else{j=k;i=c(k).isStyle("position","absolute");while(j){q=c(j);u+=j.offsetLeft;r+=j.offsetTop;i=i||q.isStyle("position","absolute");if(Ext.isGecko){r+=v=h(q.getStyle("borderTopWidth"),10)||0;u+=l=h(q.getStyle("borderLeftWidth"),10)||0;if(j!=k&&!q.isStyle("overflow","visible")){u+=l;r+=v}}j=j.offsetParent}if(Ext.isSafari&&i){u-=n.offsetLeft;r-=n.offsetTop}if(Ext.isGecko&&!i){m=c(n);u+=h(m.getStyle("borderLeftWidth"),10)||0;r+=h(m.getStyle("borderTopWidth"),10)||0}j=k.parentNode;while(j&&j!=n){if(!Ext.isOpera||(j.tagName!="TR"&&!c(j).isStyle("display","inline"))){u-=j.scrollLeft;r-=j.scrollTop}j=j.parentNode}o=[u,r]}}return o},setXY:function(j,k){(j=Ext.fly(j,"_setXY")).position();var l=j.translatePoints(k),i=j.dom.style,m;for(m in l){if(!isNaN(l[m])){i[m]=l[m]+"px"}}},setX:function(j,i){this.setXY(j,[i,false])},setY:function(i,j){this.setXY(i,[false,j])}}})();Ext.lib.Event=function(){var v=false,f={},z=0,o=[],d,A=false,k=window,E=document,l=200,r=20,p=0,i=1,s=2,w=3,t="scrollLeft",q="scrollTop",g="unload",y="mouseover",D="mouseout",e=function(){var F;if(k.addEventListener){F=function(J,H,I,G){if(H=="mouseenter"){I=I.createInterceptor(n);J.addEventListener(y,I,(G))}else{if(H=="mouseleave"){I=I.createInterceptor(n);J.addEventListener(D,I,(G))}else{J.addEventListener(H,I,(G))}}return I}}else{if(k.attachEvent){F=function(J,H,I,G){J.attachEvent("on"+H,I);return I}}else{F=function(){}}}return F}(),h=function(){var F;if(k.removeEventListener){F=function(J,H,I,G){if(H=="mouseenter"){H=y}else{if(H=="mouseleave"){H=D}}J.removeEventListener(H,I,(G))}}else{if(k.detachEvent){F=function(I,G,H){I.detachEvent("on"+G,H)}}else{F=function(){}}}return F}();function n(F){return !u(F.currentTarget,x.getRelatedTarget(F))}function u(F,G){if(F&&F.firstChild){while(G){if(G===F){return true}G=G.parentNode;if(G&&(G.nodeType!=1)){G=null}}}return false}function B(){var G=false,L=[],J,I,F,H,K=!v||(z>0);if(!A){A=true;for(I=0;I<o.length;++I){F=o[I];if(F&&(J=E.getElementById(F.id))){if(!F.checkReady||v||J.nextSibling||(E&&E.body)){H=F.override;J=H?(H===true?F.obj:H):J;F.fn.call(J,F.obj);o.remove(F);--I}else{L.push(F)}}}z=(L.length===0)?0:z-1;if(K){m()}else{clearInterval(d);d=null}G=!(A=false)}return G}function m(){if(!d){var F=function(){B()};d=setInterval(F,r)}}function C(){var F=E.documentElement,G=E.body;if(F&&(F[q]||F[t])){return[F[t],F[q]]}else{if(G){return[G[t],G[q]]}else{return[0,0]}}}function j(F,G){F=F.browserEvent||F;var H=F["page"+G];if(!H&&H!==0){H=F["client"+G]||0;if(Ext.isIE){H+=C()[G=="X"?0:1]}}return H}var x={extAdapter:true,onAvailable:function(H,F,I,G){o.push({id:H,fn:F,obj:I,override:G,checkReady:false});z=l;m()},addListener:function(H,F,G){H=Ext.getDom(H);if(H&&G){if(F==g){if(f[H.id]===undefined){f[H.id]=[]}f[H.id].push([F,G]);return G}return e(H,F,G,false)}return false},removeListener:function(L,H,K){L=Ext.getDom(L);var J,G,F,I;if(L&&K){if(H==g){if((I=f[L.id])!==undefined){for(J=0,G=I.length;J<G;J++){if((F=I[J])&&F[p]==H&&F[i]==K){f[L.id].splice(J,1)}}}return}h(L,H,K,false)}},getTarget:function(F){F=F.browserEvent||F;return this.resolveTextNode(F.target||F.srcElement)},resolveTextNode:Ext.isGecko?function(G){if(!G){return}var F=HTMLElement.prototype.toString.call(G);if(F=="[xpconnect wrapped native prototype]"||F=="[object XULElement]"){return}return G.nodeType==3?G.parentNode:G}:function(F){return F&&F.nodeType==3?F.parentNode:F},getRelatedTarget:function(F){F=F.browserEvent||F;return this.resolveTextNode(F.relatedTarget||(/(mouseout|mouseleave)/.test(F.type)?F.toElement:/(mouseover|mouseenter)/.test(F.type)?F.fromElement:null))},getPageX:function(F){return j(F,"X")},getPageY:function(F){return j(F,"Y")},getXY:function(F){return[this.getPageX(F),this.getPageY(F)]},stopEvent:function(F){this.stopPropagation(F);this.preventDefault(F)},stopPropagation:function(F){F=F.browserEvent||F;if(F.stopPropagation){F.stopPropagation()}else{F.cancelBubble=true}},preventDefault:function(F){F=F.browserEvent||F;if(F.preventDefault){F.preventDefault()}else{if(F.keyCode){F.keyCode=0}F.returnValue=false}},getEvent:function(F){F=F||k.event;if(!F){var G=this.getEvent.caller;while(G){F=G.arguments[0];if(F&&Event==F.constructor){break}G=G.caller}}return F},getCharCode:function(F){F=F.browserEvent||F;return F.charCode||F.keyCode||0},getListeners:function(G,F){Ext.EventManager.getListeners(G,F)},purgeElement:function(G,H,F){Ext.EventManager.purgeElement(G,H,F)},_load:function(F){v=true;if(Ext.isIE&&F!==true){h(k,"load",arguments.callee)}},_unload:function(J){var G=Ext.lib.Event,H,M,K,F,I,N;for(F in f){K=f[F];for(H=0,I=K.length;H<I;H++){M=K[H];if(M){try{N=M[w]?(M[w]===true?M[s]:M[w]):k;M[i].call(N,G.getEvent(J),M[s])}catch(L){}}}}Ext.EventManager._unload();h(k,g,G._unload)}};x.on=x.addListener;x.un=x.removeListener;if(E&&E.body){x._load(true)}else{e(k,"load",x._load)}e(k,g,x._unload);B();return x}();Ext.lib.Ajax=function(){var g=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP"],d="Content-Type";function h(v){var t=v.conn,w,u={};function s(x,y){for(w in y){if(y.hasOwnProperty(w)){x.setRequestHeader(w,y[w])}}}Ext.apply(u,k.headers,k.defaultHeaders);s(t,u);delete k.headers}function e(v,u,t,s){return{tId:v,status:t?-1:0,statusText:t?"transaction aborted":"communication failure",isAbort:t,isTimeout:s,argument:u}}function j(s,t){(k.headers=k.headers||{})[s]=t}function p(u,y){var C={},x,w=u.conn,A,B,v=w.status==1223;try{x=u.conn.getAllResponseHeaders();Ext.each(x.replace(/\r\n/g,"\n").split("\n"),function(s){A=s.indexOf(":");if(A>=0){B=s.substr(0,A).toLowerCase();if(s.charAt(A+1)==" "){++A}C[B]=s.substr(A+1)}})}catch(z){}return{tId:u.tId,status:v?204:w.status,statusText:v?"No Content":w.statusText,getResponseHeader:function(s){return C[s.toLowerCase()]},getAllResponseHeaders:function(){return x},responseText:w.responseText,responseXML:w.responseXML,argument:y}}function o(s){if(s.tId){k.conn[s.tId]=null}s.conn=null;s=null}function f(x,y,t,s){if(!y){o(x);return}var v,u;try{if(x.conn.status!==undefined&&x.conn.status!=0){v=x.conn.status}else{v=13030}}catch(w){v=13030}if((v>=200&&v<300)||(Ext.isIE&&v==1223)){u=p(x,y.argument);if(y.success){if(!y.scope){y.success(u)}else{y.success.apply(y.scope,[u])}}}else{switch(v){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:u=e(x.tId,y.argument,(t?t:false),s);if(y.failure){if(!y.scope){y.failure(u)}else{y.failure.apply(y.scope,[u])}}break;default:u=p(x,y.argument);if(y.failure){if(!y.scope){y.failure(u)}else{y.failure.apply(y.scope,[u])}}}}o(x);u=null}function m(u,x,s,w,t,v){if(s&&s.readyState==4){clearInterval(t[w]);t[w]=null;if(v){clearTimeout(k.timeout[w]);k.timeout[w]=null}f(u,x)}}function r(s,t){k.abort(s,t,true)}function n(u,x){x=x||{};var s=u.conn,w=u.tId,t=k.poll,v=x.timeout||null;if(v){k.conn[w]=s;k.timeout[w]=setTimeout(r.createCallback(u,x),v)}t[w]=setInterval(m.createCallback(u,x,s,w,t,v),k.pollInterval)}function i(w,t,v,s){var u=l()||null;if(u){u.conn.open(w,t,true);if(k.useDefaultXhrHeader){j("X-Requested-With",k.defaultXhrHeader)}if(s&&k.useDefaultHeader&&(!k.headers||!k.headers[d])){j(d,k.defaultPostHeader)}if(k.defaultHeaders||k.headers){h(u)}n(u,v);u.conn.send(s||null)}return u}function l(){var t;try{if(t=q(k.transactionId)){k.transactionId++}}catch(s){}finally{return t}}function q(v){var s;try{s=new XMLHttpRequest()}catch(u){for(var t=Ext.isIE6?1:0;t<g.length;++t){try{s=new ActiveXObject(g[t]);break}catch(u){}}}finally{return{conn:s,tId:v}}}var k={request:function(s,u,v,w,A){if(A){var x=this,t=A.xmlData,y=A.jsonData,z;Ext.applyIf(x,A);if(t||y){z=x.headers;if(!z||!z[d]){j(d,t?"text/xml":"application/json")}w=t||(!Ext.isPrimitive(y)?Ext.encode(y):y)}}return i(s||A.method||"POST",u,v,w)},serializeForm:function(y){var x=y.elements||(document.forms[y]||Ext.getDom(y)).elements,s=false,w=encodeURIComponent,t,z="",v,u;Ext.each(x,function(A){t=A.name;v=A.type;if(!A.disabled&&t){if(/select-(one|multiple)/i.test(v)){Ext.each(A.options,function(B){if(B.selected){u=B.hasAttribute?B.hasAttribute("value"):B.getAttributeNode("value").specified;z+=String.format("{0}={1}&",w(t),w(u?B.value:B.text))}})}else{if(!(/file|undefined|reset|button/i.test(v))){if(!(/radio|checkbox/i.test(v)&&!A.checked)&&!(v=="submit"&&s)){z+=w(t)+"="+w(A.value)+"&";s=/submit/i.test(v)}}}}});return z.substr(0,z.length-1)},useDefaultHeader:true,defaultPostHeader:"application/x-www-form-urlencoded; charset=UTF-8",useDefaultXhrHeader:true,defaultXhrHeader:"XMLHttpRequest",poll:{},timeout:{},conn:{},pollInterval:50,transactionId:0,abort:function(v,x,s){var u=this,w=v.tId,t=false;if(u.isCallInProgress(v)){v.conn.abort();clearInterval(u.poll[w]);u.poll[w]=null;clearTimeout(k.timeout[w]);u.timeout[w]=null;f(v,x,(t=true),s)}return t},isCallInProgress:function(s){return s.conn&&!{0:true,4:true}[s.conn.readyState]}};return k}();(function(){var g=Ext.lib,i=/width|height|opacity|padding/i,f=/^((width|height)|(top|left))$/,d=/width|height|top$|bottom$|left$|right$/i,h=/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,j=function(k){return typeof k!=="undefined"},e=function(){return new Date()};g.Anim={motion:function(n,l,o,p,k,m){return this.run(n,l,o,p,k,m,Ext.lib.Motion)},run:function(o,l,q,r,k,n,m){m=m||Ext.lib.AnimBase;if(typeof r=="string"){r=Ext.lib.Easing[r]}var p=new m(o,l,q,r);p.animateX(function(){if(Ext.isFunction(k)){k.call(n)}});return p}};g.AnimBase=function(l,k,m,n){if(l){this.init(l,k,m,n)}};g.AnimBase.prototype={doMethod:function(k,n,l){var m=this;return m.method(m.curFrame,n,l-n,m.totalFrames)},setAttr:function(k,m,l){if(i.test(k)&&m<0){m=0}Ext.fly(this.el,"_anim").setStyle(k,m+l)},getAttr:function(k){var m=Ext.fly(this.el),n=m.getStyle(k),l=f.exec(k)||[];if(n!=="auto"&&!h.test(n)){return parseFloat(n)}return(!!(l[2])||(m.getStyle("position")=="absolute"&&!!(l[3])))?m.dom["offset"+l[0].charAt(0).toUpperCase()+l[0].substr(1)]:0},getDefaultUnit:function(k){return d.test(k)?"px":""},animateX:function(n,k){var l=this,m=function(){l.onComplete.removeListener(m);if(Ext.isFunction(n)){n.call(k||l,l)}};l.onComplete.addListener(m,l);l.animate()},setRunAttr:function(p){var r=this,s=this.attributes[p],t=s.to,q=s.by,u=s.from,v=s.unit,l=(this.runAttrs[p]={}),m;if(!j(t)&&!j(q)){return false}var k=j(u)?u:r.getAttr(p);if(j(t)){m=t}else{if(j(q)){if(Ext.isArray(k)){m=[];for(var n=0,o=k.length;n<o;n++){m[n]=k[n]+q[n]}}else{m=k+q}}}Ext.apply(l,{start:k,end:m,unit:j(v)?v:r.getDefaultUnit(p)})},init:function(l,p,o,k){var r=this,n=0,s=g.AnimMgr;Ext.apply(r,{isAnimated:false,startTime:null,el:Ext.getDom(l),attributes:p||{},duration:o||1,method:k||g.Easing.easeNone,useSec:true,curFrame:0,totalFrames:s.fps,runAttrs:{},animate:function(){var u=this,v=u.duration;if(u.isAnimated){return false}u.curFrame=0;u.totalFrames=u.useSec?Math.ceil(s.fps*v):v;s.registerElement(u)},stop:function(u){var v=this;if(u){v.curFrame=v.totalFrames;v._onTween.fire()}s.stop(v)}});var t=function(){var v=this,u;v.onStart.fire();v.runAttrs={};for(u in this.attributes){this.setRunAttr(u)}v.isAnimated=true;v.startTime=e();n=0};var q=function(){var v=this;v.onTween.fire({duration:e()-v.startTime,curFrame:v.curFrame});var w=v.runAttrs;for(var u in w){this.setAttr(u,v.doMethod(u,w[u].start,w[u].end),w[u].unit)}++n};var m=function(){var u=this,w=(e()-u.startTime)/1000,v={duration:w,frames:n,fps:n/w};u.isAnimated=false;n=0;u.onComplete.fire(v)};r.onStart=new Ext.util.Event(r);r.onTween=new Ext.util.Event(r);r.onComplete=new Ext.util.Event(r);(r._onStart=new Ext.util.Event(r)).addListener(t);(r._onTween=new Ext.util.Event(r)).addListener(q);(r._onComplete=new Ext.util.Event(r)).addListener(m)}};Ext.lib.AnimMgr=new function(){var o=this,m=null,l=[],k=0;Ext.apply(o,{fps:1000,delay:1,registerElement:function(q){l.push(q);++k;q._onStart.fire();o.start()},unRegister:function(r,q){r._onComplete.fire();q=q||p(r);if(q!=-1){l.splice(q,1)}if(--k<=0){o.stop()}},start:function(){if(m===null){m=setInterval(o.run,o.delay)}},stop:function(s){if(!s){clearInterval(m);for(var r=0,q=l.length;r<q;++r){if(l[0].isAnimated){o.unRegister(l[0],0)}}l=[];m=null;k=0}else{o.unRegister(s)}},run:function(){var t,s,q,r;for(s=0,q=l.length;s<q;s++){r=l[s];if(r&&r.isAnimated){t=r.totalFrames;if(r.curFrame<t||t===null){++r.curFrame;if(r.useSec){n(r)}r._onTween.fire()}else{o.stop(r)}}}}});var p=function(s){var r,q;for(r=0,q=l.length;r<q;r++){if(l[r]===s){return r}}return -1};var n=function(r){var v=r.totalFrames,u=r.curFrame,t=r.duration,s=(u*t*1000/v),q=(e()-r.startTime),w=0;if(q<t*1000){w=Math.round((q/s-1)*u)}else{w=v-(u+1)}if(w>0&&isFinite(w)){if(r.curFrame+w>=v){w=v-(u+1)}r.curFrame+=w}}};g.Bezier=new function(){this.getPosition=function(p,o){var r=p.length,m=[],q=1-o,l,k;for(l=0;l<r;++l){m[l]=[p[l][0],p[l][1]]}for(k=1;k<r;++k){for(l=0;l<r-k;++l){m[l][0]=q*m[l][0]+o*m[parseInt(l+1,10)][0];m[l][1]=q*m[l][1]+o*m[parseInt(l+1,10)][1]}}return[m[0][0],m[0][1]]}};g.Easing={easeNone:function(l,k,n,m){return n*l/m+k},easeIn:function(l,k,n,m){return n*(l/=m)*l+k},easeOut:function(l,k,n,m){return -n*(l/=m)*(l-2)+k}};(function(){g.Motion=function(o,n,p,q){if(o){g.Motion.superclass.constructor.call(this,o,n,p,q)}};Ext.extend(g.Motion,Ext.lib.AnimBase);var m=g.Motion.superclass,l=/^points$/i;Ext.apply(g.Motion.prototype,{setAttr:function(n,r,q){var p=this,o=m.setAttr;if(l.test(n)){q=q||"px";o.call(p,"left",r[0],q);o.call(p,"top",r[1],q)}else{o.call(p,n,r,q)}},getAttr:function(n){var p=this,o=m.getAttr;return l.test(n)?[o.call(p,"left"),o.call(p,"top")]:o.call(p,n)},doMethod:function(n,q,o){var p=this;return l.test(n)?g.Bezier.getPosition(p.runAttrs[n],p.method(p.curFrame,0,100,p.totalFrames)/100):m.doMethod.call(p,n,q,o)},setRunAttr:function(u){if(l.test(u)){var w=this,p=this.el,z=this.attributes.points,s=z.control||[],x=z.from,y=z.to,v=z.by,A=g.Dom,o,r,q,t,n;if(s.length>0&&!Ext.isArray(s[0])){s=[s]}else{}Ext.fly(p,"_anim").position();A.setXY(p,j(x)?x:A.getXY(p));o=w.getAttr("points");if(j(y)){q=k.call(w,y,o);for(r=0,t=s.length;r<t;++r){s[r]=k.call(w,s[r],o)}}else{if(j(v)){q=[o[0]+v[0],o[1]+v[1]];for(r=0,t=s.length;r<t;++r){s[r]=[o[0]+s[r][0],o[1]+s[r][1]]}}}n=this.runAttrs[u]=[o];if(s.length>0){n=n.concat(s)}n[n.length]=q}else{m.setRunAttr.call(this,u)}}});var k=function(n,p){var o=g.Dom.getXY(this.el);return[n[0]-o[0]+p[0],n[1]-o[1]+p[1]]}})()})();(function(){var d=Math.abs,i=Math.PI,h=Math.asin,g=Math.pow,e=Math.sin,f=Ext.lib;Ext.apply(f.Easing,{easeBoth:function(k,j,m,l){return((k/=l/2)<1)?m/2*k*k+j:-m/2*((--k)*(k-2)-1)+j},easeInStrong:function(k,j,m,l){return m*(k/=l)*k*k*k+j},easeOutStrong:function(k,j,m,l){return -m*((k=k/l-1)*k*k*k-1)+j},easeBothStrong:function(k,j,m,l){return((k/=l/2)<1)?m/2*k*k*k*k+j:-m/2*((k-=2)*k*k*k-2)+j},elasticIn:function(l,j,q,o,k,n){if(l==0||(l/=o)==1){return l==0?j:j+q}n=n||(o*0.3);var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return -(k*g(2,10*(l-=1))*e((l*o-m)*(2*i)/n))+j},elasticOut:function(l,j,q,o,k,n){if(l==0||(l/=o)==1){return l==0?j:j+q}n=n||(o*0.3);var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return k*g(2,-10*l)*e((l*o-m)*(2*i)/n)+q+j},elasticBoth:function(l,j,q,o,k,n){if(l==0||(l/=o/2)==2){return l==0?j:j+q}n=n||(o*(0.3*1.5));var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return l<1?-0.5*(k*g(2,10*(l-=1))*e((l*o-m)*(2*i)/n))+j:k*g(2,-10*(l-=1))*e((l*o-m)*(2*i)/n)*0.5+q+j},backIn:function(k,j,n,m,l){l=l||1.70158;return n*(k/=m)*k*((l+1)*k-l)+j},backOut:function(k,j,n,m,l){if(!l){l=1.70158}return n*((k=k/m-1)*k*((l+1)*k+l)+1)+j},backBoth:function(k,j,n,m,l){l=l||1.70158;return((k/=m/2)<1)?n/2*(k*k*(((l*=(1.525))+1)*k-l))+j:n/2*((k-=2)*k*(((l*=(1.525))+1)*k+l)+2)+j},bounceIn:function(k,j,m,l){return m-f.Easing.bounceOut(l-k,0,m,l)+j},bounceOut:function(k,j,m,l){if((k/=l)<(1/2.75)){return m*(7.5625*k*k)+j}else{if(k<(2/2.75)){return m*(7.5625*(k-=(1.5/2.75))*k+0.75)+j}else{if(k<(2.5/2.75)){return m*(7.5625*(k-=(2.25/2.75))*k+0.9375)+j}}}return m*(7.5625*(k-=(2.625/2.75))*k+0.984375)+j},bounceBoth:function(k,j,m,l){return(k<l/2)?f.Easing.bounceIn(k*2,0,m,l)*0.5+j:f.Easing.bounceOut(k*2-l,0,m,l)*0.5+m*0.5+j}})})();(function(){var h=Ext.lib;h.Anim.color=function(p,n,q,r,m,o){return h.Anim.run(p,n,q,r,m,o,h.ColorAnim)};h.ColorAnim=function(n,m,o,p){h.ColorAnim.superclass.constructor.call(this,n,m,o,p)};Ext.extend(h.ColorAnim,h.AnimBase);var j=h.ColorAnim.superclass,i=/color$/i,f=/^transparent|rgba\(0, 0, 0, 0\)$/,l=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,d=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,e=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,g=function(m){return typeof m!=="undefined"};function k(n){var p=parseInt,o,m=null,q;if(n.length==3){return n}Ext.each([d,l,e],function(s,r){o=(r%2==0)?16:10;q=s.exec(n);if(q&&q.length==4){m=[p(q[1],o),p(q[2],o),p(q[3],o)];return false}});return m}Ext.apply(h.ColorAnim.prototype,{getAttr:function(m){var o=this,n=o.el,p;if(i.test(m)){while(n&&f.test(p=Ext.fly(n).getStyle(m))){n=n.parentNode;p="fff"}}else{p=j.getAttr.call(o,m)}return p},doMethod:function(s,m,o){var t=this,n,q=Math.floor,p,r,u;if(i.test(s)){n=[];o=o||[];for(p=0,r=m.length;p<r;p++){u=m[p];n[p]=j.doMethod.call(t,s,u,o[p])}n="rgb("+q(n[0])+","+q(n[1])+","+q(n[2])+")"}else{n=j.doMethod.call(t,s,m,o)}return n},setRunAttr:function(r){var t=this,u=t.attributes[r],v=u.to,s=u.by,n;j.setRunAttr.call(t,r);n=t.runAttrs[r];if(i.test(r)){var m=k(n.start),o=k(n.end);if(!g(v)&&g(s)){o=k(s);for(var p=0,q=m.length;p<q;p++){o[p]=m[p]+o[p]}}n.start=m;n.end=o}}})})();(function(){var d=Ext.lib;d.Anim.scroll=function(j,h,k,l,g,i){return d.Anim.run(j,h,k,l,g,i,d.Scroll)};d.Scroll=function(h,g,i,j){if(h){d.Scroll.superclass.constructor.call(this,h,g,i,j)}};Ext.extend(d.Scroll,d.ColorAnim);var f=d.Scroll.superclass,e="scroll";Ext.apply(d.Scroll.prototype,{doMethod:function(g,m,h){var k,j=this,l=j.curFrame,i=j.totalFrames;if(g==e){k=[j.method(l,m[0],h[0]-m[0],i),j.method(l,m[1],h[1]-m[1],i)]}else{k=f.doMethod.call(j,g,m,h)}return k},getAttr:function(g){var h=this;if(g==e){return[h.el.scrollLeft,h.el.scrollTop]}else{return f.getAttr.call(h,g)}},setAttr:function(g,j,i){var h=this;if(g==e){h.el.scrollLeft=j[0];h.el.scrollTop=j[1]}else{f.setAttr.call(h,g,j,i)}}})})();if(Ext.isIE){function a(){var d=Function.prototype;delete d.createSequence;delete d.defer;delete d.createDelegate;delete d.createCallback;delete d.createInterceptor;window.detachEvent("onunload",a)}window.attachEvent("onunload",a)}})();
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/ext-jquery-adapter.js b/src/main/webapp/lib/ext-3.4.0/ext-jquery-adapter.js
new file mode 100644
index 0000000000000000000000000000000000000000..3b8695956cd2d10fb2a56c74215289b270067fa7
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/ext-jquery-adapter.js
@@ -0,0 +1,7 @@
+/*
+ * Ext JS Library 3.4.0
+ * Copyright(c) 2006-2011 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+window.undefined=window.undefined;Ext={version:"3.4.0",versionDetail:{major:3,minor:4,patch:0}};Ext.apply=function(d,e,b){if(b){Ext.apply(d,b)}if(d&&e&&typeof e=="object"){for(var a in e){d[a]=e[a]}}return d};(function(){var g=0,u=Object.prototype.toString,v=navigator.userAgent.toLowerCase(),A=function(e){return e.test(v)},i=document,n=i.documentMode,l=i.compatMode=="CSS1Compat",C=A(/opera/),h=A(/\bchrome\b/),w=A(/webkit/),z=!h&&A(/safari/),f=z&&A(/applewebkit\/4/),b=z&&A(/version\/3/),D=z&&A(/version\/4/),t=!C&&A(/msie/),r=t&&(A(/msie 7/)||n==7),q=t&&(A(/msie 8/)&&n!=7),p=t&&A(/msie 9/),s=t&&!r&&!q&&!p,o=!w&&A(/gecko/),d=o&&A(/rv:1\.8/),a=o&&A(/rv:1\.9/),x=t&&!l,B=A(/windows|win32/),k=A(/macintosh|mac os x/),j=A(/adobeair/),m=A(/linux/),c=/^https/i.test(window.location.protocol);if(s){try{i.execCommand("BackgroundImageCache",false,true)}catch(y){}}Ext.apply(Ext,{SSL_SECURE_URL:c&&t?'javascript:""':"about:blank",isStrict:l,isSecure:c,isReady:false,enableForcedBoxModel:false,enableGarbageCollector:true,enableListenerCollection:false,enableNestedListenerRemoval:false,USE_NATIVE_JSON:false,applyIf:function(E,F){if(E){for(var e in F){if(!Ext.isDefined(E[e])){E[e]=F[e]}}}return E},id:function(e,E){e=Ext.getDom(e,true)||{};if(!e.id){e.id=(E||"ext-gen")+(++g)}return e.id},extend:function(){var E=function(G){for(var F in G){this[F]=G[F]}};var e=Object.prototype.constructor;return function(L,I,K){if(typeof I=="object"){K=I;I=L;L=K.constructor!=e?K.constructor:function(){I.apply(this,arguments)}}var H=function(){},J,G=I.prototype;H.prototype=G;J=L.prototype=new H();J.constructor=L;L.superclass=G;if(G.constructor==e){G.constructor=I}L.override=function(F){Ext.override(L,F)};J.superclass=J.supr=(function(){return G});J.override=E;Ext.override(L,K);L.extend=function(F){return Ext.extend(L,F)};return L}}(),override:function(e,F){if(F){var E=e.prototype;Ext.apply(E,F);if(Ext.isIE&&F.hasOwnProperty("toString")){E.toString=F.toString}}},namespace:function(){var G=arguments.length,H=0,E,F,e,J,I,K;for(;H<G;++H){e=arguments[H];J=arguments[H].split(".");K=window[J[0]];if(K===undefined){K=window[J[0]]={}}I=J.slice(1);E=I.length;for(F=0;F<E;++F){K=K[I[F]]=K[I[F]]||{}}}return K},urlEncode:function(I,H){var F,E=[],G=encodeURIComponent;Ext.iterate(I,function(e,J){F=Ext.isEmpty(J);Ext.each(F?e:J,function(K){E.push("&",G(e),"=",(!Ext.isEmpty(K)&&(K!=e||!F))?(Ext.isDate(K)?Ext.encode(K).replace(/"/g,""):G(K)):"")})});if(!H){E.shift();H=""}return H+E.join("")},urlDecode:function(F,E){if(Ext.isEmpty(F)){return{}}var I={},H=F.split("&"),J=decodeURIComponent,e,G;Ext.each(H,function(K){K=K.split("=");e=J(K[0]);G=J(K[1]);I[e]=E||!I[e]?G:[].concat(I[e]).concat(G)});return I},urlAppend:function(e,E){if(!Ext.isEmpty(E)){return e+(e.indexOf("?")===-1?"?":"&")+E}return e},toArray:function(){return t?function(F,I,G,H){H=[];for(var E=0,e=F.length;E<e;E++){H.push(F[E])}return H.slice(I||0,G||H.length)}:function(e,F,E){return Array.prototype.slice.call(e,F||0,E||e.length)}}(),isIterable:function(e){if(Ext.isArray(e)||e.callee){return true}if(/NodeList|HTMLCollection/.test(u.call(e))){return true}return((typeof e.nextNode!="undefined"||e.item)&&Ext.isNumber(e.length))},each:function(H,G,F){if(Ext.isEmpty(H,true)){return}if(!Ext.isIterable(H)||Ext.isPrimitive(H)){H=[H]}for(var E=0,e=H.length;E<e;E++){if(G.call(F||H[E],H[E],E,H)===false){return E}}},iterate:function(F,E,e){if(Ext.isEmpty(F)){return}if(Ext.isIterable(F)){Ext.each(F,E,e);return}else{if(typeof F=="object"){for(var G in F){if(F.hasOwnProperty(G)){if(E.call(e||F,G,F[G],F)===false){return}}}}}},getDom:function(F,E){if(!F||!i){return null}if(F.dom){return F.dom}else{if(typeof F=="string"){var G=i.getElementById(F);if(G&&t&&E){if(F==G.getAttribute("id")){return G}else{return null}}return G}else{return F}}},getBody:function(){return Ext.get(i.body||i.documentElement)},getHead:function(){var e;return function(){if(e==undefined){e=Ext.get(i.getElementsByTagName("head")[0])}return e}}(),removeNode:t&&!q?function(){var e;return function(E){if(E&&E.tagName!="BODY"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(E,true):Ext.EventManager.removeAll(E);e=e||i.createElement("div");e.appendChild(E);e.innerHTML="";delete Ext.elCache[E.id]}}}():function(e){if(e&&e.parentNode&&e.tagName!="BODY"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(e,true):Ext.EventManager.removeAll(e);e.parentNode.removeChild(e);delete Ext.elCache[e.id]}},isEmpty:function(E,e){return E===null||E===undefined||((Ext.isArray(E)&&!E.length))||(!e?E==="":false)},isArray:function(e){return u.apply(e)==="[object Array]"},isDate:function(e){return u.apply(e)==="[object Date]"},isObject:function(e){return !!e&&Object.prototype.toString.call(e)==="[object Object]"},isPrimitive:function(e){return Ext.isString(e)||Ext.isNumber(e)||Ext.isBoolean(e)},isFunction:function(e){return u.apply(e)==="[object Function]"},isNumber:function(e){return typeof e==="number"&&isFinite(e)},isString:function(e){return typeof e==="string"},isBoolean:function(e){return typeof e==="boolean"},isElement:function(e){return e?!!e.tagName:false},isDefined:function(e){return typeof e!=="undefined"},isOpera:C,isWebKit:w,isChrome:h,isSafari:z,isSafari3:b,isSafari4:D,isSafari2:f,isIE:t,isIE6:s,isIE7:r,isIE8:q,isIE9:p,isGecko:o,isGecko2:d,isGecko3:a,isBorderBox:x,isLinux:m,isWindows:B,isMac:k,isAir:j});Ext.ns=Ext.namespace})();Ext.ns("Ext.util","Ext.lib","Ext.data","Ext.supports");Ext.elCache={};Ext.apply(Function.prototype,{createInterceptor:function(b,a){var c=this;return !Ext.isFunction(b)?this:function(){var e=this,d=arguments;b.target=e;b.method=c;return(b.apply(a||e||window,d)!==false)?c.apply(e||window,d):null}},createCallback:function(){var a=arguments,b=this;return function(){return b.apply(window,a)}},createDelegate:function(c,b,a){var d=this;return function(){var f=b||arguments;if(a===true){f=Array.prototype.slice.call(arguments,0);f=f.concat(b)}else{if(Ext.isNumber(a)){f=Array.prototype.slice.call(arguments,0);var e=[a,0].concat(b);Array.prototype.splice.apply(f,e)}}return d.apply(c||window,f)}},defer:function(c,e,b,a){var d=this.createDelegate(e,b,a);if(c>0){return setTimeout(d,c)}d();return 0}});Ext.applyIf(String,{format:function(b){var a=Ext.toArray(arguments,1);return b.replace(/\{(\d+)\}/g,function(c,d){return a[d]})}});Ext.applyIf(Array.prototype,{indexOf:function(b,c){var a=this.length;c=c||0;c+=(c<0)?a:0;for(;c<a;++c){if(this[c]===b){return c}}return -1},remove:function(b){var a=this.indexOf(b);if(a!=-1){this.splice(a,1)}return this}});Ext.util.TaskRunner=function(e){e=e||10;var f=[],a=[],b=0,g=false,d=function(){g=false;clearInterval(b);b=0},h=function(){if(!g){g=true;b=setInterval(i,e)}},c=function(j){a.push(j);if(j.onStop){j.onStop.apply(j.scope||j)}},i=function(){var l=a.length,n=new Date().getTime();if(l>0){for(var p=0;p<l;p++){f.remove(a[p])}a=[];if(f.length<1){d();return}}for(var p=0,o,k,m,j=f.length;p<j;++p){o=f[p];k=n-o.taskRunTime;if(o.interval<=k){m=o.run.apply(o.scope||o,o.args||[++o.taskRunCount]);o.taskRunTime=n;if(m===false||o.taskRunCount===o.repeat){c(o);return}}if(o.duration&&o.duration<=(n-o.taskStartTime)){c(o)}}};this.start=function(j){f.push(j);j.taskStartTime=new Date().getTime();j.taskRunTime=0;j.taskRunCount=0;h();return j};this.stop=function(j){c(j);return j};this.stopAll=function(){d();for(var k=0,j=f.length;k<j;k++){if(f[k].onStop){f[k].onStop()}}f=[];a=[]}};Ext.TaskMgr=new Ext.util.TaskRunner();if(typeof jQuery=="undefined"){throw"Unable to load Ext, jQuery not found."}(function(){var b;Ext.lib.Dom={getViewWidth:function(d){return d?Math.max(jQuery(document).width(),jQuery(window).width()):jQuery(window).width()},getViewHeight:function(d){return d?Math.max(jQuery(document).height(),jQuery(window).height()):jQuery(window).height()},isAncestor:function(e,f){var d=false;e=Ext.getDom(e);f=Ext.getDom(f);if(e&&f){if(e.contains){return e.contains(f)}else{if(e.compareDocumentPosition){return !!(e.compareDocumentPosition(f)&16)}else{while(f=f.parentNode){d=f==e||d}}}}return d},getRegion:function(d){return Ext.lib.Region.getRegion(d)},getY:function(d){return this.getXY(d)[1]},getX:function(d){return this.getXY(d)[0]},getXY:function(f){var e,j,l,m,i=(document.body||document.documentElement);f=Ext.getDom(f);if(f==i){return[0,0]}if(f.getBoundingClientRect){l=f.getBoundingClientRect();m=c(document).getScroll();return[Math.round(l.left+m.left),Math.round(l.top+m.top)]}var n=0,k=0;e=f;var d=c(f).getStyle("position")=="absolute";while(e){n+=e.offsetLeft;k+=e.offsetTop;if(!d&&c(e).getStyle("position")=="absolute"){d=true}if(Ext.isGecko){j=c(e);var o=parseInt(j.getStyle("borderTopWidth"),10)||0;var g=parseInt(j.getStyle("borderLeftWidth"),10)||0;n+=g;k+=o;if(e!=f&&j.getStyle("overflow")!="visible"){n+=g;k+=o}}e=e.offsetParent}if(Ext.isSafari&&d){n-=i.offsetLeft;k-=i.offsetTop}if(Ext.isGecko&&!d){var h=c(i);n+=parseInt(h.getStyle("borderLeftWidth"),10)||0;k+=parseInt(h.getStyle("borderTopWidth"),10)||0}e=f.parentNode;while(e&&e!=i){if(!Ext.isOpera||(e.tagName!="TR"&&c(e).getStyle("display")!="inline")){n-=e.scrollLeft;k-=e.scrollTop}e=e.parentNode}return[n,k]},setXY:function(d,e){d=Ext.fly(d,"_setXY");d.position();var f=d.translatePoints(e);if(e[0]!==false){d.dom.style.left=f.left+"px"}if(e[1]!==false){d.dom.style.top=f.top+"px"}},setX:function(e,d){this.setXY(e,[d,false])},setY:function(d,e){this.setXY(d,[false,e])}};function c(d){if(!b){b=new Ext.Element.Flyweight()}b.dom=d;return b}Ext.lib.Event={getPageX:function(d){d=d.browserEvent||d;return d.pageX},getPageY:function(d){d=d.browserEvent||d;return d.pageY},getXY:function(d){d=d.browserEvent||d;return[d.pageX,d.pageY]},getTarget:function(d){return d.target},on:function(h,d,g,f,e){jQuery(h).bind(d,g)},un:function(f,d,e){jQuery(f).unbind(d,e)},purgeElement:function(d){jQuery(d).unbind()},preventDefault:function(d){d=d.browserEvent||d;if(d.preventDefault){d.preventDefault()}else{d.returnValue=false}},stopPropagation:function(d){d=d.browserEvent||d;if(d.stopPropagation){d.stopPropagation()}else{d.cancelBubble=true}},stopEvent:function(d){this.preventDefault(d);this.stopPropagation(d)},onAvailable:function(j,e,d){var i=new Date();var g=function(){if(i.getElapsed()>10000){clearInterval(h)}var f=document.getElementById(j);if(f){clearInterval(h);e.call(d||window,f)}};var h=setInterval(g,50)},resolveTextNode:Ext.isGecko?function(e){if(!e){return}var d=HTMLElement.prototype.toString.call(e);if(d=="[xpconnect wrapped native prototype]"||d=="[object XULElement]"){return}return e.nodeType==3?e.parentNode:e}:function(d){return d&&d.nodeType==3?d.parentNode:d},getRelatedTarget:function(e){e=e.browserEvent||e;var d=e.relatedTarget;if(!d){if(e.type=="mouseout"){d=e.toElement}else{if(e.type=="mouseover"){d=e.fromElement}}}return this.resolveTextNode(d)}};Ext.lib.Ajax=function(){var d=function(f){return function(h,g){if((g=="error"||g=="timeout")&&f.failure){f.failure.call(f.scope||window,e(f,h))}else{if(f.success){f.success.call(f.scope||window,e(f,h))}}}};var e=function(f,l){var h={},j,g,i;try{j=l.getAllResponseHeaders();Ext.each(j.replace(/\r\n/g,"\n").split("\n"),function(m){g=m.indexOf(":");if(g>=0){i=m.substr(0,g).toLowerCase();if(m.charAt(g+1)==" "){++g}h[i]=m.substr(g+1)}})}catch(k){}return{responseText:l.responseText,responseXML:l.responseXML,argument:f.argument,status:l.status,statusText:l.statusText,getResponseHeader:function(m){return h[m.toLowerCase()]},getAllResponseHeaders:function(){return j}}};return{request:function(l,i,f,j,g){var k={type:l,url:i,data:j,timeout:f.timeout,complete:d(f)};if(g){var h=g.headers;if(g.xmlData){k.data=g.xmlData;k.processData=false;k.type=(l?l:(g.method?g.method:"POST"));if(!h||!h["Content-Type"]){k.contentType="text/xml"}}else{if(g.jsonData){k.data=typeof g.jsonData=="object"?Ext.encode(g.jsonData):g.jsonData;k.processData=false;k.type=(l?l:(g.method?g.method:"POST"));if(!h||!h["Content-Type"]){k.contentType="application/json"}}}if(h){k.beforeSend=function(n){for(var m in h){if(h.hasOwnProperty(m)){n.setRequestHeader(m,h[m])}}}}}jQuery.ajax(k)},formRequest:function(j,i,g,k,f,h){jQuery.ajax({type:Ext.getDom(j).method||"POST",url:i,data:jQuery(j).serialize()+(k?"&"+k:""),timeout:g.timeout,complete:d(g)})},isCallInProgress:function(f){return false},abort:function(f){return false},serializeForm:function(f){return jQuery(f.dom||f).serialize()}}}();Ext.lib.Anim=function(){var d=function(e,f){var g=true;return{stop:function(h){},isAnimated:function(){return g},proxyCallback:function(){g=false;Ext.callback(e,f)}}};return{scroll:function(h,f,j,k,e,g){var i=d(e,g);h=Ext.getDom(h);if(typeof f.scroll.to[0]=="number"){h.scrollLeft=f.scroll.to[0]}if(typeof f.scroll.to[1]=="number"){h.scrollTop=f.scroll.to[1]}i.proxyCallback();return i},motion:function(h,f,i,j,e,g){return this.run(h,f,i,j,e,g)},color:function(h,f,j,k,e,g){var i=d(e,g);i.proxyCallback();return i},run:function(g,q,j,p,h,s,r){var l=d(h,s),m=Ext.fly(g,"_animrun");var f={};for(var i in q){switch(i){case"points":var n,u;m.position();if(n=q.points.by){var t=m.getXY();u=m.translatePoints([t[0]+n[0],t[1]+n[1]])}else{u=m.translatePoints(q.points.to)}f.left=u.left;f.top=u.top;if(!parseInt(m.getStyle("left"),10)){m.setLeft(0)}if(!parseInt(m.getStyle("top"),10)){m.setTop(0)}if(q.points.from){m.setXY(q.points.from)}break;case"width":f.width=q.width.to;if(q.width.from){m.setWidth(q.width.from)}break;case"height":f.height=q.height.to;if(q.height.from){m.setHeight(q.height.from)}break;case"opacity":f.opacity=q.opacity.to;if(q.opacity.from){m.setOpacity(q.opacity.from)}break;case"left":f.left=q.left.to;if(q.left.from){m.setLeft(q.left.from)}break;case"top":f.top=q.top.to;if(q.top.from){m.setTop(q.top.from)}break;case"callback":case"scope":case"xy":break;default:f[i]=q[i].to;if(q[i].from){m.setStyle(i,q[i].from)}break}}jQuery(g).animate(f,j*1000,undefined,l.proxyCallback);return l}}}();Ext.lib.Region=function(f,g,d,e){this.top=f;this[1]=f;this.right=g;this.bottom=d;this.left=e;this[0]=e};Ext.lib.Region.prototype={contains:function(d){return(d.left>=this.left&&d.right<=this.right&&d.top>=this.top&&d.bottom<=this.bottom)},getArea:function(){return((this.bottom-this.top)*(this.right-this.left))},intersect:function(h){var f=Math.max(this.top,h.top);var g=Math.min(this.right,h.right);var d=Math.min(this.bottom,h.bottom);var e=Math.max(this.left,h.left);if(d>=f&&g>=e){return new Ext.lib.Region(f,g,d,e)}else{return null}},union:function(h){var f=Math.min(this.top,h.top);var g=Math.max(this.right,h.right);var d=Math.max(this.bottom,h.bottom);var e=Math.min(this.left,h.left);return new Ext.lib.Region(f,g,d,e)},constrainTo:function(d){this.top=this.top.constrain(d.top,d.bottom);this.bottom=this.bottom.constrain(d.top,d.bottom);this.left=this.left.constrain(d.left,d.right);this.right=this.right.constrain(d.left,d.right);return this},adjust:function(f,e,d,g){this.top+=f;this.left+=e;this.right+=g;this.bottom+=d;return this}};Ext.lib.Region.getRegion=function(g){var i=Ext.lib.Dom.getXY(g);var f=i[1];var h=i[0]+g.offsetWidth;var d=i[1]+g.offsetHeight;var e=i[0];return new Ext.lib.Region(f,h,d,e)};Ext.lib.Point=function(d,e){if(Ext.isArray(d)){e=d[1];d=d[0]}this.x=this.right=this.left=this[0]=d;this.y=this.top=this.bottom=this[1]=e};Ext.lib.Point.prototype=new Ext.lib.Region();if(Ext.isIE){function a(){var d=Function.prototype;delete d.createSequence;delete d.defer;delete d.createDelegate;delete d.createCallback;delete d.createInterceptor;window.detachEvent("onunload",a)}window.attachEvent("onunload",a)}})();
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/corners-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/corners-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fa419b50abe5030db04492578d5dfd39c02fb6ab
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/corners-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/corners.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aa8cae5c83d8f17aefadb93aa9a6f95d6069c40
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/l-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/l-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5ed7f0043b6b0f956076e02583ca7d18a150e8f6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/l-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/l.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/l.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0160f97fe75409f17ab6c3c91f7cbdc58afa8f8f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/l.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/r-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/r-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ea5cae3b7b571ec41ac2b5d38c8a675a1f66efc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/r-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/r.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/r.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34237f6292a7da6ac5d1b95d13ce76a7194dd596
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/r.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/tb-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/tb-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4b1382c349918444e85ec948e50f47b57d0b2382
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/tb-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/box/tb.gif b/src/main/webapp/lib/ext-3.4.0/images/access/box/tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..435889bffe0a3a4f92b1cb5e781be0d1e9e355f0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/box/tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..087b450da86f4da7c5a83047fc9241d16e299e36
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/btn.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3e705baf565760d71621706987ff675fa73decea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/group-cs.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-cs.gif
new file mode 100644
index 0000000000000000000000000000000000000000..aaf0d4616b3b55cefdc90c271679e14e8178d1f1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-cs.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/group-lr.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-lr.gif
new file mode 100644
index 0000000000000000000000000000000000000000..374ea7543201c8866153c0fa6080ca3839af4c45
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-lr.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/group-tb.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..50a997290d72613891cd59c5f7916ef00230c74a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/group-tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..644e9f3c4cb192e1b73213517bd1fd3b89b188c1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ba55d0a1275dbb503b02fd13bbe762f9e47fb7ce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-b.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-bo.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-bo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c672b602be9979e3700d433aae0f7db74103837e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-bo.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f3cd351ebebf246f5d93cfdccae210cba8c27a6a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-o.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-o.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4bdafd046de7199092f9536508b70a74a0a2e8ed
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow-o.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a77be7fd660f13b6277a34ed4fa52e12eb5cbe04
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/button/s-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/editor/tb-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/editor/tb-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd4011d548cc62fcb4ecf3a92a96414fa804cac6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/editor/tb-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/checkbox.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/checkbox.gif
new file mode 100644
index 0000000000000000000000000000000000000000..835b346cc9e0e8e9089a03e4b0058653e99f765e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/checkbox.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9bfd1843ba58552e8965bf60f55aefc435e9df19
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..fcd794477c9f9b6bcbb4098afc7e4fea0f2c52f2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/clear-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..048506d71399300e424a84639ade8447daf723ac
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..d9f9be1d3ad288436855762101f72a2bc85cb23a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/date-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/error-tip-corners.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/error-tip-corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6ea4c3838768c0ec3b5dab8e789333593295c15c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/error-tip-corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/exclamation.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/exclamation.gif
new file mode 100644
index 0000000000000000000000000000000000000000..daa88b8b0544866d49f77eee405d0d888c95f6c9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/exclamation.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/radio.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/radio.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36bb91d0c5ba6b94f2fae4142e1b0daf16b11514
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/radio.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ab8b3b497d35c7989279ca2b6c501dfe0230de63
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..4f92b7256a90e362c5bee4a48e86a82e33ea5d94
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/search-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/text-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/text-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4ce90bb617630f070a19e4277426c31b9de6f21e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/text-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2574eadcccc089007cc24b56af026313577b0ded
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd255727c7b9e974677334090fcca280dd61252a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..c078133e4c958b925f21904b67596c9e6d15988b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/form/trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-left-white.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-left-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..63088f56e1c33fd23437ab00ef3e10570c4a57fa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-left-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-right-white.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-right-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e9e06789044eacb8a695cd1df46449bcb2b9aa07
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/arrow-right-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cc1e473ecc1a48f6d33d935f226588c495da4e05
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-top.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58ff32cc8fa2aa1be310b03bb2af77c1b77abe93
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/col-move-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/columns.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/columns.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2d3a82393e31768c22869778698613b2f5f2174a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/columns.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/dirty.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/dirty.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d524ee540f517e81ae2b60c58b17c10f18468161
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/dirty.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/done.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/done.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a937cb22c84a2ac6ecfc12ae9681ab72ed83ca78
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/done.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..31a332bf78624b183261a82046f3e09d10af2c12
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..926010e172a267419e420a4647973b3e1ee28926
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/footer-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/footer-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..126120f71eef89987818dcf64e6510ae83c8e18e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/footer-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..862094e6803f522712e4d193c7becd8e9b857dd3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-split.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1b0bae3a87e55ac32df29cddf3efd18150ac2faa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-blue-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..637410420736482e521957d51d44f9da47f519de
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d112c54013e1e4c2f606e848352f08958134c46f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-split.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c76a16e95997a487ee9cd1675ecdd99bd2f37c17
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-vista-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-vista-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d0972638e8305d32d4a2419b3dd317f3c8fd3fe2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid-vista-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hd-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hd-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ecd65061c767d14da711a3f09bcf2a557838a8e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hd-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow-over.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0405f6c3f02ae82f92816ed9703c7e3b90e87cff
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..509737aa017944ad89f45ce358f8f3dbb16d2983
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8ec57f578d5744dd50b064cec2b527672b95cd0a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-sel-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-sel-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..93a9ca6ab68d47ce20867d3c153ccee3edf9658c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/grid3-special-col-sel-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-by.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-by.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d6075bba2fd87519bce379df01d12cdbe67f255e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-by.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9bd255e72f6947e0cac51d1078dda0ac17bc65d7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f230489a41b20cb98f87a189898bae0d305e7289
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fd22e6bcbdd55f0a58964b35a690cc4f2bee31b2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/group-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hd-pop.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hd-pop.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eb8ba79679eabb7811c3d9d1c86c43bcf67552cc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hd-pop.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-asc.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8917e0eee0cdf7758e83c4cffa7a7239f72b8427
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-desc.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f26b7c2fc5836850958f7f2b1fafd3988a988d7a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1596126108fd99fc56226b412c6749c55ad5402b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.png b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b81e7ff284100752e155dff383c18bd00107eee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-lock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..af59cf92a4222e1cb044474c96507343dc07a3a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.png b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.png
new file mode 100644
index 0000000000000000000000000000000000000000..9dd5df34b70b94b708e862053ef4a634246acc8d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/hmenu-unlock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/invalid_line.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/invalid_line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..025cffc7f881385adfabdca9d0e81375bada8038
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/invalid_line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/mso-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/mso-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..669f3cf089a61580a9d1c7632a5b1309f8d0439a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/mso-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/nowait.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/nowait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4c5862cd554d78f20683709d0b450b67f81bd24d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/nowait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e4df7a7e66c841cf35c42fc22c5a552304390662
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first.gif
new file mode 100644
index 0000000000000000000000000000000000000000..aa0a822a9d049c39bdf975a8251fe153a5bdb770
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-first.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..67fee759aca71c329ac7b8331f2184383848f192
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e0cf1117b6ee113c173d9408e0518876f71f6df5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-last.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e3e8e8736fda9a384002963d3f10d182374e924d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69899c003278608303cb1f1928018dcf4fe99480
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-next.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0f94bf7be80e539ea17feacdbff72b60a3aade2b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev.gif
new file mode 100644
index 0000000000000000000000000000000000000000..289b12612312a511d1c490b2803686dfb9514c7d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/page-prev.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/pick-button.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/pick-button.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6957924a8bf01f24f6930aa0213d794a3f56924d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/pick-button.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/refresh.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/refresh.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8435d1e47ecad7d067fd693685a351a4faaea985
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/refresh.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-check-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-check-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..610116465e7e34fe6ec137d674a5a65eb44f3313
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-check-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6f4d874f57b160bf731c057d8bd4f85d846ba4a7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-over.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b288e38739ad9914b73eb32837303a11a37f354a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-sel.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-sel.gif
new file mode 100644
index 0000000000000000000000000000000000000000..98209e6e7f1ea8cf1ae6c1d61c49e775a37a246c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/row-sel.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..681628f35cba49d3ab1986553646ad0ea3de86ac
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_asc.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..371f5e4ceacfe79593d125baf96513c6e8ad34eb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_desc.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..000e363a78b78a40dca35ff13e7299f2c7f11662
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/sort_desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/grid/wait.gif b/src/main/webapp/lib/ext-3.4.0/images/access/grid/wait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..471c1a4f93f2cabf0b3a85c3ff8e0a8aadefc548
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/grid/wait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/checked.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fad5893727ee8a13f428aa777380ae97152adec8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/group-checked.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/group-checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d8b08f536c5e366e053640352d61b4cfed683b96
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/group-checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/item-over.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/item-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..01678393246989162922ff0051d855ea02b4c464
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/item-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu-parent.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu-parent.gif
new file mode 100644
index 0000000000000000000000000000000000000000..49286cdf848fa1db016968b8bca6d29a184f5f03
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu-parent.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9bb3960fccd6740a00d6a0009784ec6dad35b9d4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/menu.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/menu/unchecked.gif b/src/main/webapp/lib/ext-3.4.0/images/access/menu/unchecked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43823e52db80e04017b2bc1e031bef2d82c67e6a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/menu/unchecked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43e2862672c761e4d2cb33fa3b42ca0f33aa9baa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..51850b795fdd9d6184cc0fcb2c42ab9fab4c05c1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/light-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/light-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..660bedb84796eaa83297c2db1a6664b791bf606a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/light-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprite-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprite-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e6478670e37ea49286d7f29df999169959338750
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprite-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprites.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a3ffe58b47933397ab771146de9d6d7ae9a6faf3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tool-sprites.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/tools-sprites-trans.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tools-sprites-trans.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ead931ef617ac8520a24a263abb456ebc1bcd54e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/tools-sprites-trans.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6b2649dda021d776ebb3d9deb7cad5ce137d890d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..22d4bbab4c57893a9de3f374e9b9bc5d492b7551
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..51850b795fdd9d6184cc0fcb2c42ab9fab4c05c1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08f8fae1505b0e4f4321c49d734d89feee32d324
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/panel/white-top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/progress/progress-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/progress/progress-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..55629b17c2062908f76ff09f017d65e3c652bb66
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/progress/progress-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/qtip/close.gif b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69ab915e4dd194ad3680a039fd665da11201c74f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-anchor-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-anchor-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f46d31d0b68c65a664bb20a14fadb54dae64b93b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-anchor-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f6a629dc4721ed3a5791151b63f4e4861b6abed
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/qtip/tip-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/shared/glass-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/shared/glass-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ed3c88633c0dfec1e8ed3e55cd21e4f140c352fb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/shared/glass-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/shared/hd-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/shared/hd-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..446be9257c229158b7dfb7a63a4c6d0a5ee42545
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/shared/hd-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/shared/left-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/access/shared/left-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0622439459be39e2920c3c534a12d7f6acb89fce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/shared/left-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/shared/right-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/access/shared/right-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5e3215d5677c474488edc2a3abbd08a6b0a8b113
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/shared/right-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..70aad3fe71d7b4abf9653008f308ef100008545d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..52c045e22f6af155929785de347db1e12a95d4cb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3a30ca224d1fb27f5a4f966fb923c52fb84e7e5b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e48f9f9ccb39df00919c065cec005d3384006eea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/ne-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5ea8b5183018cca8ca76abc447e963eab22f9076
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..65d5cc201cf30c6e1ae95e13617ea0056b4f9707
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/nw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..421b534807c9a12e5fd6b0b09675c68c2031a79b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2b635de0d120cba0492084f6f9e7dcb7072e6a82
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..881a5c42d66b22ba04074e5ee00712285ffe2118
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5f1e3b800e11cb3983cec7b97c6461bcb79cc4c7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/square.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4dc5a2dae25407a9b8c13f1653c133b296fb427d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..030d8f8d8bde964ad5bffdf1c51120269ff2990c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..79bcb8487129724b7b4b70fa000846a969dcf50d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/sizer/sw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-bg.png b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..d213754748bcd28ac1358e39077aa40b339035d2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..4991a745da019fca4259210d0cf79069e054db2f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-bg.png b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1221c457f60f4bbbc192f689a4317326782400e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0c0e2745526c0d8f380e83697e918fbd26c4449
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/slider/slider-v-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-left.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..71a2e88c602849b1cb0947ffd8a73fbde1efe53a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-right.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8f3d6598ad404ef013d4fa0c9db9625daf137983
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/scroll-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..687af2b29c49a4b50d59b787687d3f5c7e4fb644
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3c1b3ebf55a464635a97e605be577eb16749eaf5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-inactive-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e5f827a36088c3697a48a05024d78fa4220e843b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2551f4c397b4450618b6043cee9e87793e418b6e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-btm-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef9a7c262aae098a8ea9458649bda67ca495a65b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fc1fdcdad6b9ba4c13d583ffae45479293b5f92f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-btm-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-btm-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a151553e964bc33288767da19fc688e7d6dc3c0d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tab-strip-btm-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tabs-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tabs-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8194001e3745dc1879bfe03ee0a9aa0d00c37d65
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tabs/tabs-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b67a54e2b2bc66b5664b356d32e8610437bede20
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow-light.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow-light.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b0e24b55e7ee53b419bdd5d769bb036b19fe9592
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow-light.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8acb4608d8f766bd4d808bd02712129272e8365a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-over-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-over-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ee2dd9860c799be6dc194b387c36a953c55aac59
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/btn-over-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/gray-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/gray-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd49438f33937ef9547dc8300fa73c3c239d9e7e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/gray-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/more.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/more.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4f010201be6842a2f603ae0afb1d071b123da07e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/more.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/s-arrow-bo.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/s-arrow-bo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1505eddada2b3287fdb5606fd79ce201fae0fdbd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/s-arrow-bo.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..19bbef3c687f19a70b72c454bc2542e92b04c893
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1bc0420f0f0e30675a9eef74adbcb55e3efe9d00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-sep.gif b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-sep.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30555eecf77b8d42447d1af0a6847c28a560c97a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/toolbar/tb-xl-sep.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/arrows.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/arrows.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2e635eba8c240c727e6963a97fd8543ec2e7712c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/arrows.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-add.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-add.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b22cd1448efa13c47ad6d3b75bdea8b4031c31e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-add.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-between.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-between.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5c6c09d987cf7cee99cf1baec891f85e7477cc02
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-between.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9d9c6a9ce1307c5ba072f08bf77d998bb1b716cb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-over.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30d1ca7107816233884d23239dd76fce79237fe5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-under.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-under.gif
new file mode 100644
index 0000000000000000000000000000000000000000..85f66b1e584aece5a5d6d4cf062b8c1f63edce97
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-under.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aacb307e89d690f46853e01f5c4726bd5d94e31
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b4ae5959c70d182e21ca3f4093fc1b00a6830c85
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..514cf3e0b0ba4970461ccda47173944deddf9739
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6af2e291499ad14453356a829daa8ac59e5b3ed1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..96df6795dba0b1c96b5abcb17b5ae9b9a21550a0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f24ddee799ccebea4dfe60fd65a5703a6a59d44f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-end.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-line.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..75e6da4f8eab0617854929cf5d7ab6e491377081
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b4ae5959c70d182e21ca3f4093fc1b00a6830c85
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..68ba298f4b1f5483167fc72fabee114dd186745f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6af2e291499ad14453356a829daa8ac59e5b3ed1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58ba9e47024ed706c212ce0c9115614bec1a45ba
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b8f42083895bb98276f01a5d0e33debddb3ccf1b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/elbow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder-open.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder-open.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7c52965a66627d634c94d4a2314dd206e160c799
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder-open.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..501e75c01938b9e355a695e707911606c044121b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/folder.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/leaf.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/leaf.gif
new file mode 100644
index 0000000000000000000000000000000000000000..445769d3f863fff85bf8dae9e50ca2fbdd2d580f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/leaf.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/tree/s.gif b/src/main/webapp/lib/ext-3.4.0/images/access/tree/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/tree/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-error.gif b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-error.gif
new file mode 100644
index 0000000000000000000000000000000000000000..05c713c76e7b5acc5c4d3fa4d2865af07f940ca2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-error.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-info.gif b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-info.gif
new file mode 100644
index 0000000000000000000000000000000000000000..adc06132a1376512979b729bc3db9c32bf73de1e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-info.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-question.gif b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-question.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9b31a948e2095d4d96c29ceab0c9d9359071840e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-question.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-warning.gif b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0d89077c93ddd985e31cf3eb86f2fe5c3db87a76
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/icon-warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/left-corners.png b/src/main/webapp/lib/ext-3.4.0/images/access/window/left-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee27176901c72d603ba15fdafd2e760412212b08
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/left-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/left-right.png b/src/main/webapp/lib/ext-3.4.0/images/access/window/left-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..e4123001e72587cc1834777a71732b9432080e72
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/left-right.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/right-corners.png b/src/main/webapp/lib/ext-3.4.0/images/access/window/right-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..87a30d08bf10cf9c98bc33f2753d9da068bb6e96
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/right-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/access/window/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/access/window/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..72b4050fbdb107ca967a557b09e0c90df20dfb19
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/access/window/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/corners-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/corners-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fa419b50abe5030db04492578d5dfd39c02fb6ab
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/corners-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/corners.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aa8cae5c83d8f17aefadb93aa9a6f95d6069c40
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/l-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/l-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5ed7f0043b6b0f956076e02583ca7d18a150e8f6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/l-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/l.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/l.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0160f97fe75409f17ab6c3c91f7cbdc58afa8f8f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/l.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/r-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/r-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ea5cae3b7b571ec41ac2b5d38c8a675a1f66efc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/r-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/r.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/r.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34237f6292a7da6ac5d1b95d13ce76a7194dd596
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/r.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/tb-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/tb-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..562fecca87176274af7bf13c419daaf93f169249
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/tb-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/box/tb.gif b/src/main/webapp/lib/ext-3.4.0/images/default/box/tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..435889bffe0a3a4f92b1cb5e781be0d1e9e355f0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/box/tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ab4f71ac115188898fa2701b6b11561d0461e4d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/btn.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..06b404dd7a101dcaf185a48d8e7272ed975a307a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/group-cs.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-cs.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3d1dca8f05ca550917346830a5a0ae4e16665181
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-cs.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/group-lr.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-lr.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7c549f96d6064d4b0cc022671fd823c13df36d8c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-lr.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/group-tb.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..adeb0a4cf54bdfb626ab6f3c070f6e2919f374c0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/group-tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a4220ee9066357ea2270a842ed244bbaadb23de4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b.gif
new file mode 100644
index 0000000000000000000000000000000000000000..84b64703006ca6d86d335b89f8d40b9fa3883c48
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-b.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-bo.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-bo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..548700bf45a4766e4633a2ad21cdd03a907e191c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-bo.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0953eab5c875fcb0f3b40babd89052b064bf9fec
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-o.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-o.gif
new file mode 100644
index 0000000000000000000000000000000000000000..89c70f36fa653684087485ab673043ecbf615cdd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow-o.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8940774785c25d4467b239aa608a9eee40e273d1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/button/s-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-add.gif b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-add.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b22cd1448efa13c47ad6d3b75bdea8b4031c31e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-add.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08d083355ff1b4e99b9ef8139f28ede1485b50cf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aacb307e89d690f46853e01f5c4726bd5d94e31
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/dd/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/editor/tb-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/editor/tb-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fb70577617cb872bb13241af464385904942d91b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/editor/tb-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/checkbox.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/checkbox.gif
new file mode 100644
index 0000000000000000000000000000000000000000..835b346cc9e0e8e9089a03e4b0058653e99f765e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/checkbox.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..da78d45b3214480842c62514af524f4aebb66124
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..f637fa5d1e12460beabc8b49968ebc0ac883e754
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/clear-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..25ef7b3ae73c0918e97b5fd9c3e0cc5c69bcc14b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..74883b21c54ba3552492162863caf022d51e43c1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/date-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/error-tip-corners.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/error-tip-corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6ea4c3838768c0ec3b5dab8e789333593295c15c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/error-tip-corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/exclamation.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/exclamation.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ea31a3060a36a625cb5cfdf4fdc5cb4fa5c3b239
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/exclamation.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/radio.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/radio.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36bb91d0c5ba6b94f2fae4142e1b0daf16b11514
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/radio.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..db8802beb370d7554d5319c0e0d5c4ecb8da2c5b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..b11f273000ce2ab795468b5c80f2bcdd73b70148
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/search-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/text-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/text-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4179607cc1e9486dd6fcc8467c79b5b41dbf4f76
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/text-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3004ec589026c038e7d056e2b99e3a877d1ecd50
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.psd b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.psd
new file mode 100644
index 0000000000000000000000000000000000000000..e922ee65de361157b2c9bada8704be67a50510ea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-square.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e3701a383107e090fe25d3fb8d63aaa9290435e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f6cba375ae3a96c87639a5b3034d204953d1db14
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..344c7682409411be63023e77ab2e2140403a4fcd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/form/trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-left-white.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-left-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..63088f56e1c33fd23437ab00ef3e10570c4a57fa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-left-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-right-white.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-right-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e9e06789044eacb8a695cd1df46449bcb2b9aa07
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/arrow-right-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cc1e473ecc1a48f6d33d935f226588c495da4e05
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-top.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58ff32cc8fa2aa1be310b03bb2af77c1b77abe93
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/col-move-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/columns.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/columns.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2d3a82393e31768c22869778698613b2f5f2174a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/columns.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/dirty.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/dirty.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4f217a47959965037bdaacf23dbcbe800a59273f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/dirty.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/done.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/done.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a937cb22c84a2ac6ecfc12ae9681ab72ed83ca78
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/done.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..31a332bf78624b183261a82046f3e09d10af2c12
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..926010e172a267419e420a4647973b3e1ee28926
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/footer-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/footer-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..126120f71eef89987818dcf64e6510ae83c8e18e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/footer-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..862094e6803f522712e4d193c7becd8e9b857dd3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-split.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5286f58f6f798184c3eeacba1352cfd39b9ae03e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-blue-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..637410420736482e521957d51d44f9da47f519de
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d112c54013e1e4c2f606e848352f08958134c46f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-split.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c76a16e95997a487ee9cd1675ecdd99bd2f37c17
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-vista-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-vista-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d0972638e8305d32d4a2419b3dd317f3c8fd3fe2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid-vista-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hd-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hd-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..21126075e7397dede53d3032c199cc5dff20d9a1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hd-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow-over.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f9c07af1347fc44dcabb1a9d22458deb195fd92b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8d459a304e0b224f8c28d6b7b585da7019d28cce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-rowheader.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-rowheader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2799b45c6591f1db05c8c00bd1fd0c5c01f57614
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-rowheader.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b4d6ca3bf28ba44b4ee215fddf936aab7cdd5a0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-sel-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-sel-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1dfe9a69eae133929f3835ffcfd108959539b9e5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/grid3-special-col-sel-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-by.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-by.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d6075bba2fd87519bce379df01d12cdbe67f255e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-by.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..495bb051dcee00b837a948af56f7a59e77b69aa5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9c1653b48dbd2d4bb00886c379ba3a66813737c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a33ac30bd2b3758ab2e003f70ce638ab77eaf101
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/group-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hd-pop.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hd-pop.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eb8ba79679eabb7811c3d9d1c86c43bcf67552cc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hd-pop.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-asc.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8917e0eee0cdf7758e83c4cffa7a7239f72b8427
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-desc.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f26b7c2fc5836850958f7f2b1fafd3988a988d7a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1596126108fd99fc56226b412c6749c55ad5402b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.png b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b81e7ff284100752e155dff383c18bd00107eee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-lock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..af59cf92a4222e1cb044474c96507343dc07a3a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.png b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.png
new file mode 100644
index 0000000000000000000000000000000000000000..9dd5df34b70b94b708e862053ef4a634246acc8d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/hmenu-unlock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/invalid_line.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/invalid_line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fb7e0f34d6231868ed2f80b6067be837e70cac44
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/invalid_line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/mso-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/mso-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..669f3cf089a61580a9d1c7632a5b1309f8d0439a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/mso-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/nowait.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/nowait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4c5862cd554d78f20683709d0b450b67f81bd24d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/nowait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1e02c419f5e73fc1ba5770df0448d44adf856288
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d84f41a91fca3a0ccc1107a78ffbf7b62c527afb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-first.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..869706777ce1e5c8350e0086f6febc18aa2bf814
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3df5c2ba50b143fca7d168d5acbcc4404b903ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-last.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..90a7756f6fd77f74fd2b5786dd3586b5c50c8d89
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next.gif
new file mode 100644
index 0000000000000000000000000000000000000000..960163530132545abe690cb8e49c5fef0f923344
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-next.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..37154d62406ddc064dba311b95f554e49ad38003
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eb70cf8f6a3b7f524bbeb3656d875a823b27fd7c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/page-prev.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/pick-button.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/pick-button.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6957924a8bf01f24f6930aa0213d794a3f56924d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/pick-button.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..607800b85e4dee8c3922d56b8666dff796603d6e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh.gif
new file mode 100644
index 0000000000000000000000000000000000000000..110f6844b63f04ee495cb6260aadccc5c91f3245
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/refresh.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-check-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-check-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..610116465e7e34fe6ec137d674a5a65eb44f3313
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-check-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6f4d874f57b160bf731c057d8bd4f85d846ba4a7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-over.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b288e38739ad9914b73eb32837303a11a37f354a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-sel.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-sel.gif
new file mode 100644
index 0000000000000000000000000000000000000000..98209e6e7f1ea8cf1ae6c1d61c49e775a37a246c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/row-sel.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45e545f74423d274d5ba7fd942349e9b6e377787
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_asc.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..67a2a4c669fc5821a07fc486228d626e16d6ad9e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_desc.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34db47c3b1eecab2d3873ee2fc556cd3a6e322f9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/sort_desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/grid/wait.gif b/src/main/webapp/lib/ext-3.4.0/images/default/grid/wait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..471c1a4f93f2cabf0b3a85c3ff8e0a8aadefc548
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/grid/wait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d87b0a9ddd1335a6e7a0b97d9481520f30b821c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/expand.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7b6e1c1ef82bc36104018936848c3ebfa6e05e6b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c18f9e34ac1f4d06525592c5ec25783921e7ab1c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-left.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..99f7993f260b374440c5c8baa41a600eca99d74d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-right.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5b13c5a8b91b86e33d5def2ed29b4e348a5795a2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-top.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a4ca2bb20aad89264b9022fee88ee29154dfb192
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/mini-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..df2a77e9cc50cdb15e8be856710f506d462a9677
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..77ab9dad2948270706c9b982c5fcdce78940b4c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/ns-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-close.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2bdd6239987b95025826fa39f37a036d73ae1c9a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d1daef54c578cced19b7f0c3074dd7a23d071cb1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-light-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-light-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8c2c83d82536f2e1e8c1fa15ccdf6683047b1d34
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/panel-title-light-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/stick.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/stick.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5a1e8ba19fb5b404fad09b7208df29646288345b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/stick.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/stuck.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/stuck.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0a8de4db9d6d272beb7ab432bd8cbc25c5d699de
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/stuck.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close-on.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close-on.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eacea39b623348f656de9a8f0df4ac4b74ceccbd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close-on.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45db61e6000bedd9a4eacdd171d99a9af159389b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/layout/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/checked.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fad5893727ee8a13f428aa777380ae97152adec8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/group-checked.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/group-checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d30b3e5a8f138bfbbfea3d1d6d5631a81268fe26
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/group-checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/item-over.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/item-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..01678393246989162922ff0051d855ea02b4c464
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/item-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu-parent.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu-parent.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1e375622ff951a3a3f1ccc668061e81b9c93b411
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu-parent.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30a2c4b6c0458751f85126e8bbca6ef2ccc2ff00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/menu.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/menu/unchecked.gif b/src/main/webapp/lib/ext-3.4.0/images/default/menu/unchecked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43823e52db80e04017b2bc1e031bef2d82c67e6a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/menu/unchecked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..aa0d0ed8fb4a7af14a00f77c9fb0f456144363d0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9fae2d594d21f4ecb71e577517f1eb60488e92d4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/light-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/light-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58d6747b583f82745f884ce9775dcbe3030e086b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/light-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprite-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprite-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e6478670e37ea49286d7f29df999169959338750
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprite-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprites.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2b6b8098610bd6fe8e0d140e91032bdf49a562c9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tool-sprites.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/tools-sprites-trans.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tools-sprites-trans.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ead931ef617ac8520a24a263abb456ebc1bcd54e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/tools-sprites-trans.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..be6c50e1cef86d45fbddf167e221db5fe365a80e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..578ffb6092a47d9af33fd86615855ac328958537
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..22d4bbab4c57893a9de3f374e9b9bc5d492b7551
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d82c33784d106a699921e8186376adfe08ed7159
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fe7dd1c1ebedc02d4e1aabf91fe43e1bcae824e7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/panel/white-top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/progress/progress-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/progress/progress-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1c1abeb4bda215b2c763146b803f56d52d7622b0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/progress/progress-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/qtip/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43488afdbd4924057e45df94ed68690068fbabac
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/qtip/close.gif b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69ab915e4dd194ad3680a039fd665da11201c74f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-anchor-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-anchor-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9cf485060802498647ba462c826869140085778c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-anchor-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9810acac5b323d99a641627276e8dbb9a3607d2e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/qtip/tip-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/s.gif b/src/main/webapp/lib/ext-3.4.0/images/default/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shadow-c.png b/src/main/webapp/lib/ext-3.4.0/images/default/shadow-c.png
new file mode 100644
index 0000000000000000000000000000000000000000..d435f80aeaf38aa37a2afbea4363d7cf8706205b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shadow-c.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shadow-lr.png b/src/main/webapp/lib/ext-3.4.0/images/default/shadow-lr.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb88b6f2be887650f28b16726e470c09459b9c86
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shadow-lr.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shadow.png b/src/main/webapp/lib/ext-3.4.0/images/default/shadow.png
new file mode 100644
index 0000000000000000000000000000000000000000..75c0eba3e101e3f32cef8bde7bae7383d849e935
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shadow.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/blue-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/blue-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3bbf639efae54ae59e83067121a5283ca34fc319
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/blue-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/calendar.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/calendar.gif
new file mode 100644
index 0000000000000000000000000000000000000000..133cf232b243baf857367233e750477675f3190f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/calendar.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/glass-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/glass-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..26fbbae3bc6d2510832a5ed709f0cb029c2c1170
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/glass-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/hd-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/hd-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..42da1ea1aa4322c3995eebfbbea9a6e8c3eb77ea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/hd-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/large-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/large-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b36b555b4ff04f841bb2101514d8f95bcf7358f4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/large-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/left-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/left-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a0ddd9ee8203b9fc45eb5ee78ae6bcb7e57aed7b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/left-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/loading-balls.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/loading-balls.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ce214beb5cd4db00666778d371223c605874519
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/loading-balls.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/right-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/right-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..dee63e2113fcca680699455e8a56ee3eecc81c40
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/right-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/shared/warning.gif b/src/main/webapp/lib/ext-3.4.0/images/default/shared/warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..806d4bc09385a98ef1ac19d25e30a21310964e7e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/shared/warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b5486c1a95bcc0f39a88c15c10c04ef7c3c561dd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..00ba83500851702fd0afca2129c5b53004ffd1e3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..04e5ecf7d3837aec9510f5467282c10f158a5563
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..09405c7ac7b321b3eb9170b1584167448819a071
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/ne-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6e49d6967c08db2c02a3aeb9c1f3cacb9c8665f6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2fcea8a9285dc74626ba9374055b25ab77e53a08
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/nw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4eb5f0fccb6d0e43905f732d10cd41533745c092
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bf069c243a3f5c59c4019e832bc571371987f030
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c4c1087868afab5b5bfd329f52d9907eb1c0061a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..972055e7b297a702ab9aa2d799d133b94ac92315
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/square.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..14ce6f7251071ecadda2c968ebdcc5047018de50
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..77224b0c06f1666685286c5322fb02b4cd2204bc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ca0ed96df2059fe283c1d65fa1032a777e1ff97
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/sizer/sw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-bg.png b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..999919424c820e7494e29e8d701df9b697ce9ed3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd654a4c1680183026145066b4aa1a7802605456
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-bg.png b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..121450c282e485da05b0d7e05955bd1398907e85
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b3d7258ada4c81c6fc060bd5eea69524f0ddd65
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/slider/slider-v-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-left.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f2f6d1c9e4b17d8af76e4655e913cef103e0566
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-right.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4c5e7e3958dd31d9591fb86b76bcea760d402589
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroll-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroller-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroller-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..099b90d8aca10ad0e0a87552e5eca975a72f985a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/scroller-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..188bf940c64cb483a289ca3f6a0b2cfb16a05af9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e1f5e3c5182e7d62c4b1a80532b71eab66a7271d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-inactive-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..dde796870137f9f9e091100ec800072498b64f80
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..da49c100d472066782ec8625d8634755cb0538ef
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45346ab145a9f4796dfbebe62d84c2a785e16b21
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-over-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e695186d5ebb450c6ebf6b6ef270ba407c735977
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-btm-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e699878484183bf770efe1e9376a6d0d36b5f1fa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34f13334511d9d8efe3dee18e6f69f3d1277f8e6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.png b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa8ab3f462f07ad14c7dbbf76117118a302e35a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-btm-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-btm-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5eaba1eaa33086243ab1ffed1402e8e4904443b0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tab-strip-btm-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tabs-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tabs-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e969fb0b7338c81f8e22e3f69f82fe49fb9b3d2d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tabs/tabs-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b085bf24e173f7a2568c347f3245bdaade1579b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow-light.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow-light.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b0e24b55e7ee53b419bdd5d769bb036b19fe9592
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow-light.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8acb4608d8f766bd4d808bd02712129272e8365a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-over-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-over-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ee2dd9860c799be6dc194b387c36a953c55aac59
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/btn-over-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/gray-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/gray-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd49438f33937ef9547dc8300fa73c3c239d9e7e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/gray-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/more.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/more.gif
new file mode 100644
index 0000000000000000000000000000000000000000..02c2509fee0fb4555df61072d8e8daac8dc7430e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/more.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4969e4efeb37821bba1319dce59cd339cec06f86
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..19bbef3c687f19a70b72c454bc2542e92b04c893
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1bc0420f0f0e30675a9eef74adbcb55e3efe9d00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-sep.gif b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-sep.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30555eecf77b8d42447d1af0a6847c28a560c97a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/toolbar/tb-xl-sep.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/arrows.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/arrows.gif
new file mode 100644
index 0000000000000000000000000000000000000000..26834639123c3b8c913f1862559d2431b07310d0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/arrows.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-add.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-add.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b22cd1448efa13c47ad6d3b75bdea8b4031c31e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-add.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-between.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-between.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5c6c09d987cf7cee99cf1baec891f85e7477cc02
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-between.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9d9c6a9ce1307c5ba072f08bf77d998bb1b716cb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-over.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30d1ca7107816233884d23239dd76fce79237fe5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-under.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-under.gif
new file mode 100644
index 0000000000000000000000000000000000000000..85f66b1e584aece5a5d6d4cf062b8c1f63edce97
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-under.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aacb307e89d690f46853e01f5c4726bd5d94e31
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..928779e92361aaebfe9446b236d95cb64256e443
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9a8d727d70ff5161ec18c0cd0156ae8d50a23b75
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f7f69880f48db8d86785639055fcc198764617b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5943a01bcd390798668a2722b673f6000938a52e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f24ddee799ccebea4dfe60fd65a5703a6a59d44f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-end.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-line.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..75e6da4f8eab0617854929cf5d7ab6e491377081
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..928779e92361aaebfe9446b236d95cb64256e443
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..97dcc7110f13c3cfb72a66a9891e8ab3ccef4a98
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f7f69880f48db8d86785639055fcc198764617b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..698de4793c59b2729feaeb0c49c05498d65c3b00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b8f42083895bb98276f01a5d0e33debddb3ccf1b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/elbow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder-open.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder-open.gif
new file mode 100644
index 0000000000000000000000000000000000000000..56ba737bcc7734693d7ddb2f50c8f3235fceacee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder-open.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..20412f7c1ba83b82dc3421b211db2f2e93f08bf2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/folder.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/leaf.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/leaf.gif
new file mode 100644
index 0000000000000000000000000000000000000000..445769d3f863fff85bf8dae9e50ca2fbdd2d580f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/leaf.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/tree/s.gif b/src/main/webapp/lib/ext-3.4.0/images/default/tree/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/tree/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-error.gif b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-error.gif
new file mode 100644
index 0000000000000000000000000000000000000000..397b655ab83e5362fdc7eb0d18cf361c6f86bd9d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-error.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-info.gif b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-info.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58281c3067b309779f5cf949a7196170c8ca97b9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-info.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-question.gif b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-question.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08abd82ae86c9457172c7a4fdbc527641cf28e48
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-question.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-warning.gif b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27ff98b4f787f776e24227da0227bc781e3b11e8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/icon-warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.png b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a518335d342b449d7ba38f4dda0795d8e464012
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.psd b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.psd
new file mode 100644
index 0000000000000000000000000000000000000000..3d7f0623e03727a632cf003e22e11593d547de53
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-corners.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.png b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..7586ff3339a48b828abf06c241b9a0aad9a78368
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.psd b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.psd
new file mode 100644
index 0000000000000000000000000000000000000000..59a3960a2353ebe4c9a22bde84cb79979f3150ad
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/left-right.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.png b/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..e69a3ffc962e9e3dc762ebefe931f3a42003e7e3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.psd b/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.psd
new file mode 100644
index 0000000000000000000000000000000000000000..86d5095386123b82d2cf11b8308dd1e40459fd9a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/right-corners.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..33779e76b8d7407100e44ea79974d9c8300a9573
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.psd b/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.psd
new file mode 100644
index 0000000000000000000000000000000000000000..48c5395e4a2fba1b6c354bcfb00011c7be116b1d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/default/window/top-bottom.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f90d5df4455c332d19dcc8b621a19e53c672612a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..834ff97891d8261c15166ba080df9b7296f6982f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..96ea61abb4e4b522ee314222ae59471886101c9e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-cs.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-cs.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7059e2b0ce43b8cdcc4fd0ca4491c1f2d2c55e0b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-cs.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-lr.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-lr.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3f41fbd841a22ed3f7522bb853ec09b688021e0e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-lr.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-tb.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c5ea8cab3ab64cd947776848455ffbdc7763fd5f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/group-tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-bo.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-bo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fa5b2f4e95781276d027b5d24d8e07607d8ab591
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-bo.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-o.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-o.gif
new file mode 100644
index 0000000000000000000000000000000000000000..52a514132fefe43e5ce98ab2c9198fd32eef2323
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/button/s-arrow-o.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/form/clear-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/form/clear-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..be3ff587cdb41bc01c38b02f378b7097c49e41fd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/form/clear-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/form/date-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/form/date-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e0537cbc5654132851fa5bb06712ec0c481f75f4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/form/date-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/form/search-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/form/search-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0cc4f596b4afa65392eaa6f63fad54238705eb43
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/form/search-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger-square.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger-square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7a0f585c0bc6e4bdb0550ae3984ed884cf9b6f2d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger-square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b563474bb18e44a0e06f1c08826bb691208b13a2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/form/trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c525f7ebd730582b18ee02869d9aedc9fbbf527d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-top.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ccc92b6bc2f7a55aff742a88abc09822e90237ba
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/col-move-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hd-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hd-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..daf1ef2b5d979ad22bdcaf038a4037ceb5b581f8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hd-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d37252f7ee845a7e0c92a5cfebb24c9b8c9d8857
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over2.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over2.gif
new file mode 100644
index 0000000000000000000000000000000000000000..353d90626ea426cc2fff395d3d89c7bfff4b216b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow-over2.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8d459a304e0b224f8c28d6b7b585da7019d28cce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow2.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow2.gif
new file mode 100644
index 0000000000000000000000000000000000000000..423b507bbca6e8ff21a5c1c92c052f91497ab97b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-hrow2.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..12d64d7cd45677be881f27077bb4a41a944751e2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg2.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg2.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f10e6ad1e0ba42d5235b35b10decb96d1806735b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-bg2.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-sel-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-sel-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4fa6e10714e6b2b234ba96add832107d50803cb1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/grid3-special-col-sel-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c9ad30dd91e6a867e8646c431a90025edf9d0977
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d24891de607c912cf0ffa684da447de7b74c7029
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..663b5c8413e2b56915358f4428ff10eb11dac023
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/group-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-first.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-first.gif
new file mode 100644
index 0000000000000000000000000000000000000000..60be4bcd3b851cf6f0d853b503467851014b5d2f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-first.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-last.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-last.gif
new file mode 100644
index 0000000000000000000000000000000000000000..beb4a8302a5363f25143e4934753aaae92c1029c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-last.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-next.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-next.gif
new file mode 100644
index 0000000000000000000000000000000000000000..97db1c220739ebe7f1cd7f8d44b0aa87d9eb3c19
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-next.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-prev.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-prev.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d07e61c36a89c5c40e752663e60a9500e383dc53
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/page-prev.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/refresh.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/refresh.gif
new file mode 100644
index 0000000000000000000000000000000000000000..868b2dc594ed057242f5b642e0c28a764edb9412
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/refresh.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/row-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/row-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..09c00a66baeddeeed16bc06a428b8a93bf4d944c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/row-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4cf483d25c557e7a812f364083ba0c5c1145a491
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_asc.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7e562e202dbba8990cc767b17ee85c6f73e18bfb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_desc.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9b7a871b780073954f929a901bd062a86dc97ed7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/grid/sort_desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/menu/group-checked.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/group-checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c8824887c0a6c8ad2d965bdc8cf3cc2461b61664
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/group-checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..97d5ffacb769047b4e0a889446a9df4d1ea5aac4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e0dc5f7c06c1be1b3fd4e7104be5b3dd0b63c9d8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/item-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/menu/menu-parent.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/menu-parent.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5461a8bfc3ffb5ab25cc99893e322d0ca5c58df4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/menu/menu-parent.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fad0e6d241b1023b74bbb92b9658fa5aa7a5f3a6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c5f3dca5a8d4be7a61223c1a33e2c8b50b72025a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/light-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/light-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6eb28ba00468798814887bdded6cda7c505bf296
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/light-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprite-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprite-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..18277a3d4873a92ed7b481533026dd6e6f91f831
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprite-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprites.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36b6b6755e3635ff92992745d87c7f71e7120766
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tool-sprites.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tools-sprites-trans.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tools-sprites-trans.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b6d7ba369a70e2f3ebddab526904cc3c70a489d1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/tools-sprites-trans.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..24ceb30bd6844ee3ebbe71d1d80e71175286829e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..578ffb6092a47d9af33fd86615855ac328958537
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d5b8adfd18f530a71fbbb081aef99ce7d3fc2221
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2c9e142be832aa2b1bfc7e5df32cc70f5c721c6e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..025fbd51ab056b068cd7cf2556652263d26bf578
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/panel/white-top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/progress/progress-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/progress/progress-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5585d802fb566804cffd9ca41775d2aa9fc39ed8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/progress/progress-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a9055a5ebade2f4ba2f5fd1461d9f8a3478646ac
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/close.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69ab915e4dd194ad3680a039fd665da11201c74f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-anchor-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-anchor-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0671586f3b1af76f979139cc3d9d702e7827da17
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-anchor-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4ade664ef27fa2cac59f5f12aa28e5c3e18d3151
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/qtip/tip-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/s.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/shared/hd-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/hd-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d943833e1dcd0f1418ee3a9a014837d437f19b28
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/hd-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/shared/left-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/left-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3301054ffa24c326b0f13facdb9382e53a04d9ce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/left-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/shared/right-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/right-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c529110fab1e66fe8b883c1a9053aa30ebe01315
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/shared/right-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a8ed0edee93975d0d233cffe52d9f2e85e7d0d81
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/ne-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/ne-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6f7b0c2958b20d3b23c5abda3b43dc1559f9a720
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/ne-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/nw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/nw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..92ad82cf3642db5fa14321505b5e121c878e9758
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/nw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d7eeae278cf8013f3cab45c1b9a069579cd20bdd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f011a3bb2e9fe281dbfcf9adff0eb0d370456557
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/square.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7751d5e15a785f1a50b61bfc8c5c21a0f9421358
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/sw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/sw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..aa903dd0b54ee8834378cc9db771477132da64ee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/sizer/sw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..4bf01be8952e0c2fef407b15833da6017d6109f7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-v-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-v-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b3eeb703f92943763428b44292197c8b4329fb4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/slider/slider-v-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-left.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bbb3e3d9d35fd19b61bd8d0a0bd5f42dd3e82ccf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-right.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..feb6a76f0ae36a545fcc77242b53261680199c39
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroll-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroller-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroller-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f089c0ad65ccfc9be9663e7e0d65f547e9160ac3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/scroller-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d718173fcd30bb0dc4d1f5fcc791c49f079e9bbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bf35493685825b861e5adcfe7e9c22d331a6e50f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-inactive-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..96d2e5eb8a519e15bf48608df8d4c5b5a92ec7d4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..164d1016945304e0f9bcc09126e78b21cf73dc6b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f6f04953f688ea974fafc87d1c01caee6cdb1bf0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-over-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c41cada78932294c367dfe3da5c1f6789a920fa2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-btm-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..98d5da9528411ee291e0548246d9c86a82455d32
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..040b677a52f9a5eff89870aa31d1874765ea5a39
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.png b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa8ab3f462f07ad14c7dbbf76117118a302e35a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-btm-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-btm-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f35087f2bc150f125e54c3c99004e4d27f57f966
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tab-strip-btm-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tabs-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tabs-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1901b231b007616143c945403e60d961f41e3b32
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tabs/tabs-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ab78a2ec788d6dfbbcd6212a4d3b1d9917d55e7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow-light.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow-light.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b0e24b55e7ee53b419bdd5d769bb036b19fe9592
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow-light.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8acb4608d8f766bd4d808bd02712129272e8365a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-over-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-over-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ee2dd9860c799be6dc194b387c36a953c55aac59
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/btn-over-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/gray-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/gray-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5464e21ee835d4600af2892524375b8217be88aa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/gray-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/more.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/more.gif
new file mode 100644
index 0000000000000000000000000000000000000000..77f4f237c3be34bac1b6592ef053afb7cd7453d4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/more.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4969e4efeb37821bba1319dce59cd339cec06f86
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..894fef2eef6401c22c610489f5f7936559d52dd2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/toolbar/tb-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tree/arrows.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/arrows.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a51a8e477fb2be3d370ba4841944dc6572f1673a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/arrows.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8c5bc5d4d58687fa82008a24eb12b4f4512548f2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..585051376cf71dfb82cf109d88c2857168dbd913
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..752b42a3c74c39538bfca4c94afa9bb09de0befe
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ff126359d396ef5e5c9a9bcec2bdfba4dc084a52
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/tree/elbow-end-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-error.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-error.gif
new file mode 100644
index 0000000000000000000000000000000000000000..397b655ab83e5362fdc7eb0d18cf361c6f86bd9d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-error.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-info.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-info.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58281c3067b309779f5cf949a7196170c8ca97b9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-info.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-question.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-question.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08abd82ae86c9457172c7a4fdbc527641cf28e48
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-question.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-warning.gif b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27ff98b4f787f776e24227da0227bc781e3b11e8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/icon-warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-corners.png b/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2da00dbad565f1c8b96b02e56080eafec1483b6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-right.png b/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..4c81137bbed83b71978c9092a4a228cd9731b745
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/left-right.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/right-corners.png b/src/main/webapp/lib/ext-3.4.0/images/gray/window/right-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..807eb474476ae1d1e600cdf77ff0635daba5808f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/right-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/gray/window/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/gray/window/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..f479fcf3cc6ad008991bd7feffa52364014c917b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/gray/window/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-center.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-center.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7bf4a4b41d57c4889b8551cbeef72cd4d432e24e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-center.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-left.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..94b1dafc7d708463f8998c4fc5d6cd4b9940a7ef
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-right.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6dadaf683e0cb584d9eca292808102b194873dda
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/bg-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/close.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4278db9835cf57d9c0e759204d9b7d2add221dc0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b07e297e5c64370fbe4cc8c0a57e89c10e1367e6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/dlg-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/dlg-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1a466633d70ca1475db2c11061d37911e3b7205c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/dlg-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..48877e748d8fd70185e08c4847b16c932d653664
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/expand.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5b4b0d1e950e34f602f5227eb7e0fa9d707953b0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/hd-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/hd-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3c2dd632dd60f2fbd55ca74969053abcb40a0b89
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/hd-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c13c9cdc0561773f3684528ca64dc6286eeda5b5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c4e38a2f4b416ae6be8390d665e04660be23253d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/w-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/w-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d59eafc2076a5a40099bd26d7457a73ba9bc9ac5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/basic-dialog/w-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-split.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c76a16e95997a487ee9cd1675ecdd99bd2f37c17
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-vista-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-vista-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d0972638e8305d32d4a2419b3dd317f3c8fd3fe2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/grid/grid-vista-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cbd6e081cf7a213a8e57a3096631c5e1231da477
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/expand.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8103c0dd7bee8904c73480b549fcca92c120c4d6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d311e7de678b9b299180cc43fd0e27aa094089ad
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f2ad235dad390e71a096e2e943ade1f22c1de113
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0817ec66fd410022c495adacc4855a4cc548ce0f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/ns-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-close.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4e96481a1fdb16a6f332ae06e138f15ac24fcc03
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..681f517a3c2e78c59a0a066e72c9d98c89bd5798
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-light-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-light-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..23d8288b0d3505deeb0ce924a552e2306e9ef14c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/panel-title-light-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/stick.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/stick.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7db68eec95fc77cce1fc4560a257dd0fef64c200
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/stick.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close-on.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close-on.gif
new file mode 100644
index 0000000000000000000000000000000000000000..556e905b11cddb4abcacaf2160ff811ec47a894d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close-on.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0a6f0198775daec8c8d8e40c3ecc0323b1d14232
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/layout/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5c0e8c92a810d244a29f21f467b90f5d61fdf0ec
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/tip-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/tip-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a1862865d59fd04c0d1c45b26aeb31f157e0bbbb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/qtip/tip-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/s.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eac9662eade56ad43732ddff31ebe463871c445e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f2c9f538243ecbc0364b1afd7287248ce8f2c513
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c9c041c45f673735de9f54f7967eddec62cde469
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..942ae825357ebae7f68e5ef818d7ebc5de4c02cd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/ne-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..23fced98bfa4e805e9e078fcad909735344b7957
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d39b0c38d8994139e389a7da016506e0537aac66
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/nw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ddc2e18ce48da6338fb4e065effd31f769ae3e34
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..827c3330a989b89c5ef2ecdc3078326895b290f4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1a678e67fd6edad35c463cb6d96b05fc9d6e89c8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69b5a9ed5b1347e0f0c373a93f3017aece628727
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..937102c6b23e59f512f74b5393378ced56e006c9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b9e2f563a037e362e69290dff5c19f0316f4659b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/sizer/sw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..667beeb3268f50fd40fe6dbdc5b03041b82ae006
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6c4e0a45f9e1e18625fd57c8192afd3d054d788c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-inactive-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d81e54e1043facc21074c0e90417f108e0a53f0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..47d005002984901edbb5391509f6f9c16a6dd905
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-btm-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a16eedb822c1d852020d7c58a40307659ad1f8ee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/tabs/tab-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/gray-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/gray-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9af15c262563fdf82d84fca1e6944327671f28c6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/gray-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/tb-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/tb-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f21b0d612a2e7486e9719fa076df74af31172098
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/vista/toolbar/tb-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/README.txt b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..acc5087329c401eaeb1225d0d132c7381f669e07
--- /dev/null
+++ b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/README.txt
@@ -0,0 +1,2 @@
+2010-03-16 jwr:
+The image directory, "yourtheme", is an exact copy of the "default" image directory. Remember to update your file paths in "css/yourtheme.css" if you make changes or add your own custom images for your custom theme.
\ No newline at end of file
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fa419b50abe5030db04492578d5dfd39c02fb6ab
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aa8cae5c83d8f17aefadb93aa9a6f95d6069c40
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5ed7f0043b6b0f956076e02583ca7d18a150e8f6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0160f97fe75409f17ab6c3c91f7cbdc58afa8f8f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/l.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ea5cae3b7b571ec41ac2b5d38c8a675a1f66efc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34237f6292a7da6ac5d1b95d13ce76a7194dd596
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/r.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb-blue.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb-blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..562fecca87176274af7bf13c419daaf93f169249
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb-blue.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..435889bffe0a3a4f92b1cb5e781be0d1e9e355f0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/box/tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ab4f71ac115188898fa2701b6b11561d0461e4d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/btn.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..06b404dd7a101dcaf185a48d8e7272ed975a307a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-cs.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-cs.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3d1dca8f05ca550917346830a5a0ae4e16665181
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-cs.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-lr.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-lr.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7c549f96d6064d4b0cc022671fd823c13df36d8c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-lr.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-tb.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-tb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..adeb0a4cf54bdfb626ab6f3c070f6e2919f374c0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/group-tb.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a4220ee9066357ea2270a842ed244bbaadb23de4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b.gif
new file mode 100644
index 0000000000000000000000000000000000000000..84b64703006ca6d86d335b89f8d40b9fa3883c48
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-b.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-bo.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-bo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..548700bf45a4766e4633a2ad21cdd03a907e191c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-bo.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-noline.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-noline.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0953eab5c875fcb0f3b40babd89052b064bf9fec
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-noline.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-o.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-o.gif
new file mode 100644
index 0000000000000000000000000000000000000000..89c70f36fa653684087485ab673043ecbf615cdd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow-o.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8940774785c25d4467b239aa608a9eee40e273d1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/button/s-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-add.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-add.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b22cd1448efa13c47ad6d3b75bdea8b4031c31e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-add.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08d083355ff1b4e99b9ef8139f28ede1485b50cf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aacb307e89d690f46853e01f5c4726bd5d94e31
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/dd/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/editor/tb-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/editor/tb-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fb70577617cb872bb13241af464385904942d91b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/editor/tb-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/checkbox.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/checkbox.gif
new file mode 100644
index 0000000000000000000000000000000000000000..835b346cc9e0e8e9089a03e4b0058653e99f765e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/checkbox.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..da78d45b3214480842c62514af524f4aebb66124
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..f637fa5d1e12460beabc8b49968ebc0ac883e754
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/clear-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..25ef7b3ae73c0918e97b5fd9c3e0cc5c69bcc14b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..74883b21c54ba3552492162863caf022d51e43c1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/date-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/error-tip-corners.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/error-tip-corners.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6ea4c3838768c0ec3b5dab8e789333593295c15c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/error-tip-corners.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/exclamation.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/exclamation.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ea31a3060a36a625cb5cfdf4fdc5cb4fa5c3b239
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/exclamation.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/radio.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/radio.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36bb91d0c5ba6b94f2fae4142e1b0daf16b11514
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/radio.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..db8802beb370d7554d5319c0e0d5c4ecb8da2c5b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..b11f273000ce2ab795468b5c80f2bcdd73b70148
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/search-trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/text-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/text-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4179607cc1e9486dd6fcc8467c79b5b41dbf4f76
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/text-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3004ec589026c038e7d056e2b99e3a877d1ecd50
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.psd
new file mode 100644
index 0000000000000000000000000000000000000000..e922ee65de361157b2c9bada8704be67a50510ea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-square.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e3701a383107e090fe25d3fb8d63aaa9290435e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f6cba375ae3a96c87639a5b3034d204953d1db14
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.psd
new file mode 100644
index 0000000000000000000000000000000000000000..344c7682409411be63023e77ab2e2140403a4fcd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/form/trigger.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-left-white.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-left-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..63088f56e1c33fd23437ab00ef3e10570c4a57fa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-left-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-right-white.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-right-white.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e9e06789044eacb8a695cd1df46449bcb2b9aa07
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/arrow-right-white.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cc1e473ecc1a48f6d33d935f226588c495da4e05
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-top.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58ff32cc8fa2aa1be310b03bb2af77c1b77abe93
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/col-move-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/columns.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/columns.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2d3a82393e31768c22869778698613b2f5f2174a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/columns.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/dirty.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/dirty.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4f217a47959965037bdaacf23dbcbe800a59273f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/dirty.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/done.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/done.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a937cb22c84a2ac6ecfc12ae9681ab72ed83ca78
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/done.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..31a332bf78624b183261a82046f3e09d10af2c12
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..926010e172a267419e420a4647973b3e1ee28926
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/footer-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/footer-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..126120f71eef89987818dcf64e6510ae83c8e18e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/footer-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..862094e6803f522712e4d193c7becd8e9b857dd3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-split.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5286f58f6f798184c3eeacba1352cfd39b9ae03e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-blue-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..637410420736482e521957d51d44f9da47f519de
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d112c54013e1e4c2f606e848352f08958134c46f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-split.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-split.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c76a16e95997a487ee9cd1675ecdd99bd2f37c17
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-split.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-vista-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-vista-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d0972638e8305d32d4a2419b3dd317f3c8fd3fe2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid-vista-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hd-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hd-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..21126075e7397dede53d3032c199cc5dff20d9a1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hd-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow-over.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f9c07af1347fc44dcabb1a9d22458deb195fd92b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8d459a304e0b224f8c28d6b7b585da7019d28cce
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-hrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b4d6ca3bf28ba44b4ee215fddf936aab7cdd5a0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-sel-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-sel-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1dfe9a69eae133929f3835ffcfd108959539b9e5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/grid3-special-col-sel-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-by.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-by.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d6075bba2fd87519bce379df01d12cdbe67f255e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-by.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..495bb051dcee00b837a948af56f7a59e77b69aa5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9c1653b48dbd2d4bb00886c379ba3a66813737c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a33ac30bd2b3758ab2e003f70ce638ab77eaf101
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/group-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hd-pop.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hd-pop.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eb8ba79679eabb7811c3d9d1c86c43bcf67552cc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hd-pop.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-asc.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8917e0eee0cdf7758e83c4cffa7a7239f72b8427
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-desc.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f26b7c2fc5836850958f7f2b1fafd3988a988d7a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1596126108fd99fc56226b412c6749c55ad5402b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b81e7ff284100752e155dff383c18bd00107eee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-lock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..af59cf92a4222e1cb044474c96507343dc07a3a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.png
new file mode 100644
index 0000000000000000000000000000000000000000..9dd5df34b70b94b708e862053ef4a634246acc8d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/hmenu-unlock.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/invalid_line.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/invalid_line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fb7e0f34d6231868ed2f80b6067be837e70cac44
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/invalid_line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/mso-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/mso-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..669f3cf089a61580a9d1c7632a5b1309f8d0439a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/mso-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/nowait.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/nowait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4c5862cd554d78f20683709d0b450b67f81bd24d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/nowait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1e02c419f5e73fc1ba5770df0448d44adf856288
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d84f41a91fca3a0ccc1107a78ffbf7b62c527afb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-first.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..869706777ce1e5c8350e0086f6febc18aa2bf814
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3df5c2ba50b143fca7d168d5acbcc4404b903ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-last.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..90a7756f6fd77f74fd2b5786dd3586b5c50c8d89
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next.gif
new file mode 100644
index 0000000000000000000000000000000000000000..960163530132545abe690cb8e49c5fef0f923344
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-next.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev-disabled.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev-disabled.gif
new file mode 100644
index 0000000000000000000000000000000000000000..37154d62406ddc064dba311b95f554e49ad38003
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev-disabled.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eb70cf8f6a3b7f524bbeb3656d875a823b27fd7c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/page-prev.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/pick-button.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/pick-button.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6957924a8bf01f24f6930aa0213d794a3f56924d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/pick-button.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/refresh.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/refresh.gif
new file mode 100644
index 0000000000000000000000000000000000000000..110f6844b63f04ee495cb6260aadccc5c91f3245
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/refresh.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-check-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-check-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..610116465e7e34fe6ec137d674a5a65eb44f3313
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-check-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-expand-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-expand-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6f4d874f57b160bf731c057d8bd4f85d846ba4a7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-expand-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-over.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b288e38739ad9914b73eb32837303a11a37f354a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-sel.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-sel.gif
new file mode 100644
index 0000000000000000000000000000000000000000..98209e6e7f1ea8cf1ae6c1d61c49e775a37a246c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/row-sel.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45e545f74423d274d5ba7fd942349e9b6e377787
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_asc.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_asc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..67a2a4c669fc5821a07fc486228d626e16d6ad9e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_asc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_desc.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_desc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34db47c3b1eecab2d3873ee2fc556cd3a6e322f9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/sort_desc.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/wait.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/wait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..471c1a4f93f2cabf0b3a85c3ff8e0a8aadefc548
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/grid/wait.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d87b0a9ddd1335a6e7a0b97d9481520f30b821c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/expand.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7b6e1c1ef82bc36104018936848c3ebfa6e05e6b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/gradient-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/gradient-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8134e4994f2a36da074990b94a5f17aefd378600
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/gradient-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c18f9e34ac1f4d06525592c5ec25783921e7ab1c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-left.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..99f7993f260b374440c5c8baa41a600eca99d74d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-right.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5b13c5a8b91b86e33d5def2ed29b4e348a5795a2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-top.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-top.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a4ca2bb20aad89264b9022fee88ee29154dfb192
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/mini-top.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-collapse.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-collapse.gif
new file mode 100644
index 0000000000000000000000000000000000000000..df2a77e9cc50cdb15e8be856710f506d462a9677
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-collapse.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-expand.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-expand.gif
new file mode 100644
index 0000000000000000000000000000000000000000..77ab9dad2948270706c9b982c5fcdce78940b4c4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/ns-expand.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-close.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2bdd6239987b95025826fa39f37a036d73ae1c9a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d1daef54c578cced19b7f0c3074dd7a23d071cb1
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-light-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-light-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8c2c83d82536f2e1e8c1fa15ccdf6683047b1d34
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/panel-title-light-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stick.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stick.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5a1e8ba19fb5b404fad09b7208df29646288345b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stick.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stuck.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stuck.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0a8de4db9d6d272beb7ab432bd8cbc25c5d699de
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/stuck.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close-on.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close-on.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eacea39b623348f656de9a8f0df4ac4b74ceccbd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close-on.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45db61e6000bedd9a4eacdd171d99a9af159389b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/layout/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/checked.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fad5893727ee8a13f428aa777380ae97152adec8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/group-checked.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/group-checked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d30b3e5a8f138bfbbfea3d1d6d5631a81268fe26
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/group-checked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/item-over.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/item-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..01678393246989162922ff0051d855ea02b4c464
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/item-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu-parent.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu-parent.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1e375622ff951a3a3f1ccc668061e81b9c93b411
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu-parent.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30a2c4b6c0458751f85126e8bbca6ef2ccc2ff00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/menu.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/unchecked.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/unchecked.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43823e52db80e04017b2bc1e031bef2d82c67e6a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/menu/unchecked.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..aa0d0ed8fb4a7af14a00f77c9fb0f456144363d0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9fae2d594d21f4ecb71e577517f1eb60488e92d4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/light-hd.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/light-hd.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58d6747b583f82745f884ce9775dcbe3030e086b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/light-hd.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprite-tpl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprite-tpl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e6478670e37ea49286d7f29df999169959338750
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprite-tpl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprites.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9a3c5b9ac58bb0057f1f776e170bd1aa9908dce4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tool-sprites.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tools-sprites-trans.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tools-sprites-trans.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ead931ef617ac8520a24a263abb456ebc1bcd54e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/tools-sprites-trans.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..be6c50e1cef86d45fbddf167e221db5fe365a80e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..578ffb6092a47d9af33fd86615855ac328958537
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-corners-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-corners-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..22d4bbab4c57893a9de3f374e9b9bc5d492b7551
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-corners-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-left-right.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-left-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d82c33784d106a699921e8186376adfe08ed7159
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-left-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-top-bottom.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-top-bottom.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fe7dd1c1ebedc02d4e1aabf91fe43e1bcae824e7
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/panel/white-top-bottom.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/progress/progress-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/progress/progress-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1c1abeb4bda215b2c763146b803f56d52d7622b0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/progress/progress-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43488afdbd4924057e45df94ed68690068fbabac
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/close.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..69ab915e4dd194ad3680a039fd665da11201c74f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-anchor-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-anchor-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9cf485060802498647ba462c826869140085778c
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-anchor-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9810acac5b323d99a641627276e8dbb9a3607d2e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/qtip/tip-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/s.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-c.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-c.png
new file mode 100644
index 0000000000000000000000000000000000000000..d435f80aeaf38aa37a2afbea4363d7cf8706205b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-c.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-lr.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-lr.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb88b6f2be887650f28b16726e470c09459b9c86
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow-lr.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow.png
new file mode 100644
index 0000000000000000000000000000000000000000..75c0eba3e101e3f32cef8bde7bae7383d849e935
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shadow.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/blue-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/blue-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3bbf639efae54ae59e83067121a5283ca34fc319
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/blue-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/calendar.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/calendar.gif
new file mode 100644
index 0000000000000000000000000000000000000000..133cf232b243baf857367233e750477675f3190f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/calendar.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/glass-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/glass-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..26fbbae3bc6d2510832a5ed709f0cb029c2c1170
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/glass-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/hd-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/hd-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..42da1ea1aa4322c3995eebfbbea9a6e8c3eb77ea
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/hd-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/large-loading.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/large-loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b36b555b4ff04f841bb2101514d8f95bcf7358f4
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/large-loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/left-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/left-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a0ddd9ee8203b9fc45eb5ee78ae6bcb7e57aed7b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/left-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/loading-balls.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/loading-balls.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ce214beb5cd4db00666778d371223c605874519
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/loading-balls.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/right-btn.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/right-btn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..dee63e2113fcca680699455e8a56ee3eecc81c40
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/right-btn.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/warning.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..806d4bc09385a98ef1ac19d25e30a21310964e7e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/shared/warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b5486c1a95bcc0f39a88c15c10c04ef7c3c561dd
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..00ba83500851702fd0afca2129c5b53004ffd1e3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/e-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..04e5ecf7d3837aec9510f5467282c10f158a5563
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..09405c7ac7b321b3eb9170b1584167448819a071
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/ne-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6e49d6967c08db2c02a3aeb9c1f3cacb9c8665f6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2fcea8a9285dc74626ba9374055b25ab77e53a08
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/nw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4eb5f0fccb6d0e43905f732d10cd41533745c092
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bf069c243a3f5c59c4019e832bc571371987f030
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/s-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c4c1087868afab5b5bfd329f52d9907eb1c0061a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..972055e7b297a702ab9aa2d799d133b94ac92315
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/se-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/square.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/square.gif
new file mode 100644
index 0000000000000000000000000000000000000000..14ce6f7251071ecadda2c968ebdcc5047018de50
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/square.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle-dark.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle-dark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..77224b0c06f1666685286c5322fb02b4cd2204bc
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle-dark.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3ca0ed96df2059fe283c1d65fa1032a777e1ff97
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/sizer/sw-handle.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-bg.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..999919424c820e7494e29e8d701df9b697ce9ed3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd654a4c1680183026145066b4aa1a7802605456
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-bg.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..121450c282e485da05b0d7e05955bd1398907e85
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-thumb.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-thumb.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b3d7258ada4c81c6fc060bd5eea69524f0ddd65
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/slider/slider-v-thumb.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-left.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f2f6d1c9e4b17d8af76e4655e913cef103e0566
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-left.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-right.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-right.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4c5e7e3958dd31d9591fb86b76bcea760d402589
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroll-right.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroller-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroller-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..099b90d8aca10ad0e0a87552e5eca975a72f985a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/scroller-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..188bf940c64cb483a289ca3f6a0b2cfb16a05af9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e1f5e3c5182e7d62c4b1a80532b71eab66a7271d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..dde796870137f9f9e091100ec800072498b64f80
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-left-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-left-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..da49c100d472066782ec8625d8634755cb0538ef
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-left-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..45346ab145a9f4796dfbebe62d84c2a785e16b21
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-over-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-right-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-right-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e695186d5ebb450c6ebf6b6ef270ba407c735977
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-btm-right-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-close.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e699878484183bf770efe1e9376a6d0d36b5f1fa
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-close.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..34f13334511d9d8efe3dee18e6f69f3d1277f8e6
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa8ab3f462f07ad14c7dbbf76117118a302e35a9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-bg.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-btm-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-btm-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5eaba1eaa33086243ab1ffed1402e8e4904443b0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tab-strip-btm-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tabs-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tabs-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e969fb0b7338c81f8e22e3f69f82fe49fb9b3d2d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tabs/tabs-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b085bf24e173f7a2568c347f3245bdaade1579b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow-light.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow-light.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b0e24b55e7ee53b419bdd5d769bb036b19fe9592
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow-light.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8acb4608d8f766bd4d808bd02712129272e8365a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-arrow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-over-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-over-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ee2dd9860c799be6dc194b387c36a953c55aac59
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/btn-over-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/gray-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/gray-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd49438f33937ef9547dc8300fa73c3c239d9e7e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/gray-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/more.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/more.gif
new file mode 100644
index 0000000000000000000000000000000000000000..02c2509fee0fb4555df61072d8e8daac8dc7430e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/more.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-bg.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-bg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4969e4efeb37821bba1319dce59cd339cec06f86
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-bg.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..19bbef3c687f19a70b72c454bc2542e92b04c893
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-btn-sprite.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-btn-sprite.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1bc0420f0f0e30675a9eef74adbcb55e3efe9d00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-btn-sprite.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-sep.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-sep.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30555eecf77b8d42447d1af0a6847c28a560c97a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/toolbar/tb-xl-sep.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/arrows.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/arrows.gif
new file mode 100644
index 0000000000000000000000000000000000000000..26834639123c3b8c913f1862559d2431b07310d0
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/arrows.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-add.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-add.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b22cd1448efa13c47ad6d3b75bdea8b4031c31e9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-add.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-between.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-between.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5c6c09d987cf7cee99cf1baec891f85e7477cc02
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-between.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-no.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9d9c6a9ce1307c5ba072f08bf77d998bb1b716cb
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-no.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-over.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-over.gif
new file mode 100644
index 0000000000000000000000000000000000000000..30d1ca7107816233884d23239dd76fce79237fe5
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-over.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-under.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-under.gif
new file mode 100644
index 0000000000000000000000000000000000000000..85f66b1e584aece5a5d6d4cf062b8c1f63edce97
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-under.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-yes.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-yes.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8aacb307e89d690f46853e01f5c4726bd5d94e31
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/drop-yes.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..928779e92361aaebfe9446b236d95cb64256e443
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9a8d727d70ff5161ec18c0cd0156ae8d50a23b75
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f7f69880f48db8d86785639055fcc198764617b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5943a01bcd390798668a2722b673f6000938a52e
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f24ddee799ccebea4dfe60fd65a5703a6a59d44f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-end.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-line.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-line.gif
new file mode 100644
index 0000000000000000000000000000000000000000..75e6da4f8eab0617854929cf5d7ab6e491377081
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-line.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..928779e92361aaebfe9446b236d95cb64256e443
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..97dcc7110f13c3cfb72a66a9891e8ab3ccef4a98
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-minus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus-nl.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus-nl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9f7f69880f48db8d86785639055fcc198764617b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus-nl.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus.gif
new file mode 100644
index 0000000000000000000000000000000000000000..698de4793c59b2729feaeb0c49c05498d65c3b00
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow-plus.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b8f42083895bb98276f01a5d0e33debddb3ccf1b
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/elbow.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder-open.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder-open.gif
new file mode 100644
index 0000000000000000000000000000000000000000..56ba737bcc7734693d7ddb2f50c8f3235fceacee
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder-open.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..20412f7c1ba83b82dc3421b211db2f2e93f08bf2
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/folder.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/leaf.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/leaf.gif
new file mode 100644
index 0000000000000000000000000000000000000000..445769d3f863fff85bf8dae9e50ca2fbdd2d580f
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/leaf.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/loading.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/loading.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/s.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/s.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1d11fa9ada9e93505b3d736acb204083f45d5fbf
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/tree/s.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-error.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-error.gif
new file mode 100644
index 0000000000000000000000000000000000000000..397b655ab83e5362fdc7eb0d18cf361c6f86bd9d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-error.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-info.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-info.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58281c3067b309779f5cf949a7196170c8ca97b9
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-info.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-question.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-question.gif
new file mode 100644
index 0000000000000000000000000000000000000000..08abd82ae86c9457172c7a4fdbc527641cf28e48
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-question.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-warning.gif b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27ff98b4f787f776e24227da0227bc781e3b11e8
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/icon-warning.gif differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a518335d342b449d7ba38f4dda0795d8e464012
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.psd
new file mode 100644
index 0000000000000000000000000000000000000000..3d7f0623e03727a632cf003e22e11593d547de53
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-corners.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..7586ff3339a48b828abf06c241b9a0aad9a78368
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.psd
new file mode 100644
index 0000000000000000000000000000000000000000..59a3960a2353ebe4c9a22bde84cb79979f3150ad
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/left-right.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..e69a3ffc962e9e3dc762ebefe931f3a42003e7e3
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.psd
new file mode 100644
index 0000000000000000000000000000000000000000..86d5095386123b82d2cf11b8308dd1e40459fd9a
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/right-corners.psd differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.png b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..33779e76b8d7407100e44ea79974d9c8300a9573
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.png differ
diff --git a/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.psd b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.psd
new file mode 100644
index 0000000000000000000000000000000000000000..48c5395e4a2fba1b6c354bcfb00011c7be116b1d
Binary files /dev/null and b/src/main/webapp/lib/ext-3.4.0/images/yourtheme/window/top-bottom.psd differ
diff --git a/src/main/webapp/lib/firebug/errorIcon.png b/src/main/webapp/lib/firebug/errorIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d75261bb675f5f878a9ca549340d11694287ea9
Binary files /dev/null and b/src/main/webapp/lib/firebug/errorIcon.png differ
diff --git a/src/main/webapp/lib/firebug/firebug.css b/src/main/webapp/lib/firebug/firebug.css
new file mode 100644
index 0000000000000000000000000000000000000000..1f041c4da95c0ae9e3d22af6a51d256d8b50aa17
--- /dev/null
+++ b/src/main/webapp/lib/firebug/firebug.css
@@ -0,0 +1,209 @@
+
+html, body {
+    margin: 0;
+    background: #FFFFFF;
+    font-family: Lucida Grande, Tahoma, sans-serif;
+    font-size: 11px;
+    overflow: hidden;
+}
+
+a {
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+.toolbar {
+    height: 14px;
+    border-top: 1px solid ThreeDHighlight;
+    border-bottom: 1px solid ThreeDShadow;
+    padding: 2px 6px;
+    background: ThreeDFace;
+}
+
+.toolbarRight {
+    position: absolute;
+    top: 4px;
+    right: 6px;
+}
+
+#log {
+    overflow: auto;
+    position: absolute;
+    left: 0;
+    width: 100%;
+}
+
+#commandLine {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 18px;
+    border: none;
+    border-top: 1px solid ThreeDShadow;
+}
+
+/************************************************************************************************/
+
+.logRow {
+    position: relative;
+    border-bottom: 1px solid #D7D7D7;
+    padding: 2px 4px 1px 6px;
+    background-color: #FFFFFF;
+}
+
+.logRow-command {
+    font-family: Monaco, monospace;
+    color: blue;
+}
+
+.objectBox-null {
+    padding: 0 2px;
+    border: 1px solid #666666;
+    background-color: #888888;
+    color: #FFFFFF;
+}
+
+.objectBox-string {
+    font-family: Monaco, monospace;
+    color: red;
+    white-space: pre;
+}
+
+.objectBox-number {
+    color: #000088;
+}
+
+.objectBox-function {
+    font-family: Monaco, monospace;
+    color: DarkGreen;
+}
+
+.objectBox-object {
+    color: DarkGreen;
+    font-weight: bold;
+}
+
+/************************************************************************************************/
+
+.logRow-info,
+.logRow-error,
+.logRow-warning {
+    background: #FFFFFF no-repeat 2px 2px;
+    padding-left: 20px;
+    padding-bottom: 3px;
+}
+
+.logRow-info {
+    background-image: url(infoIcon.png);
+}
+
+.logRow-warning {
+    background-color: cyan;
+    background-image: url(warningIcon.png);
+}
+
+.logRow-error {
+    background-color: LightYellow;
+    background-image: url(errorIcon.png);
+}
+
+.errorMessage {
+    vertical-align: top;
+    color: #FF0000;
+}
+
+.objectBox-sourceLink {
+    position: absolute;
+    right: 4px;
+    top: 2px;
+    padding-left: 8px;
+    font-family: Lucida Grande, sans-serif;
+    font-weight: bold;
+    color: #0000FF;
+}
+
+/************************************************************************************************/
+
+.logRow-group {
+    background: #EEEEEE;
+    border-bottom: none;
+}
+
+.logGroup {
+    background: #EEEEEE;
+}
+
+.logGroupBox {
+    margin-left: 24px;
+    border-top: 1px solid #D7D7D7;
+    border-left: 1px solid #D7D7D7;
+}
+
+/************************************************************************************************/
+
+.selectorTag,
+.selectorId,
+.selectorClass {
+    font-family: Monaco, monospace;
+    font-weight: normal;
+}
+
+.selectorTag {
+    color: #0000FF;
+}
+
+.selectorId {
+    color: DarkBlue;
+}
+
+.selectorClass {
+    color: red;
+}
+
+/************************************************************************************************/
+
+.objectBox-element {
+    font-family: Monaco, monospace;
+    color: #000088;
+}
+
+.nodeChildren {
+    margin-left: 16px;
+}
+
+.nodeTag {
+    color: blue;
+}
+
+.nodeValue {
+    color: #FF0000;
+    font-weight: normal;
+}
+
+.nodeText,
+.nodeComment {
+    margin: 0 2px;
+    vertical-align: top;
+}
+
+.nodeText {
+    color: #333333;
+}
+
+.nodeComment {
+    color: DarkGreen;
+}
+
+/************************************************************************************************/
+
+.propertyNameCell {
+    vertical-align: top;
+}
+
+.propertyName {
+    font-weight: bold;
+}
diff --git a/src/main/webapp/lib/firebug/firebug.html b/src/main/webapp/lib/firebug/firebug.html
new file mode 100644
index 0000000000000000000000000000000000000000..861e6393268a324d12c468e0b4da26beffce9137
--- /dev/null
+++ b/src/main/webapp/lib/firebug/firebug.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+    <title>Firebug</title>
+    <link rel="stylesheet" type="text/css" href="firebug.css">
+</head>
+
+<body>
+    <div id="toolbar" class="toolbar">
+        <a href="#" onclick="parent.console.clear()">Clear</a>
+        <span class="toolbarRight">
+            <a href="#" onclick="parent.console.close()">Close</a>
+        </span>
+    </div>
+    <div id="log"></div>
+    <input type="text" id="commandLine">
+    
+    <script>parent.onFirebugReady(document);</script>
+</body>
+</html>
diff --git a/src/main/webapp/lib/firebug/firebug.js b/src/main/webapp/lib/firebug/firebug.js
new file mode 100644
index 0000000000000000000000000000000000000000..a6242c3bc56486e1f0a38c283f7ddcca2d589894
--- /dev/null
+++ b/src/main/webapp/lib/firebug/firebug.js
@@ -0,0 +1,674 @@
+
+if (!window.console || !console.firebug) { (function()
+{
+    window.console = 
+    {
+        log: function()
+        {
+            logFormatted(arguments, "");
+        },
+        
+        debug: function()
+        {
+            logFormatted(arguments, "debug");
+        },
+        
+        info: function()
+        {
+            logFormatted(arguments, "info");
+        },
+        
+        warn: function()
+        {
+            logFormatted(arguments, "warning");
+        },
+        
+        error: function()
+        {
+            logFormatted(arguments, "error");
+        },
+        
+        assert: function(truth, message)
+        {
+            if (!truth)
+            {
+                var args = [];
+                for (var i = 1; i < arguments.length; ++i)
+                    args.push(arguments[i]);
+                
+                logFormatted(args.length ? args : ["Assertion Failure"], "error");
+                throw message ? message : "Assertion Failure";
+            }
+        },
+        
+        dir: function(object)
+        {
+            var html = [];
+                        
+            var pairs = [];
+            for (var name in object)
+            {
+                try
+                {
+                    pairs.push([name, object[name]]);
+                }
+                catch (exc)
+                {
+                }
+            }
+            
+            pairs.sort(function(a, b) { return a[0] < b[0] ? -1 : 1; });
+            
+            html.push('<table>');
+            for (var i = 0; i < pairs.length; ++i)
+            {
+                var name = pairs[i][0], value = pairs[i][1];
+                
+                html.push('<tr>', 
+                '<td class="propertyNameCell"><span class="propertyName">',
+                    escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
+                appendObject(value, html);
+                html.push('</span></td></tr>');
+            }
+            html.push('</table>');
+            
+            logRow(html, "dir");
+        },
+        
+        dirxml: function(node)
+        {
+            var html = [];
+            
+            appendNode(node, html);
+            logRow(html, "dirxml");
+        },
+        
+        group: function()
+        {
+            logRow(arguments, "group", pushGroup);
+        },
+        
+        groupEnd: function()
+        {
+            logRow(arguments, "", popGroup);
+        },
+        
+        time: function(name)
+        {
+            timeMap[name] = (new Date()).getTime();
+        },
+        
+        timeEnd: function(name)
+        {
+            if (name in timeMap)
+            {
+                var delta = (new Date()).getTime() - timeMap[name];
+                logFormatted([name+ ":", delta+"ms"]);
+                delete timeMap[name];
+            }
+        },
+        
+        count: function()
+        {
+            this.warn(["count() not supported."]);
+        },
+        
+        trace: function()
+        {
+            this.warn(["trace() not supported."]);
+        },
+        
+        profile: function()
+        {
+            this.warn(["profile() not supported."]);
+        },
+        
+        profileEnd: function()
+        {
+        },
+        
+        clear: function()
+        {
+            consoleBody.innerHTML = "";
+        },
+
+        open: function()
+        {
+            toggleConsole(true);
+        },
+        
+        close: function()
+        {
+            if (frameVisible)
+                toggleConsole();
+        }
+    };
+ 
+    // ********************************************************************************************
+       
+    var consoleFrame = null;
+    var consoleBody = null;
+    var commandLine = null;
+    
+    var frameVisible = false;
+    var messageQueue = [];
+    var groupStack = [];
+    var timeMap = {};
+    
+    var clPrefix = ">>> ";
+    
+    var isFirefox = navigator.userAgent.indexOf("Firefox") != -1;
+    var isIE = navigator.userAgent.indexOf("MSIE") != -1;
+    var isOpera = navigator.userAgent.indexOf("Opera") != -1;
+    var isSafari = navigator.userAgent.indexOf("AppleWebKit") != -1;
+
+    // ********************************************************************************************
+
+    function toggleConsole(forceOpen)
+    {
+        frameVisible = forceOpen || !frameVisible;
+        if (consoleFrame)
+            consoleFrame.style.visibility = frameVisible ? "visible" : "hidden";
+        else
+            waitForBody();
+    }
+
+    function focusCommandLine()
+    {
+        toggleConsole(true);
+        if (commandLine)
+            commandLine.focus();
+    }
+
+    function waitForBody()
+    {
+        if (document.body)
+            createFrame();
+        else
+            setTimeout(waitForBody, 200);
+    }    
+
+    function createFrame()
+    {
+        if (consoleFrame)
+            return;
+        
+        window.onFirebugReady = function(doc)
+        {
+            window.onFirebugReady = null;
+
+            var toolbar = doc.getElementById("toolbar");
+            toolbar.onmousedown = onSplitterMouseDown;
+
+            commandLine = doc.getElementById("commandLine");
+            addEvent(commandLine, "keydown", onCommandLineKeyDown);
+
+            addEvent(doc, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
+            
+            consoleBody = doc.getElementById("log");
+            layout();
+            flush();
+        }
+
+        var baseURL = getFirebugURL();
+
+        consoleFrame = document.createElement("iframe");
+        consoleFrame.setAttribute("src", baseURL+"/firebug.html");
+        consoleFrame.setAttribute("frameBorder", "0");
+        consoleFrame.style.visibility = (frameVisible ? "visible" : "hidden");    
+        consoleFrame.style.zIndex = "2147483583";
+        consoleFrame.style.position = document.all ? "absolute" : "fixed";
+        consoleFrame.style.width = "100%";
+        consoleFrame.style.left = "0";
+        consoleFrame.style.bottom = "0";
+        consoleFrame.style.height = "200px";
+        document.body.appendChild(consoleFrame);
+    }
+    
+    function getFirebugURL()
+    {
+        var scripts = document.getElementsByTagName("script");
+        for (var i = 0; i < scripts.length; ++i)
+        {
+            if (scripts[i].src.indexOf("firebug.js") != -1)
+            {
+                var lastSlash = scripts[i].src.lastIndexOf("/");
+                return scripts[i].src.substr(0, lastSlash);
+            }
+        }
+    }
+    
+    function evalCommandLine()
+    {
+        var text = commandLine.value;
+        commandLine.value = "";
+
+        logRow([clPrefix, text], "command");
+        
+        var value;
+        try
+        {
+            value = eval(text);
+        }
+        catch (exc)
+        {
+        }
+
+        console.log(value);
+    }
+    
+    function layout()
+    {
+        var toolbar = consoleBody.ownerDocument.getElementById("toolbar");
+        var height = consoleFrame.offsetHeight - (toolbar.offsetHeight + commandLine.offsetHeight);
+        height = Math.max(height, 0);
+        consoleBody.style.top = toolbar.offsetHeight + "px";
+        consoleBody.style.height = height + "px";
+        
+        commandLine.style.top = (consoleFrame.offsetHeight - commandLine.offsetHeight) + "px";
+    }
+    
+    function logRow(message, className, handler)
+    {
+        if (consoleBody)
+            writeMessage(message, className, handler);
+        else
+        {
+            messageQueue.push([message, className, handler]);
+            waitForBody();
+        }
+    }
+    
+    function flush()
+    {
+        var queue = messageQueue;
+        messageQueue = [];
+        
+        for (var i = 0; i < queue.length; ++i)
+            writeMessage(queue[i][0], queue[i][1], queue[i][2]);
+    }
+
+    function writeMessage(message, className, handler)
+    {
+        var isScrolledToBottom =
+            consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
+
+        if (!handler)
+            handler = writeRow;
+        
+        handler(message, className);
+        
+        if (isScrolledToBottom)
+            consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
+    }
+    
+    function appendRow(row)
+    {
+        var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
+        container.appendChild(row);
+    }
+
+    function writeRow(message, className)
+    {
+        var row = consoleBody.ownerDocument.createElement("div");
+        row.className = "logRow" + (className ? " logRow-"+className : "");
+        row.innerHTML = message.join("");
+        appendRow(row);
+    }
+
+    function pushGroup(message, className)
+    {
+        logFormatted(message, className);
+
+        var groupRow = consoleBody.ownerDocument.createElement("div");
+        groupRow.className = "logGroup";
+        var groupRowBox = consoleBody.ownerDocument.createElement("div");
+        groupRowBox.className = "logGroupBox";
+        groupRow.appendChild(groupRowBox);
+        appendRow(groupRowBox);
+        groupStack.push(groupRowBox);
+    }
+
+    function popGroup()
+    {
+        groupStack.pop();
+    }
+    
+    // ********************************************************************************************
+
+    function logFormatted(objects, className)
+    {
+        var html = [];
+
+        var format = objects[0];
+        var objIndex = 0;
+
+        if (typeof(format) != "string")
+        {
+            format = "";
+            objIndex = -1;
+        }
+
+        var parts = parseFormat(format);
+        for (var i = 0; i < parts.length; ++i)
+        {
+            var part = parts[i];
+            if (part && typeof(part) == "object")
+            {
+                var object = objects[++objIndex];
+                part.appender(object, html);
+            }
+            else
+                appendText(part, html);
+        }
+
+        for (var i = objIndex+1; i < objects.length; ++i)
+        {
+            appendText(" ", html);
+            
+            var object = objects[i];
+            if (typeof(object) == "string")
+                appendText(object, html);
+            else
+                appendObject(object, html);
+        }
+        
+        logRow(html, className);
+    }
+
+    function parseFormat(format)
+    {
+        var parts = [];
+
+        var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;    
+        var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
+
+        for (var m = reg.exec(format); m; m = reg.exec(format))
+        {
+            var type = m[8] ? m[8] : m[5];
+            var appender = type in appenderMap ? appenderMap[type] : appendObject;
+            var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
+
+            parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
+            parts.push({appender: appender, precision: precision});
+
+            format = format.substr(m.index+m[0].length);
+        }
+
+        parts.push(format);
+
+        return parts;
+    }
+
+    function escapeHTML(value)
+    {
+        function replaceChars(ch)
+        {
+            switch (ch)
+            {
+                case "<":
+                    return "&lt;";
+                case ">":
+                    return "&gt;";
+                case "&":
+                    return "&amp;";
+                case "'":
+                    return "&#39;";
+                case '"':
+                    return "&quot;";
+            }
+            return "?";
+        };
+        return String(value).replace(/[<>&"']/g, replaceChars);
+    }
+
+    function objectToString(object)
+    {
+        try
+        {
+            return object+"";
+        }
+        catch (exc)
+        {
+            return null;
+        }
+    }
+
+    // ********************************************************************************************
+
+    function appendText(object, html)
+    {
+        html.push(escapeHTML(objectToString(object)));
+    }
+
+    function appendNull(object, html)
+    {
+        html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
+    }
+
+    function appendString(object, html)
+    {
+        html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
+            '&quot;</span>');
+    }
+
+    function appendInteger(object, html)
+    {
+        html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+    }
+
+    function appendFloat(object, html)
+    {
+        html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+    }
+
+    function appendFunction(object, html)
+    {
+        var reName = /function ?(.*?)\(/;
+        var m = reName.exec(objectToString(object));
+        var name = m ? m[1] : "function";
+        html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
+    }
+    
+    function appendObject(object, html)
+    {
+        try
+        {
+            if (object == undefined)
+                appendNull("undefined", html);
+            else if (object == null)
+                appendNull("null", html);
+            else if (typeof object == "string")
+                appendString(object, html);
+            else if (typeof object == "number")
+                appendInteger(object, html);
+            else if (typeof object == "function")
+                appendFunction(object, html);
+            else if (object.nodeType == 1)
+                appendSelector(object, html);
+            else if (typeof object == "object")
+                appendObjectFormatted(object, html);
+            else
+                appendText(object, html);
+        }
+        catch (exc)
+        {
+        }
+    }
+        
+    function appendObjectFormatted(object, html)
+    {
+        var text = objectToString(object);
+        var reObject = /\[object (.*?)\]/;
+
+        var m = reObject.exec(text);
+        html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>')
+    }
+    
+    function appendSelector(object, html)
+    {
+        html.push('<span class="objectBox-selector">');
+
+        html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
+        if (object.id)
+            html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
+        if (object.className)
+            html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
+
+        html.push('</span>');
+    }
+
+    function appendNode(node, html)
+    {
+        if (node.nodeType == 1)
+        {
+            html.push(
+                '<div class="objectBox-element">',
+                    '&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
+
+            for (var i = 0; i < node.attributes.length; ++i)
+            {
+                var attr = node.attributes[i];
+                if (!attr.specified)
+                    continue;
+                
+                html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
+                    '</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
+                    '</span>&quot;')
+            }
+
+            if (node.firstChild)
+            {
+                html.push('&gt;</div><div class="nodeChildren">');
+
+                for (var child = node.firstChild; child; child = child.nextSibling)
+                    appendNode(child, html);
+                    
+                html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">', 
+                    node.nodeName.toLowerCase(), '&gt;</span></div>');
+            }
+            else
+                html.push('/&gt;</div>');
+        }
+        else if (node.nodeType == 3)
+        {
+            html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
+                '</div>');
+        }
+    }
+
+    // ********************************************************************************************
+    
+    function addEvent(object, name, handler)
+    {
+        if (document.all)
+            object.attachEvent("on"+name, handler);
+        else
+            object.addEventListener(name, handler, false);
+    }
+    
+    function removeEvent(object, name, handler)
+    {
+        if (document.all)
+            object.detachEvent("on"+name, handler);
+        else
+            object.removeEventListener(name, handler, false);
+    }
+    
+    function cancelEvent(event)
+    {
+        if (document.all)
+            event.cancelBubble = true;
+        else
+            event.stopPropagation();        
+    }
+
+    function onError(msg, href, lineNo)
+    {
+        var html = [];
+        
+        var lastSlash = href.lastIndexOf("/");
+        var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
+        
+        html.push(
+            '<span class="errorMessage">', msg, '</span>', 
+            '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
+        );
+        
+        logRow(html, "error");
+    };
+
+    function onKeyDown(event)
+    {
+        if (event.keyCode == 123)
+            toggleConsole();
+        else if ((event.keyCode == 108 || event.keyCode == 76) && event.shiftKey
+                 && (event.metaKey || event.ctrlKey))
+            focusCommandLine();
+        else
+            return;
+        
+        cancelEvent(event);
+    }
+
+    function onSplitterMouseDown(event)
+    {
+        if (isSafari || isOpera)
+            return;
+        
+        addEvent(document, "mousemove", onSplitterMouseMove);
+        addEvent(document, "mouseup", onSplitterMouseUp);
+
+        for (var i = 0; i < frames.length; ++i)
+        {
+            addEvent(frames[i].document, "mousemove", onSplitterMouseMove);
+            addEvent(frames[i].document, "mouseup", onSplitterMouseUp);
+        }
+    }
+    
+    function onSplitterMouseMove(event)
+    {
+        var win = document.all
+            ? event.srcElement.ownerDocument.parentWindow
+            : event.target.ownerDocument.defaultView;
+
+        var clientY = event.clientY;
+        if (win != win.parent)
+            clientY += win.frameElement ? win.frameElement.offsetTop : 0;
+        
+        var height = consoleFrame.offsetTop + consoleFrame.clientHeight;
+        var toolbar = consoleBody.ownerDocument.getElementById("toolbar");
+        var y = Math.max(height - clientY,
+                         toolbar.offsetHeight + commandLine.offsetHeight);
+        
+        consoleFrame.style.height = y + "px";
+        layout();
+    }
+    
+    function onSplitterMouseUp(event)
+    {
+        removeEvent(document, "mousemove", onSplitterMouseMove);
+        removeEvent(document, "mouseup", onSplitterMouseUp);
+
+        for (var i = 0; i < frames.length; ++i)
+        {
+            removeEvent(frames[i].document, "mousemove", onSplitterMouseMove);
+            removeEvent(frames[i].document, "mouseup", onSplitterMouseUp);
+        }
+    }
+    
+    function onCommandLineKeyDown(event)
+    {
+        if (event.keyCode == 13)
+            evalCommandLine();
+        else if (event.keyCode == 27)
+            commandLine.value = "";
+    }
+    
+    window.onerror = onError;
+    addEvent(document, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
+    
+    if (document.documentElement.getAttribute("debug") == "true")
+        toggleConsole(true);
+})();
+}
diff --git a/src/main/webapp/lib/firebug/firebugx.js b/src/main/webapp/lib/firebug/firebugx.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c8b30f762e2124fdd4e3e92509c808ff9a98bb4
--- /dev/null
+++ b/src/main/webapp/lib/firebug/firebugx.js
@@ -0,0 +1,9 @@
+
+if (!window.console || !console.firebug) {
+    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+
+    window.console = {};
+    for (var i = 0; i < names.length; ++i)
+        window.console[names[i]] = function() {}
+}
diff --git a/src/main/webapp/lib/firebug/infoIcon.png b/src/main/webapp/lib/firebug/infoIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..da1e5334c19375c7855e04792661bf2cc15b7e14
Binary files /dev/null and b/src/main/webapp/lib/firebug/infoIcon.png differ
diff --git a/src/main/webapp/lib/firebug/license.txt b/src/main/webapp/lib/firebug/license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ba43b7514b3bc744935364b343ec61e6e2084615
--- /dev/null
+++ b/src/main/webapp/lib/firebug/license.txt
@@ -0,0 +1,30 @@
+Software License Agreement (BSD License)
+
+Copyright (c) 2007, Parakey Inc.
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of Parakey Inc. nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of Parakey Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/main/webapp/lib/firebug/readme.txt b/src/main/webapp/lib/firebug/readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1edebf5654f19eb1c2f66a6cb02a280dc120ada8
--- /dev/null
+++ b/src/main/webapp/lib/firebug/readme.txt
@@ -0,0 +1,13 @@
+This directory contains the source for Firebug Lite
+(http://www.getfirebug.com/lite.html).  This code is distributed with a
+BSD License, Copyright (c) 2007, Parakey Inc.  See the included license.txt
+for the full text of the license.
+
+This is a patched version of the trunk from
+http://fbug.googlecode.com/svn/trunk.
+
+Revision 36 was patched to resolve the issue described here
+http://code.google.com/p/fbug/issues/detail?id=85
+
+When this issue is resolved, Firebug Lite can be used directly - no further
+modifications are needed for OpenLayers.
\ No newline at end of file
diff --git a/src/main/webapp/lib/firebug/warningIcon.png b/src/main/webapp/lib/firebug/warningIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..de51084e8489f498b89dd9a59d82eb9564b7d050
Binary files /dev/null and b/src/main/webapp/lib/firebug/warningIcon.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/GeoExt.js b/src/main/webapp/lib/geoext-1.1/GeoExt.js
new file mode 100644
index 0000000000000000000000000000000000000000..503c4bef7af8fdb71350e8ec01e484230a452512
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/GeoExt.js
@@ -0,0 +1,360 @@
+/*
+
+Copyright (c) 2008-2011, The Open Source Geospatial Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Open Source Geospatial Foundation nor the names
+      of its contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+Ext.namespace('GeoExt');GeoExt.LayerLegend=Ext.extend(Ext.Container,{layerRecord:null,showTitle:true,legendTitle:null,labelCls:null,layerStore:null,initComponent:function(){GeoExt.LayerLegend.superclass.initComponent.call(this);this.autoEl={};this.add({xtype:"label",html:this.getLayerTitle(this.layerRecord),cls:'x-form-item x-form-item-label'+
+(this.labelCls?' '+this.labelCls:'')});if(this.layerRecord&&this.layerRecord.store){this.layerStore=this.layerRecord.store;this.layerStore.on("update",this.onStoreUpdate,this);this.layerStore.on("add",this.onStoreAdd,this);this.layerStore.on("remove",this.onStoreRemove,this);}},getLabel:function(){var label=this.items.get(0);return label.rendered?label.el.dom.innerHTML:label.html;},onStoreRemove:function(store,record,index){},onStoreAdd:function(store,record,index){},onStoreUpdate:function(store,record,operation){if(record===this.layerRecord&&this.items.getCount()>0){var layer=record.getLayer();this.setVisible(layer.getVisibility()&&layer.calculateInRange()&&layer.displayInLayerSwitcher&&!record.get('hideInLegend'));this.update();}},update:function(){var title=this.getLayerTitle(this.layerRecord);var item=this.items.get(0);if(item instanceof Ext.form.Label&&this.getLabel()!==title){item.setText(title,false);}},getLayerTitle:function(record){var title=this.legendTitle||"";if(this.showTitle&&!title){if(record&&!record.get("hideTitle")){title=record.get("title")||record.get("name")||record.getLayer().name||"";}}
+return title;},beforeDestroy:function(){if(this.layerStore){this.layerStore.un("update",this.onStoreUpdate,this);this.layerStore.un("remove",this.onStoreRemove,this);this.layerStore.un("add",this.onStoreAdd,this);}
+GeoExt.LayerLegend.superclass.beforeDestroy.apply(this,arguments);},onDestroy:function(){this.layerRecord=null;this.layerStore=null;GeoExt.LayerLegend.superclass.onDestroy.apply(this,arguments);}});GeoExt.LayerLegend.getTypes=function(layerRecord,preferredTypes){var types=(preferredTypes||[]).concat(),scoredTypes=[],score,type;for(type in GeoExt.LayerLegend.types){score=GeoExt.LayerLegend.types[type].supports(layerRecord);if(score>0){if(types.indexOf(type)==-1){scoredTypes.push({type:type,score:score});}}else{types.remove(type);}}
+scoredTypes.sort(function(a,b){return a.score<b.score?1:(a.score==b.score?0:-1);});var len=scoredTypes.length,goodTypes=new Array(len);for(var i=0;i<len;++i){goodTypes[i]=scoredTypes[i].type;}
+return types.concat(goodTypes);};GeoExt.LayerLegend.supports=function(layerRecord){};GeoExt.LayerLegend.types={};Ext.namespace('GeoExt');GeoExt.VectorLegend=Ext.extend(GeoExt.LayerLegend,{layerRecord:null,layer:null,rules:null,symbolType:null,untitledPrefix:"Untitled ",clickableSymbol:false,clickableTitle:false,selectOnClick:false,enableDD:false,bodyBorder:false,feature:null,selectedRule:null,currentScaleDenominator:null,initComponent:function(){GeoExt.VectorLegend.superclass.initComponent.call(this);if(this.layerRecord){this.layer=this.layerRecord.getLayer();if(this.layer.map){this.map=this.layer.map;this.currentScaleDenominator=this.layer.map.getScale();this.layer.map.events.on({"zoomend":this.onMapZoom,scope:this});}}
+if(!this.symbolType){if(this.feature){this.symbolType=this.symbolTypeFromFeature(this.feature);}else if(this.layer){if(this.layer.features.length>0){var feature=this.layer.features[0].clone();feature.attributes={};this.feature=feature;this.symbolType=this.symbolTypeFromFeature(this.feature);}else{this.layer.events.on({featuresadded:this.onFeaturesAdded,scope:this});}}}
+if(this.layer&&this.feature&&!this.rules){this.setRules();}
+this.rulesContainer=new Ext.Container({autoEl:{}});this.add(this.rulesContainer);this.addEvents("titleclick","symbolclick","ruleclick","ruleselected","ruleunselected","rulemoved");this.update();},onMapZoom:function(){this.setCurrentScaleDenominator(this.layer.map.getScale());},symbolTypeFromFeature:function(feature){var match=feature.geometry.CLASS_NAME.match(/Point|Line|Polygon/);return(match&&match[0])||"Point";},onFeaturesAdded:function(){this.layer.events.un({featuresadded:this.onFeaturesAdded,scope:this});var feature=this.layer.features[0].clone();feature.attributes={};this.feature=feature;this.symbolType=this.symbolTypeFromFeature(this.feature);if(!this.rules){this.setRules();}
+this.update();},setRules:function(){var style=this.layer.styleMap&&this.layer.styleMap.styles["default"];if(!style){style=new OpenLayers.Style();}
+if(style.rules.length===0){this.rules=[new OpenLayers.Rule({title:style.title,symbolizer:style.createSymbolizer(this.feature)})];}else{this.rules=style.rules;}},setCurrentScaleDenominator:function(scale){if(scale!==this.currentScaleDenominator){this.currentScaleDenominator=scale;this.update();}},getRuleEntry:function(rule){return this.rulesContainer.items.get(this.rules.indexOf(rule));},addRuleEntry:function(rule,noDoLayout){this.rulesContainer.add(this.createRuleEntry(rule));if(!noDoLayout){this.doLayout();}},removeRuleEntry:function(rule,noDoLayout){var ruleEntry=this.getRuleEntry(rule);if(ruleEntry){this.rulesContainer.remove(ruleEntry);if(!noDoLayout){this.doLayout();}}},selectRuleEntry:function(rule){var newSelection=rule!=this.selectedRule;if(this.selectedRule){this.unselect();}
+if(newSelection){var ruleEntry=this.getRuleEntry(rule);ruleEntry.body.addClass("x-grid3-row-selected");this.selectedRule=rule;this.fireEvent("ruleselected",this,rule);}},unselect:function(){this.rulesContainer.items.each(function(item,i){if(this.rules[i]==this.selectedRule){item.body.removeClass("x-grid3-row-selected");this.selectedRule=null;this.fireEvent("ruleunselected",this,this.rules[i]);}},this);},createRuleEntry:function(rule){var applies=true;if(this.currentScaleDenominator!=null){if(rule.minScaleDenominator){applies=applies&&(this.currentScaleDenominator>=rule.minScaleDenominator);}
+if(rule.maxScaleDenominator){applies=applies&&(this.currentScaleDenominator<rule.maxScaleDenominator);}}
+return{xtype:"panel",layout:"column",border:false,hidden:!applies,bodyStyle:this.selectOnClick?{cursor:"pointer"}:undefined,defaults:{border:false},items:[this.createRuleRenderer(rule),this.createRuleTitle(rule)],listeners:{render:function(comp){this.selectOnClick&&comp.getEl().on({click:function(comp){this.selectRuleEntry(rule);},scope:this});if(this.enableDD==true){this.addDD(comp);}},scope:this}};},createRuleRenderer:function(rule){var types=[this.symbolType,"Point","Line","Polygon"];var type,haveType;var symbolizers=rule.symbolizers;if(!symbolizers){var symbolizer=rule.symbolizer;for(var i=0,len=types.length;i<len;++i){type=types[i];if(symbolizer[type]){symbolizer=symbolizer[type];haveType=true;break;}}
+symbolizers=[symbolizer];}else{var Type;outer:for(var i=0,ii=types.length;i<ii;++i){type=types[i];Type=OpenLayers.Symbolizer[type];if(Type){for(var j=0,jj=symbolizers.length;j<jj;++j){if(symbolizers[j]instanceof Type){haveType=true;break outer;}}}}}
+return{xtype:"gx_renderer",symbolType:haveType?type:this.symbolType,symbolizers:symbolizers,style:this.clickableSymbol?{cursor:"pointer"}:undefined,listeners:{click:function(){if(this.clickableSymbol){this.fireEvent("symbolclick",this,rule);this.fireEvent("ruleclick",this,rule);}},scope:this}};},createRuleTitle:function(rule){return{cls:"x-form-item",style:"padding: 0.2em 0.5em 0;",bodyStyle:Ext.applyIf({background:"transparent"},this.clickableTitle?{cursor:"pointer"}:undefined),html:this.getRuleTitle(rule),listeners:{render:function(comp){this.clickableTitle&&comp.getEl().on({click:function(){this.fireEvent("titleclick",this,rule);this.fireEvent("ruleclick",this,rule);},scope:this});},scope:this}};},addDD:function(component){var ct=component.ownerCt;var panel=this;new Ext.dd.DragSource(component.getEl(),{ddGroup:ct.id,onDragOut:function(e,targetId){var target=Ext.getCmp(targetId);target.removeClass("gx-ruledrag-insert-above");target.removeClass("gx-ruledrag-insert-below");return Ext.dd.DragZone.prototype.onDragOut.apply(this,arguments);},onDragEnter:function(e,targetId){var target=Ext.getCmp(targetId);var cls;var sourcePos=ct.items.indexOf(component);var targetPos=ct.items.indexOf(target);if(sourcePos>targetPos){cls="gx-ruledrag-insert-above";}else if(sourcePos<targetPos){cls="gx-ruledrag-insert-below";}
+cls&&target.addClass(cls);return Ext.dd.DragZone.prototype.onDragEnter.apply(this,arguments);},onDragDrop:function(e,targetId){panel.moveRule(ct.items.indexOf(component),ct.items.indexOf(Ext.getCmp(targetId)));return Ext.dd.DragZone.prototype.onDragDrop.apply(this,arguments);},getDragData:function(e){var sourceEl=e.getTarget(".x-column-inner");if(sourceEl){var d=sourceEl.cloneNode(true);d.id=Ext.id();return{sourceEl:sourceEl,repairXY:Ext.fly(sourceEl).getXY(),ddel:d}}}});new Ext.dd.DropTarget(component.getEl(),{ddGroup:ct.id,notifyDrop:function(){return true;}});},update:function(){GeoExt.VectorLegend.superclass.update.apply(this,arguments);if(this.symbolType&&this.rules){if(this.rulesContainer.items){var comp;for(var i=this.rulesContainer.items.length-1;i>=0;--i){comp=this.rulesContainer.getComponent(i);this.rulesContainer.remove(comp,true);}}
+for(var i=0,ii=this.rules.length;i<ii;++i){this.addRuleEntry(this.rules[i],true);}
+this.doLayout();if(this.selectedRule){this.getRuleEntry(this.selectedRule).body.addClass("x-grid3-row-selected");}}},updateRuleEntry:function(rule){var ruleEntry=this.getRuleEntry(rule);if(ruleEntry){ruleEntry.removeAll();ruleEntry.add(this.createRuleRenderer(rule));ruleEntry.add(this.createRuleTitle(rule));ruleEntry.doLayout();}},moveRule:function(sourcePos,targetPos){var srcRule=this.rules[sourcePos];this.rules.splice(sourcePos,1);this.rules.splice(targetPos,0,srcRule);this.update();this.fireEvent("rulemoved",this,srcRule);},getRuleTitle:function(rule){var title=rule.title||rule.name||"";if(!title&&this.untitledPrefix){title=this.untitledPrefix+(this.rules.indexOf(rule)+1);}
+return title;},beforeDestroy:function(){if(this.layer){if(this.layer.events){this.layer.events.un({featuresadded:this.onFeaturesAdded,scope:this});}
+if(this.layer.map&&this.layer.map.events){this.layer.map.events.un({"zoomend":this.onMapZoom,scope:this});}}
+delete this.layer;delete this.map;delete this.rules;GeoExt.VectorLegend.superclass.beforeDestroy.apply(this,arguments);},onStoreRemove:function(store,record,index){if(record.getLayer()===this.layer){if(this.map&&this.map.events){this.map.events.un({"zoomend":this.onMapZoom,scope:this});}}},onStoreAdd:function(store,records,index){for(var i=0,len=records.length;i<len;i++){var record=records[i];if(record.getLayer()===this.layer){if(this.layer.map&&this.layer.map.events){this.layer.map.events.on({"zoomend":this.onMapZoom,scope:this});}}}}});GeoExt.VectorLegend.supports=function(layerRecord){return layerRecord.getLayer()instanceof OpenLayers.Layer.Vector?1:0;};GeoExt.LayerLegend.types["gx_vectorlegend"]=GeoExt.VectorLegend;Ext.reg("gx_vectorlegend",GeoExt.VectorLegend);Ext.namespace("GeoExt.tree");GeoExt.tree.LayerContainer=Ext.extend(Ext.tree.AsyncTreeNode,{text:'Layers',constructor:function(config){config=Ext.applyIf(config||{},{text:this.text});this.loader=config.loader instanceof GeoExt.tree.LayerLoader?config.loader:new GeoExt.tree.LayerLoader(Ext.applyIf(config.loader||{},{store:config.layerStore}));GeoExt.tree.LayerContainer.superclass.constructor.call(this,config);},recordIndexToNodeIndex:function(index){var store=this.loader.store;var count=store.getCount();var nodeCount=this.childNodes.length;var nodeIndex=-1;for(var i=count-1;i>=0;--i){if(this.loader.filter(store.getAt(i))===true){++nodeIndex;if(index===i||nodeIndex>nodeCount-1){break;}}}
+return nodeIndex;},destroy:function(){delete this.layerStore;GeoExt.tree.LayerContainer.superclass.destroy.apply(this,arguments);}});Ext.tree.TreePanel.nodeTypes.gx_layercontainer=GeoExt.tree.LayerContainer;Ext.namespace("GeoExt.tree");GeoExt.tree.BaseLayerContainer=Ext.extend(GeoExt.tree.LayerContainer,{text:'Base Layer',constructor:function(config){config=Ext.applyIf(config||{},{text:this.text,loader:{}});config.loader=Ext.applyIf(config.loader,{baseAttrs:Ext.applyIf(config.loader.baseAttrs||{},{iconCls:'gx-tree-baselayer-icon',checkedGroup:'baselayer'}),filter:function(record){var layer=record.getLayer();return layer.displayInLayerSwitcher===true&&layer.isBaseLayer===true;}});GeoExt.tree.BaseLayerContainer.superclass.constructor.call(this,config);}});Ext.tree.TreePanel.nodeTypes.gx_baselayercontainer=GeoExt.tree.BaseLayerContainer;Ext.namespace("GeoExt.plugins");GeoExt.plugins.PrintExtent=Ext.extend(Ext.util.Observable,{initialConfig:null,printProvider:null,map:null,layer:null,control:null,pages:null,page:null,constructor:function(config){config=config||{};Ext.apply(this,config);this.initialConfig=config;if(!this.printProvider){this.printProvider=this.pages[0].printProvider;}
+if(!this.pages){this.pages=[];}
+this.addEvents("selectpage");GeoExt.plugins.PrintExtent.superclass.constructor.apply(this,arguments);},print:function(options){this.printProvider.print(this.map,this.pages,options);},init:function(mapPanel){this.map=mapPanel.map;mapPanel.on("destroy",this.onMapPanelDestroy,this);if(!this.layer){this.layer=new OpenLayers.Layer.Vector(null,{displayInLayerSwitcher:false});}
+this.createControl();for(var i=0,len=this.pages.length;i<len;++i){this.addPage(this.pages[i]);}
+this.show();},addPage:function(page){page=page||new GeoExt.data.PrintPage({printProvider:this.printProvider});if(this.pages.indexOf(page)===-1){this.pages.push(page);}
+this.layer.addFeatures([page.feature]);page.on("change",this.onPageChange,this);this.page=page;var map=this.map;if(map.getCenter()){this.fitPage();}else{map.events.register("moveend",this,function(){map.events.unregister("moveend",this,arguments.callee);this.fitPage();});}
+return page;},removePage:function(page){this.pages.remove(page);if(page.feature.layer){this.layer.removeFeatures([page.feature]);}
+page.un("change",this.onPageChange,this);},selectPage:function(page){this.control.active&&this.control.setFeature(page.feature);},show:function(){this.map.addLayer(this.layer);this.map.addControl(this.control);this.control.activate();if(this.page&&this.map.getCenter()){this.updateBox();}},hide:function(){var map=this.map,layer=this.layer,control=this.control;if(control&&control.events){control.deactivate();if(map&&map.events&&control.map){map.removeControl(control);}}
+if(map&&map.events&&layer&&layer.map){map.removeLayer(layer);}},onMapPanelDestroy:function(){var map=this.map;for(var len=this.pages.length-1,i=len;i>=0;i--){this.removePage(this.pages[i]);}
+this.hide();var control=this.control;if(map&&map.events&&control&&control.events){control.destroy();}
+var layer=this.layer;if(!this.initialConfig.layer&&map&&map.events&&layer&&layer.events){layer.destroy();}
+delete this.layer;delete this.control;delete this.page;this.map=null;},createControl:function(){this.control=new OpenLayers.Control.TransformFeature(this.layer,{preserveAspectRatio:true,eventListeners:{"beforesetfeature":function(e){for(var i=0,len=this.pages.length;i<len;++i){if(this.pages[i].feature===e.feature){this.page=this.pages[i];e.object.rotation=-this.pages[i].rotation;break;}}},"setfeature":function(e){for(var i=0,len=this.pages.length;i<len;++i){if(this.pages[i].feature===e.feature){this.fireEvent("selectpage",this.pages[i]);break;}}},"beforetransform":function(e){this._updating=true;var page=this.page;if(e.rotation){if(this.printProvider.layout.get("rotation")){page.setRotation(-e.object.rotation);}else{e.object.setFeature(page.feature);}}else if(e.center){page.setCenter(OpenLayers.LonLat.fromString(e.center.toShortString()));}else{page.fit(e.object.box,{mode:"closest"});var minScale=this.printProvider.scales.getAt(0);var maxScale=this.printProvider.scales.getAt(this.printProvider.scales.getCount()-1);var boxBounds=e.object.box.geometry.getBounds();var pageBounds=page.feature.geometry.getBounds();var tooLarge=page.scale===minScale&&boxBounds.containsBounds(pageBounds);var tooSmall=page.scale===maxScale&&pageBounds.containsBounds(boxBounds);if(tooLarge===true||tooSmall===true){this.updateBox();}}
+delete this._updating;return false;},"transformcomplete":this.updateBox,scope:this}});},fitPage:function(){if(this.page){this.page.fit(this.map,{mode:"screen"});}},updateBox:function(){var page=this.page;this.control.active&&this.control.setFeature(page.feature,{rotation:-page.rotation});},onPageChange:function(page,mods){if(!this._updating){this.control.active&&this.control.setFeature(page.feature,{rotation:-page.rotation});}}});Ext.preg("gx_printextent",GeoExt.plugins.PrintExtent);Ext.namespace("GeoExt");GeoExt.SliderTip=Ext.extend(Ext.slider.Tip,{hover:true,minWidth:10,offsets:[0,-10],dragging:false,init:function(slider){GeoExt.SliderTip.superclass.init.apply(this,arguments);if(this.hover){slider.on("render",this.registerThumbListeners,this);}
+this.slider=slider;},registerThumbListeners:function(){var thumb,el;for(var i=0,ii=this.slider.thumbs.length;i<ii;++i){thumb=this.slider.thumbs[i];el=thumb.tracker.el;(function(thumb,el){el.on({mouseover:function(e){this.onSlide(this.slider,e,thumb);this.dragging=false;},mouseout:function(){if(!this.dragging){this.hide.apply(this,arguments);}},scope:this})}).apply(this,[thumb,el]);}},onSlide:function(slider,e,thumb){this.dragging=true;return GeoExt.SliderTip.superclass.onSlide.apply(this,arguments);}});Ext.namespace("GeoExt");GeoExt.Lang=new(Ext.extend(Ext.util.Observable,{locale:navigator.language||navigator.userLanguage,dict:null,constructor:function(){this.addEvents("localize");this.dict={};Ext.util.Observable.constructor.apply(this,arguments);},add:function(locale,lookup){var obj=this.dict[locale];if(!obj){this.dict[locale]=Ext.apply({},lookup);}else{for(var key in lookup){obj[key]=Ext.apply(obj[key]||{},lookup[key]);}}
+if(!locale||locale===this.locale){this.set(locale);}else if(this.locale.indexOf(locale+"-")===0){this.set(this.locale);}},set:function(locale){var tags=locale?locale.split("-"):[];var id="";var lookup={},parent;for(var i=0,ii=tags.length;i<ii;++i){id+=(id&&"-"||"")+tags[i];if(id in this.dict){parent=this.dict[id];for(var str in parent){if(str in lookup){Ext.apply(lookup[str],parent[str]);}else{lookup[str]=Ext.apply({},parent[str]);}}}}
+for(var str in lookup){var obj=window;var parts=str.split(".");var missing=false;for(var i=0,ii=parts.length;i<ii;++i){var name=parts[i];if(name in obj){obj=obj[name];}else{missing=true;break;}}
+if(!missing){Ext.apply(obj,lookup[str]);}}
+this.locale=locale;this.fireEvent("localize",locale);}}))();Ext.namespace("GeoExt");GeoExt.ZoomSlider=Ext.extend(Ext.slider.SingleSlider,{map:null,baseCls:"gx-zoomslider",aggressive:false,updating:false,initComponent:function(){GeoExt.ZoomSlider.superclass.initComponent.call(this);if(this.map){if(this.map instanceof GeoExt.MapPanel){this.map=this.map.map;}
+this.bind(this.map);}
+if(this.aggressive===true){this.on('change',this.changeHandler,this);}else{this.on('changecomplete',this.changeHandler,this);}
+this.on("beforedestroy",this.unbind,this);},onRender:function(){GeoExt.ZoomSlider.superclass.onRender.apply(this,arguments);this.el.addClass(this.baseCls);},afterRender:function(){Ext.slider.SingleSlider.superclass.afterRender.apply(this,arguments);this.update();},addToMapPanel:function(panel){this.on({render:function(){var el=this.getEl();el.setStyle({position:"absolute",zIndex:panel.map.Z_INDEX_BASE.Control});el.on({mousedown:this.stopMouseEvents,click:this.stopMouseEvents});},afterrender:function(){this.bind(panel.map);},scope:this});},stopMouseEvents:function(e){e.stopEvent();},removeFromMapPanel:function(panel){var el=this.getEl();el.un("mousedown",this.stopMouseEvents,this);el.un("click",this.stopMouseEvents,this);this.unbind();},bind:function(map){this.map=map;this.map.events.on({zoomend:this.update,changebaselayer:this.initZoomValues,scope:this});if(this.map.baseLayer){this.initZoomValues();this.update();}},unbind:function(){if(this.map&&this.map.events){this.map.events.un({zoomend:this.update,changebaselayer:this.initZoomValues,scope:this});}},initZoomValues:function(){var layer=this.map.baseLayer;if(this.initialConfig.minValue===undefined){this.minValue=layer.minZoomLevel||0;}
+if(this.initialConfig.maxValue===undefined){this.maxValue=layer.minZoomLevel==null?layer.numZoomLevels-1:layer.maxZoomLevel;}},getZoom:function(){return this.getValue();},getScale:function(){return OpenLayers.Util.getScaleFromResolution(this.map.getResolutionForZoom(this.getValue()),this.map.getUnits());},getResolution:function(){return this.map.getResolutionForZoom(this.getValue());},changeHandler:function(){if(this.map&&!this.updating){this.map.zoomTo(this.getValue());}},update:function(){if(this.rendered&&this.map){this.updating=true;this.setValue(this.map.getZoom());this.updating=false;}}});Ext.reg('gx_zoomslider',GeoExt.ZoomSlider);Ext.namespace("GeoExt.tree");GeoExt.tree.WMSCapabilitiesLoader=function(config){Ext.apply(this,config);GeoExt.tree.WMSCapabilitiesLoader.superclass.constructor.call(this);};Ext.extend(GeoExt.tree.WMSCapabilitiesLoader,Ext.tree.TreeLoader,{url:null,layerOptions:null,layerParams:null,requestMethod:'GET',getParams:function(node){return{'service':'WMS','request':'GetCapabilities'};},processResponse:function(response,node,callback,scope){var capabilities=new OpenLayers.Format.WMSCapabilities().read(response.responseXML||response.responseText);capabilities.capability&&this.processLayer(capabilities.capability,capabilities.capability.request.getmap.href,node);if(typeof callback=="function"){callback.apply(scope||node,[node]);}},createWMSLayer:function(layer,url){if(layer.name){return new OpenLayers.Layer.WMS(layer.title,url,OpenLayers.Util.extend({formats:layer.formats[0],layers:layer.name},this.layerParams),OpenLayers.Util.extend({minScale:layer.minScale,queryable:layer.queryable,maxScale:layer.maxScale,metadata:layer},this.layerOptions));}else{return null;}},processLayer:function(layer,url,node){Ext.each(layer.nestedLayers,function(el){var n=this.createNode({text:el.title||el.name,nodeType:'node',layer:this.createWMSLayer(el,url),leaf:(el.nestedLayers.length===0)});if(n){node.appendChild(n);}
+if(el.nestedLayers){this.processLayer(el,url,n);}},this);}});Ext.namespace("GeoExt.data");GeoExt.data.WMSCapabilitiesReader=function(meta,recordType){meta=meta||{};if(!meta.format){meta.format=new OpenLayers.Format.WMSCapabilities();}
+if(typeof recordType!=="function"){recordType=GeoExt.data.LayerRecord.create(recordType||meta.fields||[{name:"name",type:"string"},{name:"title",type:"string"},{name:"abstract",type:"string"},{name:"queryable",type:"boolean"},{name:"opaque",type:"boolean"},{name:"noSubsets",type:"boolean"},{name:"cascaded",type:"int"},{name:"fixedWidth",type:"int"},{name:"fixedHeight",type:"int"},{name:"minScale",type:"float"},{name:"maxScale",type:"float"},{name:"prefix",type:"string"},{name:"formats"},{name:"styles"},{name:"srs"},{name:"dimensions"},{name:"bbox"},{name:"llbbox"},{name:"attribution"},{name:"keywords"},{name:"identifiers"},{name:"authorityURLs"},{name:"metadataURLs"},{name:"infoFormats"}]);}
+GeoExt.data.WMSCapabilitiesReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.WMSCapabilitiesReader,Ext.data.DataReader,{attributionCls:"gx-attribution",read:function(request){var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+return this.readRecords(data);},serviceExceptionFormat:function(formats){if(OpenLayers.Util.indexOf(formats,"application/vnd.ogc.se_inimage")>-1){return"application/vnd.ogc.se_inimage";}
+if(OpenLayers.Util.indexOf(formats,"application/vnd.ogc.se_xml")>-1){return"application/vnd.ogc.se_xml";}
+return formats[0];},imageFormat:function(layer){var formats=layer.formats;if(layer.opaque&&OpenLayers.Util.indexOf(formats,"image/jpeg")>-1){return"image/jpeg";}
+if(OpenLayers.Util.indexOf(formats,"image/png")>-1){return"image/png";}
+if(OpenLayers.Util.indexOf(formats,"image/png; mode=24bit")>-1){return"image/png; mode=24bit";}
+if(OpenLayers.Util.indexOf(formats,"image/gif")>-1){return"image/gif";}
+return formats[0];},imageTransparent:function(layer){return layer.opaque==undefined||!layer.opaque;},readRecords:function(data){if(typeof data==="string"||data.nodeType){data=this.meta.format.read(data);}
+if(!!data.error){throw new Ext.data.DataReader.Error("invalid-response",data.error);}
+var version=data.version;var capability=data.capability||{};var url=capability.request&&capability.request.getmap&&capability.request.getmap.href;var layers=capability.layers;var formats=capability.exception?capability.exception.formats:[];var exceptions=this.serviceExceptionFormat(formats);var records=[];if(url&&layers){var fields=this.recordType.prototype.fields;var layer,values,options,params,field,v;for(var i=0,lenI=layers.length;i<lenI;i++){layer=layers[i];if(layer.name){values={};for(var j=0,lenJ=fields.length;j<lenJ;j++){field=fields.items[j];v=layer[field.mapping||field.name]||field.defaultValue;v=field.convert(v);values[field.name]=v;}
+options={attribution:layer.attribution?this.attributionMarkup(layer.attribution):undefined,minScale:layer.minScale,maxScale:layer.maxScale};if(this.meta.layerOptions){Ext.apply(options,this.meta.layerOptions);}
+params={layers:layer.name,exceptions:exceptions,format:this.imageFormat(layer),transparent:this.imageTransparent(layer),version:version};if(this.meta.layerParams){Ext.apply(params,this.meta.layerParams);}
+values.layer=new OpenLayers.Layer.WMS(layer.title||layer.name,url,params,options);records.push(new this.recordType(values,values.layer.id));}}}
+return{totalRecords:records.length,success:true,records:records};},attributionMarkup:function(attribution){var markup=[];if(attribution.logo){markup.push("<img class='"+this.attributionCls+"-image' "
++"src='"+attribution.logo.href+"' />");}
+if(attribution.title){markup.push("<span class='"+this.attributionCls+"-title'>"
++attribution.title
++"</span>");}
+if(attribution.href){for(var i=0;i<markup.length;i++){markup[i]="<a class='"
++this.attributionCls+"-link' "
++"href="
++attribution.href
++">"
++markup[i]
++"</a>";}}
+return markup.join(" ");}});Ext.namespace("GeoExt.data");GeoExt.data.LayerStoreMixin=function(){return{map:null,reader:null,constructor:function(config){config=config||{};config.reader=config.reader||new GeoExt.data.LayerReader({},config.fields);delete config.fields;var map=config.map instanceof GeoExt.MapPanel?config.map.map:config.map;delete config.map;if(config.layers){config.data=config.layers;}
+delete config.layers;var options={initDir:config.initDir};delete config.initDir;arguments.callee.superclass.constructor.call(this,config);this.addEvents("bind");if(map){this.bind(map,options);}},bind:function(map,options){if(this.map){return;}
+this.map=map;options=options||{};var initDir=options.initDir;if(options.initDir==undefined){initDir=GeoExt.data.LayerStore.MAP_TO_STORE|GeoExt.data.LayerStore.STORE_TO_MAP;}
+var layers=map.layers.slice(0);if(initDir&GeoExt.data.LayerStore.STORE_TO_MAP){this.each(function(record){this.map.addLayer(record.getLayer());},this);}
+if(initDir&GeoExt.data.LayerStore.MAP_TO_STORE){this.loadData(layers,true);}
+map.events.on({"changelayer":this.onChangeLayer,"addlayer":this.onAddLayer,"removelayer":this.onRemoveLayer,scope:this});this.on({"load":this.onLoad,"clear":this.onClear,"add":this.onAdd,"remove":this.onRemove,"update":this.onUpdate,scope:this});this.data.on({"replace":this.onReplace,scope:this});this.fireEvent("bind",this,map);},unbind:function(){if(this.map){this.map.events.un({"changelayer":this.onChangeLayer,"addlayer":this.onAddLayer,"removelayer":this.onRemoveLayer,scope:this});this.un("load",this.onLoad,this);this.un("clear",this.onClear,this);this.un("add",this.onAdd,this);this.un("remove",this.onRemove,this);this.data.un("replace",this.onReplace,this);this.map=null;}},onChangeLayer:function(evt){var layer=evt.layer;var recordIndex=this.findBy(function(rec,id){return rec.getLayer()===layer;});if(recordIndex>-1){var record=this.getAt(recordIndex);if(evt.property==="order"){if(!this._adding&&!this._removing){var layerIndex=this.map.getLayerIndex(layer);if(layerIndex!==recordIndex){this._removing=true;this.remove(record);delete this._removing;this._adding=true;this.insert(layerIndex,[record]);delete this._adding;}}}else if(evt.property==="name"){record.set("title",layer.name);}else{this.fireEvent("update",this,record,Ext.data.Record.EDIT);}}},onAddLayer:function(evt){if(!this._adding){var layer=evt.layer;this._adding=true;this.loadData([layer],true);delete this._adding;}},onRemoveLayer:function(evt){if(this.map.unloadDestroy){if(!this._removing){var layer=evt.layer;this._removing=true;this.remove(this.getById(layer.id));delete this._removing;}}else{this.unbind();}},onLoad:function(store,records,options){if(!Ext.isArray(records)){records=[records];}
+if(options&&!options.add){this._removing=true;for(var i=this.map.layers.length-1;i>=0;i--){this.map.removeLayer(this.map.layers[i]);}
+delete this._removing;var len=records.length;if(len>0){var layers=new Array(len);for(var j=0;j<len;j++){layers[j]=records[j].getLayer();}
+this._adding=true;this.map.addLayers(layers);delete this._adding;}}},onClear:function(store){this._removing=true;for(var i=this.map.layers.length-1;i>=0;i--){this.map.removeLayer(this.map.layers[i]);}
+delete this._removing;},onAdd:function(store,records,index){if(!this._adding){this._adding=true;var layer;for(var i=records.length-1;i>=0;--i){layer=records[i].getLayer();this.map.addLayer(layer);if(index!==this.map.layers.length-1){this.map.setLayerIndex(layer,index);}}
+delete this._adding;}},onRemove:function(store,record,index){if(!this._removing){var layer=record.getLayer();if(this.map.getLayer(layer.id)!=null){this._removing=true;this.removeMapLayer(record);delete this._removing;}}},onUpdate:function(store,record,operation){if(operation===Ext.data.Record.EDIT){if(record.modified&&record.modified.title){var layer=record.getLayer();var title=record.get("title");if(title!==layer.name){layer.setName(title);}}}},removeMapLayer:function(record){this.map.removeLayer(record.getLayer());},onReplace:function(key,oldRecord,newRecord){this.removeMapLayer(oldRecord);},getByLayer:function(layer){var index=this.findBy(function(r){return r.getLayer()===layer;});if(index>-1){return this.getAt(index);}},destroy:function(){this.unbind();GeoExt.data.LayerStore.superclass.destroy.call(this);}};};GeoExt.data.LayerStore=Ext.extend(Ext.data.Store,new GeoExt.data.LayerStoreMixin);GeoExt.data.LayerStore.MAP_TO_STORE=1;GeoExt.data.LayerStore.STORE_TO_MAP=2;Ext.namespace("GeoExt.tree");GeoExt.tree.LayerLoader=function(config){Ext.apply(this,config);this.addEvents("beforeload","load");GeoExt.tree.LayerLoader.superclass.constructor.call(this);};Ext.extend(GeoExt.tree.LayerLoader,Ext.util.Observable,{store:null,filter:function(record){return record.getLayer().displayInLayerSwitcher==true;},baseAttrs:null,uiProviders:null,load:function(node,callback){if(this.fireEvent("beforeload",this,node)){this.removeStoreHandlers();while(node.firstChild){node.removeChild(node.firstChild);}
+if(!this.uiProviders){this.uiProviders=node.getOwnerTree().getLoader().uiProviders;}
+if(!this.store){this.store=GeoExt.MapPanel.guess().layers;}
+this.store.each(function(record){this.addLayerNode(node,record);},this);this.addStoreHandlers(node);if(typeof callback=="function"){callback();}
+this.fireEvent("load",this,node);}},onStoreAdd:function(store,records,index,node){if(!this._reordering){var nodeIndex=node.recordIndexToNodeIndex(index+records.length-1);for(var i=0;i<records.length;++i){this.addLayerNode(node,records[i],nodeIndex);}}},onStoreRemove:function(store,record,index,node){if(!this._reordering){this.removeLayerNode(node,record);}},addLayerNode:function(node,layerRecord,index){index=index||0;if(this.filter(layerRecord)===true){var child=this.createNode({nodeType:'gx_layer',layer:layerRecord.getLayer(),layerStore:this.store});var sibling=node.item(index);if(sibling){node.insertBefore(child,sibling);}else{node.appendChild(child);}
+child.on("move",this.onChildMove,this);}},removeLayerNode:function(node,layerRecord){if(this.filter(layerRecord)===true){var child=node.findChildBy(function(node){return node.layer==layerRecord.getLayer();});if(child){child.un("move",this.onChildMove,this);child.remove();node.reload();}}},onChildMove:function(tree,node,oldParent,newParent,index){this._reordering=true;var record=this.store.getByLayer(node.layer);if(newParent instanceof GeoExt.tree.LayerContainer&&this.store===newParent.loader.store){newParent.loader._reordering=true;this.store.remove(record);var newRecordIndex;if(newParent.childNodes.length>1){var searchIndex=(index===0)?index+1:index-1;newRecordIndex=this.store.findBy(function(r){return newParent.childNodes[searchIndex].layer===r.getLayer();});index===0&&newRecordIndex++;}else if(oldParent.parentNode===newParent.parentNode){var prev=newParent;do{prev=prev.previousSibling;}while(prev&&!(prev instanceof GeoExt.tree.LayerContainer&&prev.lastChild));if(prev){newRecordIndex=this.store.findBy(function(r){return prev.lastChild.layer===r.getLayer();});}else{var next=newParent;do{next=next.nextSibling;}while(next&&!(next instanceof GeoExt.tree.LayerContainer&&next.firstChild));if(next){newRecordIndex=this.store.findBy(function(r){return next.firstChild.layer===r.getLayer();});}
+newRecordIndex++;}}
+if(newRecordIndex!==undefined){this.store.insert(newRecordIndex,[record]);window.setTimeout(function(){newParent.reload();oldParent.reload();});}else{this.store.insert(oldRecordIndex,[record]);}
+delete newParent.loader._reordering;}
+delete this._reordering;},addStoreHandlers:function(node){if(!this._storeHandlers){this._storeHandlers={"add":this.onStoreAdd.createDelegate(this,[node],true),"remove":this.onStoreRemove.createDelegate(this,[node],true)};for(var evt in this._storeHandlers){this.store.on(evt,this._storeHandlers[evt],this);}}},removeStoreHandlers:function(){if(this._storeHandlers){for(var evt in this._storeHandlers){this.store.un(evt,this._storeHandlers[evt],this);}
+delete this._storeHandlers;}},createNode:function(attr){if(this.baseAttrs){Ext.apply(attr,this.baseAttrs);}
+if(typeof attr.uiProvider=='string'){attr.uiProvider=this.uiProviders[attr.uiProvider]||eval(attr.uiProvider);}
+attr.nodeType=attr.nodeType||"gx_layer";return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);},destroy:function(){this.removeStoreHandlers();}});Ext.namespace("GeoExt.plugins");GeoExt.plugins.PrintProviderField=Ext.extend(Ext.util.Observable,{target:null,constructor:function(config){this.initialConfig=config;Ext.apply(this,config);GeoExt.plugins.PrintProviderField.superclass.constructor.apply(this,arguments);},init:function(target){this.target=target;var onCfg={scope:this,"render":this.onRender,"beforedestroy":this.onBeforeDestroy};onCfg[target instanceof Ext.form.ComboBox?"select":"valid"]=this.onFieldChange;target.on(onCfg);},onRender:function(field){var printProvider=this.printProvider||field.ownerCt.printProvider;if(field.store===printProvider.layouts){field.setValue(printProvider.layout.get(field.displayField));printProvider.on({"layoutchange":this.onProviderChange,scope:this});}else if(field.store===printProvider.dpis){field.setValue(printProvider.dpi.get(field.displayField));printProvider.on({"dpichange":this.onProviderChange,scope:this});}else if(field.initialConfig.value===undefined){field.setValue(printProvider.customParams[field.name]);}},onFieldChange:function(field,record){var printProvider=this.printProvider||field.ownerCt.printProvider;var value=field.getValue();this._updating=true;if(record){switch(field.store){case printProvider.layouts:printProvider.setLayout(record);break;case printProvider.dpis:printProvider.setDpi(record);}}else{printProvider.customParams[field.name]=value;}
+delete this._updating;},onProviderChange:function(printProvider,rec){if(!this._updating){this.target.setValue(rec.get(this.target.displayField));}},onBeforeDestroy:function(){var target=this.target;target.un("beforedestroy",this.onBeforeDestroy,this);target.un("render",this.onRender,this);target.un("select",this.onFieldChange,this);target.un("valid",this.onFieldChange,this);var printProvider=this.printProvider||target.ownerCt.printProvider;printProvider.un("layoutchange",this.onProviderChange,this);printProvider.un("dpichange",this.onProviderChange,this);}});Ext.preg("gx_printproviderfield",GeoExt.plugins.PrintProviderField);Ext.namespace("GeoExt","GeoExt.data");GeoExt.data.LayerReader=function(meta,recordType){meta=meta||{};if(!(recordType instanceof Function)){recordType=GeoExt.data.LayerRecord.create(recordType||meta.fields||{});}
+GeoExt.data.LayerReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.LayerReader,Ext.data.DataReader,{totalRecords:null,readRecords:function(layers){var records=[];if(layers){var recordType=this.recordType,fields=recordType.prototype.fields;var i,lenI,j,lenJ,layer,values,field,v;for(i=0,lenI=layers.length;i<lenI;i++){layer=layers[i];values={};for(j=0,lenJ=fields.length;j<lenJ;j++){field=fields.items[j];v=layer[field.mapping||field.name]||field.defaultValue;v=field.convert(v);values[field.name]=v;}
+values.layer=layer;records[records.length]=new recordType(values,layer.id);}}
+return{records:records,totalRecords:this.totalRecords!=null?this.totalRecords:records.length};}});Ext.namespace("GeoExt.data");GeoExt.data.WMSDescribeLayerStore=function(c){c=c||{};GeoExt.data.WMSDescribeLayerStore.superclass.constructor.call(this,Ext.apply(c,{proxy:c.proxy||(!c.data?new Ext.data.HttpProxy({url:c.url,disableCaching:false,method:"GET"}):undefined),reader:new GeoExt.data.WMSDescribeLayerReader(c,c.fields)}));};Ext.extend(GeoExt.data.WMSDescribeLayerStore,Ext.data.Store);Ext.namespace("GeoExt.form");GeoExt.form.BasicForm=Ext.extend(Ext.form.BasicForm,{protocol:null,prevResponse:null,autoAbort:true,doAction:function(action,options){if(action=="search"){options=Ext.applyIf(options||{},{protocol:this.protocol,abortPrevious:this.autoAbort});action=new GeoExt.form.SearchAction(this,options);}
+return GeoExt.form.BasicForm.superclass.doAction.call(this,action,options);},search:function(options){return this.doAction("search",options);}});Ext.namespace("GeoExt.plugins");GeoExt.plugins.TreeNodeRadioButton=Ext.extend(Ext.util.Observable,{constructor:function(config){Ext.apply(this.initialConfig,Ext.apply({},config));Ext.apply(this,config);this.addEvents("radiochange");GeoExt.plugins.TreeNodeRadioButton.superclass.constructor.apply(this,arguments);},init:function(tree){tree.on({"rendernode":this.onRenderNode,"rawclicknode":this.onRawClickNode,"beforedestroy":this.onBeforeDestroy,scope:this});},onRenderNode:function(node){var a=node.attributes;if(a.radioGroup&&!a.radio){a.radio=Ext.DomHelper.insertBefore(node.ui.anchor,['<input type="radio" class="gx-tree-radio" name="',a.radioGroup,'_radio"></input>'].join(""));}},onRawClickNode:function(node,e){var el=e.getTarget('.gx-tree-radio',1);if(el){el.defaultChecked=el.checked;this.fireEvent("radiochange",node);return false;}},onBeforeDestroy:function(tree){tree.un("rendernode",this.onRenderNode,this);tree.un("rawclicknode",this.onRawClickNode,this);tree.un("beforedestroy",this.onBeforeDestroy,this);}});Ext.preg("gx_treenoderadiobutton",GeoExt.plugins.TreeNodeRadioButton);Ext.namespace("GeoExt.data");GeoExt.data.StyleReader=Ext.extend(Ext.data.JsonReader,{onMetaChange:function(){GeoExt.data.StyleReader.superclass.onMetaChange.apply(this,arguments);this.recordType.prototype.commit=Ext.createInterceptor(this.recordType.prototype.commit,function(){var reader=this.store.reader;reader.raw[reader.meta.root]=reader.meta.storeToData(this.store);});},readRecords:function(o){var type,rows;if(o instanceof OpenLayers.Symbolizer.Raster){type="colorMap";}else{type="rules";}
+this.raw=o;Ext.applyIf(this.meta,GeoExt.data.StyleReader.metaData[type]);var data={metaData:this.meta};data[type]=o[type];return GeoExt.data.StyleReader.superclass.readRecords.call(this,data);}});GeoExt.data.StyleReader.metaData={colorMap:{root:"colorMap",idProperty:"filter",fields:[{name:"symbolizers",mapping:function(v){return{fillColor:v.color,fillOpacity:v.opacity,stroke:false};}},{name:"filter",mapping:"quantity",type:"float"},{name:"label",mapping:function(v){return v.label||v.quantity;}}],storeToData:function(store){store.sort("filter","ASC");var colorMap=[];store.each(function(rec){var symbolizer=rec.get("symbolizers"),label=rec.get("label"),labelModified=rec.isModified("label");var quantity=Number(rec.get("filter"));rec.data.filter=quantity;if((!rec.json.label&&!labelModified&&rec.isModified("filter"))||(labelModified&&!label)){rec.data.label=quantity;}
+colorMap.push(Ext.apply(rec.json,{color:symbolizer.fillColor,label:typeof label=="string"?label:undefined,opacity:symbolizer.opacity,quantity:quantity}));});return colorMap;}},rules:{root:"rules",fields:["symbolizers","filter",{name:"label",mapping:"title"},"name","description","elseFilter","minScaleDenominator","maxScaleDenominator"],storeToData:function(store){var rules=[];store.each(function(rec){var filter=rec.get("filter");if(typeof filter==="string"){filter=filter?OpenLayers.Format.CQL.prototype.read(filter):null;}
+rules.push(Ext.apply(rec.json,{symbolizers:rec.get("symbolizers"),filter:filter,title:rec.get("label"),name:rec.get("name"),description:rec.get("description"),elseFilter:rec.get("elseFilter"),minScaleDenominator:rec.get("minScaleDenominator"),maxScaleDenominator:rec.get("maxScaleDenominator")}));});return rules;}}};Ext.namespace('GeoExt','GeoExt.data');GeoExt.data.FeatureReader=function(meta,recordType){meta=meta||{};if(!(recordType instanceof Function)){recordType=GeoExt.data.FeatureRecord.create(recordType||meta.fields||{});}
+GeoExt.data.FeatureReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.FeatureReader,Ext.data.DataReader,{totalRecords:null,read:function(response){return this.readRecords(response.features);},readRecords:function(features){var records=[];if(features){var recordType=this.recordType,fields=recordType.prototype.fields;var i,lenI,j,lenJ,feature,values,field,v;for(i=0,lenI=features.length;i<lenI;i++){feature=features[i];values={};if(feature.attributes){for(j=0,lenJ=fields.length;j<lenJ;j++){field=fields.items[j];if(/[\[\.]/.test(field.mapping)){try{v=new Function("obj","return obj."+field.mapping)(feature.attributes);}catch(e){v=field.defaultValue;}}
+else{v=feature.attributes[field.mapping||field.name]||field.defaultValue;}
+if(field.convert){v=field.convert(v);}
+values[field.name]=v;}}
+values.feature=feature;values.state=feature.state;values.fid=feature.fid;var id=(feature.state===OpenLayers.State.INSERT)?undefined:feature.id;records[records.length]=new recordType(values,id);}}
+return{records:records,totalRecords:this.totalRecords!=null?this.totalRecords:records.length};}});Ext.namespace('GeoExt');GeoExt.WMSLegend=Ext.extend(GeoExt.LayerLegend,{defaultStyleIsFirst:true,useScaleParameter:true,baseParams:null,initComponent:function(){GeoExt.WMSLegend.superclass.initComponent.call(this);var layer=this.layerRecord.getLayer();this._noMap=!layer.map;layer.events.register("moveend",this,this.onLayerMoveend);this.update();},onLayerMoveend:function(e){if((e.zoomChanged===true&&this.useScaleParameter===true)||this._noMap){delete this._noMap;this.update();}},getLegendUrl:function(layerName,layerNames){var rec=this.layerRecord;var url;var styles=rec&&rec.get("styles");var layer=rec.getLayer();layerNames=layerNames||[layer.params.LAYERS].join(",").split(",");var styleNames=layer.params.STYLES&&[layer.params.STYLES].join(",").split(",");var idx=layerNames.indexOf(layerName);var styleName=styleNames&&styleNames[idx];if(styles&&styles.length>0){if(styleName){Ext.each(styles,function(s){url=(s.name==styleName&&s.legend)&&s.legend.href;return!url;});}else if(this.defaultStyleIsFirst===true&&!styleNames&&!layer.params.SLD&&!layer.params.SLD_BODY){url=styles[0].legend&&styles[0].legend.href;}}
+if(!url){url=layer.getFullRequestString({REQUEST:"GetLegendGraphic",WIDTH:null,HEIGHT:null,EXCEPTIONS:"application/vnd.ogc.se_xml",LAYER:layerName,LAYERS:null,STYLE:(styleName!=='')?styleName:null,STYLES:null,SRS:null,FORMAT:null,TIME:null});}
+if(url.toLowerCase().indexOf("request=getlegendgraphic")!=-1){if(url.toLowerCase().indexOf("format=")==-1){url=Ext.urlAppend(url,"FORMAT=image/gif");}
+if(this.useScaleParameter===true){var scale=layer.map.getScale();url=Ext.urlAppend(url,"SCALE="+scale);}}
+var params=Ext.apply({},this.baseParams);if(layer.params._OLSALT){params._OLSALT=layer.params._OLSALT;}
+url=Ext.urlAppend(url,Ext.urlEncode(params));return url;},update:function(){var layer=this.layerRecord.getLayer();if(!(layer&&layer.map)){return;}
+GeoExt.WMSLegend.superclass.update.apply(this,arguments);var layerNames,layerName,i,len;layerNames=[layer.params.LAYERS].join(",").split(",");var destroyList=[];var textCmp=this.items.get(0);this.items.each(function(cmp){i=layerNames.indexOf(cmp.itemId);if(i<0&&cmp!=textCmp){destroyList.push(cmp);}else if(cmp!==textCmp){layerName=layerNames[i];var newUrl=this.getLegendUrl(layerName,layerNames);if(!OpenLayers.Util.isEquivalentUrl(newUrl,cmp.url)){cmp.setUrl(newUrl);}}},this);for(i=0,len=destroyList.length;i<len;i++){var cmp=destroyList[i];this.remove(cmp);cmp.destroy();}
+for(i=0,len=layerNames.length;i<len;i++){layerName=layerNames[i];if(!this.items||!this.getComponent(layerName)){this.add({xtype:"gx_legendimage",url:this.getLegendUrl(layerName,layerNames),itemId:layerName});}}
+this.doLayout();},beforeDestroy:function(){if(this.useScaleParameter===true){var layer=this.layerRecord.getLayer();layer&&layer.events&&layer.events.unregister("moveend",this,this.onLayerMoveend);}
+GeoExt.WMSLegend.superclass.beforeDestroy.apply(this,arguments);}});GeoExt.WMSLegend.supports=function(layerRecord){return layerRecord.getLayer()instanceof OpenLayers.Layer.WMS?1:0;};GeoExt.LayerLegend.types["gx_wmslegend"]=GeoExt.WMSLegend;Ext.reg('gx_wmslegend',GeoExt.WMSLegend);Ext.namespace("GeoExt.data");GeoExt.data.WMSDescribeLayerReader=function(meta,recordType){meta=meta||{};if(!meta.format){meta.format=new OpenLayers.Format.WMSDescribeLayer();}
+if(!(typeof recordType==="function")){recordType=Ext.data.Record.create(recordType||meta.fields||[{name:"owsType",type:"string"},{name:"owsURL",type:"string"},{name:"typeName",type:"string"}]);}
+GeoExt.data.WMSDescribeLayerReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.WMSDescribeLayerReader,Ext.data.DataReader,{read:function(request){var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+return this.readRecords(data);},readRecords:function(data){if(typeof data==="string"||data.nodeType){data=this.meta.format.read(data);}
+var records=[],description;for(var i=0,len=data.length;i<len;i++){description=data[i];if(description){records.push(new this.recordType(description));}}
+return{totalRecords:records.length,success:true,records:records};}});Ext.namespace("GeoExt.form");GeoExt.form.SearchAction=Ext.extend(Ext.form.Action,{type:"search",response:null,constructor:function(form,options){GeoExt.form.SearchAction.superclass.constructor.call(this,form,options);},run:function(){var o=this.options;var f=GeoExt.form.toFilter(this.form,o.logicalOp,o.wildcard);if(o.clientValidation===false||this.form.isValid()){if(o.abortPrevious&&this.form.prevResponse){o.protocol.abort(this.form.prevResponse);}
+this.form.prevResponse=o.protocol.read(Ext.applyIf({filter:f,callback:this.handleResponse,scope:this},o));}else if(o.clientValidation!==false){this.failureType=Ext.form.Action.CLIENT_INVALID;this.form.afterAction(this,false);}},handleResponse:function(response){this.form.prevResponse=null;this.response=response;if(response.success()){this.form.afterAction(this,true);}else{this.form.afterAction(this,false);}
+var o=this.options;if(o.callback){o.callback.call(o.scope,response);}}});Ext.namespace("GeoExt.data");GeoExt.data.FeatureRecord=Ext.data.Record.create([{name:"feature"},{name:"state"},{name:"fid"}]);GeoExt.data.FeatureRecord.prototype.getFeature=function(){return this.get("feature");};GeoExt.data.FeatureRecord.prototype.setFeature=function(feature){if(feature!==this.data.feature){this.dirty=true;if(!this.modified){this.modified={};}
+if(this.modified.feature===undefined){this.modified.feature=this.data.feature;}
+this.data.feature=feature;if(!this.editing){this.afterEdit();}}};GeoExt.data.FeatureRecord.create=function(o){var f=Ext.extend(GeoExt.data.FeatureRecord,{});var p=f.prototype;p.fields=new Ext.util.MixedCollection(false,function(field){return field.name;});GeoExt.data.FeatureRecord.prototype.fields.each(function(f){p.fields.add(f);});if(o){for(var i=0,len=o.length;i<len;i++){p.fields.add(new Ext.data.Field(o[i]));}}
+f.getField=function(name){return p.fields.get(name);};return f;};Ext.namespace("GeoExt.tree");GeoExt.tree.LayerParamLoader=function(config){Ext.apply(this,config);this.addEvents("beforeload","load");GeoExt.tree.LayerParamLoader.superclass.constructor.call(this);};Ext.extend(GeoExt.tree.LayerParamLoader,Ext.util.Observable,{param:null,delimiter:",",load:function(node,callback){if(this.fireEvent("beforeload",this,node)){while(node.firstChild){node.removeChild(node.firstChild);}
+var paramValue=(node.layer instanceof OpenLayers.Layer.HTTPRequest)&&node.layer.params[this.param];if(paramValue){var items=(paramValue instanceof Array)?paramValue.slice():paramValue.split(this.delimiter);Ext.each(items,function(item,index,allItems){this.addParamNode(item,allItems,node);},this);}
+if(typeof callback=="function"){callback();}
+this.fireEvent("load",this,node);}},addParamNode:function(paramItem,allParamItems,node){var child=this.createNode({layer:node.layer,param:this.param,item:paramItem,allItems:allParamItems,delimiter:this.delimiter});var sibling=node.item(0);if(sibling){node.insertBefore(child,sibling);}else{node.appendChild(child);}},createNode:function(attr){if(this.baseAttrs){Ext.apply(attr,this.baseAttrs);}
+if(typeof attr.uiProvider=='string'){attr.uiProvider=this.uiProviders[attr.uiProvider]||eval(attr.uiProvider);}
+attr.nodeType=attr.nodeType||"gx_layerparam";return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);}});Ext.namespace("GeoExt.data");GeoExt.data.PrintPage=Ext.extend(Ext.util.Observable,{printProvider:null,feature:null,center:null,scale:null,rotation:0,customParams:null,constructor:function(config){this.initialConfig=config;Ext.apply(this,config);if(!this.customParams){this.customParams={};}
+this.addEvents("change");GeoExt.data.PrintPage.superclass.constructor.apply(this,arguments);this.feature=new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POLYGON((-1 -1,1 -1,1 1,-1 1,-1 -1))"));if(this.printProvider.capabilities){this.setScale(this.printProvider.scales.getAt(0));}else{this.printProvider.on({"loadcapabilities":function(){this.setScale(this.printProvider.scales.getAt(0));},scope:this,single:true});}
+this.printProvider.on({"layoutchange":this.onLayoutChange,scope:this});},getPrintExtent:function(map){map=map instanceof GeoExt.MapPanel?map.map:map;return this.calculatePageBounds(this.scale,map.getUnits());},setScale:function(scale,units){var bounds=this.calculatePageBounds(scale,units);var geom=bounds.toGeometry();var rotation=this.rotation;if(rotation!=0){geom.rotate(-rotation,geom.getCentroid());}
+this.updateFeature(geom,{scale:scale});},setCenter:function(center){var geom=this.feature.geometry;var oldCenter=geom.getBounds().getCenterLonLat();var dx=center.lon-oldCenter.lon;var dy=center.lat-oldCenter.lat;geom.move(dx,dy);this.updateFeature(geom,{center:center});},setRotation:function(rotation,force){if(force||this.printProvider.layout.get("rotation")===true){var geom=this.feature.geometry;geom.rotate(this.rotation-rotation,geom.getCentroid());this.updateFeature(geom,{rotation:rotation});}},fit:function(fitTo,options){options=options||{};var map=fitTo,extent;if(fitTo instanceof GeoExt.MapPanel){map=fitTo.map;}else if(fitTo instanceof OpenLayers.Feature.Vector){map=fitTo.layer.map;extent=fitTo.geometry.getBounds();}
+if(!extent){extent=map.getExtent();if(!extent){return;}}
+this._updating=true;var center=extent.getCenterLonLat();this.setCenter(center);var units=map.getUnits();var scale=this.printProvider.scales.getAt(0);var closest=Number.POSITIVE_INFINITY;var mapWidth=extent.getWidth();var mapHeight=extent.getHeight();this.printProvider.scales.each(function(rec){var bounds=this.calculatePageBounds(rec,units);if(options.mode=="closest"){var diff=Math.abs(bounds.getWidth()-mapWidth)+
+Math.abs(bounds.getHeight()-mapHeight);if(diff<closest){closest=diff;scale=rec;}}else{var contains=options.mode=="screen"?!extent.containsBounds(bounds):bounds.containsBounds(extent);if(contains||(options.mode=="screen"&&!contains)){scale=rec;}
+return contains;}},this);this.setScale(scale,units);delete this._updating;this.updateFeature(this.feature.geometry,{center:center,scale:scale});},updateFeature:function(geometry,mods){var f=this.feature;var modified=f.geometry!==geometry;geometry.id=f.geometry.id;f.geometry=geometry;if(!this._updating){for(var property in mods){if(mods[property]===this[property]){delete mods[property];}else{this[property]=mods[property];modified=true;}}
+Ext.apply(this,mods);f.layer&&f.layer.drawFeature(f);modified&&this.fireEvent("change",this,mods);}},calculatePageBounds:function(scale,units){var s=scale.get("value");var f=this.feature;var geom=this.feature.geometry;var center=geom.getBounds().getCenterLonLat();var size=this.printProvider.layout.get("size");var units=units||(f.layer&&f.layer.map&&f.layer.map.getUnits())||"dd";var unitsRatio=OpenLayers.INCHES_PER_UNIT[units];var w=size.width/72/unitsRatio*s/2;var h=size.height/72/unitsRatio*s/2;return new OpenLayers.Bounds(center.lon-w,center.lat-h,center.lon+w,center.lat+h);},onLayoutChange:function(){if(this.printProvider.layout.get("rotation")===false){this.setRotation(0,true);}
+this.scale&&this.setScale(this.scale);},destroy:function(){this.printProvider.un("layoutchange",this.onLayoutChange,this);}});Ext.namespace("GeoExt.data");GeoExt.data.LayerRecord=Ext.data.Record.create([{name:"layer"},{name:"title",type:"string",mapping:"name"}]);GeoExt.data.LayerRecord.prototype.getLayer=function(){return this.get("layer");};GeoExt.data.LayerRecord.prototype.setLayer=function(layer){if(layer!==this.data.layer){this.dirty=true;if(!this.modified){this.modified={};}
+if(this.modified.layer===undefined){this.modified.layer=this.data.layer;}
+this.data.layer=layer;if(!this.editing){this.afterEdit();}}};GeoExt.data.LayerRecord.prototype.clone=function(id){var layer=this.getLayer()&&this.getLayer().clone();return new this.constructor(Ext.applyIf({layer:layer},this.data),id||layer.id);};GeoExt.data.LayerRecord.create=function(o){var f=Ext.extend(GeoExt.data.LayerRecord,{});var p=f.prototype;p.fields=new Ext.util.MixedCollection(false,function(field){return field.name;});GeoExt.data.LayerRecord.prototype.fields.each(function(f){p.fields.add(f);});if(o){for(var i=0,len=o.length;i<len;i++){p.fields.add(new Ext.data.Field(o[i]));}}
+f.getField=function(name){return p.fields.get(name);};return f;};Ext.namespace("GeoExt.form");GeoExt.form.toFilter=function(form,logicalOp,wildcard){if(form instanceof Ext.form.FormPanel){form=form.getForm();}
+var filters=[],values=form.getValues(false);for(var prop in values){var s=prop.split("__");var value=values[prop],type;if(s.length>1&&(type=GeoExt.form.toFilter.FILTER_MAP[s[1]])!==undefined){prop=s[0];}else{type=OpenLayers.Filter.Comparison.EQUAL_TO;}
+if(type===OpenLayers.Filter.Comparison.LIKE){switch(wildcard){case GeoExt.form.ENDS_WITH:value='.*'+value;break;case GeoExt.form.STARTS_WITH:value+='.*';break;case GeoExt.form.CONTAINS:value='.*'+value+'.*';break;default:break;}}
+filters.push(new OpenLayers.Filter.Comparison({type:type,value:value,property:prop}));}
+return filters.length==1&&logicalOp!=OpenLayers.Filter.Logical.NOT?filters[0]:new OpenLayers.Filter.Logical({type:logicalOp||OpenLayers.Filter.Logical.AND,filters:filters});};GeoExt.form.toFilter.FILTER_MAP={"eq":OpenLayers.Filter.Comparison.EQUAL_TO,"ne":OpenLayers.Filter.Comparison.NOT_EQUAL_TO,"lt":OpenLayers.Filter.Comparison.LESS_THAN,"le":OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,"gt":OpenLayers.Filter.Comparison.GREATER_THAN,"ge":OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,"like":OpenLayers.Filter.Comparison.LIKE};GeoExt.form.ENDS_WITH=1;GeoExt.form.STARTS_WITH=2;GeoExt.form.CONTAINS=3;GeoExt.form.recordToField=function(record,options){options=options||{};var type=record.get("type");if(typeof type==="object"&&type.xtype){return type;}
+type=type.split(":").pop();var field;var name=record.get("name");var restriction=record.get("restriction")||{};var nillable=record.get("nillable")||false;var label=record.get("label");var labelTpl=options.labelTpl;if(labelTpl){var tpl=(labelTpl instanceof Ext.Template)?labelTpl:new Ext.XTemplate(labelTpl);label=tpl.apply(record.data);}else if(label==null){label=name;}
+var baseOptions={name:name,labelStyle:nillable?'':options.mandatoryFieldLabelStyle!=null?options.mandatoryFieldLabelStyle:'font-weight:bold;'};var r=GeoExt.form.recordToField.REGEXES;if(type.match(r["text"])){var maxLength=restriction["maxLength"]!==undefined?parseFloat(restriction["maxLength"]):undefined;var minLength=restriction["minLength"]!==undefined?parseFloat(restriction["minLength"]):undefined;field=Ext.apply({xtype:"textfield",fieldLabel:label,maxLength:maxLength,minLength:minLength},baseOptions);}else if(type.match(r["number"])){var maxValue=restriction["maxInclusive"]!==undefined?parseFloat(restriction["maxInclusive"]):undefined;var minValue=restriction["minInclusive"]!==undefined?parseFloat(restriction["minInclusive"]):undefined;field=Ext.apply({xtype:"numberfield",fieldLabel:label,maxValue:maxValue,minValue:minValue},baseOptions);}else if(type.match(r["boolean"])){field=Ext.apply({xtype:"checkbox"},baseOptions);var labelProperty=options.checkboxLabelProperty||"boxLabel";field[labelProperty]=label;}else if(type.match(r["date"])){field=Ext.apply({xtype:"datefield",fieldLabel:label,format:'c'},baseOptions);}
+return field;};GeoExt.form.recordToField.REGEXES={"text":new RegExp("^(text|string)$","i"),"number":new RegExp("^(number|float|decimal|double|int|long|integer|short)$","i"),"boolean":new RegExp("^(boolean)$","i"),"date":new RegExp("^(date|dateTime)$","i")};Ext.namespace('GeoExt');GeoExt.FeatureRenderer=Ext.extend(Ext.BoxComponent,{feature:undefined,symbolizers:[OpenLayers.Feature.Vector.style["default"]],symbolType:"Polygon",resolution:1,minWidth:20,minHeight:20,renderers:["SVG","VML","Canvas"],rendererOptions:null,pointFeature:undefined,lineFeature:undefined,polygonFeature:undefined,renderer:null,initComponent:function(){GeoExt.FeatureRenderer.superclass.initComponent.apply(this,arguments);Ext.applyIf(this,{pointFeature:new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0)),lineFeature:new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([new OpenLayers.Geometry.Point(-8,-3),new OpenLayers.Geometry.Point(-3,3),new OpenLayers.Geometry.Point(3,-3),new OpenLayers.Geometry.Point(8,3)])),polygonFeature:new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(-8,-4),new OpenLayers.Geometry.Point(-6,-6),new OpenLayers.Geometry.Point(6,-6),new OpenLayers.Geometry.Point(8,-4),new OpenLayers.Geometry.Point(8,4),new OpenLayers.Geometry.Point(6,6),new OpenLayers.Geometry.Point(-6,6),new OpenLayers.Geometry.Point(-8,4)])]))});if(!this.feature){this.setFeature(null,{draw:false});}
+this.addEvents("click");},initCustomEvents:function(){this.clearCustomEvents();this.el.on("click",this.onClick,this);},clearCustomEvents:function(){if(this.el&&this.el.removeAllListeners){this.el.removeAllListeners();}},onClick:function(){this.fireEvent("click",this);},onRender:function(ct,position){if(!this.el){this.el=document.createElement("div");this.el.id=this.getId();}
+if(!this.renderer||!this.renderer.supported()){this.assignRenderer();}
+this.renderer.map={getResolution:(function(){return this.resolution;}).createDelegate(this)};GeoExt.FeatureRenderer.superclass.onRender.apply(this,arguments);this.drawFeature();},afterRender:function(){GeoExt.FeatureRenderer.superclass.afterRender.apply(this,arguments);this.initCustomEvents();},onResize:function(w,h){this.setRendererDimensions();GeoExt.FeatureRenderer.superclass.onResize.apply(this,arguments);},setRendererDimensions:function(){var gb=this.feature.geometry.getBounds();var gw=gb.getWidth();var gh=gb.getHeight();var resolution=this.initialConfig.resolution;if(!resolution){resolution=Math.max(gw/this.width||0,gh/this.height||0)||1;}
+this.resolution=resolution;var width=Math.max(this.width||this.minWidth,gw/resolution);var height=Math.max(this.height||this.minHeight,gh/resolution);var center=gb.getCenterPixel();var bhalfw=width*resolution/2;var bhalfh=height*resolution/2;var bounds=new OpenLayers.Bounds(center.x-bhalfw,center.y-bhalfh,center.x+bhalfw,center.y+bhalfh);this.renderer.setSize(new OpenLayers.Size(Math.round(width),Math.round(height)));this.renderer.setExtent(bounds,true);},assignRenderer:function(){for(var i=0,len=this.renderers.length;i<len;++i){var Renderer=OpenLayers.Renderer[this.renderers[i]];if(Renderer&&Renderer.prototype.supported()){this.renderer=new Renderer(this.el,this.rendererOptions);break;}}},setSymbolizers:function(symbolizers,options){this.symbolizers=symbolizers;if(!options||options.draw){this.drawFeature();}},setSymbolType:function(type,options){this.symbolType=type;this.setFeature(null,options);},setFeature:function(feature,options){this.feature=feature||this[this.symbolType.toLowerCase()+"Feature"];if(!options||options.draw){this.drawFeature();}},drawFeature:function(){this.renderer.clear();this.setRendererDimensions();var Symbolizer=OpenLayers.Symbolizer;var Text=Symbolizer&&Symbolizer.Text;var symbolizer,feature,geomType;for(var i=0,len=this.symbolizers.length;i<len;++i){symbolizer=this.symbolizers[i];feature=this.feature;if(!Text||!(symbolizer instanceof Text)){if(Symbolizer&&(symbolizer instanceof Symbolizer)){symbolizer=symbolizer.clone();if(!this.initialConfig.feature){geomType=symbolizer.CLASS_NAME.split(".").pop().toLowerCase();feature=this[geomType+"Feature"];}}else{symbolizer=Ext.apply({},symbolizer);}
+this.renderer.drawFeature(feature.clone(),symbolizer);}}},update:function(options){options=options||{};if(options.feature){this.setFeature(options.feature,{draw:false});}else if(options.symbolType){this.setSymbolType(options.symbolType,{draw:false});}
+if(options.symbolizers){this.setSymbolizers(options.symbolizers,{draw:false});}
+this.drawFeature();},beforeDestroy:function(){this.clearCustomEvents();if(this.renderer){this.renderer.destroy();}}});Ext.reg('gx_renderer',GeoExt.FeatureRenderer);Ext.namespace("GeoExt");GeoExt.Popup=Ext.extend(Ext.Window,{anchored:true,map:null,panIn:true,unpinnable:true,location:null,insideViewport:null,animCollapse:false,draggable:false,shadow:false,popupCls:"gx-popup",ancCls:null,anchorPosition:"auto",initComponent:function(){if(this.map instanceof GeoExt.MapPanel){this.map=this.map.map;}
+if(!this.map&&this.location instanceof OpenLayers.Feature.Vector&&this.location.layer){this.map=this.location.layer.map;}
+if(this.location instanceof OpenLayers.Feature.Vector){this.location=this.location.geometry;}
+if(this.location instanceof OpenLayers.Geometry){if(typeof this.location.getCentroid=="function"){this.location=this.location.getCentroid();}
+this.location=this.location.getBounds().getCenterLonLat();}else if(this.location instanceof OpenLayers.Pixel){this.location=this.map.getLonLatFromViewPortPx(this.location);}
+var mapExtent=this.map.getExtent();if(mapExtent&&this.location){this.insideViewport=mapExtent.containsLonLat(this.location);}
+if(this.anchored){this.addAnchorEvents();}
+this.baseCls=this.popupCls+" "+this.baseCls;this.elements+=',anc';GeoExt.Popup.superclass.initComponent.call(this);},onRender:function(ct,position){GeoExt.Popup.superclass.onRender.call(this,ct,position);this.ancCls=this.popupCls+"-anc";this.createElement("anc",this.el.dom);},initTools:function(){if(this.unpinnable){this.addTool({id:'unpin',handler:this.unanchorPopup.createDelegate(this,[])});}
+GeoExt.Popup.superclass.initTools.call(this);},show:function(){GeoExt.Popup.superclass.show.apply(this,arguments);if(this.anchored){this.position();if(this.panIn&&!this._mapMove){this.panIntoView();}}},maximize:function(){if(!this.maximized&&this.anc){this.unanchorPopup();}
+GeoExt.Popup.superclass.maximize.apply(this,arguments);},setSize:function(w,h){if(this.anc){var ancSize=this.anc.getSize();if(typeof w=='object'){h=w.height-ancSize.height;w=w.width;}else if(!isNaN(h)){h=h-ancSize.height;}}
+GeoExt.Popup.superclass.setSize.call(this,w,h);},position:function(){if(this._mapMove===true){this.insideViewport=this.map.getExtent().containsLonLat(this.location);if(this.insideViewport!==this.isVisible()){this.setVisible(this.insideViewport);}}
+if(this.isVisible()){var locationPx=this.map.getPixelFromLonLat(this.location),mapBox=Ext.fly(this.map.div).getBox(true),top=locationPx.y+mapBox.y,left=locationPx.x+mapBox.x,elSize=this.el.getSize(),ancSize=this.anc.getSize(),ancPos=this.anchorPosition;if(ancPos.indexOf("right")>-1||locationPx.x>mapBox.width/2){this.anc.addClass("right");var ancRight=this.el.getX(true)+elSize.width-
+this.anc.getX(true)-ancSize.width;left-=elSize.width-ancRight-ancSize.width/2;}else{this.anc.removeClass("right");var ancLeft=this.anc.getLeft(true);left-=ancLeft+ancSize.width/2;}
+if(ancPos.indexOf("bottom")>-1||locationPx.y>mapBox.height/2){this.anc.removeClass("top");top-=elSize.height+ancSize.height;}else{this.anc.addClass("top");top+=ancSize.height;}
+this.setPosition(left,top);}},unanchorPopup:function(){this.removeAnchorEvents();this.draggable=true;this.header.addClass("x-window-draggable");this.dd=new Ext.Window.DD(this);this.anc.remove();this.anc=null;this.tools.unpin.hide();},panIntoView:function(){var mapBox=Ext.fly(this.map.div).getBox(true);var popupPos=this.getPosition(true);popupPos[0]-=mapBox.x;popupPos[1]-=mapBox.y;var panelSize=[mapBox.width,mapBox.height];var popupSize=this.getSize();var newPos=[popupPos[0],popupPos[1]];var padding=this.map.paddingForPopups;if(popupPos[0]<padding.left){newPos[0]=padding.left;}else if(popupPos[0]+popupSize.width>panelSize[0]-padding.right){newPos[0]=panelSize[0]-padding.right-popupSize.width;}
+if(popupPos[1]<padding.top){newPos[1]=padding.top;}else if(popupPos[1]+popupSize.height>panelSize[1]-padding.bottom){newPos[1]=panelSize[1]-padding.bottom-popupSize.height;}
+var dx=popupPos[0]-newPos[0];var dy=popupPos[1]-newPos[1];this.map.pan(dx,dy);},onMapMove:function(){if(!(this.hidden&&this.insideViewport)){this._mapMove=true;this.position();delete this._mapMove;}},addAnchorEvents:function(){this.map.events.on({"move":this.onMapMove,scope:this});this.on({"resize":this.position,"collapse":this.position,"expand":this.position,scope:this});},removeAnchorEvents:function(){this.map.events.un({"move":this.onMapMove,scope:this});this.un("resize",this.position,this);this.un("collapse",this.position,this);this.un("expand",this.position,this);},beforeDestroy:function(){if(this.anchored){this.removeAnchorEvents();}
+GeoExt.Popup.superclass.beforeDestroy.call(this);}});Ext.reg('gx_popup',GeoExt.Popup);Ext.namespace("GeoExt.data");GeoExt.data.AttributeStoreMixin=function(){return{constructor:function(c){c=c||{};arguments.callee.superclass.constructor.call(this,Ext.apply(c,{proxy:c.proxy||(!c.data?new Ext.data.HttpProxy({url:c.url,disableCaching:false,method:"GET"}):undefined),reader:new GeoExt.data.AttributeReader(c,c.fields||["name","type","restriction",{name:"nillable",type:"boolean"}])}));if(this.feature){this.bind();}},bind:function(){this.on({"update":this.onUpdate,"load":this.onLoad,"add":this.onAdd,scope:this});var records=[];this.each(function(record){records.push(record);});this.updateFeature(records);},onUpdate:function(store,record,operation){this.updateFeature([record]);},onLoad:function(store,records,options){if(!options||options.add!==true){this.updateFeature(records);}},onAdd:function(store,records,index){this.updateFeature(records);},updateFeature:function(records){var feature=this.feature,layer=feature.layer;var i,len,record,name,value,oldValue,dirty;for(i=0,len=records.length;i<len;i++){record=records[i];name=record.get("name");value=record.get("value");oldValue=feature.attributes[name];if(oldValue!==value){dirty=true;}}
+if(dirty&&layer&&layer.events&&layer.events.triggerEvent("beforefeaturemodified",{feature:feature})!==false){for(i=0,len=records.length;i<len;i++){record=records[i];name=record.get("name");value=record.get("value");feature.attributes[name]=value;}
+layer.events.triggerEvent("featuremodified",{feature:feature});layer.drawFeature(feature);}}};};GeoExt.data.AttributeStore=Ext.extend(Ext.data.Store,GeoExt.data.AttributeStoreMixin());Ext.namespace("GeoExt.form");GeoExt.form.FormPanel=Ext.extend(Ext.form.FormPanel,{protocol:null,createForm:function(){delete this.initialConfig.listeners;return new GeoExt.form.BasicForm(null,this.initialConfig);},search:function(options){this.getForm().search(options);}});Ext.reg("gx_formpanel",GeoExt.form.FormPanel);Ext.namespace("GeoExt.data");GeoExt.data.WMCReader=function(meta,recordType){meta=meta||{};if(!meta.format){meta.format=new OpenLayers.Format.WMC();}
+if(!(typeof recordType==="function")){recordType=GeoExt.data.LayerRecord.create(recordType||meta.fields||[{name:"abstract",type:"string"},{name:"metadataURL",type:"string"},{name:"queryable",type:"boolean"},{name:"formats"},{name:"styles"}]);}
+GeoExt.data.WMCReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.WMCReader,Ext.data.DataReader,{read:function(request){var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+return this.readRecords(data);},readRecords:function(data){var format=this.meta.format;if(typeof data==="string"||data.nodeType){data=format.read(data);}
+var layersContext=data?data.layersContext:undefined;var records=[];if(layersContext){var recordType=this.recordType,fields=recordType.prototype.fields;var i,lenI,j,lenJ,layerContext,values,field,v;for(i=0,lenI=layersContext.length;i<lenI;i++){layerContext=layersContext[i];values={};for(j=0,lenJ=fields.length;j<lenJ;j++){field=fields.items[j];v=layerContext[field.mapping||field.name]||field.defaultValue;v=field.convert(v);values[field.name]=v;}
+values.layer=format.getLayerFromContext(layerContext);records.push(new this.recordType(values,values.layer.id));}}
+return{totalRecords:records.length,success:true,records:records};}});GeoExt.Lang.add("fr",{"GeoExt.tree.LayerContainer.prototype":{text:"Couches"},"GeoExt.tree.BaseLayerContainer.prototype":{text:"Couches de base"},"GeoExt.tree.OverlayLayerContainer.prototype":{text:"Couches additionnelles"}});Ext.namespace("GeoExt.tree");GeoExt.tree.OverlayLayerContainer=Ext.extend(GeoExt.tree.LayerContainer,{text:'Overlays',constructor:function(config){config=Ext.applyIf(config||{},{text:this.text});config.loader=Ext.applyIf(config.loader||{},{filter:function(record){var layer=record.getLayer();return layer.displayInLayerSwitcher===true&&layer.isBaseLayer===false;}});GeoExt.tree.OverlayLayerContainer.superclass.constructor.call(this,config);}});Ext.tree.TreePanel.nodeTypes.gx_overlaylayercontainer=GeoExt.tree.OverlayLayerContainer;Ext.namespace("GeoExt.data");GeoExt.data.WFSCapabilitiesReader=function(meta,recordType){meta=meta||{};if(!meta.format){meta.format=new OpenLayers.Format.WFSCapabilities();}
+if(!(typeof recordType==="function")){recordType=GeoExt.data.LayerRecord.create(recordType||meta.fields||[{name:"name",type:"string"},{name:"title",type:"string"},{name:"namespace",type:"string",mapping:"featureNS"},{name:"abstract",type:"string"}]);}
+GeoExt.data.WFSCapabilitiesReader.superclass.constructor.call(this,meta,recordType);};Ext.extend(GeoExt.data.WFSCapabilitiesReader,Ext.data.DataReader,{read:function(request){var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+return this.readRecords(data);},readRecords:function(data){if(typeof data==="string"||data.nodeType){data=this.meta.format.read(data);}
+var featureTypes=data.featureTypeList.featureTypes;var fields=this.recordType.prototype.fields;var featureType,values,field,v,parts,layer;var layerOptions,protocolOptions;var protocolDefaults={url:data.capability.request.getfeature.href.post};var records=[];for(var i=0,lenI=featureTypes.length;i<lenI;i++){featureType=featureTypes[i];if(featureType.name){values={};for(var j=0,lenJ=fields.length;j<lenJ;j++){field=fields.items[j];v=featureType[field.mapping||field.name]||field.defaultValue;v=field.convert(v);values[field.name]=v;}
+protocolOptions={featureType:featureType.name,featureNS:featureType.featureNS};if(this.meta.protocolOptions){Ext.apply(protocolOptions,this.meta.protocolOptions,protocolDefaults);}else{Ext.apply(protocolOptions,{},protocolDefaults);}
+layerOptions={protocol:new OpenLayers.Protocol.WFS(protocolOptions),strategies:[new OpenLayers.Strategy.Fixed()]};var metaLayerOptions=this.meta.layerOptions;if(metaLayerOptions){Ext.apply(layerOptions,Ext.isFunction(metaLayerOptions)?metaLayerOptions():metaLayerOptions);}
+values.layer=new OpenLayers.Layer.Vector(featureType.title||featureType.name,layerOptions);records.push(new this.recordType(values,values.layer.id));}}
+return{totalRecords:records.length,success:true,records:records};}});Ext.namespace('GeoExt');GeoExt.LegendPanel=Ext.extend(Ext.Panel,{dynamic:true,layerStore:null,preferredTypes:null,filter:function(record){return true;},initComponent:function(){GeoExt.LegendPanel.superclass.initComponent.call(this);},onRender:function(){GeoExt.LegendPanel.superclass.onRender.apply(this,arguments);if(!this.layerStore){this.layerStore=GeoExt.MapPanel.guess().layers;}
+this.layerStore.each(function(record){this.addLegend(record);},this);if(this.dynamic){this.layerStore.on({"add":this.onStoreAdd,"remove":this.onStoreRemove,"clear":this.onStoreClear,scope:this});}},recordIndexToPanelIndex:function(index){var store=this.layerStore;var count=store.getCount();var panelIndex=-1;var legendCount=this.items?this.items.length:0;var record,layer;for(var i=count-1;i>=0;--i){record=store.getAt(i);layer=record.getLayer();var types=GeoExt.LayerLegend.getTypes(record);if(layer.displayInLayerSwitcher&&types.length>0&&(store.getAt(i).get("hideInLegend")!==true)){++panelIndex;if(index===i||panelIndex>legendCount-1){break;}}}
+return panelIndex;},getIdForLayer:function(layer){return this.id+"-"+layer.id;},onStoreAdd:function(store,records,index){var panelIndex=this.recordIndexToPanelIndex(index+records.length-1);for(var i=0,len=records.length;i<len;i++){this.addLegend(records[i],panelIndex);}
+this.doLayout();},onStoreRemove:function(store,record,index){this.removeLegend(record);},removeLegend:function(record){if(this.items){var legend=this.getComponent(this.getIdForLayer(record.getLayer()));if(legend){this.remove(legend,true);this.doLayout();}}},onStoreClear:function(store){this.removeAllLegends();},removeAllLegends:function(){this.removeAll(true);this.doLayout();},addLegend:function(record,index){if(this.filter(record)===true){var layer=record.getLayer();index=index||0;var legend;var types=GeoExt.LayerLegend.getTypes(record,this.preferredTypes);if(layer.displayInLayerSwitcher&&!record.get('hideInLegend')&&types.length>0){this.insert(index,{xtype:types[0],id:this.getIdForLayer(layer),layerRecord:record,hidden:!((!layer.map&&layer.visibility)||(layer.getVisibility()&&layer.calculateInRange()))});}}},onDestroy:function(){if(this.layerStore){this.layerStore.un("add",this.onStoreAdd,this);this.layerStore.un("remove",this.onStoreRemove,this);this.layerStore.un("clear",this.onStoreClear,this);}
+GeoExt.LegendPanel.superclass.onDestroy.apply(this,arguments);}});Ext.reg('gx_legendpanel',GeoExt.LegendPanel);Ext.namespace("GeoExt.plugins");GeoExt.plugins.TreeNodeActions=Ext.extend(Ext.util.Observable,{actionsCls:"gx-tree-layer-actions",actionCls:"gx-tree-layer-action",constructor:function(config){Ext.apply(this.initialConfig,Ext.apply({},config));Ext.apply(this,config);this.addEvents("action");GeoExt.plugins.TreeNodeActions.superclass.constructor.apply(this,arguments);},init:function(tree){tree.on({"rendernode":this.onRenderNode,"rawclicknode":this.onRawClickNode,"beforedestroy":this.onBeforeDestroy,scope:this});},onRenderNode:function(node){var rendered=node.rendered;if(!rendered){var attr=node.attributes;var actions=attr.actions||this.actions;if(actions&&actions.length>0){var html=['<div class="',this.actionsCls,'">'];for(var i=0,len=actions.length;i<len;i++){var a=actions[i];html=html.concat(['<img id="'+node.id+'_'+a.action,'" ext:qtip="'+a.qtip,'" src="'+Ext.BLANK_IMAGE_URL,'" class="'+this.actionCls+' '+a.action+'" />']);}
+html.concat(['</div>']);Ext.DomHelper.insertFirst(node.ui.elNode,html.join(""));}
+if(node.layer&&node.layer.map){this.updateActions(node);}else if(node.layerStore){node.layerStore.on({'bind':function(){this.updateActions(node);},scope:this});}}},updateActions:function(node){var actions=node.attributes.actions||this.actions||[];Ext.each(actions,function(a,index){var el=Ext.get(node.id+'_'+a.action);if(el&&typeof a.update=="function"){a.update.call(node,el);}});},onRawClickNode:function(node,e){if(e.getTarget('.'+this.actionCls,1)){var t=e.getTarget('.'+this.actionCls,1);var action=t.className.replace(this.actionCls+' ','');this.fireEvent("action",node,action,e);return false;}},onBeforeDestroy:function(tree){tree.un("rendernode",this.onRenderNode,this);tree.un("rawclicknode",this.onRawClickNode,this);tree.un("beforedestroy",this.onBeforeDestroy,this);}});Ext.preg("gx_treenodeactions",GeoExt.plugins.TreeNodeActions);GeoExt.Lang.add("nl",{"GeoExt.tree.LayerContainer.prototype":{text:"Kaartlagen"},"GeoExt.tree.BaseLayerContainer.prototype":{text:"Basis kaarten"},"GeoExt.tree.OverlayLayerContainer.prototype":{text:"Kaart overlays"}});Ext.namespace("GeoExt.plugins");GeoExt.plugins.PrintPageField=Ext.extend(Ext.util.Observable,{printPage:null,target:null,constructor:function(config){this.initialConfig=config;Ext.apply(this,config);GeoExt.plugins.PrintPageField.superclass.constructor.apply(this,arguments);},init:function(target){this.target=target;var onCfg={"beforedestroy":this.onBeforeDestroy,scope:this};var eventName=target instanceof Ext.form.ComboBox?"select":target instanceof Ext.form.Checkbox?"check":"valid";onCfg[eventName]=this.onFieldChange;target.on(onCfg);this.printPage.on({"change":this.onPageChange,scope:this});this.printPage.printProvider.on({"layoutchange":this.onLayoutChange,scope:this});this.setValue(this.printPage);},onFieldChange:function(field,record){var printProvider=this.printPage.printProvider;var value=field.getValue();this._updating=true;if(field.store===printProvider.scales||field.name==="scale"){this.printPage.setScale(record);}else if(field.name=="rotation"){!isNaN(value)&&this.printPage.setRotation(value);}else{this.printPage.customParams[field.name]=value;}
+delete this._updating;},onPageChange:function(printPage){if(!this._updating){this.setValue(printPage);}},onLayoutChange:function(printProvider,layout){var t=this.target;t.name=="rotation"&&t.setDisabled(!layout.get("rotation"));},setValue:function(printPage){var t=this.target;t.suspendEvents();if(t.store===printPage.printProvider.scales||t.name==="scale"){if(printPage.scale){t.setValue(printPage.scale.get(t.displayField));}}else if(t.name=="rotation"){t.setValue(printPage.rotation);}
+t.resumeEvents();},onBeforeDestroy:function(){this.target.un("beforedestroy",this.onBeforeDestroy,this);this.target.un("select",this.onFieldChange,this);this.target.un("valid",this.onFieldChange,this);this.printPage.un("change",this.onPageChange,this);this.printPage.printProvider.un("layoutchange",this.onLayoutChange,this);}});Ext.preg("gx_printpagefield",GeoExt.plugins.PrintPageField);Ext.namespace("GeoExt.tree");GeoExt.tree.LayerNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{constructor:function(config){GeoExt.tree.LayerNodeUI.superclass.constructor.apply(this,arguments);},render:function(bulkRender){var a=this.node.attributes;if(a.checked===undefined){a.checked=this.node.layer.getVisibility();}
+GeoExt.tree.LayerNodeUI.superclass.render.apply(this,arguments);var cb=this.checkbox;if(a.checkedGroup){var radio=Ext.DomHelper.insertAfter(cb,['<input type="radio" name="',a.checkedGroup,'_checkbox" class="',cb.className,cb.checked?'" checked="checked"':'','"></input>'].join(""));radio.defaultChecked=cb.defaultChecked;Ext.get(cb).remove();this.checkbox=radio;}
+this.enforceOneVisible();},onClick:function(e){if(e.getTarget('.x-tree-node-cb',1)){this.toggleCheck(this.isChecked());}else{GeoExt.tree.LayerNodeUI.superclass.onClick.apply(this,arguments);}},toggleCheck:function(value){value=(value===undefined?!this.isChecked():value);GeoExt.tree.LayerNodeUI.superclass.toggleCheck.call(this,value);this.enforceOneVisible();},enforceOneVisible:function(){var attributes=this.node.attributes;var group=attributes.checkedGroup;if(group&&group!=="gx_baselayer"){var layer=this.node.layer;var checkedNodes=this.node.getOwnerTree().getChecked();var checkedCount=0;Ext.each(checkedNodes,function(n){var l=n.layer
+if(!n.hidden&&n.attributes.checkedGroup===group){checkedCount++;if(l!=layer&&attributes.checked){l.setVisibility(false);}}});if(checkedCount===0&&attributes.checked==false){layer.setVisibility(true);}}},appendDDGhost:function(ghostNode){var n=this.elNode.cloneNode(true);var radio=Ext.DomQuery.select("input[type='radio']",n);Ext.each(radio,function(r){r.name=r.name+"_clone";});ghostNode.appendChild(n);}});GeoExt.tree.LayerNode=Ext.extend(Ext.tree.AsyncTreeNode,{layer:null,layerStore:null,constructor:function(config){config.leaf=config.leaf||!(config.children||config.loader);if(!config.iconCls&&!config.children){config.iconCls="gx-tree-layer-icon";}
+if(config.loader&&!(config.loader instanceof Ext.tree.TreeLoader)){config.loader=new GeoExt.tree.LayerParamLoader(config.loader);}
+this.defaultUI=this.defaultUI||GeoExt.tree.LayerNodeUI;Ext.apply(this,{layer:config.layer,layerStore:config.layerStore});if(config.text){this.fixedText=true;}
+GeoExt.tree.LayerNode.superclass.constructor.apply(this,arguments);},render:function(bulkRender){var layer=this.layer instanceof OpenLayers.Layer&&this.layer;if(!layer){if(!this.layerStore||this.layerStore=="auto"){this.layerStore=GeoExt.MapPanel.guess().layers;}
+var i=this.layerStore.findBy(function(o){return o.get("title")==this.layer;},this);if(i!=-1){layer=this.layerStore.getAt(i).getLayer();}}
+if(!this.rendered||!layer){var ui=this.getUI();if(layer){this.layer=layer;if(layer.isBaseLayer){this.draggable=false;Ext.applyIf(this.attributes,{checkedGroup:"gx_baselayer"});}
+if(!this.text){this.text=layer.name;}
+ui.show();this.addVisibilityEventHandlers();}else{ui.hide();}
+if(this.layerStore instanceof GeoExt.data.LayerStore){this.addStoreEventHandlers(layer);}}
+GeoExt.tree.LayerNode.superclass.render.apply(this,arguments);},addVisibilityEventHandlers:function(){this.layer.events.on({"visibilitychanged":this.onLayerVisibilityChanged,scope:this});this.on({"checkchange":this.onCheckChange,scope:this});},onLayerVisibilityChanged:function(){if(!this._visibilityChanging){this.getUI().toggleCheck(this.layer.getVisibility());}},onCheckChange:function(node,checked){if(checked!=this.layer.getVisibility()){this._visibilityChanging=true;var layer=this.layer;if(checked&&layer.isBaseLayer&&layer.map){layer.map.setBaseLayer(layer);}else{layer.setVisibility(checked);}
+delete this._visibilityChanging;}},addStoreEventHandlers:function(){this.layerStore.on({"add":this.onStoreAdd,"remove":this.onStoreRemove,"update":this.onStoreUpdate,scope:this});},onStoreAdd:function(store,records,index){var l;for(var i=0;i<records.length;++i){l=records[i].getLayer();if(this.layer==l){this.getUI().show();break;}else if(this.layer==l.name){this.render();break;}}},onStoreRemove:function(store,record,index){if(this.layer==record.getLayer()){this.getUI().hide();}},onStoreUpdate:function(store,record,operation){var layer=record.getLayer();if(!this.fixedText&&(this.layer==layer&&this.text!==layer.name)){this.setText(layer.name);}},destroy:function(){var layer=this.layer;if(layer instanceof OpenLayers.Layer){layer.events.un({"visibilitychanged":this.onLayerVisibilityChanged,scope:this});}
+delete this.layer;var layerStore=this.layerStore;if(layerStore){layerStore.un("add",this.onStoreAdd,this);layerStore.un("remove",this.onStoreRemove,this);layerStore.un("update",this.onStoreUpdate,this);}
+delete this.layerStore;this.un("checkchange",this.onCheckChange,this);GeoExt.tree.LayerNode.superclass.destroy.apply(this,arguments);}});Ext.tree.TreePanel.nodeTypes.gx_layer=GeoExt.tree.LayerNode;Ext.namespace("GeoExt.tree");GeoExt.tree.LayerParamNode=Ext.extend(Ext.tree.TreeNode,{layer:null,param:null,item:null,delimiter:null,allItems:null,constructor:function(attributes){var config=attributes||{};config.iconCls=config.iconCls||"gx-tree-layerparam-icon";config.text=config.text||config.item;this.param=config.param;this.item=config.item;this.delimiter=config.delimiter||",";this.allItems=config.allItems;GeoExt.tree.LayerParamNode.superclass.constructor.apply(this,arguments);this.getLayer();if(this.layer){if(!this.allItems){this.allItems=this.getItemsFromLayer();}
+if(this.attributes.checked==null){this.attributes.checked=this.layer.getVisibility()&&this.getItemsFromLayer().indexOf(this.item)>=0;}else{this.onCheckChange(this,this.attributes.checked);}
+this.layer.events.on({"visibilitychanged":this.onLayerVisibilityChanged,scope:this});this.on({"checkchange":this.onCheckChange,scope:this});}},getLayer:function(){if(!this.layer){var layer=this.attributes.layer;if(typeof layer=="string"){var store=this.attributes.layerStore||GeoExt.MapPanel.guess().layers;var i=store.findBy(function(o){return o.get("title")==layer;});layer=i!=-1?store.getAt(i).getLayer():null;}
+this.layer=layer;}
+return this.layer;},getItemsFromLayer:function(){var paramValue=this.layer.params[this.param];return paramValue instanceof Array?paramValue:(paramValue?paramValue.split(this.delimiter):[]);},createParams:function(items){var params={};params[this.param]=this.layer.params[this.param]instanceof Array?items:items.join(this.delimiter);return params;},onLayerVisibilityChanged:function(){if(this.getItemsFromLayer().length===0){this.layer.mergeNewParams(this.createParams(this.allItems));}
+var visible=this.layer.getVisibility();if(visible&&this.getItemsFromLayer().indexOf(this.item)!==-1){this.getUI().toggleCheck(true);}
+if(!visible){this.layer.mergeNewParams(this.createParams([]));this.getUI().toggleCheck(false);}},onCheckChange:function(node,checked){var layer=this.layer;var newItems=[];var curItems=this.getItemsFromLayer();if(checked===true&&layer.getVisibility()===false&&curItems.length===this.allItems.length){curItems=[];}
+Ext.each(this.allItems,function(item){if((item!==this.item&&curItems.indexOf(item)!==-1)||(checked===true&&item===this.item)){newItems.push(item);}},this);var visible=(newItems.length>0);visible&&layer.mergeNewParams(this.createParams(newItems));if(visible!==layer.getVisibility()){layer.setVisibility(visible);}
+(!visible)&&layer.mergeNewParams(this.createParams([]));},destroy:function(){var layer=this.layer;if(layer instanceof OpenLayers.Layer){layer.events.un({"visibilitychanged":this.onLayerVisibilityChanged,scope:this});}
+delete this.layer;this.un("checkchange",this.onCheckChange,this);GeoExt.tree.LayerParamNode.superclass.destroy.apply(this,arguments);}});Ext.tree.TreePanel.nodeTypes.gx_layerparam=GeoExt.tree.LayerParamNode;Ext.namespace('GeoExt');GeoExt.UrlLegend=Ext.extend(GeoExt.LayerLegend,{initComponent:function(){GeoExt.UrlLegend.superclass.initComponent.call(this);this.add(new GeoExt.LegendImage({url:this.layerRecord.get("legendURL")}));},update:function(){GeoExt.UrlLegend.superclass.update.apply(this,arguments);this.items.get(1).setUrl(this.layerRecord.get("legendURL"));}});GeoExt.UrlLegend.supports=function(layerRecord){return layerRecord.get("legendURL")==null?0:10;};GeoExt.LayerLegend.types["gx_urllegend"]=GeoExt.UrlLegend;Ext.reg('gx_urllegend',GeoExt.UrlLegend);Ext.namespace("GeoExt.state");GeoExt.state.PermalinkProvider=function(config){GeoExt.state.PermalinkProvider.superclass.constructor.apply(this,arguments);config=config||{};var url=config.url;delete config.url;Ext.apply(this,config);this.state=this.readURL(url);};Ext.extend(GeoExt.state.PermalinkProvider,Ext.state.Provider,{encodeType:true,readURL:function(url){var state={};var params=OpenLayers.Util.getParameters(url);var k,split,stateId;for(k in params){if(params.hasOwnProperty(k)){split=k.split("_");if(split.length>1){stateId=split[0];state[stateId]=state[stateId]||{};state[stateId][split.slice(1).join("_")]=this.encodeType?this.decodeValue(params[k]):params[k];}}}
+return state;},getLink:function(base){base=base||document.location.href;var params={};var id,k,state=this.state;for(id in state){if(state.hasOwnProperty(id)){for(k in state[id]){params[id+"_"+k]=this.encodeType?unescape(this.encodeValue(state[id][k])):state[id][k];}}}
+OpenLayers.Util.applyDefaults(params,OpenLayers.Util.getParameters(base));var paramsStr=OpenLayers.Util.getParameterString(params);var qMark=base.indexOf("?");if(qMark>0){base=base.substring(0,qMark);}
+return Ext.urlAppend(base,paramsStr);}});Ext.namespace('GeoExt');GeoExt.LegendImage=Ext.extend(Ext.BoxComponent,{url:null,defaultImgSrc:null,imgCls:null,initComponent:function(){GeoExt.LegendImage.superclass.initComponent.call(this);if(this.defaultImgSrc===null){this.defaultImgSrc=Ext.BLANK_IMAGE_URL;}
+this.autoEl={tag:"img","class":(this.imgCls?this.imgCls:""),src:this.defaultImgSrc};},setUrl:function(url){this.url=url;var el=this.getEl();if(el){el.un("error",this.onImageLoadError,this);el.on("error",this.onImageLoadError,this,{single:true});el.dom.src=url;}},onRender:function(ct,position){GeoExt.LegendImage.superclass.onRender.call(this,ct,position);if(this.url){this.setUrl(this.url);}},onDestroy:function(){var el=this.getEl();if(el){el.un("error",this.onImageLoadError,this);}
+GeoExt.LegendImage.superclass.onDestroy.apply(this,arguments);},onImageLoadError:function(){this.getEl().dom.src=this.defaultImgSrc;}});Ext.reg('gx_legendimage',GeoExt.LegendImage);Ext.namespace("GeoExt");GeoExt.LayerOpacitySlider=Ext.extend(Ext.slider.SingleSlider,{layer:null,complementaryLayer:null,delay:5,changeVisibilityDelay:5,aggressive:false,changeVisibility:false,value:null,inverse:false,constructor:function(config){if(config.layer){this.layer=this.getLayer(config.layer);this.bind();this.complementaryLayer=this.getLayer(config.complementaryLayer);if(config.inverse!==undefined){this.inverse=config.inverse;}
+config.value=(config.value!==undefined)?config.value:this.getOpacityValue(this.layer);delete config.layer;delete config.complementaryLayer;}
+GeoExt.LayerOpacitySlider.superclass.constructor.call(this,config);},bind:function(){if(this.layer&&this.layer.map){this.layer.map.events.on({changelayer:this.update,scope:this});}},unbind:function(){if(this.layer&&this.layer.map&&this.layer.map.events){this.layer.map.events.un({changelayer:this.update,scope:this});}},update:function(evt){if(evt.property==="opacity"&&evt.layer==this.layer&&!this._settingOpacity){this.setValue(this.getOpacityValue(this.layer));}},setLayer:function(layer){this.unbind();this.layer=this.getLayer(layer);this.setValue(this.getOpacityValue(layer));this.bind();},getOpacityValue:function(layer){var value;if(layer&&layer.opacity!==null){value=parseInt(layer.opacity*(this.maxValue-this.minValue));}else{value=this.maxValue;}
+if(this.inverse===true){value=(this.maxValue-this.minValue)-value;}
+return value;},getLayer:function(layer){if(layer instanceof OpenLayers.Layer){return layer;}else if(layer instanceof GeoExt.data.LayerRecord){return layer.getLayer();}},initComponent:function(){GeoExt.LayerOpacitySlider.superclass.initComponent.call(this);if(this.changeVisibility&&this.layer&&(this.layer.opacity==0||(this.inverse===false&&this.value==this.minValue)||(this.inverse===true&&this.value==this.maxValue))){this.layer.setVisibility(false);}
+if(this.complementaryLayer&&((this.layer&&this.layer.opacity==1)||(this.inverse===false&&this.value==this.maxValue)||(this.inverse===true&&this.value==this.minValue))){this.complementaryLayer.setVisibility(false);}
+if(this.aggressive===true){this.on('change',this.changeLayerOpacity,this,{buffer:this.delay});}else{this.on('changecomplete',this.changeLayerOpacity,this);}
+if(this.changeVisibility===true){this.on('change',this.changeLayerVisibility,this,{buffer:this.changeVisibilityDelay});}
+if(this.complementaryLayer){this.on('change',this.changeComplementaryLayerVisibility,this,{buffer:this.changeVisibilityDelay});}
+this.on("beforedestroy",this.unbind,this);},changeLayerOpacity:function(slider,value){if(this.layer){value=value/(this.maxValue-this.minValue);if(this.inverse===true){value=1-value;}
+this._settingOpacity=true;this.layer.setOpacity(value);delete this._settingOpacity;}},changeLayerVisibility:function(slider,value){var currentVisibility=this.layer.getVisibility();if((this.inverse===false&&value==this.minValue)||(this.inverse===true&&value==this.maxValue)&&currentVisibility===true){this.layer.setVisibility(false);}else if((this.inverse===false&&value>this.minValue)||(this.inverse===true&&value<this.maxValue)&&currentVisibility==false){this.layer.setVisibility(true);}},changeComplementaryLayerVisibility:function(slider,value){var currentVisibility=this.complementaryLayer.getVisibility();if((this.inverse===false&&value==this.maxValue)||(this.inverse===true&&value==this.minValue)&&currentVisibility===true){this.complementaryLayer.setVisibility(false);}else if((this.inverse===false&&value<this.maxValue)||(this.inverse===true&&value>this.minValue)&&currentVisibility==false){this.complementaryLayer.setVisibility(true);}},addToMapPanel:function(panel){this.on({render:function(){var el=this.getEl();el.setStyle({position:"absolute",zIndex:panel.map.Z_INDEX_BASE.Control});el.on({mousedown:this.stopMouseEvents,click:this.stopMouseEvents});},scope:this});},removeFromMapPanel:function(panel){var el=this.getEl();el.un({mousedown:this.stopMouseEvents,click:this.stopMouseEvents,scope:this});this.unbind();},stopMouseEvents:function(e){e.stopEvent();}});Ext.reg('gx_opacityslider',GeoExt.LayerOpacitySlider);Ext.namespace("GeoExt.data");GeoExt.data.AttributeReader=function(meta,recordType){meta=meta||{};if(!meta.format){meta.format=new OpenLayers.Format.WFSDescribeFeatureType();}
+GeoExt.data.AttributeReader.superclass.constructor.call(this,meta,recordType||meta.fields);if(meta.feature){this.recordType.prototype.fields.add(new Ext.data.Field("value"));}};Ext.extend(GeoExt.data.AttributeReader,Ext.data.DataReader,{read:function(request){var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+return this.readRecords(data);},readRecords:function(data){var attributes;if(data instanceof Array){attributes=data;}else{attributes=this.meta.format.read(data).featureTypes[0].properties;}
+var feature=this.meta.feature;var recordType=this.recordType;var fields=recordType.prototype.fields;var numFields=fields.length;var attr,values,name,record,ignore,value,field,records=[];for(var i=0,len=attributes.length;i<len;++i){ignore=false;attr=attributes[i];values={};for(var j=0;j<numFields;++j){field=fields.items[j];name=field.name;value=field.convert(attr[name]);if(this.ignoreAttribute(name,value)){ignore=true;break;}
+values[name]=value;}
+if(feature){value=feature.attributes[values["name"]];if(value!==undefined){if(this.ignoreAttribute("value",value)){ignore=true;}else{values["value"]=value;}}}
+if(!ignore){records[records.length]=new recordType(values);}}
+return{success:true,records:records,totalRecords:records.length};},ignoreAttribute:function(name,value){var ignore=false;if(this.meta.ignore&&this.meta.ignore[name]){var matches=this.meta.ignore[name];if(typeof matches=="string"){ignore=(matches===value);}else if(matches instanceof Array){ignore=(matches.indexOf(value)>-1);}else if(matches instanceof RegExp){ignore=(matches.test(value));}}
+return ignore;}});Ext.namespace('GeoExt.grid');GeoExt.grid.SymbolizerColumn=Ext.extend(Ext.grid.Column,{renderer:function(value,meta){if(value!=null){var id=Ext.id();window.setTimeout(function(){var ct=Ext.get(id);if(ct){new GeoExt.FeatureRenderer({symbolizers:value instanceof Array?value:[value],renderTo:ct});}},0);meta.css="gx-grid-symbolizercol";return'<div id="'+id+'"></div>';}}});Ext.grid.Column.types.gx_symbolizercolumn=GeoExt.grid.SymbolizerColumn;Ext.namespace("GeoExt.plugins");GeoExt.plugins.TreeNodeComponent=Ext.extend(Ext.util.Observable,{constructor:function(config){Ext.apply(this.initialConfig,Ext.apply({},config));Ext.apply(this,config);GeoExt.plugins.TreeNodeComponent.superclass.constructor.apply(this,arguments);},init:function(tree){tree.on({"rendernode":this.onRenderNode,"beforedestroy":this.onBeforeDestroy,scope:this});},onRenderNode:function(node){var rendered=node.rendered;var attr=node.attributes;var component=attr.component||this.component;if(!rendered&&component){var elt=Ext.DomHelper.append(node.ui.elNode,[{"tag":"div"}]);if(typeof component=="function"){component=component(node,elt);}else if(typeof component=="object"&&typeof component.fn=="function"){component=component.fn.apply(component.scope,[node,elt]);}
+if(typeof component=="object"&&typeof component.xtype=="string"){component=Ext.ComponentMgr.create(component);}
+if(component instanceof Ext.Component){component.render(elt);node.component=component;}}},onBeforeDestroy:function(tree){tree.un("rendernode",this.onRenderNode,this);tree.un("beforedestroy",this.onBeforeDestroy,this);}});Ext.preg("gx_treenodecomponent",GeoExt.plugins.TreeNodeComponent);Ext.namespace("GeoExt");GeoExt.ZoomSliderTip=Ext.extend(GeoExt.SliderTip,{template:'<div>Zoom Level: {zoom}</div>'+'<div>Resolution: {resolution}</div>'+'<div>Scale: 1 : {scale}</div>',compiledTemplate:null,init:function(slider){this.compiledTemplate=new Ext.Template(this.template);GeoExt.ZoomSliderTip.superclass.init.call(this,slider);},getText:function(thumb){var data={zoom:thumb.value,resolution:this.slider.getResolution(),scale:Math.round(this.slider.getScale())};return this.compiledTemplate.apply(data);}});Ext.namespace("GeoExt.data");GeoExt.data.PrintProvider=Ext.extend(Ext.util.Observable,{url:null,capabilities:null,method:"POST",encoding:document.charset||document.characterSet||"UTF-8",timeout:30000,customParams:null,scales:null,dpis:null,layouts:null,dpi:null,layout:null,constructor:function(config){this.initialConfig=config;Ext.apply(this,config);if(!this.customParams){this.customParams={};}
+this.addEvents("loadcapabilities","layoutchange","dpichange","beforeprint","print","printexception","beforeencodelayer","encodelayer","beforedownload");GeoExt.data.PrintProvider.superclass.constructor.apply(this,arguments);this.scales=new Ext.data.JsonStore({root:"scales",sortInfo:{field:"value",direction:"DESC"},fields:["name",{name:"value",type:"float"}]});this.dpis=new Ext.data.JsonStore({root:"dpis",fields:["name",{name:"value",type:"float"}]});this.layouts=new Ext.data.JsonStore({root:"layouts",fields:["name",{name:"size",mapping:"map"},{name:"rotation",type:"boolean"}]});if(config.capabilities){this.loadStores();}else{if(this.url.split("/").pop()){this.url+="/";}
+this.initialConfig.autoLoad&&this.loadCapabilities();}},setLayout:function(layout){this.layout=layout;this.fireEvent("layoutchange",this,layout);},setDpi:function(dpi){this.dpi=dpi;this.fireEvent("dpichange",this,dpi);},print:function(map,pages,options){if(map instanceof GeoExt.MapPanel){map=map.map;}
+pages=pages instanceof Array?pages:[pages];options=options||{};if(this.fireEvent("beforeprint",this,map,pages,options)===false){return;}
+var jsonData=Ext.apply({units:map.getUnits(),srs:map.baseLayer.projection.getCode(),layout:this.layout.get("name"),dpi:this.dpi.get("value")},this.customParams);var pagesLayer=pages[0].feature.layer;var encodedLayers=[];var layers=map.layers.concat();layers.remove(map.baseLayer);layers.unshift(map.baseLayer);Ext.each(layers,function(layer){if(layer!==pagesLayer&&layer.getVisibility()===true){var enc=this.encodeLayer(layer);enc&&encodedLayers.push(enc);}},this);jsonData.layers=encodedLayers;var encodedPages=[];Ext.each(pages,function(page){encodedPages.push(Ext.apply({center:[page.center.lon,page.center.lat],scale:page.scale.get("value"),rotation:page.rotation},page.customParams));},this);jsonData.pages=encodedPages;if(options.overview){var encodedOverviewLayers=[];Ext.each(options.overview.layers,function(layer){var enc=this.encodeLayer(layer);enc&&encodedOverviewLayers.push(enc);},this);jsonData.overviewLayers=encodedOverviewLayers;}
+if(options.legend){var legend=options.legend;var rendered=legend.rendered;if(!rendered){legend=legend.cloneConfig({renderTo:document.body,hidden:true});}
+var encodedLegends=[];legend.items&&legend.items.each(function(cmp){if(!cmp.hidden){var encFn=this.encoders.legends[cmp.getXType()];encodedLegends=encodedLegends.concat(encFn.call(this,cmp,jsonData.pages[0].scale));}},this);if(!rendered){legend.destroy();}
+jsonData.legends=encodedLegends;}
+if(this.method==="GET"){var url=Ext.urlAppend(this.capabilities.printURL,"spec="+encodeURIComponent(Ext.encode(jsonData)));this.download(url);}else{Ext.Ajax.request({url:this.capabilities.createURL,timeout:this.timeout,jsonData:jsonData,headers:{"Content-Type":"application/json; charset="+this.encoding},success:function(response){var url=Ext.decode(response.responseText).getURL;this.download(url);},failure:function(response){this.fireEvent("printexception",this,response);},params:this.initialConfig.baseParams,scope:this});}},download:function(url){if(this.fireEvent("beforedownload",this,url)!==false){if(Ext.isOpera){window.open(url);}else{window.location.href=url;}}
+this.fireEvent("print",this,url);},loadCapabilities:function(){if(!this.url){return;}
+var url=this.url+"info.json";Ext.Ajax.request({url:url,method:"GET",disableCaching:false,success:function(response){this.capabilities=Ext.decode(response.responseText);this.loadStores();},params:this.initialConfig.baseParams,scope:this});},loadStores:function(){this.scales.loadData(this.capabilities);this.dpis.loadData(this.capabilities);this.layouts.loadData(this.capabilities);this.setLayout(this.layouts.getAt(0));this.setDpi(this.dpis.getAt(0));this.fireEvent("loadcapabilities",this,this.capabilities);},encodeLayer:function(layer){var encLayer;for(var c in this.encoders.layers){if(OpenLayers.Layer[c]&&layer instanceof OpenLayers.Layer[c]){if(this.fireEvent("beforeencodelayer",this,layer)===false){return;}
+encLayer=this.encoders.layers[c].call(this,layer);this.fireEvent("encodelayer",this,layer,encLayer);break;}}
+return(encLayer&&encLayer.type)?encLayer:null;},getAbsoluteUrl:function(url){var a;if(Ext.isIE6||Ext.isIE7||Ext.isIE8){a=document.createElement("<a href='"+url+"'/>");a.style.display="none";document.body.appendChild(a);a.href=a.href;document.body.removeChild(a);}else{a=document.createElement("a");a.href=url;}
+return a.href;},encoders:{"layers":{"Layer":function(layer){var enc={};if(layer.options&&layer.options.maxScale){enc.minScaleDenominator=layer.options.maxScale;}
+if(layer.options&&layer.options.minScale){enc.maxScaleDenominator=layer.options.minScale;}
+return enc;},"WMS":function(layer){var enc=this.encoders.layers.HTTPRequest.call(this,layer);Ext.apply(enc,{type:'WMS',layers:[layer.params.LAYERS].join(",").split(","),format:layer.params.FORMAT,styles:[layer.params.STYLES].join(",").split(",")});var param;for(var p in layer.params){param=p.toLowerCase();if(!layer.DEFAULT_PARAMS[param]&&"layers,styles,width,height,srs".indexOf(param)==-1){if(!enc.customParams){enc.customParams={};}
+enc.customParams[p]=layer.params[p];}}
+return enc;},"OSM":function(layer){var enc=this.encoders.layers.TileCache.call(this,layer);return Ext.apply(enc,{type:'OSM',baseURL:enc.baseURL.substr(0,enc.baseURL.indexOf("$")),extension:"png"});},"TMS":function(layer){var enc=this.encoders.layers.TileCache.call(this,layer);return Ext.apply(enc,{type:'TMS',format:layer.type});},"TileCache":function(layer){var enc=this.encoders.layers.HTTPRequest.call(this,layer);return Ext.apply(enc,{type:'TileCache',layer:layer.layername,maxExtent:layer.maxExtent.toArray(),tileSize:[layer.tileSize.w,layer.tileSize.h],extension:layer.extension,resolutions:layer.serverResolutions||layer.resolutions});},"WMTS":function(layer){var enc=this.encoders.layers.HTTPRequest.call(this,layer);return Ext.apply(enc,{type:'WMTS',layer:layer.layer,version:layer.version,requestEncoding:layer.requestEncoding,tileOrigin:[layer.tileOrigin.lon,layer.tileOrigin.lat],tileSize:[layer.tileSize.w,layer.tileSize.h],style:layer.style,formatSuffix:layer.formatSuffix,dimensions:layer.dimensions,params:layer.params,maxExtent:(layer.tileFullExtent!=null)?layer.tileFullExtent.toArray():layer.maxExtent.toArray(),matrixSet:layer.matrixSet,zoomOffset:layer.zoomOffset,resolutions:layer.serverResolutions||layer.resolutions});},"KaMapCache":function(layer){var enc=this.encoders.layers.KaMap.call(this,layer);return Ext.apply(enc,{type:'KaMapCache',group:layer.params['g'],metaTileWidth:layer.params['metaTileSize']['w'],metaTileHeight:layer.params['metaTileSize']['h']});},"KaMap":function(layer){var enc=this.encoders.layers.HTTPRequest.call(this,layer);return Ext.apply(enc,{type:'KaMap',map:layer.params['map'],extension:layer.params['i'],group:layer.params['g']||"",maxExtent:layer.maxExtent.toArray(),tileSize:[layer.tileSize.w,layer.tileSize.h],resolutions:layer.serverResolutions||layer.resolutions});},"HTTPRequest":function(layer){var enc=this.encoders.layers.Layer.call(this,layer);return Ext.apply(enc,{baseURL:this.getAbsoluteUrl(layer.url instanceof Array?layer.url[0]:layer.url),opacity:(layer.opacity!=null)?layer.opacity:1.0,singleTile:layer.singleTile});},"Image":function(layer){var enc=this.encoders.layers.Layer.call(this,layer);return Ext.apply(enc,{type:'Image',baseURL:this.getAbsoluteUrl(layer.getURL(layer.extent)),opacity:(layer.opacity!=null)?layer.opacity:1.0,extent:layer.extent.toArray(),pixelSize:[layer.size.w,layer.size.h],name:layer.name});},"Vector":function(layer){if(!layer.features.length){return;}
+var encFeatures=[];var encStyles={};var features=layer.features;var featureFormat=new OpenLayers.Format.GeoJSON();var styleFormat=new OpenLayers.Format.JSON();var nextId=1;var styleDict={};var feature,style,dictKey,dictItem,styleName;for(var i=0,len=features.length;i<len;++i){feature=features[i];style=feature.style||layer.style||layer.styleMap.createSymbolizer(feature,feature.renderIntent);dictKey=styleFormat.write(style);dictItem=styleDict[dictKey];if(dictItem){styleName=dictItem;}else{styleDict[dictKey]=styleName=nextId++;if(style.externalGraphic){encStyles[styleName]=Ext.applyIf({externalGraphic:this.getAbsoluteUrl(style.externalGraphic)},style);}else{encStyles[styleName]=style;}}
+var featureGeoJson=featureFormat.extract.feature.call(featureFormat,feature);featureGeoJson.properties=OpenLayers.Util.extend({_gx_style:styleName},featureGeoJson.properties);encFeatures.push(featureGeoJson);}
+var enc=this.encoders.layers.Layer.call(this,layer);return Ext.apply(enc,{type:'Vector',styles:encStyles,styleProperty:'_gx_style',geoJson:{type:"FeatureCollection",features:encFeatures},name:layer.name,opacity:(layer.opacity!=null)?layer.opacity:1.0});},"Markers":function(layer){var features=[];for(var i=0,len=layer.markers.length;i<len;i++){var marker=layer.markers[i];var geometry=new OpenLayers.Geometry.Point(marker.lonlat.lon,marker.lonlat.lat);var style={externalGraphic:marker.icon.url,graphicWidth:marker.icon.size.w,graphicHeight:marker.icon.size.h,graphicXOffset:marker.icon.offset.x,graphicYOffset:marker.icon.offset.y};var feature=new OpenLayers.Feature.Vector(geometry,{},style);features.push(feature);}
+var vector=new OpenLayers.Layer.Vector(layer.name);vector.addFeatures(features);var output=this.encoders.layers.Vector.call(this,vector);vector.destroy();return output;}},"legends":{"gx_wmslegend":function(legend,scale){var enc=this.encoders.legends.base.call(this,legend);var icons=[];for(var i=1,len=legend.items.getCount();i<len;++i){var url=legend.items.get(i).url;if(legend.useScaleParameter===true&&url.toLowerCase().indexOf('request=getlegendgraphic')!=-1){var split=url.split("?");var params=Ext.urlDecode(split[1]);params['SCALE']=scale;url=split[0]+"?"+Ext.urlEncode(params);}
+icons.push(this.getAbsoluteUrl(url));}
+enc[0].classes[0]={name:"",icons:icons};return enc;},"gx_urllegend":function(legend){var enc=this.encoders.legends.base.call(this,legend);enc[0].classes.push({name:"",icon:this.getAbsoluteUrl(legend.items.get(1).url)});return enc;},"base":function(legend){return[{name:legend.getLabel(),classes:[]}];}}}});Ext.namespace("GeoExt");GeoExt.MapPanel=Ext.extend(Ext.Panel,{map:null,layers:null,center:null,zoom:null,extent:null,prettyStateKeys:false,stateEvents:["aftermapmove","afterlayervisibilitychange","afterlayeropacitychange","afterlayerorderchange","afterlayernamechange","afterlayeradd","afterlayerremove"],initComponent:function(){if(!(this.map instanceof OpenLayers.Map)){this.map=new OpenLayers.Map(Ext.applyIf(this.map||{},{allOverlays:true}));}
+var layers=this.layers;if(!layers||layers instanceof Array){this.layers=new GeoExt.data.LayerStore({layers:layers,map:this.map.layers.length>0?this.map:null});}
+if(typeof this.center=="string"){this.center=OpenLayers.LonLat.fromString(this.center);}else if(this.center instanceof Array){this.center=new OpenLayers.LonLat(this.center[0],this.center[1]);}
+if(typeof this.extent=="string"){this.extent=OpenLayers.Bounds.fromString(this.extent);}else if(this.extent instanceof Array){this.extent=OpenLayers.Bounds.fromArray(this.extent);}
+GeoExt.MapPanel.superclass.initComponent.call(this);this.addEvents("aftermapmove","afterlayervisibilitychange","afterlayeropacitychange","afterlayerorderchange","afterlayernamechange","afterlayeradd","afterlayerremove");this.map.events.on({"moveend":this.onMoveend,"changelayer":this.onChangelayer,"addlayer":this.onAddlayer,"removelayer":this.onRemovelayer,scope:this});},onMoveend:function(){this.fireEvent("aftermapmove");},onChangelayer:function(e){if(e.property){if(e.property==="visibility"){this.fireEvent("afterlayervisibilitychange");}else if(e.property==="order"){this.fireEvent("afterlayerorderchange");}else if(e.property==="name"){this.fireEvent("afterlayernamechange");}else if(e.property==="opacity"){this.fireEvent("afterlayeropacitychange");}}},onAddlayer:function(){this.fireEvent("afterlayeradd");},onRemovelayer:function(){this.fireEvent("afterlayerremove");},applyState:function(state){this.center=new OpenLayers.LonLat(state.x,state.y);this.zoom=state.zoom;var i,l,layer,layerId,visibility,opacity;var layers=this.map.layers;for(i=0,l=layers.length;i<l;i++){layer=layers[i];layerId=this.prettyStateKeys?layer.name:layer.id;visibility=state["visibility_"+layerId];if(visibility!==undefined){visibility=(/^true$/i).test(visibility);if(layer.isBaseLayer){if(visibility){this.map.setBaseLayer(layer);}}else{layer.setVisibility(visibility);}}
+opacity=state["opacity_"+layerId];if(opacity!==undefined){layer.setOpacity(opacity);}}},getState:function(){var state;if(!this.map){return;}
+var center=this.map.getCenter();state=center?{x:center.lon,y:center.lat,zoom:this.map.getZoom()}:{};var i,l,layer,layerId,layers=this.map.layers;for(i=0,l=layers.length;i<l;i++){layer=layers[i];layerId=this.prettyStateKeys?layer.name:layer.id;state["visibility_"+layerId]=layer.getVisibility();state["opacity_"+layerId]=layer.opacity==null?1:layer.opacity;}
+return state;},updateMapSize:function(){if(this.map){this.map.updateSize();}},renderMap:function(){var map=this.map;map.render(this.body.dom);this.layers.bind(map);if(map.layers.length>0){this.setInitialExtent();}else{this.layers.on("add",this.setInitialExtent,this,{single:true});}},setInitialExtent:function(){var map=this.map;if(this.center||this.zoom!=null){map.setCenter(this.center,this.zoom);}else if(this.extent){map.zoomToExtent(this.extent);}else{map.zoomToMaxExtent();}},afterRender:function(){GeoExt.MapPanel.superclass.afterRender.apply(this,arguments);if(!this.ownerCt){this.renderMap();}else{this.ownerCt.on("move",this.updateMapSize,this);this.ownerCt.on({"afterlayout":this.afterLayout,scope:this});}},afterLayout:function(){var width=this.getInnerWidth()-
+this.body.getBorderWidth("lr");var height=this.getInnerHeight()-
+this.body.getBorderWidth("tb");if(width>0&&height>0){this.ownerCt.un("afterlayout",this.afterLayout,this);this.renderMap();}},onResize:function(){GeoExt.MapPanel.superclass.onResize.apply(this,arguments);this.updateMapSize();},onBeforeAdd:function(item){if(typeof item.addToMapPanel==="function"){item.addToMapPanel(this);}
+GeoExt.MapPanel.superclass.onBeforeAdd.apply(this,arguments);},remove:function(item,autoDestroy){if(typeof item.removeFromMapPanel==="function"){item.removeFromMapPanel(this);}
+GeoExt.MapPanel.superclass.remove.apply(this,arguments);},beforeDestroy:function(){if(this.ownerCt){this.ownerCt.un("move",this.updateMapSize,this);}
+if(this.map&&this.map.events){this.map.events.un({"moveend":this.onMoveend,"changelayer":this.onChangelayer,"addlayer":this.onAddlayer,"removelayer":this.onRemovelayer,scope:this});}
+if(!this.initialConfig.map||!(this.initialConfig.map instanceof OpenLayers.Map)){if(this.map&&this.map.destroy){this.map.destroy();}}
+delete this.map;GeoExt.MapPanel.superclass.beforeDestroy.apply(this,arguments);}});GeoExt.MapPanel.guess=function(){return Ext.ComponentMgr.all.find(function(o){return o instanceof GeoExt.MapPanel;});};Ext.reg('gx_mappanel',GeoExt.MapPanel);Ext.namespace("GeoExt");GeoExt.PrintMapPanel=Ext.extend(GeoExt.MapPanel,{sourceMap:null,printProvider:null,printPage:null,previewScales:null,center:null,zoom:null,extent:null,currentZoom:null,initComponent:function(){if(this.sourceMap instanceof GeoExt.MapPanel){this.sourceMap=this.sourceMap.map;}
+if(!this.map){this.map={};}
+Ext.applyIf(this.map,{projection:this.sourceMap.getProjection(),maxExtent:this.sourceMap.getMaxExtent(),maxResolution:this.sourceMap.getMaxResolution(),units:this.sourceMap.getUnits()});if(!(this.printProvider instanceof GeoExt.data.PrintProvider)){this.printProvider=new GeoExt.data.PrintProvider(this.printProvider);}
+this.printPage=new GeoExt.data.PrintPage({printProvider:this.printProvider});this.previewScales=new Ext.data.Store();this.previewScales.add(this.printProvider.scales.getRange());this.layers=[];var layer;Ext.each(this.sourceMap.layers,function(layer){layer.getVisibility()===true&&this.layers.push(layer.clone());},this);this.extent=this.sourceMap.getExtent();GeoExt.PrintMapPanel.superclass.initComponent.call(this);},bind:function(){this.printPage.on("change",this.fitZoom,this);this.printProvider.on("layoutchange",this.syncSize,this);this.map.events.register("moveend",this,this.updatePage);this.printPage.fit(this.sourceMap);if(this.initialConfig.limitScales===true){this.on("resize",this.calculatePreviewScales,this);this.calculatePreviewScales();}},afterRender:function(){GeoExt.PrintMapPanel.superclass.afterRender.apply(this,arguments);this.syncSize();if(!this.ownerCt){this.bind();}else{this.ownerCt.on({"afterlayout":{fn:this.bind,scope:this,single:true}});}},adjustSize:function(width,height){var printSize=this.printProvider.layout.get("size");var ratio=printSize.width/printSize.height;var ownerCt=this.ownerCt;var targetWidth=(ownerCt&&ownerCt.autoWidth)?0:(width||this.initialConfig.width);var targetHeight=(ownerCt&&ownerCt.autoHeight)?0:(height||this.initialConfig.height);if(targetWidth){height=targetWidth/ratio;if(targetHeight&&height>targetHeight){height=targetHeight;width=height*ratio;}else{width=targetWidth;}}else if(targetHeight){width=targetHeight*ratio;height=targetHeight;}
+return{width:width,height:height};},fitZoom:function(){if(!this._updating&&this.printPage.scale){this._updating=true;var printBounds=this.printPage.getPrintExtent(this.map);this.currentZoom=this.map.getZoomForExtent(printBounds);this.map.zoomToExtent(printBounds);delete this._updating;}},updatePage:function(){if(!this._updating){var zoom=this.map.getZoom();this._updating=true;if(zoom===this.currentZoom){this.printPage.setCenter(this.map.getCenter());}else{this.printPage.fit(this.map);}
+delete this._updating;this.currentZoom=zoom;}},calculatePreviewScales:function(){this.previewScales.removeAll();this.printPage.suspendEvents();var scale=this.printPage.scale;var viewSize=this.map.getSize();var scalesByZoom={};var zooms=[];this.printProvider.scales.each(function(rec){this.printPage.setScale(rec);var extent=this.printPage.getPrintExtent(this.map);var zoom=this.map.getZoomForExtent(extent);var idealResolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);var resolution=this.map.getResolutionForZoom(zoom);var diff=Math.abs(idealResolution-resolution);if(!(zoom in scalesByZoom)||scalesByZoom[zoom].diff>diff){scalesByZoom[zoom]={rec:rec,diff:diff};zooms.indexOf(zoom)==-1&&zooms.push(zoom);}},this);for(var i=0,ii=zooms.length;i<ii;++i){this.previewScales.add(scalesByZoom[zooms[i]].rec);}
+scale&&this.printPage.setScale(scale);this.printPage.resumeEvents();if(scale&&this.previewScales.getCount()>0){var maxScale=this.previewScales.getAt(0);var minScale=this.previewScales.getAt(this.previewScales.getCount()-1);if(scale.get("value")<minScale.get("value")){this.printPage.setScale(minScale);}else if(scale.get("value")>maxScale.get("value")){this.printPage.setScale(maxScale);}}
+this.fitZoom();},print:function(options){this.printProvider.print(this.map,[this.printPage],options);},beforeDestroy:function(){this.map.events.unregister("moveend",this,this.updatePage);this.printPage.un("change",this.fitZoom,this);this.printProvider.un("layoutchange",this.syncSize,this);GeoExt.PrintMapPanel.superclass.beforeDestroy.apply(this,arguments);}});Ext.reg('gx_printmappanel',GeoExt.PrintMapPanel);Ext.namespace("GeoExt.data");GeoExt.data.ScaleStore=Ext.extend(Ext.data.Store,{map:null,constructor:function(config){var map=(config.map instanceof GeoExt.MapPanel?config.map.map:config.map);delete config.map;config=Ext.applyIf(config,{reader:new Ext.data.JsonReader({},["level","resolution","scale"])});GeoExt.data.ScaleStore.superclass.constructor.call(this,config);if(map){this.bind(map);}},bind:function(map,options){this.map=(map instanceof GeoExt.MapPanel?map.map:map);this.map.events.register('changebaselayer',this,this.populateFromMap);if(this.map.baseLayer){this.populateFromMap();}else{this.map.events.register('addlayer',this,this.populateOnAdd);}},unbind:function(){if(this.map){this.map.events.unregister('addlayer',this,this.populateOnAdd);this.map.events.unregister('changebaselayer',this,this.populateFromMap);delete this.map;}},populateOnAdd:function(evt){if(evt.layer.isBaseLayer){this.populateFromMap();this.map.events.unregister('addlayer',this,this.populateOnAdd);}},populateFromMap:function(){var zooms=[];var resolutions=this.map.baseLayer.resolutions;var units=this.map.baseLayer.units;for(var i=resolutions.length-1;i>=0;i--){var res=resolutions[i];zooms.push({level:i,resolution:res,scale:OpenLayers.Util.getScaleFromResolution(res,units)});}
+this.loadData(zooms);},destroy:function(){this.unbind();GeoExt.data.ScaleStore.superclass.destroy.apply(this,arguments);}});Ext.namespace("GeoExt.data");GeoExt.data.FeatureStoreMixin=function(){return{layer:null,reader:null,featureFilter:null,constructor:function(config){config=config||{};config.reader=config.reader||new GeoExt.data.FeatureReader({},config.fields);var layer=config.layer;delete config.layer;if(config.features){config.data=config.features;}
+delete config.features;var options={initDir:config.initDir};delete config.initDir;arguments.callee.superclass.constructor.call(this,config);if(layer){this.bind(layer,options);}},bind:function(layer,options){if(this.layer){return;}
+this.layer=layer;options=options||{};var initDir=options.initDir;if(options.initDir==undefined){initDir=GeoExt.data.FeatureStore.LAYER_TO_STORE|GeoExt.data.FeatureStore.STORE_TO_LAYER;}
+var features=layer.features.slice(0);if(initDir&GeoExt.data.FeatureStore.STORE_TO_LAYER){var records=this.getRange();for(var i=records.length-1;i>=0;i--){this.layer.addFeatures([records[i].getFeature()]);}}
+if(initDir&GeoExt.data.FeatureStore.LAYER_TO_STORE){this.loadData(features,true);}
+layer.events.on({"featuresadded":this.onFeaturesAdded,"featuresremoved":this.onFeaturesRemoved,"featuremodified":this.onFeatureModified,scope:this});this.on({"load":this.onLoad,"clear":this.onClear,"add":this.onAdd,"remove":this.onRemove,"update":this.onUpdate,scope:this});},unbind:function(){if(this.layer){this.layer.events.un({"featuresadded":this.onFeaturesAdded,"featuresremoved":this.onFeaturesRemoved,"featuremodified":this.onFeatureModified,scope:this});this.un("load",this.onLoad,this);this.un("clear",this.onClear,this);this.un("add",this.onAdd,this);this.un("remove",this.onRemove,this);this.un("update",this.onUpdate,this);this.layer=null;}},getRecordFromFeature:function(feature){return this.getByFeature(feature)||null;},getByFeature:function(feature){var record;if(feature.state!==OpenLayers.State.INSERT){record=this.getById(feature.id);}else{var index=this.findBy(function(r){return r.getFeature()===feature;});if(index>-1){record=this.getAt(index);}}
+return record;},onFeaturesAdded:function(evt){if(!this._adding){var features=evt.features,toAdd=features;if(this.featureFilter){toAdd=[];var i,len,feature;for(var i=0,len=features.length;i<len;i++){feature=features[i];if(this.featureFilter.evaluate(feature)!==false){toAdd.push(feature);}}}
+this._adding=true;this.loadData(toAdd,true);delete this._adding;}},onFeaturesRemoved:function(evt){if(!this._removing){var features=evt.features,feature,record,i;for(i=features.length-1;i>=0;i--){feature=features[i];record=this.getByFeature(feature);if(record!==undefined){this._removing=true;this.remove(record);delete this._removing;}}}},onFeatureModified:function(evt){if(!this._updating){var feature=evt.feature;var record=this.getByFeature(feature);if(record!==undefined){record.beginEdit();var attributes=feature.attributes;if(attributes){var fields=this.recordType.prototype.fields;for(var i=0,len=fields.length;i<len;i++){var field=fields.items[i];var key=field.mapping||field.name;if(key in attributes){record.set(field.name,field.convert(attributes[key]));}}}
+record.set("state",feature.state);record.set("fid",feature.fid);record.setFeature(feature);this._updating=true;record.endEdit();delete this._updating;}}},addFeaturesToLayer:function(records){var i,len,features;features=new Array((len=records.length));for(i=0;i<len;i++){features[i]=records[i].getFeature();}
+if(features.length>0){this._adding=true;this.layer.addFeatures(features);delete this._adding;}},onLoad:function(store,records,options){if(!options||options.add!==true){this._removing=true;this.layer.removeFeatures(this.layer.features);delete this._removing;this.addFeaturesToLayer(records);}},onClear:function(store){this._removing=true;this.layer.removeFeatures(this.layer.features);delete this._removing;},onAdd:function(store,records,index){if(!this._adding){this.addFeaturesToLayer(records);}},onRemove:function(store,record,index){if(!this._removing){var feature=record.getFeature();if(this.layer.getFeatureById(feature.id)!=null){this._removing=true;this.layer.removeFeatures([record.getFeature()]);delete this._removing;}}},onUpdate:function(store,record,operation){if(!this._updating){var defaultFields=new GeoExt.data.FeatureRecord().fields;var feature=record.getFeature();if(feature.state!==OpenLayers.State.INSERT){feature.state=OpenLayers.State.UPDATE;}
+if(record.fields){var cont=this.layer.events.triggerEvent("beforefeaturemodified",{feature:feature});if(cont!==false){var attributes=feature.attributes;record.fields.each(function(field){var key=field.mapping||field.name;if(!defaultFields.containsKey(key)){attributes[key]=record.get(field.name);}});this._updating=true;this.layer.events.triggerEvent("featuremodified",{feature:feature});delete this._updating;if(this.layer.getFeatureById(feature.id)!=null){this.layer.drawFeature(feature);}}}}},destroy:function(){this.unbind();GeoExt.data.FeatureStore.superclass.destroy.call(this);}};};GeoExt.data.FeatureStore=Ext.extend(Ext.data.Store,new GeoExt.data.FeatureStoreMixin);GeoExt.data.FeatureStore.LAYER_TO_STORE=1;GeoExt.data.FeatureStore.STORE_TO_LAYER=2;Ext.namespace("GeoExt.data");GeoExt.data.WFSCapabilitiesStore=function(c){c=c||{};GeoExt.data.WFSCapabilitiesStore.superclass.constructor.call(this,Ext.apply(c,{proxy:c.proxy||(!c.data?new Ext.data.HttpProxy({url:c.url,disableCaching:false,method:"GET"}):undefined),reader:new GeoExt.data.WFSCapabilitiesReader(c,c.fields)}));};Ext.extend(GeoExt.data.WFSCapabilitiesStore,Ext.data.Store);Ext.namespace("GeoExt.plugins");GeoExt.plugins.AttributeForm=function(config){Ext.apply(this,config);};GeoExt.plugins.AttributeForm.prototype={attributeStore:null,formPanel:null,init:function(formPanel){this.formPanel=formPanel;if(this.attributeStore instanceof Ext.data.Store){this.fillForm();this.bind(this.attributeStore);}
+formPanel.on("destroy",this.onFormDestroy,this);},bind:function(store){this.unbind();store.on({"load":this.onLoad,scope:this});this.attributeStore=store;},unbind:function(){if(this.attributeStore){this.attributeStore.un("load",this.onLoad,this);}},onLoad:function(){if(this.formPanel.items){this.formPanel.removeAll();}
+this.fillForm();},fillForm:function(){this.attributeStore.each(function(record){var field=GeoExt.form.recordToField(record,Ext.apply({checkboxLabelProperty:'fieldLabel'},this.recordToFieldOptions||{}));if(field){this.formPanel.add(field);}},this);this.formPanel.doLayout();},onFormDestroy:function(){this.unbind();}};Ext.preg("gx_attributeform",GeoExt.plugins.AttributeForm);Ext.namespace('GeoExt','GeoExt.data');GeoExt.data.ProtocolProxy=function(config){Ext.apply(this,config);GeoExt.data.ProtocolProxy.superclass.constructor.apply(this,arguments);};Ext.extend(GeoExt.data.ProtocolProxy,Ext.data.DataProxy,{protocol:null,abortPrevious:true,setParamsAsOptions:false,response:null,load:function(params,reader,callback,scope,arg){if(this.fireEvent("beforeload",this,params)!==false){var o={params:params||{},request:{callback:callback,scope:scope,arg:arg},reader:reader};var cb=OpenLayers.Function.bind(this.loadResponse,this,o);if(this.abortPrevious){this.abortRequest();}
+var options={params:params,callback:cb,scope:this};Ext.applyIf(options,arg);if(this.setParamsAsOptions===true){Ext.applyIf(options,options.params);delete options.params;}
+this.response=this.protocol.read(options);}else{callback.call(scope||this,null,arg,false);}},abortRequest:function(){if(this.response){this.protocol.abort(this.response);this.response=null;}},loadResponse:function(o,response){if(response.success()){var result=o.reader.read(response);this.fireEvent("load",this,o,o.request.arg);o.request.callback.call(o.request.scope,result,o.request.arg,true);}else{this.fireEvent("loadexception",this,o,response);o.request.callback.call(o.request.scope,null,o.request.arg,false);}}});Ext.namespace("GeoExt");GeoExt.Action=Ext.extend(Ext.Action,{control:null,activateOnEnable:false,deactivateOnDisable:false,map:null,uScope:null,uHandler:null,uToggleHandler:null,uCheckHandler:null,constructor:function(config){this.uScope=config.scope;this.uHandler=config.handler;this.uToggleHandler=config.toggleHandler;this.uCheckHandler=config.checkHandler;config.scope=this;config.handler=this.pHandler;config.toggleHandler=this.pToggleHandler;config.checkHandler=this.pCheckHandler;var ctrl=this.control=config.control;delete config.control;this.activateOnEnable=!!config.activateOnEnable;delete config.activateOnEnable;this.deactivateOnDisable=!!config.deactivateOnDisable;delete config.deactivateOnDisable;if(ctrl){if(config.map){config.map.addControl(ctrl);delete config.map;}
+if((config.pressed||config.checked)&&ctrl.map){ctrl.activate();}
+if(ctrl.active){config.pressed=true;config.checked=true;}
+ctrl.events.on({activate:this.onCtrlActivate,deactivate:this.onCtrlDeactivate,scope:this});}
+arguments.callee.superclass.constructor.call(this,config);},pHandler:function(cmp){var ctrl=this.control;if(ctrl&&ctrl.type==OpenLayers.Control.TYPE_BUTTON){ctrl.trigger();}
+if(this.uHandler){this.uHandler.apply(this.uScope,arguments);}},pToggleHandler:function(cmp,state){this.changeControlState(state);if(this.uToggleHandler){this.uToggleHandler.apply(this.uScope,arguments);}},pCheckHandler:function(cmp,state){this.changeControlState(state);if(this.uCheckHandler){this.uCheckHandler.apply(this.uScope,arguments);}},changeControlState:function(state){if(state){if(!this._activating){this._activating=true;this.control.activate();this.initialConfig.pressed=true;this.initialConfig.checked=true;this._activating=false;}}else{if(!this._deactivating){this._deactivating=true;this.control.deactivate();this.initialConfig.pressed=false;this.initialConfig.checked=false;this._deactivating=false;}}},onCtrlActivate:function(){var ctrl=this.control;if(ctrl.type==OpenLayers.Control.TYPE_BUTTON){this.enable();}else{this.safeCallEach("toggle",[true]);this.safeCallEach("setChecked",[true]);}},onCtrlDeactivate:function(){var ctrl=this.control;if(ctrl.type==OpenLayers.Control.TYPE_BUTTON){this.disable();}else{this.safeCallEach("toggle",[false]);this.safeCallEach("setChecked",[false]);}},safeCallEach:function(fnName,args){var cs=this.items;for(var i=0,len=cs.length;i<len;i++){if(cs[i][fnName]){cs[i].rendered?cs[i][fnName].apply(cs[i],args):cs[i].on({"render":cs[i][fnName].createDelegate(cs[i],args),single:true});}}},setDisabled:function(v){if(!v&&this.activateOnEnable&&this.control&&!this.control.active){this.control.activate();}
+if(v&&this.deactivateOnDisable&&this.control&&this.control.active){this.control.deactivate();}
+return GeoExt.Action.superclass.setDisabled.apply(this,arguments);}});Ext.namespace("GeoExt.tree");GeoExt.tree.TreeNodeUIEventMixin=function(){return{constructor:function(node){node.addEvents("rendernode","rawclicknode");this.superclass=arguments.callee.superclass;this.superclass.constructor.apply(this,arguments);},render:function(bulkRender){if(!this.rendered){this.superclass.render.apply(this,arguments);this.fireEvent("rendernode",this.node);}},onClick:function(e){if(this.fireEvent("rawclicknode",this.node,e)!==false){this.superclass.onClick.apply(this,arguments);}}};};Ext.namespace('GeoExt.grid');GeoExt.grid.FeatureSelectionModelMixin=function(){return{autoActivateControl:true,layerFromStore:true,selectControl:null,bound:false,superclass:null,selectedFeatures:[],autoPanMapOnSelection:false,constructor:function(config){config=config||{};if(config.selectControl instanceof OpenLayers.Control.SelectFeature){if(!config.singleSelect){var ctrl=config.selectControl;config.singleSelect=!(ctrl.multiple||!!ctrl.multipleKey);}}else if(config.layer instanceof OpenLayers.Layer.Vector){this.selectControl=this.createSelectControl(config.layer,config.selectControl);delete config.layer;delete config.selectControl;}
+if(config.autoPanMapOnSelection){this.autoPanMapOnSelection=true;delete config.autoPanMapOnSelection;}
+this.superclass=arguments.callee.superclass;this.superclass.constructor.call(this,config);},initEvents:function(){this.superclass.initEvents.call(this);if(this.layerFromStore){var layer=this.grid.getStore()&&this.grid.getStore().layer;if(layer&&!(this.selectControl instanceof OpenLayers.Control.SelectFeature)){this.selectControl=this.createSelectControl(layer,this.selectControl);}}
+if(this.selectControl){this.bind(this.selectControl);}},createSelectControl:function(layer,config){config=config||{};var singleSelect=config.singleSelect!==undefined?config.singleSelect:this.singleSelect;config=OpenLayers.Util.extend({toggle:true,multipleKey:singleSelect?null:(Ext.isMac?"metaKey":"ctrlKey")},config);var selectControl=new OpenLayers.Control.SelectFeature(layer,config);layer.map.addControl(selectControl);return selectControl;},bind:function(obj,options){if(!this.bound){options=options||{};this.selectControl=obj;if(obj instanceof OpenLayers.Layer.Vector){this.selectControl=this.createSelectControl(obj,options.controlConfig);}
+if(this.autoActivateControl){this.selectControl.activate();}
+var layers=this.getLayers();for(var i=0,len=layers.length;i<len;i++){layers[i].events.on({featureselected:this.featureSelected,featureunselected:this.featureUnselected,scope:this});}
+this.on("rowselect",this.rowSelected,this);this.on("rowdeselect",this.rowDeselected,this);this.bound=true;}
+return this.selectControl;},unbind:function(){var selectControl=this.selectControl;if(this.bound){var layers=this.getLayers();for(var i=0,len=layers.length;i<len;i++){layers[i].events.un({featureselected:this.featureSelected,featureunselected:this.featureUnselected,scope:this});}
+this.un("rowselect",this.rowSelected,this);this.un("rowdeselect",this.rowDeselected,this);if(this.autoActivateControl){selectControl.deactivate();}
+this.selectControl=null;this.bound=false;}
+return selectControl;},featureSelected:function(evt){if(!this._selecting){var store=this.grid.store;var row=store.findBy(function(record,id){return record.getFeature()==evt.feature;});if(row!=-1&&!this.isSelected(row)){this._selecting=true;this.selectRow(row,!this.singleSelect);this._selecting=false;this.grid.getView().focusRow(row);}}},featureUnselected:function(evt){if(!this._selecting){var store=this.grid.store;var row=store.findBy(function(record,id){return record.getFeature()==evt.feature;});if(row!=-1&&this.isSelected(row)){this._selecting=true;this.deselectRow(row);this._selecting=false;this.grid.getView().focusRow(row);}}},rowSelected:function(model,row,record){var feature=record.getFeature();if(!this._selecting&&feature){var layers=this.getLayers();for(var i=0,len=layers.length;i<len;i++){if(layers[i].selectedFeatures.indexOf(feature)==-1){this._selecting=true;this.selectControl.select(feature);this._selecting=false;this.selectedFeatures.push(feature);break;}}
+if(this.autoPanMapOnSelection){this.recenterToSelectionExtent();}}},rowDeselected:function(model,row,record){var feature=record.getFeature();if(!this._selecting&&feature){var layers=this.getLayers();for(var i=0,len=layers.length;i<len;i++){if(layers[i].selectedFeatures.indexOf(feature)!=-1){this._selecting=true;this.selectControl.unselect(feature);this._selecting=false;OpenLayers.Util.removeItem(this.selectedFeatures,feature);break;}}
+if(this.autoPanMapOnSelection&&this.selectedFeatures.length>0){this.recenterToSelectionExtent();}}},getLayers:function(){return this.selectControl.layers||[this.selectControl.layer];},recenterToSelectionExtent:function(){var map=this.selectControl.map;var selectionExtent=this.getSelectionExtent();var selectionExtentZoom=map.getZoomForExtent(selectionExtent,false);if(selectionExtentZoom>map.getZoom()){map.setCenter(selectionExtent.getCenterLonLat());}
+else{map.zoomToExtent(selectionExtent);}},getSelectionExtent:function(){var maxExtent=null;var features=this.selectedFeatures;if(features&&(features.length>0)){var geometry=null;for(var i=0,len=features.length;i<len;i++){geometry=features[i].geometry;if(geometry){if(maxExtent===null){maxExtent=new OpenLayers.Bounds();}
+maxExtent.extend(geometry.getBounds());}}}
+return maxExtent;}};};GeoExt.grid.FeatureSelectionModel=Ext.extend(Ext.grid.RowSelectionModel,new GeoExt.grid.FeatureSelectionModelMixin);Ext.namespace("GeoExt.data");GeoExt.data.WMSCapabilitiesStore=function(c){c=c||{};GeoExt.data.WMSCapabilitiesStore.superclass.constructor.call(this,Ext.apply(c,{proxy:c.proxy||(!c.data?new Ext.data.HttpProxy({url:c.url,disableCaching:false,method:"GET"}):undefined),reader:new GeoExt.data.WMSCapabilitiesReader(c,c.fields)}));};Ext.extend(GeoExt.data.WMSCapabilitiesStore,Ext.data.Store);Ext.namespace("GeoExt");GeoExt.LayerOpacitySliderTip=Ext.extend(GeoExt.SliderTip,{template:'<div>{opacity}%</div>',compiledTemplate:null,init:function(slider){this.compiledTemplate=new Ext.Template(this.template);GeoExt.LayerOpacitySliderTip.superclass.init.call(this,slider);},getText:function(thumb){var data={opacity:thumb.value};return this.compiledTemplate.apply(data);}});GeoExt.version='1.1';
diff --git a/src/main/webapp/lib/geoext-1.1/css/geoext-all-debug.css b/src/main/webapp/lib/geoext-1.1/css/geoext-all-debug.css
new file mode 100644
index 0000000000000000000000000000000000000000..33d69c354bb9836076d569d72e4ed04078aa37c9
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/geoext-all-debug.css
@@ -0,0 +1,8 @@
+/**
+ * This file combines all default css files. It will be parsed by the build
+ * processor to generate a minified geoext-all.css file. Theme specific
+ * overrides go into gxtheme-<theme>.css
+ */
+@import "popup.css";
+@import "layerlegend.css";
+@import "symbolizercolumn.css";
diff --git a/src/main/webapp/lib/geoext-1.1/css/geoext-all.css b/src/main/webapp/lib/geoext-1.1/css/geoext-all.css
new file mode 100644
index 0000000000000000000000000000000000000000..e29c8dc34377a2b3b9a10cf08bfe7643b20f9b12
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/geoext-all.css
@@ -0,0 +1,2 @@
+
+.gx-popup-anc{background:transparent url(../images/default/anchor.png) no-repeat 0 0;position:absolute;left:5px;z-index:2;height:16px;width:31px;pointer-events:none;}.gx-popup-anc.top{background:transparent url(../images/default/anchor-top.png) no-repeat 0 0;top:-16px;}.gx-popup-anc.right{left:auto;right:5px;}.gx-ruledrag-insert-below{border-bottom:1px dotted;}.gx-ruledrag-insert-above{border-top:1px dotted;}.gx-grid-symbolizercol div{padding:0;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/css/gxtheme-gray.css b/src/main/webapp/lib/geoext-1.1/css/gxtheme-gray.css
new file mode 100644
index 0000000000000000000000000000000000000000..fe5feea5d947362db83d45f54466fe0310937a26
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/gxtheme-gray.css
@@ -0,0 +1 @@
+.gx-popup-anc{background-image:url(../images/gray/anchor.png);}.gx-popup-anc.top{background-image:url(../images/gray/anchor-top.png);}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/css/gxtheme-slate.css b/src/main/webapp/lib/geoext-1.1/css/gxtheme-slate.css
new file mode 100644
index 0000000000000000000000000000000000000000..d2efc664b4bb0ef76b2d7746e98ea8cbf0e7f675
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/gxtheme-slate.css
@@ -0,0 +1 @@
+.gx-popup-anc{background-image:url(../images/slate/anchor.png);}.gx-popup-anc.top{background-image:url(../images/slate/anchor-top.png);}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/css/layerlegend.css b/src/main/webapp/lib/geoext-1.1/css/layerlegend.css
new file mode 100644
index 0000000000000000000000000000000000000000..b19c40f8ce05d6ad0168ebc86e0950425f22afd5
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/layerlegend.css
@@ -0,0 +1 @@
+.gx-ruledrag-insert-below{border-bottom:1px dotted;}.gx-ruledrag-insert-above{border-top:1px dotted;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/css/popup.css b/src/main/webapp/lib/geoext-1.1/css/popup.css
new file mode 100644
index 0000000000000000000000000000000000000000..8d17a7b350b1b7c19e39188d02bd6a6c4fb1b5c1
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/popup.css
@@ -0,0 +1 @@
+.gx-popup-anc{background:transparent url(../images/default/anchor.png) no-repeat 0 0;position:absolute;left:5px;z-index:2;height:16px;width:31px;pointer-events:none;}.gx-popup-anc.top{background:transparent url(../images/default/anchor-top.png) no-repeat 0 0;top:-16px;}.gx-popup-anc.right{left:auto;right:5px;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/css/symbolizercolumn.css b/src/main/webapp/lib/geoext-1.1/css/symbolizercolumn.css
new file mode 100644
index 0000000000000000000000000000000000000000..b820b8aa1e426c0db3c7cd3f1c8559cec58368be
--- /dev/null
+++ b/src/main/webapp/lib/geoext-1.1/css/symbolizercolumn.css
@@ -0,0 +1 @@
+.gx-grid-symbolizercol div{padding:0;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/geoext-1.1/images/default/anchor-top.png b/src/main/webapp/lib/geoext-1.1/images/default/anchor-top.png
new file mode 100644
index 0000000000000000000000000000000000000000..f75f36a5e5a38c3bb7895ad6014621abaf1308ab
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/default/anchor-top.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/default/anchor.png b/src/main/webapp/lib/geoext-1.1/images/default/anchor.png
new file mode 100644
index 0000000000000000000000000000000000000000..0cffbc377764a1e02c61c820600c2a0d8e2c0993
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/default/anchor.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_down.png b/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b23c06d7b4f4689dc8c9fd4e9d4d1f199fe376f
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_down.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_up.png b/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_up.png
new file mode 100644
index 0000000000000000000000000000000000000000..24df0f42129c291ddb3dd50c8ba2884dc23a2c43
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/default/bullet_arrow_up.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/default/delete.png b/src/main/webapp/lib/geoext-1.1/images/default/delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..08f249365afd29594b51210c6e21ba253897505d
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/default/delete.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/gray/anchor-top.png b/src/main/webapp/lib/geoext-1.1/images/gray/anchor-top.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d57033658892322b6e91ca8442bb2ffc3ccdae7
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/gray/anchor-top.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/gray/anchor.png b/src/main/webapp/lib/geoext-1.1/images/gray/anchor.png
new file mode 100644
index 0000000000000000000000000000000000000000..84bd53d799b2b3c74d030db19b9d763270e457b6
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/gray/anchor.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/slate/anchor-top.png b/src/main/webapp/lib/geoext-1.1/images/slate/anchor-top.png
new file mode 100644
index 0000000000000000000000000000000000000000..70110bf4fcc5e51a00ea5926fb9c45d8b0639c04
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/slate/anchor-top.png differ
diff --git a/src/main/webapp/lib/geoext-1.1/images/slate/anchor.png b/src/main/webapp/lib/geoext-1.1/images/slate/anchor.png
new file mode 100644
index 0000000000000000000000000000000000000000..18d1ac6f4e1c0016d403aa7b09b1bf1771b614fa
Binary files /dev/null and b/src/main/webapp/lib/geoext-1.1/images/slate/anchor.png differ
diff --git a/src/main/webapp/lib/isochrones/iso_main.js b/src/main/webapp/lib/isochrones/iso_main.js
new file mode 100644
index 0000000000000000000000000000000000000000..c6426711858be5c01bb274a6c97fbb63c67310c3
--- /dev/null
+++ b/src/main/webapp/lib/isochrones/iso_main.js
@@ -0,0 +1,1741 @@
+//include util.js
+var scriptNode = document.createElement('script');
+scriptNode.type = 'text/javascript';
+scriptNode.src = "./lib/isochrones/util.js";
+document.getElementsByTagName("head")[0].appendChild(scriptNode);
+
+var baseLayerLabels = {
+	google : {
+		name : "Google"
+	},
+	osm : {
+		name : "OSM"
+	},
+	qPoint : {
+		name : "QP",
+		symbol : "./img/poi_black.png"
+	}
+};
+var isoLayerNames = [];
+var sqlLayerNames = [];
+
+var controlsLabels = {
+	drawQ : "Draw Feature",
+	selectQ : "Select QFeature",
+	dragQ : "Drag Feature",
+	selectF : "Select VFeature"
+};
+
+// constants
+var ID_ALGO = "algorithm";
+var ID_DSET = "dataset";
+var ID_DMAX = "dmax";
+var ID_DATE = "q_date";
+var ID_SPEED = "speed";
+var ID_TIME = "q_time";
+var ID_COORD = "q_coord";
+var ID_MODE = "t_mode";
+var ID_DIR = "direction";
+var ID_COVER = "coverage";
+var ID_EXPMODE = "expirationMode";
+var ID_SQL_QUERIES = "sqlqueries";
+var ID_SQL_SPATIALPR = "spatialPredicate";
+var ID_SQL = "sql";
+var ID_CATEGORY = "category";
+var ID_MULTIPLE_Q = "multipleQ";
+
+// API key for accessing bing map tiles.
+var apiKey = "AgBRlAhgOa-0regAi6reU2LktedK82PoG4-6-NRXQkJ4n_UlGXNhU4NIkxfwbu1Z";
+
+// immutable global variables
+var FEATURE_CONTAINER = "Feature Container";
+var SELECTOR_NAME = "Selector";
+var CTRL_DRAW_FEATURE = "Draw Feature";
+var CTRL_SELECT_FEATURE = "Select Feature";
+var CTRL_DRAG_QPOINT_FEATURE = "Drag QPointFeature";
+var CLIENT_EPSG = "EPSG:3857";
+
+// mutable global variables
+var selectedDataset = "BZ";
+var selectedCategory = "";
+
+// global panels
+// main panels
+var queryPanel, sqlPanel, layerPanel, statusPanel;
+// sub panels
+var mapPanel, isoLayerTreePanel, statisticsPanel, sqlResultTablePanel;
+// dialogs or windows
+var featureInfoDialog;
+
+var sqlDatastore;
+
+var wmsNodeLegend;
+
+var tSystems = {
+	ped : {
+		name : "Pedestrian",
+		type : 0,
+		img : "./img/ped.png"
+	},
+	tram : {
+		name : "Tram",
+		type : 1,
+		img : "./img/tram.png"
+	},
+	train : {
+		name : "Train",
+		type : 2,
+		img : "./img/train.png"
+	},
+	bus : {
+		name : "Bus",
+		type : 3,
+		img : "./img/bus.png"
+	},
+	ferry : {
+		name : "Ferry",
+		type : 4,
+		img : "./img/ferry.png"
+	},
+	cable : {
+		name : "Cablecar",
+		type : 5,
+		img : "./img/cablecar.png"
+	},
+	gond : {
+		name : "Gondola",
+		type : 6,
+		img : "./img/gondola.png"
+	},
+	funi : {
+		name : "Funicular",
+		type : 7,
+		img : "./img/funicular.png"
+	}
+};
+
+var sqlPredefinedItems = [
+		[ "Reachable primary school pupils",
+				"select sum(age_6to11) from bz_inhabitants where age_6to11>0" ],
+		[ "Secondary school pupils",
+				"select age_11to14,id from bz_inhabitants where age_11to14>0" ],
+		[
+				"Rentable flats teachers",
+				"select avg_rent,id from bz_buildings where avg_rent between 500 and 800 and inhabitants>0" ],
+		[ "Rentable flats students",
+				"select avg_rent,id from bz_buildings where avg_rent < 600 and inhabitants>0" ],
+		[ "Schools",
+				"select p.category,p.cat_type from bz_pois p where p.category like '%Bildung%'" ] ];
+
+var poiItems = {
+	poi : {
+		category : "Coordinate",
+		img : "./img/poi_black.png"
+	},
+	kindergarten : {
+		category : "Kindergarten",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type='Kindergarten'",
+		img : "./img/kindergarten.png"
+	},
+	primarySchool : {
+		category : "Primary School",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type='Grundschule'",
+		img : "./img/prim_school.gif"
+	},
+	secondarySchool : {
+		category : "Secondary school",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type='Mittelschule'",
+		img : "./img/sec_school.png"
+	},
+	theater : {
+		category : "Theater",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type like 'Theater%'",
+		img : "./img/theater.png"
+	},
+	/*
+	 * outdoor : { category : "Outdoor sport", sql : "select
+	 * category,cat_type,geometry from bz_pois where cat_type='Anlage fŸr
+	 * AktivitÅ ten im Freien'", img : "./img/outdoor.png" },
+	 */
+	swimming : {
+		category : "Swimming pools",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type='Badeanstalt'",
+		img : "./img/swimming.svg"
+	},
+	hall : {
+		category: "Hall",
+		sql : "select category,cat_type,geometry from bz_pois where cat_type like 'Anlage%dachte%'",
+		img : "./img/school-icon.png"
+	}
+};
+
+var tSMapping;
+var map;
+var globalLayers = new Object();
+var globalControls = new Object();
+var datasetCfgs = new Object();
+var cfg = new Object();
+var multipleQueryPointSelection = false;
+var tArrival;
+var url;
+progressBar;
+var popupFeature;
+var resultSQLLayer;
+
+var progressBar;
+
+function init() {
+	OpenLayers.Feature.Vector.style['default'].cursor = 'pointer';
+	OpenLayers.ProxyHost = "proxy?targetURL=";
+	// init some initial variables
+	tSMapping = new Object();
+	tSMapping[tSystems.ped.type] = tSystems.ped;
+	tSMapping[tSystems.tram.type] = tSystems.tram;
+	tSMapping[tSystems.train.type] = tSystems.train;
+	tSMapping[tSystems.bus.type] = tSystems.bus;
+	tSMapping[tSystems.cable.type] = tSystems.cable;
+	tSMapping[tSystems.gond.type] = tSystems.gond;
+	tSMapping[tSystems.funi.type] = tSystems.funi;
+
+	var dSet = datasetCfgs["BZ"];
+	initMap(dSet);
+	initPanels(dSet);
+	map.zoomToExtent(dSet.bbox, true);
+	progressBar.updateText("Ready");
+	statusPanel.setTitle("Status: ready");
+}
+
+function initMap(dSet) {
+	var mapOptions = {
+		units : 'm',
+		projection : new OpenLayers.Projection(CLIENT_EPSG),
+		maxExtent : dSet.bbox,
+		numZoomLevels : 18
+	};
+	map = new OpenLayers.Map('map', mapOptions);
+	map.addLayers(getBaseLayers());
+
+	// add query point layer
+	var layerQ = new OpenLayers.Layer.Vector(baseLayerLabels.qPoint.name, {
+		displayInLayerSwitcher : false,
+		isBaseLayer : false
+	});
+	globalLayers[layerQ.name] = layerQ;
+	// styling the layer correctly
+	layerQ.styleMap = new OpenLayers.StyleMap({
+		"default" : new OpenLayers.Style({
+			externalGraphic : poiItems.poi.img,
+			pointRadius : 10
+		}),
+		"select" : new OpenLayers.Style({
+			pointRadius : 12
+		})
+	});
+	layerQ.events.on({
+		"featureselected" : function(e) {
+			
+			var queryParams = extractFormParameters(queryPanel);
+ 			var lonLat = new OpenLayers.LonLat(e.feature.geometry.x,
+					e.feature.geometry.y);
+			var popup = new OpenLayers.Popup("chicken", lonLat, new OpenLayers.Size(
+					150, 50), IsoUtil.queryPointToHtml(queryParams.time, queryParams.dmax,queryParams.direction), false);
+			popup.setBackgroundColor('#99BBE8');
+			popup.setOpacity(0.9);
+			popup.setBorder("2px solid");
+			e.feature.popup = popup;
+			map.addPopup(popup, true);
+			
+		},
+		"featureunselected" : function(e) {
+			if (e.feature.popup) {
+				e.feature.popup.destroy();
+			}
+		}
+	});
+
+	var featureQ = new OpenLayers.Feature.Vector(dSet.queryPoint);
+	layerQ.removeAllFeatures();
+	layerQ.addFeatures([ featureQ ]);
+
+	// control that enable to position the feature per mouse click
+	var ctrlDrawFeature = new OpenLayers.Control.DrawFeature(layerQ,
+			OpenLayers.Handler.Point);
+	ctrlDrawFeature.featureAdded = function(feature) {
+		if (!multipleQueryPointSelection) {
+			updateCoordinateField(feature.geometry);
+			var featuresToDelete = new Array();
+			for ( var i = 0; i < layerQ.features.length; i++) {
+				var currentFeature = layerQ.features[i];
+				if (currentFeature.id != feature.id) {
+					featuresToDelete.push(currentFeature);
+				}
+			}
+			if (featuresToDelete.length > 0) {
+				layerQ.removeFeatures(featuresToDelete);
+			}
+			delete featuresToDelete;
+		}
+	};
+	globalControls[controlsLabels.drawQ] = ctrlDrawFeature;
+
+	// control that enable to drag a feature
+	var ctrlDragQPoint = new OpenLayers.Control.DragFeature(layerQ);
+	ctrlDragQPoint.onComplete = function(feature) {
+		// starts the computation when query point is manually moved
+		updateCoordinateField(queryPanel, feature.geometry);
+		computeIsochrone(extractFormParameters(queryPanel));
+	};
+	globalControls[controlsLabels.draqQ] = ctrlDragQPoint;
+	map.addLayer(layerQ);
+
+	addSingleQueryPointSelector(layerQ);
+
+	var controls = [ ctrlDrawFeature, ctrlDragQPoint,
+			new OpenLayers.Control.LoadingPanel(),
+			new OpenLayers.Control.Navigation({
+				zoomWheelEnabled : true
+			}),
+			new OpenLayers.Control.ScaleLine({
+				bottomOutUnits : "",
+				maxWidth : 100
+			}) ];
+
+	map.addControls(controls);
+	ctrlDragQPoint.activate();
+}
+
+/**
+ * @returns {Array} an array of all base layers
+ */
+function getBaseLayers() {
+	var layerGoogle = new OpenLayers.Layer.Google(baseLayerLabels.google.name, {
+		"sphericalMercator" : true,
+		minZoomLevel : 1,
+		maxZoomLevel : 19
+	});
+	globalLayers[layerGoogle.name] = layerGoogle;
+	var layerOSM = new OpenLayers.Layer.OSM(baseLayerLabels.osm.name);
+	globalLayers[layerOSM.name] = layerOSM;
+	return [ layerGoogle, layerOSM ];
+}
+
+function initPanels(dSet) {
+	// init datasetItems
+	var dsetComboItem = [];
+	var dsItems = [];
+	var current = {};
+	for (current in datasetCfgs) {
+		dsItems.push(current);
+	}
+	dsItems.sort();
+	for ( var i = 0; i < dsItems.length; i++) {
+		current = dsItems[i];
+		var currentCfg = datasetCfgs[current];
+		dsetComboItem.push([ current, currentCfg.name ? currentCfg.name : current ]);
+	}
+
+	// init category poi items
+	var categoryItems = [];
+	for ( var poiCat in poiItems) {
+		var catItem = poiItems[poiCat];
+		categoryItems.push([ poiCat, catItem.category ]);
+	}
+
+	// panel that includes the map
+	mapPanel = new GeoExt.MapPanel({
+		ref : "mapPanel",
+		region : "center",
+		title : "ISOGA: Isochrones for Geospatial Analysis",
+		zoom : 12,
+		map : map
+	});
+	
+	featureInfoDialog = new Ext.Window({
+		id: 'featureInfo',
+		renderTo: "featureInfoDiv",
+		width:76,
+		autoHeight:true,
+		border: false,
+		plain: true,
+		resizable: false,
+		closeAction: 'hide', 
+		closable: true,
+		html: ''
+	});
+	
+	queryPanel = new Ext.form.FormPanel({
+		frame : true,
+		ref : 'queryPanel',
+		title : 'Isochrone',
+		width : 300,
+		layout : 'fit',
+		border : false,
+		closable : false,
+		bodyStyle : 'padding:2px',
+		autoScroll : true,
+		defaults : {
+			layout : 'form',
+			bodyStyle : 'padding:2px'
+		},
+		items : [ {
+			xtype : 'fieldset',
+			autoHeight : true,
+			border : false,
+			defaults : {
+				autoWidth : true,
+				labelWidth : 80
+			},
+			items : [
+				{
+					fieldLabel : 'Algorithm',
+					xtype : 'combo',
+					id : ID_ALGO,
+					name : ID_ALGO,
+					forceSelection : true,
+					heigth : 28,
+					width : 130,
+					triggerAction : 'all',
+					lazyRenderer : true,
+					mode : 'local',
+					store : new Ext.data.ArrayStore({
+						id : 0,
+						fields : [ 'dispItem', 'displayText' ],
+						data : [ [ 'MineX', 'MineX' ],
+							 [ 'MrneX', 'MrneX' ],
+							 [ 'MDijkstra', 'MDijkstra' ] ]
+					}),
+					valueField : 'dispItem',
+					displayField : 'displayText',
+					value : 'MineX'
+				},
+
+				{
+					xtype : 'combo',
+					fieldLabel : 'Dataset',
+					id : ID_DSET,
+					autoSelect : true,
+					name : 'dataset',
+					heigth : 20,
+					width : 130,
+					mode : 'local',
+					triggerAction : 'all',
+					store : new Ext.data.ArrayStore({
+						fields : [ 'datasetItem', 'displayText' ],
+						data : dsetComboItem
+					}),
+					valueField : 'datasetItem',
+					displayField : 'displayText',
+					value : selectedDataset,
+					listeners : {
+						select : {
+							fn : function(combo, value) {
+								if (this.value != selectedDataset) {
+									updateDataset(queryPanel, this.value);
+								}
+							}
+						}
+					}
+				},
+				{
+					fieldLabel : 'Dmax',
+					xtype : 'numberfield',
+					id : ID_DMAX,
+					name : ID_DMAX,
+					value : '15',
+					width : 130,
+					minValue : 1,
+					maxValue : 60
+				},
+				{
+					fieldLabel : 'Date',
+					xtype : 'datefield',
+					name : ID_DATE,
+					id : ID_DATE,
+					width : 130,
+					value : '14/10/2011',
+					format : 'd/m/Y'
+				},
+				{
+					fieldLabel : 'Time',
+					xtype : 'timefield',
+					name : ID_TIME,
+					id : ID_TIME,
+					width : 130,
+					value : '9:00',
+					format : 'H:i'
+				},
+				{
+					fieldLabel : 'Speed',
+					xtype : 'numberfield',
+					width : 130,
+					name : ID_SPEED,
+					id : ID_SPEED,
+					value : '0.5',
+					allowBlank : false,
+					decimalPrecision : 2
+				},
+				{
+					xtype : 'fieldset',
+					labelWidth : 90,
+					title : '<font style="left:0px;font-style:normal;font-weight:normal;color:black;">Query category</font>',
+					autoHeight : true,
+					autoWidth : true,
+					border : false,
+					bodyStyle : 'padding:0px',
+					items : [ {
+						fieldLabel : 'Coordinate',
+						xtype : 'textfield',
+						name : ID_COORD,
+						id : ID_COORD,
+						value : '1263595, 5860641',
+						width : 130
+					}, {
+						fieldLabel : 'Multiple Q',
+						xtype : 'checkbox',
+						id : ID_MULTIPLE_Q,
+						name : ID_MULTIPLE_Q,
+						listeners : {
+							check : {
+								fn : function(chkbox, checked) {
+									if (checked) {
+										multipleQueryPointSelection = true;
+										var poiCtrl = globalControls[controlsLabels.drawQ];
+										map.div.style.cursor = 'crosshair';
+										poiCtrl.activate();
+									} else {
+										multipleQueryPointSelection = false;
+										var poiCtrl = globalControls[controlsLabels.drawQ];
+										map.div.style.cursor = null;
+										poiCtrl.deactivate();
+									}
+								}
+							}
+						}
+					},  
+						  {
+							  xtype : 'combo',
+							  fieldLabel : 'Category',
+							  id : ID_CATEGORY,
+							  forceSelection : true,
+							  queryMode : 'local',
+							  triggerAction : 'all',
+							  typeAhead : true,
+							  name : 'category',
+							  heigth : 20,
+							  width : 130,
+							  mode : 'local',
+							  store : new Ext.data.ArrayStore({
+								  fields : [ 'poiItem', 'poiLabel' ],
+								  data : categoryItems
+							  }),
+							  valueField : 'poiItem',
+							  displayField : 'poiLabel',
+							  value : 'Coordinate',
+							  listeners : {
+								  select : {
+									  fn : function(combo, value) {
+										  if (this.value != selectedCategory) {
+											  clearIsochrone();
+											  var poiObj = poiItems[this.value];
+											  updatePoiCategory(queryPanel, poiObj);
+										  }
+									  }
+								  }
+							  }
+						  } ]
+				},
+				{
+					fieldLabel : 'T-Mode',
+					xtype : 'combo',
+					id : ID_MODE,
+					name : ID_MODE,
+					forceSelection : true,
+					heigth : 28,
+					width : 130,
+					lazyRenderer : true,
+					mode : 'local',
+					triggerAction : 'all',
+					store : new Ext.data.ArrayStore({
+						id : 0,
+						fields : [ 'dispItem', 'displayText' ],
+						data : [ [ 'UNIMODAL', 'Unimodal' ],
+							 [ 'MULTIMODAL', 'Multimodal' ] ]
+					}),
+					valueField : 'dispItem',
+					displayField : 'displayText',
+					value : 'MULTIMODAL'
+				},
+				{
+					fieldLabel : 'Direction',
+					xtype : 'combo',
+					id : ID_DIR,
+					name : ID_DIR,
+					forceSelection : true,
+					heigth : 28,
+					width : 130,
+					triggerAction : 'all',
+					lazyRenderer : true,
+					mode : 'local',
+					store : new Ext.data.ArrayStore({
+						id : 0,
+						fields : [ 'dispItem', 'displayText' ],
+						data : [ [ 'INCOMING', 'Incoming' ],
+							 [ 'OUTGOING', 'Outgoing' ] ]
+					}),
+					valueField : 'dispItem',
+					displayField : 'displayText',
+					value : 'INCOMING'
+				}, {
+					fieldLabel : 'Enclosure',
+					xtype : 'combo',
+					id : ID_COVER,
+					name : ID_COVER,
+					heigth : 28,
+					width : 130,
+					// emptyText:'Select ...',
+					lazyRenderer : true,
+					mode : 'local',
+					triggerAction : 'all',
+					store : new Ext.data.ArrayStore({
+						id : 0,
+						fields : [ 'dispItem', 'displayText' ],
+						data : [ [ 'EB', 'Buffer' ], [ 'SB', 'Surface' ] ]
+					}),
+					valueField : 'dispItem',
+					displayField : 'displayText',
+					value : 'SB'
+				}, {
+					fieldLabel : 'ExpirationMode',
+					xtype : 'checkbox',
+					id : ID_EXPMODE,
+					name : ID_EXPMODE
+				} ]// items
+			,
+			buttons : [ {
+				text : 'Compute',
+				listeners : {
+					click : function() {
+						computeIsochrone(extractFormParameters());
+						Ext.getCmp('runSQLQuery').enable();
+					}
+				}
+			}, {
+				text : 'Clear',
+				listeners : {
+					click : function() {
+						clearIsochrone();
+					}
+				}
+			} ]
+		} ]
+	});
+
+	// displays the panel for creating queries on the result
+	sqlQueryPanel = new Ext.form.FormPanel({
+		frame : true,
+		ref : 'sqlQueryPanel',
+		width : 300,
+		layout : 'fit',
+		border : false,
+		closable : false,
+		bodyStyle : 'padding:0px',
+		autoScroll : true,
+		// collapsible : true,
+		cls : 'settings',
+		// flex : 1,
+		height : '25%',
+		id : 'sqlQueryPanel',
+		defaults : {
+			layout : 'form',
+			// border : true,
+			bodyStyle : 'padding:0px'
+		},
+		items : [ {
+			xtype : 'fieldset',
+			border : false,
+			autoHeight : true,
+			defaults : {
+				anchor : '-20', // leave room for error icon
+				border : false,
+				hideLabel : true
+			},
+			items : [
+				{
+					fieldLabel : 'SQL',
+					xtype : 'textarea',
+					name : ID_SQL,
+					id : ID_SQL,
+					height : 50,
+					width : "100%",
+					value : 'Specify your own sql query...'
+				},
+				{
+					xtype : 'label',
+					heigth : 20,
+					width : "100%",
+					value : 'Precompiled Queries',
+					disabled : true
+				},
+				{
+					xtype : 'combo',
+					id : ID_SQL_QUERIES,
+					name : ID_SQL_QUERIES,
+					forceSelection : true,
+					queryMode : 'local',
+					typeAhead : true,
+					triggerAction : 'all',
+					heigth : 28,
+					width : 290,
+					mode : 'local',
+					store : new Ext.data.ArrayStore({
+						fields : [ 'queryItem', 'queryText' ],
+						data : sqlPredefinedItems
+					}),
+					valueField : 'queryText',
+					displayField : 'queryItem',
+					// value : "Predefined queries",
+					listeners : {
+						select : {
+							fn : function(combo, value) {
+								sqlQueryPanel.find('name', ID_SQL)[0]
+									.setValue(this.value);
+							}
+						}
+					}
+				},
+				{
+					xtype : 'combo',
+					id : ID_SQL_SPATIALPR,
+					name : ID_SQL_SPATIALPR,
+					forceSelection : true,
+					queryMode : 'local',
+					typeAhead : true,
+					triggerAction : 'all',
+					heigth : 28,
+					width : 290,
+					mode : 'local',
+					store : new Ext.data.ArrayStore({
+						fields : [ 'queryItem', 'queryText' ],
+						data : [ [ 'ST_Within', 'Within Isochrone' ],
+							 [ 'Not ST_Within', 'Outside Isochrone' ] ]
+					}),
+					valueField : 'queryItem',
+					displayField : 'queryText',
+					value : 'ST_Within'
+				} ], // items
+			buttons : [
+				{
+					text : 'Run',
+					id : 'runSQLQuery',
+					name : 'runSQLQuery',
+					disabled : true,
+					listeners : {
+						click : function() {
+							var params = {
+								coverageTable : datasetCfgs[selectedDataset]["isoCoverageLayer"].layer,
+								sqlQuery : sqlQueryPanel.find('name', ID_SQL)[0].getValue(),
+								spatialPredicate : sqlQueryPanel.find('name', ID_SQL_SPATIALPR)[0].getValue()
+							};
+							removeSQLResult();
+							computeQueryOnCoverage(params);
+						}
+					}
+				},
+				{
+					text : 'Reset',
+					listeners : {
+						click : function() {
+							removeSQLResult();
+							sqlQueryPanel.find('name', ID_SQL)[0]
+								.setValue("Specify your own sql query...");
+						}
+					}
+				} ]
+		} ]
+	});
+
+	sqlPanel = new Ext.Panel({
+		frame : true,
+		ref : 'sqlPanel',
+		id : 'sqlPanel',
+		split : true,
+		width : 300,
+		title : 'Geo Analysis',
+		border : false,
+		cls : 'settings',
+		layout : {
+			type : 'vbox',
+			align : 'stretch',
+			pack : 'start'
+		},
+		items : [ sqlQueryPanel ]
+	});
+
+	// treePanel
+	// create specific layer node UI class
+	var LayerNodeUI = Ext.extend(GeoExt.tree.LayerNodeUI,
+			new GeoExt.tree.TreeNodeUIEventMixin());
+
+	// baseLayer json decoder
+	var treeConfigLayers = new OpenLayers.Format.JSON().write([ {
+		text : 'Base layers',
+		nodeType : "gx_baselayercontainer",
+		expanded : true
+	} ], true);
+
+	// tree panel that contains all base layers
+	var baseLayerTreePanel = new Ext.tree.TreePanel({
+		ref : "baseLayerTreePanel",
+		cls : 'settings',
+		border : false,
+		collapsed : false,
+		rootVisible : false,
+		lines : false,
+		animate : true,
+		loader : new Ext.tree.TreeLoader({
+			applyLoader : false,
+			uiProviders : {
+				"layernodeui" : LayerNodeUI
+			}
+		}),
+		root : {
+			nodeType : "async",
+			children : Ext.decode(treeConfigLayers)
+		}
+	});
+
+	// tree panel that contains the layers (vertices,edges,areas) of the
+	// isochrone
+	var isoLayerTreePanel = {
+		xtype : "treepanel",
+		ref : "isoLayerTreePanel",
+		border : false,
+		cls : 'treepanel',
+		rootVisible : true,
+		lines : false,
+		animate : true,
+		resizable : true,
+		layout : 'fit',
+		flex : 1,
+		plugins : [ {
+			ptype : "gx_treenodecomponent"
+		} ],
+		root : new Ext.tree.TreeNode({
+			text : 'Isochrone layers',
+			expandable : true,
+			singleClickExpand : true,
+			listeners : {
+				'beforeclick' : function(rootNode) {
+					if (rootNode.hasChildNodes()) {
+						rootNode.removeAll(true);
+					}
+					// here dynamically the nodes are added
+					var endNode = new GeoExt.tree.LayerNode({
+						'nodeType' : 'gx_layer',
+						'layer' : 'None',
+						'checkedGroup' : 'foo',
+						'checked' : true
+					});
+					rootNode.appendChild(endNode);
+
+					if (rootNode.isExpanded())
+						return false;
+				},
+				'checkchange' : function(node, check) {
+					if (check) {
+						activeLayer = node.layer.name;
+						if (activeLayer != 'None')
+							node.component.show();
+					} else {
+						if (node.layer.name != 'None')
+							node.component.hide();
+					}
+				}
+			},
+			root : {
+				nodeType : "async"
+			}
+		})
+	};
+
+	layerPanel = new Ext.Panel({
+		frame : true,
+		xtype : 'panel',
+		ref : 'layerPanel',
+		title : 'Layers',
+		border : false,
+		bodyBorder : false,
+		cls : 'settings',
+		layout : {
+			type : 'vbox',
+			align : 'stretch',
+			pack : 'start'
+		},
+		items : [ baseLayerTreePanel, isoLayerTreePanel ]
+	});
+
+	var helpPanel = {
+		xtype : 'panel',
+		title : 'Help',
+		cls : 'settings',
+		frame : true
+	};
+
+	var aboutPanel = {
+		xtype : 'panel',
+		title : 'About',
+		cls : 'settings',
+		frame : true
+	};
+
+	var accordionPanel = new Ext.Panel({
+		region : 'east',
+		ref : 'accordionPanel',
+		title : 'Settings',
+		collapsible : true,
+		border : true,
+		split : true,
+		width : '300px',
+		layout : 'accordion',
+		margins : '0 0 0 0',
+		items : [ queryPanel, sqlPanel, layerPanel ]
+	});
+
+	mainPanel = new Ext.Viewport({
+		id : 'mainPanel',
+		layout : 'border',
+		style : 'background: #fff; text-align:left;',
+		items : [ {
+			ref : 'centerPanel',
+			region : "center",
+			border : false,
+			bodyBorder : false,
+			split : false,
+			margins : '20 1 1 1',
+			layout : {
+				type : 'border',
+				align : 'stretch'
+			},
+			items : [ mapPanel, accordionPanel ]
+		} ],
+		renderTo : Ext.getBody()
+	});
+
+}
+
+/*
+ * Update the query points layer with the coordinates of the selected category
+ * @param queryPanel the source query panel @param poiObj the selected poi
+ * object
+ */
+function updatePoiCategory(queryPanel, poiObj) {
+
+	if (poiObj.category == "Coordinate") {
+		var layerQ = globalLayers[baseLayerLabels.qPoint.name];
+		layerQ.removeAllFeatures();
+		var featureQ = new OpenLayers.Feature.Vector(
+				datasetCfgs[selectedDataset].queryPoint);
+		layerQ.addFeatures([ featureQ ]);
+		layerQ.styleMap = new OpenLayers.StyleMap({
+			"default" : new OpenLayers.Style({
+				externalGraphic : poiObj.img,
+				pointRadius : 10
+			}),
+			"select" : new OpenLayers.Style({
+				pointRadius : 12
+			})
+		});
+		layerQ.redraw();
+		updateCoordinateField(queryPanel, featureQ.geometry);
+	} else {
+		$.cometd.subscribe('/service/getPOIFeatures', function(message) {
+			var result = jQuery.parseJSON(message.data);
+			if (result.type == "FeatureCollection") {
+				// we show the feature collection in a table and in the map
+				var featureCollection = result.featureCollection;
+				var geoJSFormat = new OpenLayers.Format.GeoJSON();
+				var featureColl = geoJSFormat.read(featureCollection);
+
+				updateCoordinateField(queryPanel, {
+					x : "",
+					y : ""
+				});
+				var layerQ = globalLayers[baseLayerLabels.qPoint.name];
+				layerQ.removeAllFeatures();
+				layerQ.addFeatures(featureColl);
+				layerQ.styleMap = new OpenLayers.StyleMap({
+					"default" : new OpenLayers.Style({
+						externalGraphic : poiObj.img,
+						pointRadius : 10
+					}),
+					"select" : new OpenLayers.Style({
+						pointRadius : 12
+					})
+				});
+				layerQ.redraw();
+			}
+
+		});
+		// publishes the query
+		$.cometd.publish('/service/getPOIFeatures', {
+			query : poiObj.sql
+		});
+	}
+}
+
+/**
+ * @returns {hashtable} the parameters as a hash table
+ */
+function extractFormParameters() {
+	// collect all coordinates from array
+	var queryPointFeatures = globalLayers[baseLayerLabels.qPoint.name].features;
+	var queryPoints = "[";
+	for ( var i = 0; i < queryPointFeatures.length; i++) {
+		var point = queryPointFeatures[i];
+		queryPoints += "[" + point.geometry.x + "," + point.geometry.y + "]";
+		if (i < queryPointFeatures.length - 1) {
+			queryPoints += ",";
+		}
+	}
+	queryPoints += "]";
+	var queryParameters;
+	queryParameters = {
+		dataset : selectedDataset,
+		algorithm : queryPanel.find('name', ID_ALGO)[0].getValue(),
+		dmax : queryPanel.find('name', ID_DMAX)[0].getValue(),
+		mode : queryPanel.find('name', ID_MODE)[0].getValue(),
+		speed : queryPanel.find('name', ID_SPEED)[0].getValue(),
+		date : queryPanel.find('name', ID_DATE)[0].getValue().format('d/m/Y'),
+		time : queryPanel.find('name', ID_TIME)[0].getValue(),
+		queryPoints : queryPoints,
+		direction : queryPanel.find('name', ID_DIR)[0].getValue(),
+		coverage : queryPanel.find('name', ID_COVER)[0].getValue(),
+		expirationMode : queryPanel.find('name', ID_EXPMODE)[0].getValue()
+	};
+	return queryParameters;
+}
+
+function clearIsochrone() {
+	destroyDynamicLayers();
+}
+
+/**
+ * Sends a message that contains as message to start the computation of MineX
+ * 
+ * @param queryParameters
+ *          the parameter object that is passed
+ */
+function computeIsochrone(queryParameters) {
+	var LOG_PARSING_TIME = 0;
+
+	progressBar.setVisible(true);
+	progressBar.show();
+	progressBar.updateProgress(0, "processing");
+	destroyDynamicLayers();
+
+	var firstInvocation = true;
+
+	// subscribes an isochrone request
+	$.cometd.subscribe('/service/isochrones', function(message) {
+		var start = Date.now();
+		var result = jQuery.parseJSON(message.data);
+		LOG_PARSING_TIME += Date.now() - start;
+
+		if (result) {
+			if (result.status == "processing") {
+				var prctg = result.processed;
+				progressBar.updateProgress(prctg, prctg * 100 + "% processed");
+			} else if (result.status == "inserting") {
+				progressBar.updateText("Inserting");
+			} else if (result.status == "coveraging") {
+				progressBar.updateText("Coveraging");
+			} else if (result.status == "finished" && firstInvocation) {
+				firstInvocation = false;
+				createResultLayers(queryParameters, result);
+				progressBar.updateProgress(1, "Finished");
+			}
+		}
+		LOG_PARSING_TIME += Date.now() - start;
+	});
+	// publishes the query
+	$.cometd.publish('/service/isochrones', queryParameters);
+}
+
+/**
+ * @param queryParameters
+ *          an object with all parameters used
+ * @param result
+ *          the result of the query
+ */
+function createResultLayers(queryParameters, result) {
+	var isMultimodal = queryParameters.mode == "MULTIMODAL";
+	var isExpirationMode = queryParameters.expirationMode;
+	var timeQ = queryParameters.time;
+
+	// empties the result tree node with elements
+	var isoLayerRootNode = mainPanel.centerPanel.accordionPanel.layerPanel.isoLayerTreePanel
+			.getRootNode();
+	// create edge layer
+	var currentDSetConfig = datasetCfgs[selectedDataset];
+	var edgeLayer = currentDSetConfig["isoEdgeLayer"];
+	var wmsEdgeLayer = new OpenLayers.Layer.WMS(edgeLayer["name"],
+			config.mapserverUrl + "/wms", {
+				format : "image/png",
+				transparent : "TRUE",
+				layers : currentDSetConfig.prefix + ":" + edgeLayer["layer"],
+				styles : isExpirationMode ? "StyleEdgeExpiration" : "StyleEdge"
+			}, {
+				maxExtent : map.baseLayer.maxExtent,
+				maxResolution : map.baseLayer.maxResolution, // "auto" if not defined in the context
+				minResolution : map.baseLayer.minResolution, // "auto" if not defined in the context
+				isBaseLayer : false,
+				displayOutsideMaxExtent : true,
+				transitionEffect : "resize",
+				calculateInRange : function() {
+					return true;
+				}
+			});
+	isoLayerNames.push(wmsEdgeLayer.name);
+	map.addLayer(wmsEdgeLayer);
+	// add edge layer in tree
+	var edgeTreeNode = new GeoExt.tree.LayerNode({
+		'nodeType' : 'gx_layer',
+		'layer' : wmsEdgeLayer,
+		'checked' : true
+	});
+	isoLayerRootNode.appendChild(edgeTreeNode);
+	wmsEdgeLayer.redraw(true);
+
+	var filter = new OpenLayers.Filter.Comparison({
+		type : OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+		property : "ROUTE_ID",
+		value : -1
+	});
+
+	var parser = new OpenLayers.Format.Filter.v1_1_0();
+	var filterAsXml = parser.write(filter);
+	var xml = new OpenLayers.Format.XML();
+	var filterAsString = xml.write(filterAsXml);
+
+	// create node layer
+	var wmsVertexLayer;
+	if (isExpirationMode || isMultimodal) {
+		var vertexLayer = currentDSetConfig["isoVertexLayer"];
+		wmsVertexLayer = new OpenLayers.Layer.WMS(vertexLayer["name"],
+							  config.mapserverUrl + "/wms", {
+								  format : "image/png",
+								  transparent : "TRUE",
+								  layers : currentDSetConfig.prefix + ":" + vertexLayer["layer"],
+								  styles : isExpirationMode ? "StyleVertexExpiration"
+									  : "StyleTransportationStations",
+								  filter : isExpirationMode ? "" : filterAsString
+							  }, {
+								  maxExtent : map.baseLayer.maxExtent,
+								  maxResolution : map.baseLayer.maxResolution, // "auto" if not defined in the context
+								  minResolution : map.baseLayer.minResolution, // "auto" if not defined in the context
+								  isBaseLayer : false,
+								  displayOutsideMaxExtent : true,
+								  transitionEffect : "resize",
+								  calculateInRange : function() {
+									  return true;
+								  }
+							  });
+		map.addLayer(wmsVertexLayer);
+		isoLayerNames.push(wmsVertexLayer.name);
+		
+		var ctrlGetFeature = new OpenLayers.Control.WMSGetFeatureInfo({
+			url: config.mapserverUrl + "/wms",
+			hover: true,
+			queryVisible: true,
+			infoFormat: 'application/vnd.ogc.gml',
+			handlerOptions : {
+				"click": {delay: 10},
+				"hover": {delay: 300}
+			}
+		});
+		
+		ctrlGetFeature.events.on({
+			beforegetfeatureinfo: function(e) {
+				this.layers = [wmsVertexLayer]; 
+			},
+			getfeatureinfo: function(e) {
+				var features = this.format.read(e.text);
+				
+				if (features && features.length > 0) {
+                    			var feature = features[0];
+                    			var data = feature.data;
+             				var distance = data.DISTANCE;
+             				var timeObject = IsoUtil.asDateObject(timeQ);
+             				var isIncoming = queryParameters.direction == "INCOMING";
+             				var distanceInTime = isIncoming ? IsoUtil.addSeconds(timeObject,
+             										     -distance) : IsoUtil.addSeconds(timeObject, distance);
+             				var walkingDistStation = queryParameters.dmax * 60 - distance;
+             				
+             				featureInfoDialog.setPagePosition((e.xy.x+10),(e.xy.y));
+             				featureInfoDialog.update(IsoUtil.featureInfoToHTML(data.ID, distance,
+     											   distanceInTime, walkingDistStation, isIncoming));
+             				if(data.ID) {
+             					featureInfoDialog.setTitle("Id Stop Station:" + data.ID);
+             				} else {
+             					featureInfoDialog.setTitle("Stop Station:");
+             				}
+             				featureInfoDialog.setWidth(200);
+             				featureInfoDialog.show();
+				} else {
+                    			featureInfoDialog.hide();
+				}
+			}
+		});
+		map.addControl(ctrlGetFeature);
+		ctrlGetFeature.activate();
+		
+		globalControls[controlsLabels.selectF] = ctrlGetFeature;
+
+		var legendUrl = config.mapserverUrl
+			+ "/wms?request=GetLegendGraphic&TRANSPARENT=TRUE&SERVICE=WMS&version=1.1.1&FORMAT=image/png&STYLE="
+			+ wmsVertexLayer.params.STYLES + "&LAYER="
+			+ wmsVertexLayer.params.LAYERS;
+		// add vertex layer in tree
+		var vertexTreeNode = new GeoExt.tree.LayerNode({
+			'nodeType' : 'gx_layer',
+			'uiProvider' : Ext.extend(GeoExt.tree.LayerNodeUI,
+						  new GeoExt.tree.TreeNodeUIEventMixin()),
+			'layer' : wmsVertexLayer,
+			'style' : {
+				"background-color" : "white"
+			},
+			'component' : {
+				xtype : "box",
+				hidden : false,
+				style : {
+					"padding-bottom" : "10px",
+					"padding-left" : "35px"
+				},
+				autoEl : {
+					tag : "img",
+					src : legendUrl
+				}
+			}
+		});
+		isoLayerRootNode.appendChild(vertexTreeNode);
+		wmsVertexLayer.redraw(true);
+	}
+
+	if (!isExpirationMode) {
+		// create coverage layer
+		var coverageLayer = currentDSetConfig["isoCoverageLayer"];
+		var wmsCoverageLayer = new OpenLayers.Layer.WMS(coverageLayer["name"],
+								config.mapserverUrl + "/wms", {
+									format : "image/png",
+									transparent : "TRUE",
+									layers : currentDSetConfig.prefix + ":" + coverageLayer["layer"],
+									styles : "StyleIsoCoverage"
+								}, {
+									maxExtent : map.baseLayer.maxExtent,
+									maxResolution : map.baseLayer.maxResolution, // "auto" if not defined in the context
+									minResolution : map.baseLayer.minResolution, // "auto" if not defined in the context
+									isBaseLayer : false,
+									displayOutsideMaxExtent : true,
+									transitionEffect : true,
+									calculateInRange : function() {
+										return true;
+									}
+								});
+		map.addLayer(wmsCoverageLayer);
+		isoLayerNames.push(wmsCoverageLayer.name);
+
+		// set display hierarchy of layers
+		map.setLayerIndex(wmsCoverageLayer, 2);
+
+		// add coverage layer to tree
+		var coverageTreeNode = new GeoExt.tree.LayerNode({
+			'nodeType' : 'gx_layer',
+			'layer' : wmsCoverageLayer,
+			'checked' : true
+		});
+		isoLayerRootNode.appendChild(coverageTreeNode);
+		wmsCoverageLayer.redraw(true);
+	}
+
+	if (result.status == "finished") {
+		var bbox = result.bbox;
+		bbox = new OpenLayers.Bounds(bbox[0], bbox[1], bbox[2], bbox[3]);
+		map.zoomToExtent(bbox, false);
+		isoLayerRootNode.expand();
+		// repaint this panel
+		mainPanel.centerPanel.accordionPanel.layerPanel.isoLayerTreePanel
+				.doLayout();
+
+		if (isExpirationMode) {
+			mainPanel.centerPanel.accordionPanel.layerPanel.expand();
+		} else {
+			mainPanel.centerPanel.accordionPanel.sqlPanel.expand();
+		}
+	}
+}
+
+/**
+ * This web processing service performs operations on the isochrone result. The
+ * message contains an sql expression that is performed on the isochrone result
+ * 
+ * @param params
+ */
+function computeQueryOnCoverage(params) {
+	var firstInvocation = true;
+	$.cometd.subscribe('/service/wpsIsochrones',
+					function(message) {
+						if (firstInvocation) {
+							// the result can be of different type of
+							var result = jQuery.parseJSON(message.data);
+							firstInvocation = false;
+
+							var statisticItems = [];
+
+							var totalItems = [];
+							var isoItems = [];
+							var prctgItems = [];
+							var headerItems = [];
+
+							if (result.statistics.sum) {
+								totalItems.push({
+									fieldLabel : 'Sum',
+									xtype : 'textfield',
+									hideLabel : false,
+									value : result.statistics.sum
+								});
+								headerItems.push({
+									disabled : true,
+									xtype : 'textfield',
+									value : 'Sum'
+								});
+
+								if (result.statistics.joinedSum) {
+									isoItems.push({
+										fieldLabel : 'Sum',
+										xtype : 'textfield',
+										hideLabel : false,
+										value : result.statistics.joinedSum
+									});
+									var percentage = result.statistics.joinedSum
+											/ result.statistics.sum * 100;
+									prctgItems.push({
+										fieldLabel : 'Sum',
+										xtype : 'textfield',
+										hideLabel : false,
+										value : percentage.toFixed(2)
+									});
+								}
+							} else if (result.statistics.count) {
+								totalItems.push({
+									xtype : 'textfield',
+									fieldLabel : 'Count',
+									value : result.statistics.count
+								});
+								headerItems.push({
+									disabled : true,
+									xtype : 'textfield',
+									value : 'Count'
+								});
+
+								if (result.statistics.joinedCount) {
+									isoItems.push({
+										fieldLabel : 'Count',
+										xtype : 'textfield',
+										hideLabel : false,
+										value : result.statistics.joinedCount
+									});
+									var percentage = result.statistics.joinedCount
+											/ result.statistics.count * 100;
+									prctgItems.push({
+										fieldLabel : 'Count',
+										xtype : 'textfield',
+										hideLabel : false,
+										value : percentage.toFixed(2)
+									});
+								}
+							}
+
+							statisticItems.push({
+								xtype : 'compositefield',
+								fieldLabel : '',
+								msgTarget : 'side',
+								anchor : '-20',
+								defaults : {
+									flex : 1
+								},
+								items : headerItems
+							});
+
+							statisticItems.push({
+								xtype : 'compositefield',
+								fieldLabel : 'Total',
+								msgTarget : 'side',
+								anchor : '-20',
+								defaults : {
+									flex : 1,
+									hideLabel : false
+								},
+								items : totalItems
+							});
+
+							statisticItems.push({
+								xtype : 'compositefield',
+								fieldLabel : 'Iso',
+								msgTarget : 'side',
+								anchor : '-20',
+								defaults : {
+									flex : 1,
+									hideLabel : false
+								},
+								items : isoItems
+							});
+
+							statisticItems.push({
+								xtype : 'compositefield',
+								fieldLabel : 'Percentage',
+								msgTarget : 'side',
+								anchor : '-20',
+								defaults : {
+									flex : 1,
+									hideLabel : false
+								},
+								items : prctgItems
+							});
+
+							statisticsPanel = new Ext.form.FormPanel(
+									{
+										frame : true,
+										ref : 'statisticsPanel',
+										id : 'statisticsPanel',
+										width : 300,
+										height : 150,
+										title : '<font style="left:0px;font-style:normal;font-weight:normal;color:black;">Summary</font>',
+										border : false,
+										cls : 'settings',
+										defaults : {
+											bodyStyle : 'padding:2px',
+											width : 50,
+											border : false,
+											hideLabel : false,
+											// disabled : true,
+											labelWidth : 80
+										},
+										items : statisticItems
+									});
+							sqlPanel.add(statisticsPanel);
+
+							if (result.queryType == "SELECT") {
+								// we show the feature collection in a table and in the map
+								var featureCollJSON = result.featureCollection;
+								resultSQLLayer = new OpenLayers.Layer.Vector(
+										"QueryResultLayer", {
+											visibility : true,
+											displayInLayerSwitcher : true,
+											renderers : [ "SVG", "Canvas", "VML" ],
+											styleMap : new OpenLayers.StyleMap({
+												"default" : new OpenLayers.Style({
+													'pointRadius' : 4,
+													'strokeColor' : '#000000',
+													'fillColor' : '#ffffff',
+													'fillOpacity' : 0.6
+												}),
+												"select" : new OpenLayers.Style({
+													'pointRadius' : 4,
+													'fillColor' : '#A8A5A6',
+												})
+											})
+										});
+
+								map.addLayer(resultSQLLayer);
+								sqlLayerNames.push(resultSQLLayer.name);
+								var columnLabels = [], fields = [];
+								for ( var i = 0; i < result.columnLabels.length; i++) {
+									var columnLabel = result.columnLabels[i];
+									if (columnLabel.label != "geometry") {
+										columnLabels.push({
+											header : columnLabel.label,
+											width : 70,
+											dataIndex : columnLabel.label,
+											sortable : true
+										});
+										fields.push({
+											name : columnLabel.label,
+											type : columnLabel.type
+										});
+									}
+								}
+
+								var geoJSFormat = new OpenLayers.Format.GeoJSON();
+								var sqlDatastore = new GeoExt.data.FeatureStore({
+									layer : resultSQLLayer,
+									fields : fields,
+									autoLoad : true,
+									features : geoJSFormat.read(featureCollJSON)
+								});
+								sqlDatastore.bind(resultSQLLayer);
+
+								sqlResultTablePanel = new Ext.grid.GridPanel(
+										{
+											frame : false,
+											id : "sqlResultTablePanel",
+											title : '<font style="left:0px;font-style:normal;font-weight:normal;color:black;">Details</font>',
+											ref : 'sqlResultTablePanel',
+											store : sqlDatastore,
+											width : 300,
+											columns : columnLabels,
+											cls : 'settings',
+											flex : 2,
+											sm : new GeoExt.grid.FeatureSelectionModel()
+										});
+								sqlPanel.add(sqlResultTablePanel);
+
+							}
+							sqlPanel.doLayout();
+						}
+					});
+
+	// publishes the query
+	$.cometd.publish('/service/wpsIsochrones', params);
+
+}
+
+function addSingleQueryPointSelector(qPointlayer) {
+	var ctrlSelectFeature = new OpenLayers.Control.SelectFeature(qPointlayer, {
+		clickout : false,
+		toggle : false,
+		multiple : false,
+		hover : true
+	});
+	globalControls[controlsLabels.selectQ] = ctrlSelectFeature;
+	map.addControl(ctrlSelectFeature);
+	ctrlSelectFeature.activate();
+	// can only be activated after it is added to the map
+}
+
+/**
+ * Updates the coordinat field with the specified values, that will be rounded
+ * 
+ * @param {Object}
+ *          OpenLayers.Geometry.Point
+ */
+function updateCoordinateField(container, point) {
+	var el = container.find('name', ID_COORD)[0];
+	el.setValue(Math.round(point.x) + ", " + Math.round(point.y));
+}
+
+/**
+ * Update the field with the correpsponding value
+ * 
+ * @param dateString
+ */
+function updateDateField(container, dateString) {
+	var el = container.find('name', ID_DATE)[0];
+	el.setValue(dateString);
+}
+
+/**
+ * Update the field with the correpsponding value
+ * 
+ * @param timeString
+ */
+function updateTimeField(container, timeString) {
+	var el = container.find('name', ID_TIME)[0];
+	el.setValue(timeString);
+}
+
+/**
+ * Should be invoked, when a different dataset is selected from the user
+ * interface
+ * 
+ * @param container
+ *          the container in which the datasets belong to
+ * @param val
+ *          the new value of the dataset
+ */
+function updateDataset(container, val) {
+	selectedDataset = val;
+
+	if (map.layers.length > globalLayers.length) {
+		destroyDynamicLayers();
+	}
+	var newCfg = datasetCfgs[val];
+	var queryPointFeature = new OpenLayers.Feature.Vector(newCfg.queryPoint, {
+		calculateInRange : function() {
+			return true;
+		}
+	});
+	var querypointLayer = globalLayers[baseLayerLabels.qPoint.name];
+	querypointLayer.destroyFeatures();
+	querypointLayer.addFeatures([ queryPointFeature ]);
+	map.setCenter(newCfg.queryPoint);
+	map.zoomToExtent(newCfg.bbox, true);
+	querypointLayer.drawFeature(queryPointFeature);
+	updateCoordinateField(container, newCfg.queryPoint);
+	updateDateField(container, newCfg.date);
+	updateTimeField(container, newCfg.time);
+	addSingleQueryPointSelector(querypointLayer);
+}
+
+/**
+ * destroys dynamic layer from node tree and from the map
+ */
+function destroyDynamicLayers() {
+	var isoLayerRootNode = layerPanel.isoLayerTreePanel.getRootNode();
+	
+	while (isoLayerRootNode.firstChild) {
+		isoLayerRootNode.removeChild(isoLayerRootNode.firstChild, true);
+	}
+	var layersToRemove = [];
+	// remove non global layers from map
+	for ( var i = 0; i < isoLayerNames.length; i++) {
+		var layers = map.getLayersByName(isoLayerNames[i]);
+		if (layers) {
+			for ( var j = 0; j < layers.length; j++) {
+				layersToRemove.push(layers[j]);
+			}
+		}
+	}
+	for ( var i = 0; i < layersToRemove.length; i++) {
+		try {
+			map.removeLayer(layersToRemove[i]);
+			layersToRemove[i].destroy();
+		} catch (err) {
+		}
+	}
+	isoLayerNames = [];
+	removeSQLResult();
+}
+
+function loadSchedules(stopId, inDir, dNetQ, remDist) {
+
+	var params = new Object();
+	params["stopId"] = stopId;
+
+	$.cometd.subscribe('/service/getFeatureInfo',
+			function(message) {
+				var result = jQuery.parseJSON(message.data);
+				var s = "<table>";
+				s += "<tr><td>Dist. to q: </td><td>" + dNetQ + "</td></tr>";
+				s += "<tr><td>Remaining dist. <img src=\"./img/ped.png\" style=\"width: 15px; height: 15px;\"></td><td>" + remDist + "</td></tr>";
+				s += "<tr>";
+				s += "<td>Route</td>";
+				s += "<td>" + (inDir ? "T.Dep" : "T.Arr" ) + "</td>";
+				s += "</tr>"; 
+
+				jQuery.each(result.vertexAnnotation, function() {
+					// for each result we create a html table row containing
+					// icon mean of transport, the name of the route and the
+					// time when it passes on the stop
+					s += "<tr>";
+					s += "<td> <img src=\"" + tSMapping[this.routeType].img + "\" style=\"width: 15px; height: 15px;\">" + this.routeName + "</td>" ; 
+					s += "<td>" + this.time + "</td>" ;
+					s += "</tr>";
+					
+				});
+				s += "</table>";
+			
+				featureInfoDialog.update(s);
+			});
+	$.cometd.publish('/service/getFeatureInfo', params);
+}
+
+function fillResultTabPane(obj) {
+	$("#resultContainer").empty();
+	var infoString = "<b>Statistics:</b><br/>";
+	infoString += "<span>Reached inhabitants: " + obj.reachedInhabitants
+			+ "</span>";
+	infoString += " <br/> ";
+	infoString += "<span>Total inhabitants: " + obj.totalInhabitants + "</span>";
+	infoString += " <br/> ";
+	infoString += "<span>Percentage: " + obj.averageInhabitants + "%</span>";
+	$("#resultContainer").append(infoString);
+	$("#resultTabPane").css("visibility", "visible");
+	OpenLayers.Console
+			.log("Time iso area initialization: " + obj.isoAreaInitTime);
+	OpenLayers.Console.log("Time iso area calculation: "
+			+ obj.isoAreaCalculationTime);
+	OpenLayers.Console.log("Time stats computation: " + obj.statsComputationTime);
+
+}
+
+function changeQPointSelectionMode() {
+	if ($("input[name=multipleSelection]").attr('checked')) {
+		// change to multiple queryPoint selection
+		$("#queryPointField").attr('disabled', true);
+		multipleQueryPointSelection = true;
+	} else {
+		$("#queryPointField").attr('disabled', false);
+		multipleQueryPointSelection = false;
+	}
+}
+
+/**
+ * Function that specifies if for a specific dataset the area creatin can be done
+ */
+function enableCoverageMode() {
+	var dSet = new O;
+	var dataSets = $("input[name=dataset]");
+	for ( var i = 0; i < dataSets.length; i++) {
+		var currentSet = dataSets[i];
+		if (currentSet.checked) {
+			dSet = currentSet.value;
+			break;
+		}
+	}
+	switch (dSet) {
+	case "BZ":
+		if ($("input[name=enableCoverage]").attr('checked')) {
+			// change to multiple queryPoint selection
+			$("#queryBufferDistance").attr('disabled', false);
+		} else {
+			$("#queryBufferDistance").attr('disabled', true);
+		}
+		break;
+	default:
+		alert("For the dataset " + dSet + " no inhabitants data are available");
+		$("input[name=enableCoverage]").attr('checked', false);
+	}
+}
+
+/**
+ * remove the result info from the client. This means the layer and its
+ * features, the table and the panel
+ */
+function removeSQLResult() {
+	if (statisticsPanel && !statisticsPanel.isDestroyed) {
+		try {
+			statisticsPanel.removeAll();
+			sqlPanel.remove(statisticsPanel, true);
+		} catch (err) {
+		}
+	}
+
+	if (sqlResultTablePanel && !sqlResultTablePanel.isDestroyed) {
+		try {
+			sqlResultTablePanel.removeAll();
+			sqlPanel.remove(sqlResultTablePanel, true);
+		} catch (err) {
+		}
+		sqlPanel.doLayout();
+	}
+
+	for ( var i = 0; i < sqlLayerNames.length; i++) {
+		var layers = map.getLayersByName(sqlLayerNames[i]);
+		if (layers) {
+			for ( var i = 0; i < layers.length; i++) {
+				var toRemove = layers[i];
+				try {
+					map.removeLayer(toRemove);
+				} catch (err) {
+				}
+				try {
+					toRemove.destroy();
+				} catch (err) {
+				}
+			}
+		}
+	}
+	if (sqlLayerNames.length > 0) {
+		sqlLayerNames = [];
+	}
+}
diff --git a/src/main/webapp/lib/isochrones/util.js b/src/main/webapp/lib/isochrones/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..7a67c3f295cc798c65b45cb53ee2f6b8ced86f83
--- /dev/null
+++ b/src/main/webapp/lib/isochrones/util.js
@@ -0,0 +1,207 @@
+function IsoUtil() {
+}
+
+/**
+ * Converts km per hour in meters per second
+ * 
+ * @param {number} speed value in km per hours
+ * @return {number} the value in meters per second
+ */
+IsoUtil.kmp2mps = function(speed) {
+	return parseFloat(speed) / 3.6;
+};
+
+/**
+ * Converts minutes in seconds
+ */
+IsoUtil.minutes2seconds = function(minutes) {
+	return parseInt(minutes) * 60;
+};
+
+/**
+ * @param {Date} the date instance to be converted
+ * @return {String} the string value in pattern: YYYY/MM/DD:hh24:mi
+ */
+IsoUtil.date2String = function(date) {
+	var sep = "/";
+	var dateString = date.getFullYear() + sep;
+	dateString += IsoUtil.fillZeroPrefix(date.getMonth() + 1) + sep;
+	dateString += IsoUtil.fillZeroPrefix(date.getDate()) + sep;
+	dateString += IsoUtil.fillZeroPrefix(date.getHours()) + ":";
+	dateString += IsoUtil.fillZeroPrefix(date.getMinutes());
+	return dateString;
+};
+
+IsoUtil.string2Date = function(dateString) {
+	return new Date(dateString);
+};
+
+/**
+ * @return {String} the date string in format YYYY-MM-DD
+ */
+IsoUtil.date2DayString = function(date) {
+	var sep = "-";
+	var dateString = IsoUtil.fillZeroPrefix(date.getDate()) + sep;
+	dateString += IsoUtil.fillZeroPrefix(date.getMonth() + 1) + sep;
+	dateString += IsoUtil.fillZeroPrefix(date.getFullYear());
+	return dateString;
+};
+
+IsoUtil.asHTML_old = function(id, distance, distanceInTime,walkingTime,isIncoming) {
+	var s = "<html><style type=\"text/css\">table.featureInfo,table.featureInfo td,table.featureInfo th { ";
+	s += "border: 1px solid #ddd;border-collapse: collapse;	margin: 0;padding: 0;font-size:medium;padding: .2em .1em;width:100%} ";
+	s += "table.featureInfo th {padding: .2em .2em;	font-weight: bold;	background: #eee;} ";
+	s += "table.featureInfo td {background: #fff;} ";
+	s += "table.featureInfo tr.odd td \{	background: #eee;\} ";
+	s += "table.featureInfo caption {	text-align: left; font-size: 100%; font-weight: bold; text-transform: uppercase; padding: .2em .2em;}";
+	s += "a:link {text-decoration:none;}	a:visited {text-decoration:none;} a:hover {text-decoration:underline;} a:active {text-decoration:underline;}";
+	s += "</style>";
+	s += "<body><table class=\"featureInfo\" id=\"popupTable\">";
+	s += "<tr><td style=\"width:55%;\">Dist. </td><td>" + IsoUtil.showDistance(distance) + "</td></tr>";
+	s += "<tr><td style=\"width:55%;\"><img src=\"./img/ped.png\" style=\"width: 15px; height: 15px;\"/></td><td>" + IsoUtil.showDistance(walkingTime) + "</td></tr>";
+	s += "<tr><td id=\"loadSchedulesCell\"colspan=\"2\"><a id=\"loadSchedulesLink\" onclick=\"loadSchedules(" + id + "," + isIncoming
+			+ ")\">Show schedule</a></td></tr>";
+	s += "</table></body></html>";
+	return s;
+};
+
+IsoUtil.featureInfoToHTML = function(id, distance, distanceInTime, walkingTime,isIncoming) {
+	var s = "<table>";
+	var dNetQ = IsoUtil.showDistance(distance);
+	var remDist = IsoUtil.showDistance(walkingTime);
+	s += "<tr><td>Dist. to q: </td><td>" + dNetQ + "</td></tr>";
+	s += "<tr><td>Remaining dist. <img src=\"./img/ped.png\" style=\"width: 15px; height: 15px;\"/></td><td>" + remDist + "</td></tr>";
+	s += "<tr><td id=\"loadSchedulesCell\"colspan=\"2\"><a id=\"loadSchedulesLink\" onclick=\"loadSchedules(" + id + "," + isIncoming + ",'" +  dNetQ + "','" +  remDist + "')\">Show schedule</a></td></tr>";
+	s += "</table>";
+	return s;
+};
+
+IsoUtil.queryPointToHtml = function(timeQ, dmax, incoming) {
+	var s = "<table>";
+	s += "<tr><td>Dmax:</td><td>" + dmax + " min</td></tr>";
+	if(incoming=="INCOMING") {
+		s += "<tr><td><img src='./img/clock.png' style='width: 15px; height: 15px;'/>Arrival:</td><td>" + timeQ + "</td></tr>";
+	} else {
+		s += "<tr><td><img src='./img/clock.png' style='width: 15px; height: 15px;'/>Departure:</td><td>" + timeQ + "</td></tr>";
+	}
+	s += "</table>";
+	return s;
+};
+
+/**
+ * @return {String} the time string in format hh:mm
+ */
+IsoUtil.date2TimeString = function(date) {
+	var timeString = IsoUtil.fillZeroPrefix(date.getHours()) + ":";
+	timeString += IsoUtil.fillZeroPrefix(date.getMinutes());
+	return timeString;
+};
+
+IsoUtil.showDistance = function(distance) {
+	var dist =  distance<60 ? distance.toFixed(0) + " sec" : (distance/60).toFixed(0)+ " min";
+	return dist.replace(/\.{0,2}/, "");
+};
+
+/**
+ * @param {String}
+ *          date the date string in pattern DD/MM/YYYY
+ * @param {String}
+ *          time the time string in pattern hh:mm
+ * @return {Date} the date instance
+ */
+IsoUtil.mergeDate = function(date, time) {
+	var result;
+	result = date.substring(6, 10) + "/" + date.substring(3, 5) + "/" + date.substring(0, 2) + "/" + time;
+	return new Date(result);
+};
+
+/**
+ * transforms a time string HH:mm in a date object
+ */
+IsoUtil.asDateObject = function(timeString) {
+	var item = timeString.split(":");
+	var d = new Date();
+	d.setHours(item[0]);
+	d.setMinutes(item[1]);
+	d.setMinutes(item[1]);
+	d.setSeconds(0);
+	d.setMilliseconds(0);
+	return d;
+};
+
+/**
+ * 
+ * @param {Date}
+ *          dateObj the date object
+ * @param {integer}
+ *          seconds the seconds to be subtracted
+ */
+IsoUtil.addSeconds = function(dateObj, seconds) {
+	var d = new Date(dateObj.getTime());
+	if (seconds) {
+		d.setSeconds(seconds);
+	}
+	var timeString = IsoUtil.fillZeroPrefix(d.getHours());
+	timeString += ":" + IsoUtil.fillZeroPrefix(d.getMinutes());
+	timeString += ":" + IsoUtil.fillZeroPrefix(d.getSeconds());
+	return timeString;
+};
+
+/**
+ * 
+ * @param {Date}
+ *          the date instance
+ * @param {Object}
+ *          feature the feature from which to extract the information
+ * @return {String} a div element containing the information to be displayed
+ */
+IsoUtil.toHtml = function(time, feature) {
+	var htmlToReturn = "<div style='font-size:0.8em;overflow:hidden'>";
+	htmlToReturn += "<img src='img/clock.png' width='15' height='15' alt='bus'/> <b>";
+	if (!feature) {
+		htmlToReturn += time;
+	} else {
+		htmlToReturn += IsoUtil.addSeconds(time, -feature.data.distance);
+		htmlToReturn += "</b>";
+
+		for (var i = 0; i < feature.data.routes.length; i++) {
+			var routeAnns = feature.data.routes[i];
+			var routeType = routeAnns.routeType == null ? 1 : routeAnns.routeType;
+			var routeSymbol = imgLookup[routeType];
+			var tokens = routeAnns.routeName.split(" ");
+			var routeName = "";
+			for (var j = 0; j < tokens.length; j++) {
+				var token = tokens[j];
+				if (j < tokens.length - 1) {
+					routeName += token;
+				} else {
+					if (token == "BZ" || token == "ME") {;
+					} else {
+						routeName += token;
+					}
+				}
+			}
+			htmlToReturn += " <img src='" + routeSymbol + "' width='15' height='15' alt='bus'/> " + routeName;
+		}
+	}
+	htmlToReturn += "</div>";
+	return htmlToReturn;
+};
+
+/**
+ * @return {String} the value in string format with leading zero in case of 1
+ *         digit
+ */
+IsoUtil.fillZeroPrefix = function(val) {
+	if (val < 10)
+		return "0" + val;
+	else
+		return val;
+
+};
+
+IsoUtil.asId = function(featureId) {
+	// remember: each regex has to start and end with a / character
+	var id = featureId.replace(/[\w]*\./, "");
+	return parseInt(id);
+};
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png
new file mode 100644
index 0000000000000000000000000000000000000000..954e22dbd99e8c6dd7091335599abf2d10bf8003
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644
index 0000000000000000000000000000000000000000..64ece5707d91a6edf9fad4bfcce0c4dbcafcf58d
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..abdc01082bf3534eafecc5819d28c9574d44ea89
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b383f4d2eab09c0f2a739d6b232c32934bc620b
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..a23baad25b1d1ff36e17361eab24271f2e9b7326
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..39d5824d6af5456f1e89fc7847ea3599ea5fd815
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1273672d253263b7564e9e21d69d7d9d0b337d9
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..359397acffdd84bd102f0e8a951c9d744f278db5
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..a641a371afa0fbb08ba599dc7ddf14b9bfc3c84f
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..85e63e9f604ce042d59eb06a8428eeb7cb7896c9
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..e117effa3dca24e7978cfc5f8b967f661e81044f
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..42f8f992c727ddaa617da224a522e463df690387
Binary files /dev/null and b/src/main/webapp/lib/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png differ
diff --git a/src/main/webapp/lib/jquery/css/ui-lightness/jquery-ui-1.8.6.custom.css b/src/main/webapp/lib/jquery/css/ui-lightness/jquery-ui-1.8.6.custom.css
new file mode 100644
index 0000000000000000000000000000000000000000..dc6020061666201dc8721bbc0fc0e34f57ee5f1c
--- /dev/null
+++ b/src/main/webapp/lib/jquery/css/ui-lightness/jquery-ui-1.8.6.custom.css
@@ -0,0 +1,572 @@
+/*
+ * jQuery UI CSS Framework 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*
+ * jQuery UI CSS Framework 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
+.ui-widget-content a { color: #333333; }
+.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
+.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*
+ * jQuery UI Resizable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
+ * jQuery UI Selectable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*
+ * jQuery UI Accordion 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }/*
+ * jQuery UI Autocomplete 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }	
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+	list-style:none;
+	padding: 2px;
+	margin: 0;
+	display:block;
+	float: left;
+}
+.ui-menu .ui-menu {
+	margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+	margin:0;
+	padding: 0;
+	zoom: 1;
+	float: left;
+	clear: left;
+	width: 100%;
+}
+.ui-menu .ui-menu-item a {
+	text-decoration:none;
+	display:block;
+	padding:.2em .4em;
+	line-height:1.5;
+	zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+	font-weight: normal;
+	margin: -1px;
+}
+/*
+ * jQuery UI Button 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; } 
+button.ui-button-icons-only { width: 3.7em; } 
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4;  }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*
+ * jQuery UI Dialog 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*
+ * jQuery UI Slider 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
+ * jQuery UI Tabs 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*
+ * jQuery UI Datepicker 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}/*
+ * jQuery UI Progressbar 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/src/main/webapp/lib/jquery/jquery-1.8.2.js b/src/main/webapp/lib/jquery/jquery-1.8.2.js
new file mode 100644
index 0000000000000000000000000000000000000000..d4f3bb38cdab24303efed50e482aecc949fcdb53
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery-1.8.2.js
@@ -0,0 +1,9440 @@
+/*!
+ * jQuery JavaScript Library v1.8.2
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time)
+ */
+(function( window, undefined ) {
+var
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// The deferred used on DOM ready
+	readyList,
+
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+	location = window.location,
+	navigator = window.navigator,
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// Save a reference to some core methods
+	core_push = Array.prototype.push,
+	core_slice = Array.prototype.slice,
+	core_indexOf = Array.prototype.indexOf,
+	core_toString = Object.prototype.toString,
+	core_hasOwn = Object.prototype.hasOwnProperty,
+	core_trim = String.prototype.trim,
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context, rootjQuery );
+	},
+
+	// Used for matching numbers
+	core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
+
+	// Used for detecting and trimming whitespace
+	core_rnotwhite = /\S/,
+	core_rspace = /\s+/,
+
+	// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return ( letter + "" ).toUpperCase();
+	},
+
+	// The ready event handler and self cleanup method
+	DOMContentLoaded = function() {
+		if ( document.addEventListener ) {
+			document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+			jQuery.ready();
+		} else if ( document.readyState === "complete" ) {
+			// we're here because readyState === "complete" in oldIE
+			// which is good enough for us to call the dom ready!
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	},
+
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	constructor: jQuery,
+	init: function( selector, context, rootjQuery ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+					doc = ( context && context.nodeType ? context.ownerDocument || context : document );
+
+					// scripts is true for back-compat
+					selector = jQuery.parseHTML( match[1], doc, true );
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						this.attr.call( selector, context, true );
+					}
+
+					return jQuery.merge( this, selector );
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.8.2",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return core_slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this[ this.length + num ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	ready: function( fn ) {
+		// Add the callback
+		jQuery.ready.promise().done( fn );
+
+		return this;
+	},
+
+	eq: function( i ) {
+		i = +i;
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( core_slice.apply( this, arguments ),
+			"slice", core_slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: core_push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		if ( window.$ === jQuery ) {
+			window.$ = _$;
+		}
+
+		if ( deep && window.jQuery === jQuery ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( !document.body ) {
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.trigger ) {
+			jQuery( document ).trigger("ready").off("ready");
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		return !isNaN( parseFloat(obj) ) && isFinite( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ core_toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!core_hasOwn.call(obj, "constructor") &&
+				!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+
+		var key;
+		for ( key in obj ) {}
+
+		return key === undefined || core_hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	// data: string of html
+	// context (optional): If specified, the fragment will be created in this context, defaults to document
+	// scripts (optional): If true, will include scripts passed in the html string
+	parseHTML: function( data, context, scripts ) {
+		var parsed;
+		if ( !data || typeof data !== "string" ) {
+			return null;
+		}
+		if ( typeof context === "boolean" ) {
+			scripts = context;
+			context = 0;
+		}
+		context = context || document;
+
+		// Single tag
+		if ( (parsed = rsingleTag.exec( data )) ) {
+			return [ context.createElement( parsed[1] ) ];
+		}
+
+		parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
+		return jQuery.merge( [],
+			(parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
+	},
+
+	parseJSON: function( data ) {
+		if ( !data || typeof data !== "string") {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+
+		// Attempt to parse using the native JSON parser first
+		if ( window.JSON && window.JSON.parse ) {
+			return window.JSON.parse( data );
+		}
+
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+			.replace( rvalidtokens, "]" )
+			.replace( rvalidbraces, "")) ) {
+
+			return ( new Function( "return " + data ) )();
+
+		}
+		jQuery.error( "Invalid JSON: " + data );
+	},
+
+	// Cross-browser xml parsing
+	parseXML: function( data ) {
+		var xml, tmp;
+		if ( !data || typeof data !== "string" ) {
+			return null;
+		}
+		try {
+			if ( window.DOMParser ) { // Standard
+				tmp = new DOMParser();
+				xml = tmp.parseFromString( data , "text/xml" );
+			} else { // IE
+				xml = new ActiveXObject( "Microsoft.XMLDOM" );
+				xml.async = "false";
+				xml.loadXML( data );
+			}
+		} catch( e ) {
+			xml = undefined;
+		}
+		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+			jQuery.error( "Invalid XML: " + data );
+		}
+		return xml;
+	},
+
+	noop: function() {},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && core_rnotwhite.test( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var name,
+			i = 0,
+			length = obj.length,
+			isObj = length === undefined || jQuery.isFunction( obj );
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in obj ) {
+					if ( callback.apply( obj[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( obj[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in obj ) {
+					if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+		function( text ) {
+			return text == null ?
+				"" :
+				core_trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				( text + "" ).replace( rtrim, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var type,
+			ret = results || [];
+
+		if ( arr != null ) {
+			// The window, strings (and functions) also have 'length'
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			type = jQuery.type( arr );
+
+			if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
+				core_push.call( ret, arr );
+			} else {
+				jQuery.merge( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		var len;
+
+		if ( arr ) {
+			if ( core_indexOf ) {
+				return core_indexOf.call( arr, elem, i );
+			}
+
+			len = arr.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in arr && arr[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var l = second.length,
+			i = first.length,
+			j = 0;
+
+		if ( typeof l === "number" ) {
+			for ( ; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var retVal,
+			ret = [],
+			i = 0,
+			length = elems.length;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value, key,
+			ret = [],
+			i = 0,
+			length = elems.length,
+			// jquery objects are treated as arrays
+			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+		// Go through the array, translating each of the items to their
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( key in elems ) {
+				value = callback( elems[ key ], key, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var tmp, args, proxy;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = core_slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	// Multifunctional method to get and set values of a collection
+	// The value/s can optionally be executed if it's a function
+	access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+		var exec,
+			bulk = key == null,
+			i = 0,
+			length = elems.length;
+
+		// Sets many values
+		if ( key && typeof key === "object" ) {
+			for ( i in key ) {
+				jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+			}
+			chainable = 1;
+
+		// Sets one value
+		} else if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = pass === undefined && jQuery.isFunction( value );
+
+			if ( bulk ) {
+				// Bulk operations only iterate when executing function values
+				if ( exec ) {
+					exec = fn;
+					fn = function( elem, key, value ) {
+						return exec.call( jQuery( elem ), value );
+					};
+
+				// Otherwise they run against the entire set
+				} else {
+					fn.call( elems, value );
+					fn = null;
+				}
+			}
+
+			if ( fn ) {
+				for (; i < length; i++ ) {
+					fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+				}
+			}
+
+			chainable = 1;
+		}
+
+		return chainable ?
+			elems :
+
+			// Gets
+			bulk ?
+				fn.call( elems ) :
+				length ? fn( elems[0], key ) : emptyGet;
+	},
+
+	now: function() {
+		return ( new Date() ).getTime();
+	}
+});
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// we once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready, 1 );
+
+		// Standards-based browsers support DOMContentLoaded
+		} else if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else {
+			// Ensure firing before onload, maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var top = false;
+
+			try {
+				top = window.frameElement == null && document.documentElement;
+			} catch(e) {}
+
+			if ( top && top.doScroll ) {
+				(function doScrollCheck() {
+					if ( !jQuery.isReady ) {
+
+						try {
+							// Use the trick by Diego Perini
+							// http://javascript.nwbox.com/IEContentLoaded/
+							top.doScroll("left");
+						} catch(e) {
+							return setTimeout( doScrollCheck, 50 );
+						}
+
+						// and execute any waiting functions
+						jQuery.ready();
+					}
+				})();
+			}
+		}
+	}
+	return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.split( core_rspace ), function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// Flag to know if list is currently firing
+		firing,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) {
+								list.push( arg );
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Control if a given callback is in the list
+			has: function( fn ) {
+				return jQuery.inArray( fn, list ) > -1;
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				args = args || [];
+				args = [ context, args.slice ? args.slice() : args ];
+				if ( list && ( !fired || stack ) ) {
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var action = tuple[ 0 ],
+								fn = fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
+								function() {
+									var returned = fn.apply( this, arguments );
+									if ( returned && jQuery.isFunction( returned.promise ) ) {
+										returned.promise()
+											.done( newDefer.resolve )
+											.fail( newDefer.reject )
+											.progress( newDefer.notify );
+									} else {
+										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+									}
+								} :
+								newDefer[ action ]
+							);
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ] = list.fire
+			deferred[ tuple[0] ] = list.fire;
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = core_slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+					if( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+					} else if ( !( --remaining ) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// if we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+jQuery.support = (function() {
+
+	var support,
+		all,
+		a,
+		select,
+		opt,
+		input,
+		fragment,
+		eventName,
+		i,
+		isSupported,
+		clickFn,
+		div = document.createElement("div");
+
+	// Preliminary tests
+	div.setAttribute( "className", "t" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+	all = div.getElementsByTagName("*");
+	a = div.getElementsByTagName("a")[ 0 ];
+	a.style.cssText = "top:1px;float:left;opacity:.5";
+
+	// Can't get basic test support
+	if ( !all || !all.length ) {
+		return {};
+	}
+
+	// First batch of supports tests
+	select = document.createElement("select");
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName("input")[ 0 ];
+
+	support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText instead)
+		style: /top/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.5/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: ( input.value === "on" ),
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+		getSetAttribute: div.className !== "t",
+
+		// Tests for enctype support on a form(#6743)
+		enctype: !!document.createElement("form").enctype,
+
+		// Makes sure cloning an html5 element does not cause problems
+		// Where outerHTML is undefined, this still works
+		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+		// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+		boxModel: ( document.compatMode === "CSS1Compat" ),
+
+		// Will be defined later
+		submitBubbles: true,
+		changeBubbles: true,
+		focusinBubbles: false,
+		deleteExpando: true,
+		noCloneEvent: true,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableMarginRight: true,
+		boxSizingReliable: true,
+		pixelPosition: false
+	};
+
+	// Make sure checked status is properly cloned
+	input.checked = true;
+	support.noCloneChecked = input.cloneNode( true ).checked;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete div.test;
+	} catch( e ) {
+		support.deleteExpando = false;
+	}
+
+	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+		div.attachEvent( "onclick", clickFn = function() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			support.noCloneEvent = false;
+		});
+		div.cloneNode( true ).fireEvent("onclick");
+		div.detachEvent( "onclick", clickFn );
+	}
+
+	// Check if a radio maintains its value
+	// after being appended to the DOM
+	input = document.createElement("input");
+	input.value = "t";
+	input.setAttribute( "type", "radio" );
+	support.radioValue = input.value === "t";
+
+	input.setAttribute( "checked", "checked" );
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+	fragment = document.createDocumentFragment();
+	fragment.appendChild( div.lastChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	support.appendChecked = input.checked;
+
+	fragment.removeChild( input );
+	fragment.appendChild( div );
+
+	// Technique from Juriy Zaytsev
+	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+	// We only care about the case where non-standard event systems
+	// are used, namely in IE. Short-circuiting here helps us to
+	// avoid an eval call (in setAttribute) which can cause CSP
+	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+	if ( div.attachEvent ) {
+		for ( i in {
+			submit: true,
+			change: true,
+			focusin: true
+		}) {
+			eventName = "on" + i;
+			isSupported = ( eventName in div );
+			if ( !isSupported ) {
+				div.setAttribute( eventName, "return;" );
+				isSupported = ( typeof div[ eventName ] === "function" );
+			}
+			support[ i + "Bubbles" ] = isSupported;
+		}
+	}
+
+	// Run tests that need a body at doc ready
+	jQuery(function() {
+		var container, div, tds, marginDiv,
+			divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
+			body = document.getElementsByTagName("body")[0];
+
+		if ( !body ) {
+			// Return for frameset docs that don't have a body
+			return;
+		}
+
+		container = document.createElement("div");
+		container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
+		body.insertBefore( container, body.firstChild );
+
+		// Construct the test element
+		div = document.createElement("div");
+		container.appendChild( div );
+
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		// (only IE 8 fails this test)
+		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+		tds = div.getElementsByTagName("td");
+		tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+		isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+		tds[ 0 ].style.display = "";
+		tds[ 1 ].style.display = "none";
+
+		// Check if empty table cells still have offsetWidth/Height
+		// (IE <= 8 fail this test)
+		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+		// Check box-sizing and margin behavior
+		div.innerHTML = "";
+		div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+		support.boxSizing = ( div.offsetWidth === 4 );
+		support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+		// NOTE: To any future maintainer, we've window.getComputedStyle
+		// because jsdom on node.js will break without it.
+		if ( window.getComputedStyle ) {
+			support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+			support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+			// Check if div with explicit width and no margin-right incorrectly
+			// gets computed margin-right based on width of container. For more
+			// info see bug #3333
+			// Fails in WebKit before Feb 2011 nightlies
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			marginDiv = document.createElement("div");
+			marginDiv.style.cssText = div.style.cssText = divReset;
+			marginDiv.style.marginRight = marginDiv.style.width = "0";
+			div.style.width = "1px";
+			div.appendChild( marginDiv );
+			support.reliableMarginRight =
+				!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+		}
+
+		if ( typeof div.style.zoom !== "undefined" ) {
+			// Check if natively block-level elements act like inline-block
+			// elements when setting their display to 'inline' and giving
+			// them layout
+			// (IE < 8 does this)
+			div.innerHTML = "";
+			div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+			support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+			// Check if elements with layout shrink-wrap their children
+			// (IE 6 does this)
+			div.style.display = "block";
+			div.style.overflow = "visible";
+			div.innerHTML = "<div></div>";
+			div.firstChild.style.width = "5px";
+			support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+			container.style.zoom = 1;
+		}
+
+		// Null elements to avoid leaks in IE
+		body.removeChild( container );
+		container = div = tds = marginDiv = null;
+	});
+
+	// Null elements to avoid leaks in IE
+	fragment.removeChild( div );
+	all = a = select = opt = input = fragment = div = null;
+
+	return support;
+})();
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+	cache: {},
+
+	deletedIds: [],
+
+	// Remove at next major release (1.9/2.0)
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page
+	// Non-digits removed to match rinlinejQuery
+	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var thisCache, ret,
+			internalKey = jQuery.expando,
+			getByName = typeof name === "string",
+
+			// We have to handle DOM nodes and JS objects differently because IE6-7
+			// can't GC object references properly across the DOM-JS boundary
+			isNode = elem.nodeType,
+
+			// Only DOM nodes need the global jQuery cache; JS object data is
+			// attached directly to the object so GC can occur automatically
+			cache = isNode ? jQuery.cache : elem,
+
+			// Only defining an ID for JS objects if its cache already exists allows
+			// the code to shortcut on the same path as a DOM node with no cache
+			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+		// Avoid doing any more work than we need to when trying to get data on an
+		// object that has no data at all
+		if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+			return;
+		}
+
+		if ( !id ) {
+			// Only DOM nodes need a new unique ID for each element since their data
+			// ends up in the global cache
+			if ( isNode ) {
+				elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
+			} else {
+				id = internalKey;
+			}
+		}
+
+		if ( !cache[ id ] ) {
+			cache[ id ] = {};
+
+			// Avoids exposing jQuery metadata on plain JS objects when the object
+			// is serialized using JSON.stringify
+			if ( !isNode ) {
+				cache[ id ].toJSON = jQuery.noop;
+			}
+		}
+
+		// An object can be passed to jQuery.data instead of a key/value pair; this gets
+		// shallow copied over onto the existing cache
+		if ( typeof name === "object" || typeof name === "function" ) {
+			if ( pvt ) {
+				cache[ id ] = jQuery.extend( cache[ id ], name );
+			} else {
+				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+			}
+		}
+
+		thisCache = cache[ id ];
+
+		// jQuery data() is stored in a separate object inside the object's internal data
+		// cache in order to avoid key collisions between internal data and user-defined
+		// data.
+		if ( !pvt ) {
+			if ( !thisCache.data ) {
+				thisCache.data = {};
+			}
+
+			thisCache = thisCache.data;
+		}
+
+		if ( data !== undefined ) {
+			thisCache[ jQuery.camelCase( name ) ] = data;
+		}
+
+		// Check for both converted-to-camel and non-converted data property names
+		// If a data property was specified
+		if ( getByName ) {
+
+			// First Try to find as-is property data
+			ret = thisCache[ name ];
+
+			// Test for null|undefined property data
+			if ( ret == null ) {
+
+				// Try to find the camelCased property
+				ret = thisCache[ jQuery.camelCase( name ) ];
+			}
+		} else {
+			ret = thisCache;
+		}
+
+		return ret;
+	},
+
+	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var thisCache, i, l,
+
+			isNode = elem.nodeType,
+
+			// See jQuery.data for more information
+			cache = isNode ? jQuery.cache : elem,
+			id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+		// If there is already no cache entry for this object, there is no
+		// purpose in continuing
+		if ( !cache[ id ] ) {
+			return;
+		}
+
+		if ( name ) {
+
+			thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+			if ( thisCache ) {
+
+				// Support array or space separated string names for data keys
+				if ( !jQuery.isArray( name ) ) {
+
+					// try the string as a key before any manipulation
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+
+						// split the camel cased version by spaces unless a key with the spaces exists
+						name = jQuery.camelCase( name );
+						if ( name in thisCache ) {
+							name = [ name ];
+						} else {
+							name = name.split(" ");
+						}
+					}
+				}
+
+				for ( i = 0, l = name.length; i < l; i++ ) {
+					delete thisCache[ name[i] ];
+				}
+
+				// If there is no data left in the cache, we want to continue
+				// and let the cache object itself get destroyed
+				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+					return;
+				}
+			}
+		}
+
+		// See jQuery.data for more information
+		if ( !pvt ) {
+			delete cache[ id ].data;
+
+			// Don't destroy the parent cache unless the internal data object
+			// had been the only thing left in it
+			if ( !isEmptyDataObject( cache[ id ] ) ) {
+				return;
+			}
+		}
+
+		// Destroy the cache
+		if ( isNode ) {
+			jQuery.cleanData( [ elem ], true );
+
+		// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+		} else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+			delete cache[ id ];
+
+		// When all else fails, null
+		} else {
+			cache[ id ] = null;
+		}
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return jQuery.data( elem, name, data, true );
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+		// nodes accept data unless otherwise specified; rejection can be conditional
+		return !noData || noData !== true && elem.getAttribute("classid") === noData;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var parts, part, attr, name, l,
+			elem = this[0],
+			i = 0,
+			data = null;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					attr = elem.attributes;
+					for ( l = attr.length; i < l; i++ ) {
+						name = attr[i].name;
+
+						if ( !name.indexOf( "data-" ) ) {
+							name = jQuery.camelCase( name.substring(5) );
+
+							dataAttr( elem, name, data[ name ] );
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		parts = key.split( ".", 2 );
+		parts[1] = parts[1] ? "." + parts[1] : "";
+		part = parts[1] + "!";
+
+		return jQuery.access( this, function( value ) {
+
+			if ( value === undefined ) {
+				data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+				// Try to fetch any internally stored data first
+				if ( data === undefined && elem ) {
+					data = jQuery.data( elem, key );
+					data = dataAttr( elem, key, data );
+				}
+
+				return data === undefined && parts[1] ?
+					this.data( parts[0] ) :
+					data;
+			}
+
+			parts[1] = value;
+			this.each(function() {
+				var self = jQuery( this );
+
+				self.triggerHandler( "setData" + part, parts );
+				jQuery.data( this, key, value );
+				self.triggerHandler( "changeData" + part, parts );
+			});
+		}, null, value, arguments.length > 1, null, false );
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				// Only convert to a number if it doesn't change the string
+				+data + "" === data ? +data :
+				rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	var name;
+	for ( name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray(data) ) {
+					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// not intended for public consumption - generates a queueHooks object, or returns the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				jQuery.removeData( elem, type + "queue", true );
+				jQuery.removeData( elem, key, true );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function( next, hooks ) {
+			var timeout = setTimeout( next, time );
+			hooks.stop = function() {
+				clearTimeout( timeout );
+			};
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while( i-- ) {
+			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var nodeHook, boolHook, fixSpecified,
+	rclass = /[\t\r\n]/g,
+	rreturn = /\r/g,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea|)$/i,
+	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+	getSetAttribute = jQuery.support.getSetAttribute;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	},
+
+	prop: function( name, value ) {
+		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	},
+
+	addClass: function( value ) {
+		var classNames, i, l, elem,
+			setClass, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			classNames = value.split( core_rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className && classNames.length === 1 ) {
+						elem.className = value;
+
+					} else {
+						setClass = " " + elem.className + " ";
+
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
+								setClass += classNames[ c ] + " ";
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var removes, className, elem, c, cl, i, l;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call(this, j, this.className) );
+			});
+		}
+		if ( (value && typeof value === "string") || value === undefined ) {
+			removes = ( value || "" ).split( core_rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+				if ( elem.nodeType === 1 && elem.className ) {
+
+					className = (" " + elem.className + " ").replace( rclass, " " );
+
+					// loop over each item in the removal list
+					for ( c = 0, cl = removes.length; c < cl; c++ ) {
+						// Remove until there is nothing to remove,
+						while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
+							className = className.replace( " " + removes[ c ] + " " , " " );
+						}
+					}
+					elem.className = value ? jQuery.trim( className ) : "";
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( core_rspace );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space separated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val,
+				self = jQuery(this);
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, self.val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map(val, function ( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				// attributes.value is undefined in Blackberry 4.7 but
+				// uses .value. See #6932
+				var val = elem.attributes.value;
+				return !val || val.specified ? elem.value : elem.text;
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, i, max, option,
+					index = elem.selectedIndex,
+					values = [],
+					options = elem.options,
+					one = elem.type === "select-one";
+
+				// Nothing was selected
+				if ( index < 0 ) {
+					return null;
+				}
+
+				// Loop through all the selected options
+				i = one ? index : 0;
+				max = one ? index + 1 : options.length;
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// Don't return options that are disabled or in a disabled optgroup
+					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+				if ( one && !values.length && options.length ) {
+					return jQuery( options[ index ] ).val();
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var values = jQuery.makeArray( value );
+
+				jQuery(elem).find("option").each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	},
+
+	// Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
+	attrFn: {},
+
+	attr: function( elem, name, value, pass ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
+			return jQuery( elem )[ name ]( value );
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === "undefined" ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( notxml ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+				return;
+
+			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+
+			ret = elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret === null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var propName, attrNames, name, isBool,
+			i = 0;
+
+		if ( value && elem.nodeType === 1 ) {
+
+			attrNames = value.split( core_rspace );
+
+			for ( ; i < attrNames.length; i++ ) {
+				name = attrNames[ i ];
+
+				if ( name ) {
+					propName = jQuery.propFix[ name ] || name;
+					isBool = rboolean.test( name );
+
+					// See #9699 for explanation of this approach (setting first, then removal)
+					// Do not do this for boolean attributes (see #10870)
+					if ( !isBool ) {
+						jQuery.attr( elem, name, "" );
+					}
+					elem.removeAttribute( getSetAttribute ? name : propName );
+
+					// Set corresponding property to false for boolean attributes
+					if ( isBool && propName in elem ) {
+						elem[ propName ] = false;
+					}
+				}
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to it's default in case type is set after value
+					// This is for element creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		},
+		// Use the value property for back compat
+		// Use the nodeHook for button elements in IE6/7 (#1954)
+		value: {
+			get: function( elem, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.get( elem, name );
+				}
+				return name in elem ?
+					elem.value :
+					null;
+			},
+			set: function( elem, value, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.set( elem, value, name );
+				}
+				// Does not return so that setAttribute is also used
+				elem.value = value;
+			}
+		}
+	},
+
+	propFix: {
+		tabindex: "tabIndex",
+		readonly: "readOnly",
+		"for": "htmlFor",
+		"class": "className",
+		maxlength: "maxLength",
+		cellspacing: "cellSpacing",
+		cellpadding: "cellPadding",
+		rowspan: "rowSpan",
+		colspan: "colSpan",
+		usemap: "useMap",
+		frameborder: "frameBorder",
+		contenteditable: "contentEditable"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				return ( elem[ name ] = value );
+			}
+
+		} else {
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+				return ret;
+
+			} else {
+				return elem[ name ];
+			}
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				var attributeNode = elem.getAttributeNode("tabindex");
+
+				return attributeNode && attributeNode.specified ?
+					parseInt( attributeNode.value, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+		}
+	}
+});
+
+// Hook for boolean attributes
+boolHook = {
+	get: function( elem, name ) {
+		// Align boolean attributes with corresponding properties
+		// Fall back to attribute presence where some booleans are not supported
+		var attrNode,
+			property = jQuery.prop( elem, name );
+		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+			name.toLowerCase() :
+			undefined;
+	},
+	set: function( elem, value, name ) {
+		var propName;
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			// value is true since we know at this point it's type boolean and not false
+			// Set boolean attributes to the same name and set the DOM property
+			propName = jQuery.propFix[ name ] || name;
+			if ( propName in elem ) {
+				// Only set the IDL specifically if it already exists on the element
+				elem[ propName ] = true;
+			}
+
+			elem.setAttribute( name, name.toLowerCase() );
+		}
+		return name;
+	}
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	fixSpecified = {
+		name: true,
+		id: true,
+		coords: true
+	};
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret;
+			ret = elem.getAttributeNode( name );
+			return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
+				ret.value :
+				undefined;
+		},
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				ret = document.createAttribute( name );
+				elem.setAttributeNode( ret );
+			}
+			return ( ret.value = value + "" );
+		}
+	};
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		});
+	});
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		get: nodeHook.get,
+		set: function( elem, value, name ) {
+			if ( value === "" ) {
+				value = "false";
+			}
+			nodeHook.set( elem, value, name );
+		}
+	};
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			get: function( elem ) {
+				var ret = elem.getAttribute( name, 2 );
+				return ret === null ? undefined : ret;
+			}
+		});
+	});
+}
+
+if ( !jQuery.support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Normalize to lowercase since IE uppercases css property names
+			return elem.style.cssText.toLowerCase() || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = value + "" );
+		}
+	};
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	});
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+	jQuery.each([ "radio", "checkbox" ], function() {
+		jQuery.valHooks[ this ] = {
+			get: function( elem ) {
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				return elem.getAttribute("value") === null ? "on" : elem.value;
+			}
+		};
+	});
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	});
+});
+var rformElems = /^(?:textarea|input|select)$/i,
+	rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
+	rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	hoverHack = function( events ) {
+		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+	};
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var elemData, eventHandle, events,
+			t, tns, type, namespaces, handleObj,
+			handleObjIn, handlers, special;
+
+		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
+		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		events = elemData.events;
+		if ( !events ) {
+			elemData.events = events = {};
+		}
+		eventHandle = elemData.handle;
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = jQuery.trim( hoverHack(types) ).split( " " );
+		for ( t = 0; t < types.length; t++ ) {
+
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = tns[1];
+			namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: tns[1],
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			handlers = events[ type ];
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var t, tns, type, origType, namespaces, origCount,
+			j, events, special, eventType, handleObj,
+			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+		for ( t = 0; t < types.length; t++ ) {
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tns[1];
+			namespaces = tns[2];
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector? special.delegateType : special.bindType ) || type;
+			eventType = events[ type ] || [];
+			origCount = eventType.length;
+			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+
+			// Remove matching events
+			for ( j = 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					 ( !handler || handler.guid === handleObj.guid ) &&
+					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					eventType.splice( j--, 1 );
+
+					if ( handleObj.selector ) {
+						eventType.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( eventType.length === 0 && origCount !== eventType.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery.removeData( elem, "events", true );
+		}
+	},
+
+	// Events that are safe to short-circuit if no handlers are attached.
+	// Native DOM events should not be added, they may have inline handlers.
+	customEvent: {
+		"getData": true,
+		"setData": true,
+		"changeData": true
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		// Don't do events on text and comment nodes
+		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+			return;
+		}
+
+		// Event object or event type
+		var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
+			type = event.type || event,
+			namespaces = [];
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf( "!" ) >= 0 ) {
+			// Exclusive events trigger only for the exact event (no namespaces)
+			type = type.slice(0, -1);
+			exclusive = true;
+		}
+
+		if ( type.indexOf( "." ) >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+
+		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+			// No jQuery handlers for this event type, and it can't have inline handlers
+			return;
+		}
+
+		// Caller can pass in an Event, Object, or just an event type string
+		event = typeof event === "object" ?
+			// jQuery.Event object
+			event[ jQuery.expando ] ? event :
+			// Object literal
+			new jQuery.Event( type, event ) :
+			// Just the event type (string)
+			new jQuery.Event( type );
+
+		event.type = type;
+		event.isTrigger = true;
+		event.exclusive = exclusive;
+		event.namespace = namespaces.join( "." );
+		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+		// Handle a global trigger
+		if ( !elem ) {
+
+			// TODO: Stop taunting the data cache; remove global events and always attach to document
+			cache = jQuery.cache;
+			for ( i in cache ) {
+				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+				}
+			}
+			return;
+		}
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data != null ? jQuery.makeArray( data ) : [];
+		data.unshift( event );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		eventPath = [[ elem, special.bindType || type ]];
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+			for ( old = elem; cur; cur = cur.parentNode ) {
+				eventPath.push([ cur, bubbleType ]);
+				old = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( old === (elem.ownerDocument || document) ) {
+				eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+			}
+		}
+
+		// Fire handlers on the event path
+		for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+			cur = eventPath[i][0];
+			event.type = eventPath[i][1];
+
+			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+			// Note that this is a bare JS function and not a jQuery handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+				event.preventDefault();
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Can't use an .isFunction() check here because IE6/7 fails that test.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				// IE<9 dies on focus/blur to hidden element (#1486)
+				if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					old = elem[ ontype ];
+
+					if ( old ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					elem[ type ]();
+					jQuery.event.triggered = undefined;
+
+					if ( old ) {
+						elem[ ontype ] = old;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event || window.event );
+
+		var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
+			handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+			delegateCount = handlers.delegateCount,
+			args = core_slice.call( arguments ),
+			run_all = !event.exclusive && !event.namespace,
+			special = jQuery.event.special[ event.type ] || {},
+			handlerQueue = [];
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers that should run if there are delegated events
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && !(event.button && event.type === "click") ) {
+
+			for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+
+				// Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.disabled !== true || event.type !== "click" ) {
+					selMatch = {};
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+						sel = handleObj.selector;
+
+						if ( selMatch[ sel ] === undefined ) {
+							selMatch[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( selMatch[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, matches: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( handlers.length > delegateCount ) {
+			handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+		}
+
+		// Run delegates first; they may want to stop propagation beneath us
+		for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+			matched = handlerQueue[ i ];
+			event.currentTarget = matched.elem;
+
+			for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+				handleObj = matched.matches[ j ];
+
+				// Triggered event must either 1) be non-exclusive and have no namespace, or
+				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+				if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.data = handleObj.data;
+					event.handleObj = handleObj;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						event.result = ret;
+						if ( ret === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+	props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var eventDoc, doc, body,
+				button = original.button,
+				fromElement = original.fromElement;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add relatedTarget, if necessary
+			if ( !event.relatedTarget && fromElement ) {
+				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop,
+			originalEvent = event,
+			fixHook = jQuery.event.fixHooks[ event.type ] || {},
+			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = jQuery.Event( originalEvent );
+
+		for ( i = copy.length; i; ) {
+			prop = copy[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+		if ( !event.target ) {
+			event.target = originalEvent.srcElement || document;
+		}
+
+		// Target should not be a text node (#504, Safari)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
+		event.metaKey = !!event.metaKey;
+
+		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+
+		focus: {
+			delegateType: "focusin"
+		},
+		blur: {
+			delegateType: "focusout"
+		},
+
+		beforeunload: {
+			setup: function( data, namespaces, eventHandle ) {
+				// We only want to do this special case on windows
+				if ( jQuery.isWindow( this ) ) {
+					this.onbeforeunload = eventHandle;
+				}
+			},
+
+			teardown: function( namespaces, eventHandle ) {
+				if ( this.onbeforeunload === eventHandle ) {
+					this.onbeforeunload = null;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{ type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} :
+	function( elem, type, handle ) {
+		var name = "on" + type;
+
+		if ( elem.detachEvent ) {
+
+			// #8545, #7054, preventing memory leaks for custom events in IE6-8 –
+			// detachEvent needed property on element, by name of that event, to properly expose it to GC
+			if ( typeof elem[ name ] === "undefined" ) {
+				elem[ name ] = null;
+			}
+
+			elem.detachEvent( name, handle );
+		}
+	};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+	return false;
+}
+function returnTrue() {
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+
+		// if preventDefault exists run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// otherwise set the returnValue property of the original event to false (IE)
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		// if stopPropagation exists run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj,
+				selector = handleObj.selector;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Lazy-add a submit handler when a descendant form may potentially be submitted
+			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+				// Node name check avoids a VML-related crash in IE (#9807)
+				var elem = e.target,
+					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+				if ( form && !jQuery._data( form, "_submit_attached" ) ) {
+					jQuery.event.add( form, "submit._submit", function( event ) {
+						event._submit_bubble = true;
+					});
+					jQuery._data( form, "_submit_attached", true );
+				}
+			});
+			// return undefined since we don't need an event listener
+		},
+
+		postDispatch: function( event ) {
+			// If form was submitted by the user, bubble the event up the tree
+			if ( event._submit_bubble ) {
+				delete event._submit_bubble;
+				if ( this.parentNode && !event.isTrigger ) {
+					jQuery.event.simulate( "submit", this.parentNode, event, true );
+				}
+			}
+		},
+
+		teardown: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+			jQuery.event.remove( this, "._submit" );
+		}
+	};
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+	jQuery.event.special.change = {
+
+		setup: function() {
+
+			if ( rformElems.test( this.nodeName ) ) {
+				// IE doesn't fire change on a check/radio until blur; trigger it on click
+				// after a propertychange. Eat the blur-change in special.change.handle.
+				// This still fires onchange a second time for check/radio after blur.
+				if ( this.type === "checkbox" || this.type === "radio" ) {
+					jQuery.event.add( this, "propertychange._change", function( event ) {
+						if ( event.originalEvent.propertyName === "checked" ) {
+							this._just_changed = true;
+						}
+					});
+					jQuery.event.add( this, "click._change", function( event ) {
+						if ( this._just_changed && !event.isTrigger ) {
+							this._just_changed = false;
+						}
+						// Allow triggered, simulated change events (#11500)
+						jQuery.event.simulate( "change", this, event, true );
+					});
+				}
+				return false;
+			}
+			// Delegated event; lazy-add a change handler on descendant inputs
+			jQuery.event.add( this, "beforeactivate._change", function( e ) {
+				var elem = e.target;
+
+				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
+					jQuery.event.add( elem, "change._change", function( event ) {
+						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+							jQuery.event.simulate( "change", this.parentNode, event, true );
+						}
+					});
+					jQuery._data( elem, "_change_attached", true );
+				}
+			});
+		},
+
+		handle: function( event ) {
+			var elem = event.target;
+
+			// Swallow native change events from checkbox/radio, we already triggered them above
+			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+				return event.handleObj.handler.apply( this, arguments );
+			}
+		},
+
+		teardown: function() {
+			jQuery.event.remove( this, "._change" );
+
+			return !rformElems.test( this.nodeName );
+		}
+	};
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler while someone wants focusin/focusout
+		var attaches = 0,
+			handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				if ( attaches++ === 0 ) {
+					document.addEventListener( orig, handler, true );
+				}
+			},
+			teardown: function() {
+				if ( --attaches === 0 ) {
+					document.removeEventListener( orig, handler, true );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var origFn, type;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) { // && selector != null
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	live: function( types, data, fn ) {
+		jQuery( this.context ).on( types, this.selector, data, fn );
+		return this;
+	},
+	die: function( types, fn ) {
+		jQuery( this.context ).off( types, this.selector || "**", fn );
+		return this;
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		if ( this[0] ) {
+			return jQuery.event.trigger( type, data, this[0], true );
+		}
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments,
+			guid = fn.guid || jQuery.guid++,
+			i = 0,
+			toggler = function( event ) {
+				// Figure out which function to execute
+				var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+				jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+				// Make sure that clicks stop
+				event.preventDefault();
+
+				// and execute the function
+				return args[ lastToggle ].apply( this, arguments ) || false;
+			};
+
+		// link all the functions, so any of them can unbind this click handler
+		toggler.guid = guid;
+		while ( i < args.length ) {
+			args[ i++ ].guid = guid;
+		}
+
+		return this.click( toggler );
+	},
+
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	}
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		if ( fn == null ) {
+			fn = data;
+			data = null;
+		}
+
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+
+	if ( rkeyEvent.test( name ) ) {
+		jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+	}
+
+	if ( rmouseEvent.test( name ) ) {
+		jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+	}
+});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function( window, undefined ) {
+
+var cachedruns,
+	assertGetIdNotName,
+	Expr,
+	getText,
+	isXML,
+	contains,
+	compile,
+	sortOrder,
+	hasDuplicate,
+	outermostContext,
+
+	baseHasDuplicate = true,
+	strundefined = "undefined",
+
+	expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
+
+	Token = String,
+	document = window.document,
+	docElem = document.documentElement,
+	dirruns = 0,
+	done = 0,
+	pop = [].pop,
+	push = [].push,
+	slice = [].slice,
+	// Use a stripped-down indexOf if a native one is unavailable
+	indexOf = [].indexOf || function( elem ) {
+		var i = 0,
+			len = this.length;
+		for ( ; i < len; i++ ) {
+			if ( this[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	// Augment a function for special use by Sizzle
+	markFunction = function( fn, value ) {
+		fn[ expando ] = value == null || value;
+		return fn;
+	},
+
+	createCache = function() {
+		var cache = {},
+			keys = [];
+
+		return markFunction(function( key, value ) {
+			// Only keep the most recent entries
+			if ( keys.push( key ) > Expr.cacheLength ) {
+				delete cache[ keys.shift() ];
+			}
+
+			return (cache[ key ] = value);
+		}, cache );
+	},
+
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+
+	// Regex
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+	operators = "([*^$|!~]?=)",
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+		"*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+	// Prefer arguments not in parens/brackets,
+	//   then attribute selectors and non-pseudos (denoted by :),
+	//   then anything else
+	// These preferences are here to reduce the number of selectors
+	//   needing tokenize in the PSEUDO preFilter
+	pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
+
+	// For matchExpr.POS and matchExpr.needsContext
+	pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
+		"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+	rpseudo = new RegExp( pseudos ),
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
+
+	rnot = /^:not/,
+	rsibling = /[\x20\t\r\n\f]*[+~]/,
+	rendsWithNot = /:not\($/,
+
+	rheader = /h\d/i,
+	rinputs = /input|select|textarea|button/i,
+
+	rbackslash = /\\(?!\\)/g,
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"POS": new RegExp( pos, "i" ),
+		"CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		// For use in libraries implementing .is()
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
+	},
+
+	// Support
+
+	// Used for testing something on an element
+	assert = function( fn ) {
+		var div = document.createElement("div");
+
+		try {
+			return fn( div );
+		} catch (e) {
+			return false;
+		} finally {
+			// release memory in IE
+			div = null;
+		}
+	},
+
+	// Check if getElementsByTagName("*") returns only elements
+	assertTagNameNoComments = assert(function( div ) {
+		div.appendChild( document.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	}),
+
+	// Check if getAttribute returns normalized href attributes
+	assertHrefNotNormalized = assert(function( div ) {
+		div.innerHTML = "<a href='#'></a>";
+		return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+			div.firstChild.getAttribute("href") === "#";
+	}),
+
+	// Check if attributes should be retrieved by attribute nodes
+	assertAttributes = assert(function( div ) {
+		div.innerHTML = "<select></select>";
+		var type = typeof div.lastChild.getAttribute("multiple");
+		// IE8 returns a string for some attributes even when not present
+		return type !== "boolean" && type !== "string";
+	}),
+
+	// Check if getElementsByClassName can be trusted
+	assertUsableClassName = assert(function( div ) {
+		// Opera can't find a second classname (in 9.6)
+		div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
+		if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+			return false;
+		}
+
+		// Safari 3.2 caches class attributes and doesn't catch changes
+		div.lastChild.className = "e";
+		return div.getElementsByClassName("e").length === 2;
+	}),
+
+	// Check if getElementById returns elements by name
+	// Check if getElementsByName privileges form controls or returns elements by ID
+	assertUsableName = assert(function( div ) {
+		// Inject content
+		div.id = expando + 0;
+		div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
+		docElem.insertBefore( div, docElem.firstChild );
+
+		// Test
+		var pass = document.getElementsByName &&
+			// buggy browsers will return fewer than the correct 2
+			document.getElementsByName( expando ).length === 2 +
+			// buggy browsers will return more than the correct 0
+			document.getElementsByName( expando + 0 ).length;
+		assertGetIdNotName = !document.getElementById( expando );
+
+		// Cleanup
+		docElem.removeChild( div );
+
+		return pass;
+	});
+
+// If slice is not available, provide a backup
+try {
+	slice.call( docElem.childNodes, 0 )[0].nodeType;
+} catch ( e ) {
+	slice = function( i ) {
+		var elem,
+			results = [];
+		for ( ; (elem = this[i]); i++ ) {
+			results.push( elem );
+		}
+		return results;
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	results = results || [];
+	context = context || document;
+	var match, elem, xml, m,
+		nodeType = context.nodeType;
+
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	if ( nodeType !== 1 && nodeType !== 9 ) {
+		return [];
+	}
+
+	xml = isXML( context );
+
+	if ( !xml && !seed ) {
+		if ( (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {
+				push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+				return results;
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );
+}
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	return Sizzle( expr, null, null, [ elem ] ).length > 0;
+};
+
+// Returns a function to use in pseudos for input types
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+// Returns a function to use in pseudos for buttons
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+// Returns a function to use in pseudos for positionals
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( nodeType ) {
+		if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+			// Use textContent for elements
+			// innerText usage removed for consistency of new lines (see #11153)
+			if ( typeof elem.textContent === "string" ) {
+				return elem.textContent;
+			} else {
+				// Traverse its children
+				for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+					ret += getText( elem );
+				}
+			}
+		} else if ( nodeType === 3 || nodeType === 4 ) {
+			return elem.nodeValue;
+		}
+		// Do not include comment or processing instruction nodes
+	} else {
+
+		// If no nodeType, this is expected to be an array
+		for ( ; (node = elem[i]); i++ ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	}
+	return ret;
+};
+
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+// Element contains another
+contains = Sizzle.contains = docElem.contains ?
+	function( a, b ) {
+		var adown = a.nodeType === 9 ? a.documentElement : a,
+			bup = b && b.parentNode;
+		return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
+	} :
+	docElem.compareDocumentPosition ?
+	function( a, b ) {
+		return b && !!( a.compareDocumentPosition( b ) & 16 );
+	} :
+	function( a, b ) {
+		while ( (b = b.parentNode) ) {
+			if ( b === a ) {
+				return true;
+			}
+		}
+		return false;
+	};
+
+Sizzle.attr = function( elem, name ) {
+	var val,
+		xml = isXML( elem );
+
+	if ( !xml ) {
+		name = name.toLowerCase();
+	}
+	if ( (val = Expr.attrHandle[ name ]) ) {
+		return val( elem );
+	}
+	if ( xml || assertAttributes ) {
+		return elem.getAttribute( name );
+	}
+	val = elem.getAttributeNode( name );
+	return val ?
+		typeof elem[ name ] === "boolean" ?
+			elem[ name ] ? name : null :
+			val.specified ? val.value : null :
+		null;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	// IE6/7 return a modified href
+	attrHandle: assertHrefNotNormalized ?
+		{} :
+		{
+			"href": function( elem ) {
+				return elem.getAttribute( "href", 2 );
+			},
+			"type": function( elem ) {
+				return elem.getAttribute("type");
+			}
+		},
+
+	find: {
+		"ID": assertGetIdNotName ?
+			function( id, context, xml ) {
+				if ( typeof context.getElementById !== strundefined && !xml ) {
+					var m = context.getElementById( id );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					return m && m.parentNode ? [m] : [];
+				}
+			} :
+			function( id, context, xml ) {
+				if ( typeof context.getElementById !== strundefined && !xml ) {
+					var m = context.getElementById( id );
+
+					return m ?
+						m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+							[m] :
+							undefined :
+						[];
+				}
+			},
+
+		"TAG": assertTagNameNoComments ?
+			function( tag, context ) {
+				if ( typeof context.getElementsByTagName !== strundefined ) {
+					return context.getElementsByTagName( tag );
+				}
+			} :
+			function( tag, context ) {
+				var results = context.getElementsByTagName( tag );
+
+				// Filter out possible comments
+				if ( tag === "*" ) {
+					var elem,
+						tmp = [],
+						i = 0;
+
+					for ( ; (elem = results[i]); i++ ) {
+						if ( elem.nodeType === 1 ) {
+							tmp.push( elem );
+						}
+					}
+
+					return tmp;
+				}
+				return results;
+			},
+
+		"NAME": assertUsableName && function( tag, context ) {
+			if ( typeof context.getElementsByName !== strundefined ) {
+				return context.getElementsByName( name );
+			}
+		},
+
+		"CLASS": assertUsableClassName && function( className, context, xml ) {
+			if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
+				return context.getElementsByClassName( className );
+			}
+		}
+	},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( rbackslash, "" );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				3 xn-component of xn+y argument ([+-]?\d*n|)
+				4 sign of xn-component
+				5 x of xn-component
+				6 sign of y-component
+				7 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1] === "nth" ) {
+				// nth-child requires argument
+				if ( !match[2] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
+				match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[2] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var unquoted, excess;
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			if ( match[3] ) {
+				match[2] = match[3];
+			} else if ( (unquoted = match[4]) ) {
+				// Only check arguments that contain a pseudo
+				if ( rpseudo.test(unquoted) &&
+					// Get excess from tokenize (recursively)
+					(excess = tokenize( unquoted, true )) &&
+					// advance to the next closing parenthesis
+					(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+					// excess is a negative index
+					unquoted = unquoted.slice( 0, excess );
+					match[0] = match[0].slice( 0, excess );
+				}
+				match[2] = unquoted;
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+		"ID": assertGetIdNotName ?
+			function( id ) {
+				id = id.replace( rbackslash, "" );
+				return function( elem ) {
+					return elem.getAttribute("id") === id;
+				};
+			} :
+			function( id ) {
+				id = id.replace( rbackslash, "" );
+				return function( elem ) {
+					var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+					return node && node.value === id;
+				};
+			},
+
+		"TAG": function( nodeName ) {
+			if ( nodeName === "*" ) {
+				return function() { return true; };
+			}
+			nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();
+
+			return function( elem ) {
+				return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+			};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ expando ][ className ];
+			if ( !pattern ) {
+				pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") );
+			}
+			return function( elem ) {
+				return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+			};
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem, context ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.substr( result.length - check.length ) === check :
+					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, argument, first, last ) {
+
+			if ( type === "nth" ) {
+				return function( elem ) {
+					var node, diff,
+						parent = elem.parentNode;
+
+					if ( first === 1 && last === 0 ) {
+						return true;
+					}
+
+					if ( parent ) {
+						diff = 0;
+						for ( node = parent.firstChild; node; node = node.nextSibling ) {
+							if ( node.nodeType === 1 ) {
+								diff++;
+								if ( elem === node ) {
+									break;
+								}
+							}
+						}
+					}
+
+					// Incorporate the offset (or cast to NaN), then check against cycle size
+					diff -= last;
+					return diff === first || ( diff % first === 0 && diff / first >= 0 );
+				};
+			}
+
+			return function( elem ) {
+				var node = elem;
+
+				switch ( type ) {
+					case "only":
+					case "first":
+						while ( (node = node.previousSibling) ) {
+							if ( node.nodeType === 1 ) {
+								return false;
+							}
+						}
+
+						if ( type === "first" ) {
+							return true;
+						}
+
+						node = elem;
+
+						/* falls through */
+					case "last":
+						while ( (node = node.nextSibling) ) {
+							if ( node.nodeType === 1 ) {
+								return false;
+							}
+						}
+
+						return true;
+				}
+			};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf.call( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+			//   not comment, processing instructions, or others
+			// Thanks to Diego Perini for the nodeName shortcut
+			//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+			var nodeType;
+			elem = elem.firstChild;
+			while ( elem ) {
+				if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {
+					return false;
+				}
+				elem = elem.nextSibling;
+			}
+			return true;
+		},
+
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"text": function( elem ) {
+			var type, attr;
+			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+			// use getAttribute instead to test this case
+			return elem.nodeName.toLowerCase() === "input" &&
+				(type = elem.type) === "text" &&
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
+		},
+
+		// Input types
+		"radio": createInputPseudo("radio"),
+		"checkbox": createInputPseudo("checkbox"),
+		"file": createInputPseudo("file"),
+		"password": createInputPseudo("password"),
+		"image": createInputPseudo("image"),
+
+		"submit": createButtonPseudo("submit"),
+		"reset": createButtonPseudo("reset"),
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"focus": function( elem ) {
+			var doc = elem.ownerDocument;
+			return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
+		},
+
+		"active": function( elem ) {
+			return elem === elem.ownerDocument.activeElement;
+		},
+
+		// Positional types
+		"first": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			for ( var i = 0; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			for ( var i = 1; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+function siblingCheck( a, b, ret ) {
+	if ( a === b ) {
+		return ret;
+	}
+
+	var cur = a.nextSibling;
+
+	while ( cur ) {
+		if ( cur === b ) {
+			return -1;
+		}
+
+		cur = cur.nextSibling;
+	}
+
+	return 1;
+}
+
+sortOrder = docElem.compareDocumentPosition ?
+	function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
+			a.compareDocumentPosition :
+			a.compareDocumentPosition(b) & 4
+		) ? -1 : 1;
+	} :
+	function( a, b ) {
+		// The nodes are identical, we can exit early
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+
+		// Fallback to using sourceIndex (in IE) if it's available on both nodes
+		} else if ( a.sourceIndex && b.sourceIndex ) {
+			return a.sourceIndex - b.sourceIndex;
+		}
+
+		var al, bl,
+			ap = [],
+			bp = [],
+			aup = a.parentNode,
+			bup = b.parentNode,
+			cur = aup;
+
+		// If the nodes are siblings (or identical) we can do a quick check
+		if ( aup === bup ) {
+			return siblingCheck( a, b );
+
+		// If no parents were found then the nodes are disconnected
+		} else if ( !aup ) {
+			return -1;
+
+		} else if ( !bup ) {
+			return 1;
+		}
+
+		// Otherwise they're somewhere else in the tree so we need
+		// to build up a full list of the parentNodes for comparison
+		while ( cur ) {
+			ap.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		cur = bup;
+
+		while ( cur ) {
+			bp.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		al = ap.length;
+		bl = bp.length;
+
+		// Start walking down the tree looking for a discrepancy
+		for ( var i = 0; i < al && i < bl; i++ ) {
+			if ( ap[i] !== bp[i] ) {
+				return siblingCheck( ap[i], bp[i] );
+			}
+		}
+
+		// We ended someplace up the tree so do a sibling check
+		return i === al ?
+			siblingCheck( a, bp[i], -1 ) :
+			siblingCheck( ap[i], b, 1 );
+	};
+
+// Always assume the presence of duplicates if sort doesn't
+// pass them to our comparison function (as in Google Chrome).
+[0, 0].sort( sortOrder );
+baseHasDuplicate = !hasDuplicate;
+
+// Document sorting and removing duplicates
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		i = 1;
+
+	hasDuplicate = baseHasDuplicate;
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		for ( ; (elem = results[i]); i++ ) {
+			if ( elem === results[ i - 1 ] ) {
+				results.splice( i--, 1 );
+			}
+		}
+	}
+
+	return results;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+function tokenize( selector, parseOnly ) {
+	var matched, match, tokens, type, soFar, groups, preFilters,
+		cached = tokenCache[ expando ][ selector ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				soFar = soFar.slice( match[0].length );
+			}
+			groups.push( tokens = [] );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			tokens.push( matched = new Token( match.shift() ) );
+			soFar = soFar.slice( matched.length );
+
+			// Cast descendant combinators to space
+			matched.type = match[0].replace( rtrim, " " );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				// The last two arguments here are (context, xml) for backCompat
+				(match = preFilters[ type ]( match, document, true ))) ) {
+
+				tokens.push( matched = new Token( match.shift() ) );
+				soFar = soFar.slice( matched.length );
+				matched.type = type;
+				matched.matches = match;
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && combinator.dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( checkNonElements || elem.nodeType === 1  ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( !xml ) {
+				var cache,
+					dirkey = dirruns + " " + doneName + " ",
+					cachedkey = dirkey + cachedruns;
+				while ( (elem = elem[ dir ]) ) {
+					if ( checkNonElements || elem.nodeType === 1 ) {
+						if ( (cache = elem[ expando ]) === cachedkey ) {
+							return elem.sizset;
+						} else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
+							if ( elem.sizset ) {
+								return elem;
+							}
+						} else {
+							elem[ expando ] = cachedkey;
+							if ( matcher( elem, context, xml ) ) {
+								elem.sizset = true;
+								return elem;
+							}
+							elem.sizset = false;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( checkNonElements || elem.nodeType === 1 ) {
+						if ( matcher( elem, context, xml ) ) {
+							return elem;
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		// Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
+		if ( seed && postFinder ) {
+			return;
+		}
+
+		var i, elem, postFilterIn,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			postFilterIn = condense( matcherOut, postMap );
+			postFilter( postFilterIn, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = postFilterIn.length;
+			while ( i-- ) {
+				if ( (elem = postFilterIn[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		// Keep seed and results synchronized
+		if ( seed ) {
+			// Ignore postFinder because it can't coexist with seed
+			i = preFilter && matcherOut.length;
+			while ( i-- ) {
+				if ( (elem = matcherOut[i]) ) {
+					seed[ preMap[i] ] = !(results[ preMap[i] ] = elem);
+				}
+			}
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf.call( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
+		} else {
+			// The concatenated values are (context, xml) for backCompat
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && tokens.join("")
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, expandContext ) {
+			var elem, j, matcher,
+				setMatched = [],
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				outermost = expandContext != null,
+				contextBackup = outermostContext,
+				// We must always have either seed elements or context
+				elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+				// Nested matchers should use non-integer dirruns
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+				cachedruns = superMatcher.el;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			for ( ; (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					for ( j = 0; (matcher = elementMatchers[j]); j++ ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+						cachedruns = ++superMatcher.el;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				for ( j = 0; (matcher = setMatchers[j]); j++ ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	superMatcher.el = 0;
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ expando ][ selector ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !group ) {
+			group = tokenize( selector );
+		}
+		i = group.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( group[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+	}
+	return cached;
+};
+
+function multipleContexts( selector, contexts, results, seed ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results, seed );
+	}
+	return results;
+}
+
+function select( selector, context, results, seed, xml ) {
+	var i, tokens, token, type, find,
+		match = tokenize( selector ),
+		j = match.length;
+
+	if ( !seed ) {
+		// Try to minimize operations if there is only one group
+		if ( match.length === 1 ) {
+
+			// Take a shortcut and set the context if the root selector is an ID
+			tokens = match[0] = match[0].slice( 0 );
+			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+					context.nodeType === 9 && !xml &&
+					Expr.relative[ tokens[1].type ] ) {
+
+				context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];
+				if ( !context ) {
+					return results;
+				}
+
+				selector = selector.slice( tokens.shift().length );
+			}
+
+			// Fetch a seed set for right-to-left matching
+			for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {
+				token = tokens[i];
+
+				// Abort if we hit a combinator
+				if ( Expr.relative[ (type = token.type) ] ) {
+					break;
+				}
+				if ( (find = Expr.find[ type ]) ) {
+					// Search, expanding context for leading sibling combinators
+					if ( (seed = find(
+						token.matches[0].replace( rbackslash, "" ),
+						rsibling.test( tokens[0].type ) && context.parentNode || context,
+						xml
+					)) ) {
+
+						// If seed is empty or no tokens remain, we can return early
+						tokens.splice( i, 1 );
+						selector = seed.length && tokens.join("");
+						if ( !selector ) {
+							push.apply( results, slice.call( seed, 0 ) );
+							return results;
+						}
+
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function
+	// Provide `match` to avoid retokenization if we modified the selector above
+	compile( selector, match )(
+		seed,
+		context,
+		xml,
+		results,
+		rsibling.test( selector )
+	);
+	return results;
+}
+
+if ( document.querySelectorAll ) {
+	(function() {
+		var disconnectedMatch,
+			oldSelect = select,
+			rescape = /'|\\/g,
+			rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+			// qSa(:focus) reports false when true (Chrome 21),
+			// A support test would require too much code (would include document ready)
+			rbuggyQSA = [":focus"],
+
+			// matchesSelector(:focus) reports false when true (Chrome 21),
+			// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+			// A support test would require too much code (would include document ready)
+			// just skip matchesSelector for :active
+			rbuggyMatches = [ ":active", ":focus" ],
+			matches = docElem.matchesSelector ||
+				docElem.mozMatchesSelector ||
+				docElem.webkitMatchesSelector ||
+				docElem.oMatchesSelector ||
+				docElem.msMatchesSelector;
+
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explictly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			div.innerHTML = "<select><option selected=''></option></select>";
+
+			// IE8 - Some boolean attributes are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here (do not put tests after this one)
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+		});
+
+		assert(function( div ) {
+
+			// Opera 10-12/IE9 - ^= $= *= and empty values
+			// Should not select anything
+			div.innerHTML = "<p test=''></p>";
+			if ( div.querySelectorAll("[test^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here (do not put tests after this one)
+			div.innerHTML = "<input type='hidden'/>";
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push(":enabled", ":disabled");
+			}
+		});
+
+		// rbuggyQSA always contains :focus, so no need for a length check
+		rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );
+
+		select = function( selector, context, results, seed, xml ) {
+			// Only use querySelectorAll when not filtering,
+			// when this is not xml,
+			// and when no QSA bugs apply
+			if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+				var groups, i,
+					old = true,
+					nid = expando,
+					newContext = context,
+					newSelector = context.nodeType === 9 && selector;
+
+				// qSA works strangely on Element-rooted queries
+				// We can work around this by specifying an extra ID on the root
+				// and working up from there (Thanks to Andrew Dupont for the technique)
+				// IE 8 doesn't work on object elements
+				if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+					groups = tokenize( selector );
+
+					if ( (old = context.getAttribute("id")) ) {
+						nid = old.replace( rescape, "\\$&" );
+					} else {
+						context.setAttribute( "id", nid );
+					}
+					nid = "[id='" + nid + "'] ";
+
+					i = groups.length;
+					while ( i-- ) {
+						groups[i] = nid + groups[i].join("");
+					}
+					newContext = rsibling.test( selector ) && context.parentNode || context;
+					newSelector = groups.join(",");
+				}
+
+				if ( newSelector ) {
+					try {
+						push.apply( results, slice.call( newContext.querySelectorAll(
+							newSelector
+						), 0 ) );
+						return results;
+					} catch(qsaError) {
+					} finally {
+						if ( !old ) {
+							context.removeAttribute("id");
+						}
+					}
+				}
+			}
+
+			return oldSelect( selector, context, results, seed, xml );
+		};
+
+		if ( matches ) {
+			assert(function( div ) {
+				// Check to see if it's possible to do matchesSelector
+				// on a disconnected node (IE 9)
+				disconnectedMatch = matches.call( div, "div" );
+
+				// This should fail with an exception
+				// Gecko does not error, returns false instead
+				try {
+					matches.call( div, "[test!='']:sizzle" );
+					rbuggyMatches.push( "!=", pseudos );
+				} catch ( e ) {}
+			});
+
+			// rbuggyMatches always contains :active and :focus, so no need for a length check
+			rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
+
+			Sizzle.matchesSelector = function( elem, expr ) {
+				// Make sure that attribute selectors are quoted
+				expr = expr.replace( rattributeQuotes, "='$1']" );
+
+				// rbuggyMatches always contains :active, so no need for an existence check
+				if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {
+					try {
+						var ret = matches.call( elem, expr );
+
+						// IE 9's matchesSelector returns false on disconnected nodes
+						if ( ret || disconnectedMatch ||
+								// As well, disconnected nodes are said to be in a document
+								// fragment in IE 9
+								elem.document && elem.document.nodeType !== 11 ) {
+							return ret;
+						}
+					} catch(e) {}
+				}
+
+				return Sizzle( expr, null, null, [ elem ] ).length > 0;
+			};
+		}
+	})();
+}
+
+// Deprecated
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Back-compat
+function setFilters() {}
+Expr.filters = setFilters.prototype = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+var runtil = /Until$/,
+	rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	isSimple = /^.[^:#\[\.,]*$/,
+	rneedsContext = jQuery.expr.match.needsContext,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i, l, length, n, r, ret,
+			self = this;
+
+		if ( typeof selector !== "string" ) {
+			return jQuery( selector ).filter(function() {
+				for ( i = 0, l = self.length; i < l; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			});
+		}
+
+		ret = this.pushStack( "", "find", selector );
+
+		for ( i = 0, l = this.length; i < l; i++ ) {
+			length = ret.length;
+			jQuery.find( selector, this[i], ret );
+
+			if ( i > 0 ) {
+				// Make sure that the results are unique
+				for ( n = length; n < ret.length; n++ ) {
+					for ( r = 0; r < length; r++ ) {
+						if ( ret[r] === ret[n] ) {
+							ret.splice(n--, 1);
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	has: function( target ) {
+		var i,
+			targets = jQuery( target, this ),
+			len = targets.length;
+
+		return this.filter(function() {
+			for ( i = 0; i < len; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector, false), "not", selector);
+	},
+
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector, true), "filter", selector );
+	},
+
+	is: function( selector ) {
+		return !!selector && (
+			typeof selector === "string" ?
+				// If this is a positional/relative selector, check membership in the returned set
+				// so $("p:first").is("p:last") won't return true for a doc with two "p".
+				rneedsContext.test( selector ) ?
+					jQuery( selector, this.context ).index( this[0] ) >= 0 :
+					jQuery.filter( selector, this ).length > 0 :
+				this.filter( selector ).length > 0 );
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			ret = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			cur = this[i];
+
+			while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+					ret.push( cur );
+					break;
+				}
+				cur = cur.parentNode;
+			}
+		}
+
+		ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+		return this.pushStack( ret, "closest", selectors );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+		}
+
+		// index in selector
+		if ( typeof elem === "string" ) {
+			return jQuery.inArray( this[0], jQuery( elem ) );
+		}
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		var set = typeof selector === "string" ?
+				jQuery( selector, context ) :
+				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+			all = jQuery.merge( this.get(), set );
+
+		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+			all :
+			jQuery.unique( all ) );
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+	return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+function sibling( cur, dir ) {
+	do {
+		cur = cur[ dir ];
+	} while ( cur && cur.nodeType !== 1 );
+
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+
+		if ( !runtil.test( name ) ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+		if ( this.length > 1 && rparentsprev.test( name ) ) {
+			ret = ret.reverse();
+		}
+
+		return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
+	};
+});
+
+jQuery.extend({
+	filter: function( expr, elems, not ) {
+		if ( not ) {
+			expr = ":not(" + expr + ")";
+		}
+
+		return elems.length === 1 ?
+			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+			jQuery.find.matches(expr, elems);
+	},
+
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+	// Can't pass null or undefined to indexOf in Firefox 4
+	// Set to 0 to skip string check
+	qualifier = qualifier || 0;
+
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			var retVal = !!qualifier.call( elem, i, elem );
+			return retVal === keep;
+		});
+
+	} else if ( qualifier.nodeType ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			return ( elem === qualifier ) === keep;
+		});
+
+	} else if ( typeof qualifier === "string" ) {
+		var filtered = jQuery.grep(elements, function( elem ) {
+			return elem.nodeType === 1;
+		});
+
+		if ( isSimple.test( qualifier ) ) {
+			return jQuery.filter(qualifier, filtered, !keep);
+		} else {
+			qualifier = jQuery.filter( qualifier, filtered );
+		}
+	}
+
+	return jQuery.grep(elements, function( elem, i ) {
+		return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+	});
+}
+function createSafeFragment( document ) {
+	var list = nodeNames.split( "|" ),
+	safeFrag = document.createDocumentFragment();
+
+	if ( safeFrag.createElement ) {
+		while ( list.length ) {
+			safeFrag.createElement(
+				list.pop()
+			);
+		}
+	}
+	return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	rnocache = /<(?:script|object|embed|option|style)/i,
+	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+	rcheckableType = /^(?:checkbox|radio)$/,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /\/(java|ecma)script/i,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		area: [ 1, "<map>", "</map>" ],
+		_default: [ 0, "", "" ]
+	},
+	safeFragment = createSafeFragment( document ),
+	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+// unless wrapped in a div with non-breaking characters in front of it.
+if ( !jQuery.support.htmlSerialize ) {
+	wrapMap._default = [ 1, "X<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return jQuery.access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+		}, null, value, arguments.length );
+	},
+
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function(i) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 ) {
+				this.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 ) {
+				this.insertBefore( elem, this.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		if ( !isDisconnected( this[0] ) ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this );
+			});
+		}
+
+		if ( arguments.length ) {
+			var set = jQuery.clean( arguments );
+			return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
+		}
+	},
+
+	after: function() {
+		if ( !isDisconnected( this[0] ) ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			});
+		}
+
+		if ( arguments.length ) {
+			var set = jQuery.clean( arguments );
+			return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
+		}
+	},
+
+	// keepData is for internal use only--do not document
+	remove: function( selector, keepData ) {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+				if ( !keepData && elem.nodeType === 1 ) {
+					jQuery.cleanData( elem.getElementsByTagName("*") );
+					jQuery.cleanData( [ elem ] );
+				}
+
+				if ( elem.parentNode ) {
+					elem.parentNode.removeChild( elem );
+				}
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( elem.getElementsByTagName("*") );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map( function () {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return jQuery.access( this, function( value ) {
+			var elem = this[0] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined ) {
+				return elem.nodeType === 1 ?
+					elem.innerHTML.replace( rinlinejQuery, "" ) :
+					undefined;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+				( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+				!wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for (; i < l; i++ ) {
+						// Remove element nodes and prevent memory leaks
+						elem = this[i] || {};
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( elem.getElementsByTagName( "*" ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch(e) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function( value ) {
+		if ( !isDisconnected( this[0] ) ) {
+			// Make sure that the elements are removed from the DOM before they are inserted
+			// this can help fix replacing a parent with child elements
+			if ( jQuery.isFunction( value ) ) {
+				return this.each(function(i) {
+					var self = jQuery(this), old = self.html();
+					self.replaceWith( value.call( this, i, old ) );
+				});
+			}
+
+			if ( typeof value !== "string" ) {
+				value = jQuery( value ).detach();
+			}
+
+			return this.each(function() {
+				var next = this.nextSibling,
+					parent = this.parentNode;
+
+				jQuery( this ).remove();
+
+				if ( next ) {
+					jQuery(next).before( value );
+				} else {
+					jQuery(parent).append( value );
+				}
+			});
+		}
+
+		return this.length ?
+			this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+			this;
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, table, callback ) {
+
+		// Flatten any nested arrays
+		args = [].concat.apply( [], args );
+
+		var results, first, fragment, iNoClone,
+			i = 0,
+			value = args[0],
+			scripts = [],
+			l = this.length;
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
+			return this.each(function() {
+				jQuery(this).domManip( args, table, callback );
+			});
+		}
+
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				args[0] = value.call( this, i, table ? self.html() : undefined );
+				self.domManip( args, table, callback );
+			});
+		}
+
+		if ( this[0] ) {
+			results = jQuery.buildFragment( args, this, scripts );
+			fragment = results.fragment;
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				table = table && jQuery.nodeName( first, "tr" );
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				// Fragments from the fragment cache must always be cloned and never used in place.
+				for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
+					callback.call(
+						table && jQuery.nodeName( this[i], "table" ) ?
+							findOrAppend( this[i], "tbody" ) :
+							this[i],
+						i === iNoClone ?
+							fragment :
+							jQuery.clone( fragment, true, true )
+					);
+				}
+			}
+
+			// Fix #11809: Avoid leaking memory
+			fragment = first = null;
+
+			if ( scripts.length ) {
+				jQuery.each( scripts, function( i, elem ) {
+					if ( elem.src ) {
+						if ( jQuery.ajax ) {
+							jQuery.ajax({
+								url: elem.src,
+								type: "GET",
+								dataType: "script",
+								async: false,
+								global: false,
+								"throws": true
+							});
+						} else {
+							jQuery.error("no ajax");
+						}
+					} else {
+						jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
+					}
+
+					if ( elem.parentNode ) {
+						elem.parentNode.removeChild( elem );
+					}
+				});
+			}
+		}
+
+		return this;
+	}
+});
+
+function findOrAppend( elem, tag ) {
+	return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+function cloneCopyEvent( src, dest ) {
+
+	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+		return;
+	}
+
+	var type, i, l,
+		oldData = jQuery._data( src ),
+		curData = jQuery._data( dest, oldData ),
+		events = oldData.events;
+
+	if ( events ) {
+		delete curData.handle;
+		curData.events = {};
+
+		for ( type in events ) {
+			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+				jQuery.event.add( dest, type, events[ type ][ i ] );
+			}
+		}
+	}
+
+	// make the cloned public data object a copy from the original
+	if ( curData.data ) {
+		curData.data = jQuery.extend( {}, curData.data );
+	}
+}
+
+function cloneFixAttributes( src, dest ) {
+	var nodeName;
+
+	// We do not need to do anything for non-Elements
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	// clearAttributes removes the attributes, which we don't want,
+	// but also removes the attachEvent events, which we *do* want
+	if ( dest.clearAttributes ) {
+		dest.clearAttributes();
+	}
+
+	// mergeAttributes, in contrast, only merges back on the
+	// original attributes, not the events
+	if ( dest.mergeAttributes ) {
+		dest.mergeAttributes( src );
+	}
+
+	nodeName = dest.nodeName.toLowerCase();
+
+	if ( nodeName === "object" ) {
+		// IE6-10 improperly clones children of object elements using classid.
+		// IE10 throws NoModificationAllowedError if parent is null, #12132.
+		if ( dest.parentNode ) {
+			dest.outerHTML = src.outerHTML;
+		}
+
+		// This path appears unavoidable for IE9. When cloning an object
+		// element in IE9, the outerHTML strategy above is not sufficient.
+		// If the src has innerHTML and the destination does not,
+		// copy the src.innerHTML into the dest.innerHTML. #10324
+		if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
+			dest.innerHTML = src.innerHTML;
+		}
+
+	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		// IE6-8 fails to persist the checked state of a cloned checkbox
+		// or radio button. Worse, IE6-7 fail to give the cloned element
+		// a checked appearance if the defaultChecked value isn't also set
+
+		dest.defaultChecked = dest.checked = src.checked;
+
+		// IE6-7 get confused and end up setting the value of a cloned
+		// checkbox/radio button to an empty string instead of "on"
+		if ( dest.value !== src.value ) {
+			dest.value = src.value;
+		}
+
+	// IE6-8 fails to return the selected option to the default selected
+	// state when cloning options
+	} else if ( nodeName === "option" ) {
+		dest.selected = src.defaultSelected;
+
+	// IE6-8 fails to set the defaultValue to the correct value when
+	// cloning other types of input fields
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+
+	// IE blanks contents when cloning scripts
+	} else if ( nodeName === "script" && dest.text !== src.text ) {
+		dest.text = src.text;
+	}
+
+	// Event data gets referenced instead of copied if the expando
+	// gets copied too
+	dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, context, scripts ) {
+	var fragment, cacheable, cachehit,
+		first = args[ 0 ];
+
+	// Set context from what may come in as undefined or a jQuery collection or a node
+	// Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
+	// also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
+	context = context || document;
+	context = !context.nodeType && context[0] || context;
+	context = context.ownerDocument || context;
+
+	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+	// Cloning options loses the selected state, so don't cache them
+	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+	// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+	if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
+		first.charAt(0) === "<" && !rnocache.test( first ) &&
+		(jQuery.support.checkClone || !rchecked.test( first )) &&
+		(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+		// Mark cacheable and look for a hit
+		cacheable = true;
+		fragment = jQuery.fragments[ first ];
+		cachehit = fragment !== undefined;
+	}
+
+	if ( !fragment ) {
+		fragment = context.createDocumentFragment();
+		jQuery.clean( args, context, fragment, scripts );
+
+		// Update the cache, but only store false
+		// unless this is a second parsing of the same content
+		if ( cacheable ) {
+			jQuery.fragments[ first ] = cachehit && fragment;
+		}
+	}
+
+	return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			i = 0,
+			ret = [],
+			insert = jQuery( selector ),
+			l = insert.length,
+			parent = this.length === 1 && this[0].parentNode;
+
+		if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
+			insert[ original ]( this[0] );
+			return this;
+		} else {
+			for ( ; i < l; i++ ) {
+				elems = ( i > 0 ? this.clone(true) : this ).get();
+				jQuery( insert[i] )[ original ]( elems );
+				ret = ret.concat( elems );
+			}
+
+			return this.pushStack( ret, name, insert.selector );
+		}
+	};
+});
+
+function getAll( elem ) {
+	if ( typeof elem.getElementsByTagName !== "undefined" ) {
+		return elem.getElementsByTagName( "*" );
+
+	} else if ( typeof elem.querySelectorAll !== "undefined" ) {
+		return elem.querySelectorAll( "*" );
+
+	} else {
+		return [];
+	}
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+	if ( rcheckableType.test( elem.type ) ) {
+		elem.defaultChecked = elem.checked;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var srcElements,
+			destElements,
+			i,
+			clone;
+
+		if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+			clone = elem.cloneNode( true );
+
+		// IE<=8 does not properly clone detached, unknown element nodes
+		} else {
+			fragmentDiv.innerHTML = elem.outerHTML;
+			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+		}
+
+		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+			// IE copies events bound via attachEvent when using cloneNode.
+			// Calling detachEvent on the clone will also remove the events
+			// from the original. In order to get around this, we use some
+			// proprietary methods to clear the events. Thanks to MooTools
+			// guys for this hotness.
+
+			cloneFixAttributes( elem, clone );
+
+			// Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+			srcElements = getAll( elem );
+			destElements = getAll( clone );
+
+			// Weird iteration because IE will replace the length property
+			// with an element if you are cloning the body and one of the
+			// elements on the page has a name or id of "length"
+			for ( i = 0; srcElements[i]; ++i ) {
+				// Ensure that the destination node is not null; Fixes #9587
+				if ( destElements[i] ) {
+					cloneFixAttributes( srcElements[i], destElements[i] );
+				}
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			cloneCopyEvent( elem, clone );
+
+			if ( deepDataAndEvents ) {
+				srcElements = getAll( elem );
+				destElements = getAll( clone );
+
+				for ( i = 0; srcElements[i]; ++i ) {
+					cloneCopyEvent( srcElements[i], destElements[i] );
+				}
+			}
+		}
+
+		srcElements = destElements = null;
+
+		// Return the cloned set
+		return clone;
+	},
+
+	clean: function( elems, context, fragment, scripts ) {
+		var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
+			safe = context === document && safeFragment,
+			ret = [];
+
+		// Ensure that context is a document
+		if ( !context || typeof context.createDocumentFragment === "undefined" ) {
+			context = document;
+		}
+
+		// Use the already-created safe fragment if context permits
+		for ( i = 0; (elem = elems[i]) != null; i++ ) {
+			if ( typeof elem === "number" ) {
+				elem += "";
+			}
+
+			if ( !elem ) {
+				continue;
+			}
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" ) {
+				if ( !rhtml.test( elem ) ) {
+					elem = context.createTextNode( elem );
+				} else {
+					// Ensure a safe container in which to render the html
+					safe = safe || createSafeFragment( context );
+					div = context.createElement("div");
+					safe.appendChild( div );
+
+					// Fix "XHTML"-style tags in all browsers
+					elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+					// Go to html and back, then peel off extra wrappers
+					tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+					depth = wrap[0];
+					div.innerHTML = wrap[1] + elem + wrap[2];
+
+					// Move to the right depth
+					while ( depth-- ) {
+						div = div.lastChild;
+					}
+
+					// Remove IE's autoinserted <tbody> from table fragments
+					if ( !jQuery.support.tbody ) {
+
+						// String was a <table>, *may* have spurious <tbody>
+						hasBody = rtbody.test(elem);
+							tbody = tag === "table" && !hasBody ?
+								div.firstChild && div.firstChild.childNodes :
+
+								// String was a bare <thead> or <tfoot>
+								wrap[1] === "<table>" && !hasBody ?
+									div.childNodes :
+									[];
+
+						for ( j = tbody.length - 1; j >= 0 ; --j ) {
+							if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+								tbody[ j ].parentNode.removeChild( tbody[ j ] );
+							}
+						}
+					}
+
+					// IE completely kills leading whitespace when innerHTML is used
+					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+						div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+					}
+
+					elem = div.childNodes;
+
+					// Take out of fragment container (we need a fresh div each time)
+					div.parentNode.removeChild( div );
+				}
+			}
+
+			if ( elem.nodeType ) {
+				ret.push( elem );
+			} else {
+				jQuery.merge( ret, elem );
+			}
+		}
+
+		// Fix #11356: Clear elements from safeFragment
+		if ( div ) {
+			elem = div = safe = null;
+		}
+
+		// Reset defaultChecked for any radios and checkboxes
+		// about to be appended to the DOM in IE 6/7 (#8060)
+		if ( !jQuery.support.appendChecked ) {
+			for ( i = 0; (elem = ret[i]) != null; i++ ) {
+				if ( jQuery.nodeName( elem, "input" ) ) {
+					fixDefaultChecked( elem );
+				} else if ( typeof elem.getElementsByTagName !== "undefined" ) {
+					jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+				}
+			}
+		}
+
+		// Append elements to a provided document fragment
+		if ( fragment ) {
+			// Special handling of each script element
+			handleScript = function( elem ) {
+				// Check if we consider it executable
+				if ( !elem.type || rscriptType.test( elem.type ) ) {
+					// Detach the script and store it in the scripts array (if provided) or the fragment
+					// Return truthy to indicate that it has been handled
+					return scripts ?
+						scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
+						fragment.appendChild( elem );
+				}
+			};
+
+			for ( i = 0; (elem = ret[i]) != null; i++ ) {
+				// Check if we're done after handling an executable script
+				if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
+					// Append to fragment and handle embedded scripts
+					fragment.appendChild( elem );
+					if ( typeof elem.getElementsByTagName !== "undefined" ) {
+						// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
+						jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
+
+						// Splice the scripts into ret after their former ancestor and advance our index beyond them
+						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+						i += jsTags.length;
+					}
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	cleanData: function( elems, /* internal */ acceptData ) {
+		var data, id, elem, type,
+			i = 0,
+			internalKey = jQuery.expando,
+			cache = jQuery.cache,
+			deleteExpando = jQuery.support.deleteExpando,
+			special = jQuery.event.special;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+
+			if ( acceptData || jQuery.acceptData( elem ) ) {
+
+				id = elem[ internalKey ];
+				data = id && cache[ id ];
+
+				if ( data ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+
+					// Remove cache only if it was not already removed by jQuery.event.remove
+					if ( cache[ id ] ) {
+
+						delete cache[ id ];
+
+						// IE does not allow us to delete expando properties from nodes,
+						// nor does it have a removeAttribute function on Document nodes;
+						// we must handle all of these cases
+						if ( deleteExpando ) {
+							delete elem[ internalKey ];
+
+						} else if ( elem.removeAttribute ) {
+							elem.removeAttribute( internalKey );
+
+						} else {
+							elem[ internalKey ] = null;
+						}
+
+						jQuery.deletedIds.push( id );
+					}
+				}
+			}
+		}
+	}
+});
+// Limit scope pollution from any deprecated API
+(function() {
+
+var matched, browser;
+
+// Use of jQuery.browser is frowned upon.
+// More details: http://api.jquery.com/jQuery.browser
+// jQuery.uaMatch maintained for back-compat
+jQuery.uaMatch = function( ua ) {
+	ua = ua.toLowerCase();
+
+	var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+		/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+		/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+		/(msie) ([\w.]+)/.exec( ua ) ||
+		ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+		[];
+
+	return {
+		browser: match[ 1 ] || "",
+		version: match[ 2 ] || "0"
+	};
+};
+
+matched = jQuery.uaMatch( navigator.userAgent );
+browser = {};
+
+if ( matched.browser ) {
+	browser[ matched.browser ] = true;
+	browser.version = matched.version;
+}
+
+// Chrome is Webkit, but Webkit is also Safari.
+if ( browser.chrome ) {
+	browser.webkit = true;
+} else if ( browser.webkit ) {
+	browser.safari = true;
+}
+
+jQuery.browser = browser;
+
+jQuery.sub = function() {
+	function jQuerySub( selector, context ) {
+		return new jQuerySub.fn.init( selector, context );
+	}
+	jQuery.extend( true, jQuerySub, this );
+	jQuerySub.superclass = this;
+	jQuerySub.fn = jQuerySub.prototype = this();
+	jQuerySub.fn.constructor = jQuerySub;
+	jQuerySub.sub = this.sub;
+	jQuerySub.fn.init = function init( selector, context ) {
+		if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+			context = jQuerySub( context );
+		}
+
+		return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+	};
+	jQuerySub.fn.init.prototype = jQuerySub.fn;
+	var rootjQuerySub = jQuerySub(document);
+	return jQuerySub;
+};
+
+})();
+var curCSS, iframe, iframeDoc,
+	ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity=([^)]*)/,
+	rposition = /^(top|right|bottom|left)$/,
+	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rmargin = /^margin/,
+	rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+	rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+	rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
+	elemdisplay = {},
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: 0,
+		fontWeight: 400
+	},
+
+	cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+
+	eventsToggle = jQuery.fn.toggle;
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// check for vendor prefixed names
+	var capName = name.charAt(0).toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function isHidden( elem, el ) {
+	elem = el || elem;
+	return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+	var elem, display,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		values[ index ] = jQuery._data( elem, "olddisplay" );
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && elem.style.display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+			}
+		} else {
+			display = curCSS( elem, "display" );
+
+			if ( !values[ index ] && display !== "none" ) {
+				jQuery._data( elem, "olddisplay", display );
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return jQuery.access( this, function( elem, name, value ) {
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state, fn2 ) {
+		var bool = typeof state === "boolean";
+
+		if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
+			return eventsToggle.apply( this, arguments );
+		}
+
+		return this.each(function() {
+			if ( bool ? state : isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+
+				}
+			}
+		}
+	},
+
+	// Exclude the following css properties to add px
+	cssNumber: {
+		"fillOpacity": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// convert relative number strings (+= or -=) to relative numbers. #7345
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that NaN and null values aren't set. See: #7116
+			if ( value == null || type === "number" && isNaN( value ) ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+				// Fixes bug #5509
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, numeric, extra ) {
+		var val, num, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name );
+		}
+
+		//convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Return, converting to number if forced or a qualifier was provided and val looks numeric
+		if ( numeric || extra !== undefined ) {
+			num = parseFloat( val );
+			return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var ret, name,
+			old = {};
+
+		// Remember the old values, and insert the new ones
+		for ( name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		ret = callback.call( elem );
+
+		// Revert the old values
+		for ( name in options ) {
+			elem.style[ name ] = old[ name ];
+		}
+
+		return ret;
+	}
+});
+
+// NOTE: To any future maintainer, we've window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+	curCSS = function( elem, name ) {
+		var ret, width, minWidth, maxWidth,
+			computed = window.getComputedStyle( elem, null ),
+			style = elem.style;
+
+		if ( computed ) {
+
+			ret = computed[ name ];
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+
+			// A tribute to the "awesome hack by Dean Edwards"
+			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+				width = style.width;
+				minWidth = style.minWidth;
+				maxWidth = style.maxWidth;
+
+				style.minWidth = style.maxWidth = style.width = ret;
+				ret = computed.width;
+
+				style.width = width;
+				style.minWidth = minWidth;
+				style.maxWidth = maxWidth;
+			}
+		}
+
+		return ret;
+	};
+} else if ( document.documentElement.currentStyle ) {
+	curCSS = function( elem, name ) {
+		var left, rsLeft,
+			ret = elem.currentStyle && elem.currentStyle[ name ],
+			style = elem.style;
+
+		// Avoid setting ret to empty string here
+		// so we don't default to auto
+		if ( ret == null && style && style[ name ] ) {
+			ret = style[ name ];
+		}
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		// but not position css attributes, as those are proportional to the parent element instead
+		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+			// Remember the original values
+			left = style.left;
+			rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+			// Put in the new values to get a computed value out
+			if ( rsLeft ) {
+				elem.runtimeStyle.left = elem.currentStyle.left;
+			}
+			style.left = name === "fontSize" ? "1em" : ret;
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			if ( rsLeft ) {
+				elem.runtimeStyle.left = rsLeft;
+			}
+		}
+
+		return ret === "" ? "auto" : ret;
+	};
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+			Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+			value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			// we use jQuery.css instead of curCSS here
+			// because of the reliableMarginRight CSS hook!
+			val += jQuery.css( elem, extra + cssExpand[ i ], true );
+		}
+
+		// From this point on we use curCSS for maximum performance (relevant in animations)
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+			}
+
+			// at this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+			}
+		} else {
+			// at this point, extra isn't content, so add padding
+			val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+
+			// at this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		valueIsBorderBox = true,
+		isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
+
+	// some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// we need the check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox
+		)
+	) + "px";
+}
+
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+	if ( elemdisplay[ nodeName ] ) {
+		return elemdisplay[ nodeName ];
+	}
+
+	var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
+		display = elem.css("display");
+	elem.remove();
+
+	// If the simple way fails,
+	// get element's real default display by attaching it to a temp iframe
+	if ( display === "none" || display === "" ) {
+		// Use the already-created iframe if possible
+		iframe = document.body.appendChild(
+			iframe || jQuery.extend( document.createElement("iframe"), {
+				frameBorder: 0,
+				width: 0,
+				height: 0
+			})
+		);
+
+		// Create a cacheable copy of the iframe document on first call.
+		// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+		// document to it; WebKit & Firefox won't allow reusing the iframe document.
+		if ( !iframeDoc || !iframe.createElement ) {
+			iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+			iframeDoc.write("<!doctype html><html><body>");
+			iframeDoc.close();
+		}
+
+		elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
+
+		display = curCSS( elem, "display" );
+		document.body.removeChild( iframe );
+	}
+
+	// Store the correct default display
+	elemdisplay[ nodeName ] = display;
+
+	return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+				// certain elements can have dimension info if we invisibly show them
+				// however, it must have a current display style that would benefit from this
+				if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
+					return jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					});
+				} else {
+					return getWidthOrHeight( elem, name, extra );
+				}
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
+				) : 0
+			);
+		}
+	};
+});
+
+if ( !jQuery.support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style,
+				currentStyle = elem.currentStyle,
+				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+				filter = currentStyle && currentStyle.filter || style.filter || "";
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+			if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+				style.removeAttribute ) {
+
+				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+				// if "filter:" is present at all, clearType is disabled, we want to avoid this
+				// style.removeAttribute is IE Only, but so apparently is this code path...
+				style.removeAttribute( "filter" );
+
+				// if there there is no filter style applied in a css rule, we are done
+				if ( currentStyle && !currentStyle.filter ) {
+					return;
+				}
+			}
+
+			// otherwise, set new filter values
+			style.filter = ralpha.test( filter ) ?
+				filter.replace( ralpha, opacity ) :
+				filter + " " + opacity;
+		}
+	};
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+	if ( !jQuery.support.reliableMarginRight ) {
+		jQuery.cssHooks.marginRight = {
+			get: function( elem, computed ) {
+				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+				// Work around by temporarily setting element display to inline-block
+				return jQuery.swap( elem, { "display": "inline-block" }, function() {
+					if ( computed ) {
+						return curCSS( elem, "marginRight" );
+					}
+				});
+			}
+		};
+	}
+
+	// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+	// getComputedStyle returns percent when specified for top/left/bottom/right
+	// rather than make the css module depend on the offset module, we just check for it here
+	if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+		jQuery.each( [ "top", "left" ], function( i, prop ) {
+			jQuery.cssHooks[ prop ] = {
+				get: function( elem, computed ) {
+					if ( computed ) {
+						var ret = curCSS( elem, prop );
+						// if curCSS returns percentage, fallback to offset
+						return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
+					}
+				}
+			};
+		});
+	}
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.hidden = function( elem ) {
+		return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
+	};
+
+	jQuery.expr.filters.visible = function( elem ) {
+		return !jQuery.expr.filters.hidden( elem );
+	};
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i,
+
+				// assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ],
+				expanded = {};
+
+			for ( i = 0; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+	rselectTextarea = /^(?:select|textarea)/i;
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return this.elements ? jQuery.makeArray( this.elements ) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled &&
+				( this.checked || rselectTextarea.test( this.nodeName ) ||
+					rinput.test( this.type ) );
+		})
+		.map(function( i, elem ){
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val, i ){
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// If array item is non-scalar (array or object), encode its
+				// numeric index to resolve deserialization ambiguity issues.
+				// Note that rack (as of 1.0.0) can't currently deserialize
+				// nested arrays properly, and attempting to do so may cause
+				// a server error. Possible fixes are to modify rack's
+				// deserialization algorithm or to provide an option or flag
+				// to force array serialization to be shallow.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+var
+	// Document location
+	ajaxLocParts,
+	ajaxLocation,
+
+	rhash = /#.*$/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rquery = /\?/,
+	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+	rts = /([?&])_=[^&]*/,
+	rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+	// Keep a copy of the old load method
+	_load = jQuery.fn.load,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+	ajaxLocation = location.href;
+} catch( e ) {
+	// Use the href attribute of an A element
+	// since IE will modify it given document.location
+	ajaxLocation = document.createElement( "a" );
+	ajaxLocation.href = "";
+	ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType, list, placeBefore,
+			dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
+			i = 0,
+			length = dataTypes.length;
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			for ( ; i < length; i++ ) {
+				dataType = dataTypes[ i ];
+				// We control if we're asked to add before
+				// any existing element
+				placeBefore = /^\+/.test( dataType );
+				if ( placeBefore ) {
+					dataType = dataType.substr( 1 ) || "*";
+				}
+				list = structure[ dataType ] = structure[ dataType ] || [];
+				// then we add to the structure accordingly
+				list[ placeBefore ? "unshift" : "push" ]( func );
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+		dataType /* internal */, inspected /* internal */ ) {
+
+	dataType = dataType || options.dataTypes[ 0 ];
+	inspected = inspected || {};
+
+	inspected[ dataType ] = true;
+
+	var selection,
+		list = structure[ dataType ],
+		i = 0,
+		length = list ? list.length : 0,
+		executeOnly = ( structure === prefilters );
+
+	for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+		selection = list[ i ]( options, originalOptions, jqXHR );
+		// If we got redirected to another dataType
+		// we try there if executing only and not done already
+		if ( typeof selection === "string" ) {
+			if ( !executeOnly || inspected[ selection ] ) {
+				selection = undefined;
+			} else {
+				options.dataTypes.unshift( selection );
+				selection = inspectPrefiltersOrTransports(
+						structure, options, originalOptions, jqXHR, selection, inspected );
+			}
+		}
+	}
+	// If we're only executing or nothing was selected
+	// we try the catchall dataType if not done already
+	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+		selection = inspectPrefiltersOrTransports(
+				structure, options, originalOptions, jqXHR, "*", inspected );
+	}
+	// unnecessary when only executing (prefilters)
+	// but it'll be ignored by the caller in that case
+	return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var key, deep,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	// Don't do a request if no elements are being requested
+	if ( !this.length ) {
+		return this;
+	}
+
+	var selector, type, response,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = url.slice( off, url.length );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// Request the remote document
+	jQuery.ajax({
+		url: url,
+
+		// if "type" variable is undefined, then "GET" method will be used
+		type: type,
+		dataType: "html",
+		data: params,
+		complete: function( jqXHR, status ) {
+			if ( callback ) {
+				self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+			}
+		}
+	}).done(function( responseText ) {
+
+		// Save response for use in complete callback
+		response = arguments;
+
+		// See if a selector was specified
+		self.html( selector ?
+
+			// Create a dummy div to hold the results
+			jQuery("<div>")
+
+				// inject the contents of the document in, removing the scripts
+				// to avoid any 'Permission Denied' errors in IE
+				.append( responseText.replace( rscript, "" ) )
+
+				// Locate the specified elements
+				.find( selector ) :
+
+			// If not, just inject the full result
+			responseText );
+
+	});
+
+	return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+	jQuery.fn[ o ] = function( f ){
+		return this.on( o, f );
+	};
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			type: method,
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	};
+});
+
+jQuery.extend({
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		if ( settings ) {
+			// Building a settings object
+			ajaxExtend( target, jQuery.ajaxSettings );
+		} else {
+			// Extending ajaxSettings
+			settings = target;
+			target = jQuery.ajaxSettings;
+		}
+		ajaxExtend( target, settings );
+		return target;
+	},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			text: "text/plain",
+			json: "application/json, text/javascript",
+			"*": allTypes
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText"
+		},
+
+		// List of data converters
+		// 1) key format is "source_type destination_type" (a single space in-between)
+		// 2) the catchall symbol "*" can be used for source_type
+		converters: {
+
+			// Convert anything to text
+			"* text": window.String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			context: true,
+			url: true
+		}
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var // ifModified key
+			ifModifiedKey,
+			// Response headers
+			responseHeadersString,
+			responseHeaders,
+			// transport
+			transport,
+			// timeout handle
+			timeoutTimer,
+			// Cross-domain detection vars
+			parts,
+			// To know if global events are to be dispatched
+			fireGlobals,
+			// Loop variable
+			i,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events
+			// It's the callbackContext if one was provided in the options
+			// and if it's a DOM node or a jQuery collection
+			globalEventContext = callbackContext !== s &&
+				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+						jQuery( callbackContext ) : jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks( "once memory" ),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+
+				readyState: 0,
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					if ( !state ) {
+						var lname = name.toLowerCase();
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match === undefined ? null : match;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					statusText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( statusText );
+					}
+					done( 0, statusText );
+					return this;
+				}
+			};
+
+		// Callback for when everything is done
+		// It is defined here because jslint complains if it is declared
+		// at the end of the function (which would be more logical and readable)
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// If successful, handle type chaining
+			if ( status >= 200 && status < 300 || status === 304 ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ ifModifiedKey ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("Etag");
+					if ( modified ) {
+						jQuery.etag[ ifModifiedKey ] = modified;
+					}
+				}
+
+				// If not modified
+				if ( status === 304 ) {
+
+					statusText = "notmodified";
+					isSuccess = true;
+
+				// If we have data
+				} else {
+
+					isSuccess = ajaxConvert( s, response );
+					statusText = isSuccess.state;
+					success = isSuccess.data;
+					error = isSuccess.error;
+					isSuccess = !error;
+				}
+			} else {
+				// We extract error from statusText
+				// then normalize statusText and status for non-aborts
+				error = statusText;
+				if ( !statusText || status ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+						[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger( "ajaxStop" );
+				}
+			}
+		}
+
+		// Attach deferreds
+		deferred.promise( jqXHR );
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+		jqXHR.complete = completeDeferred.add;
+
+		// Status-dependent callbacks
+		jqXHR.statusCode = function( map ) {
+			if ( map ) {
+				var tmp;
+				if ( state < 2 ) {
+					for ( tmp in map ) {
+						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+					}
+				} else {
+					tmp = map[ jqXHR.status ];
+					jqXHR.always( tmp );
+				}
+			}
+			return this;
+		};
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() ) || false;
+			s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !==
+				( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) );
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		fireGlobals = s.global;
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger( "ajaxStart" );
+		}
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Get ifModifiedKey before adding the anti-cache parameter
+			ifModifiedKey = s.url;
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+
+				var ts = jQuery.now(),
+					// try replacing _= if it is there
+					ret = s.url.replace( rts, "$1_=" + ts );
+
+				// if nothing was replaced, add timestamp to the end
+				s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			ifModifiedKey = ifModifiedKey || s.url;
+			if ( jQuery.lastModified[ ifModifiedKey ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+			}
+			if ( jQuery.etag[ ifModifiedKey ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+			}
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+				// Abort if not done already and return
+				return jqXHR.abort();
+
+		}
+
+		// aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout( function(){
+					jqXHR.abort( "timeout" );
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch (e) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+	var ct, type, finalDataType, firstDataType,
+		contents = s.contents,
+		dataTypes = s.dataTypes,
+		responseFields = s.responseFields;
+
+	// Fill responseXXX fields
+	for ( type in responseFields ) {
+		if ( type in responses ) {
+			jqXHR[ responseFields[type] ] = responses[ type ];
+		}
+	}
+
+	// Remove auto dataType and get content-type in the process
+	while( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+	var conv, conv2, current, tmp,
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice(),
+		prev = dataTypes[ 0 ],
+		converters = {},
+		i = 0;
+
+	// Apply the dataFilter if provided
+	if ( s.dataFilter ) {
+		response = s.dataFilter( response, s.dataType );
+	}
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	// Convert to each sequential dataType, tolerating list modification
+	for ( ; (current = dataTypes[++i]); ) {
+
+		// There's only work to do if current dataType is non-auto
+		if ( current !== "*" ) {
+
+			// Convert response if prev dataType is non-auto and differs from current
+			if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split(" ");
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.splice( i--, 0, current );
+								}
+
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s["throws"] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+
+			// Update prev for next iteration
+			prev = current;
+		}
+	}
+
+	return { state: "success", data: response };
+}
+var oldCallbacks = [],
+	rquestion = /\?/,
+	rjsonp = /(=)\?(?=&|$)|\?\?/,
+	nonce = jQuery.now();
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		data = s.data,
+		url = s.url,
+		hasCallback = s.jsonp !== false,
+		replaceInUrl = hasCallback && rjsonp.test( url ),
+		replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
+			!( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
+			rjsonp.test( data );
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+		overwritten = window[ callbackName ];
+
+		// Insert callback into url or form data
+		if ( replaceInUrl ) {
+			s.url = url.replace( rjsonp, "$1" + callbackName );
+		} else if ( replaceInData ) {
+			s.data = data.replace( rjsonp, "$1" + callbackName );
+		} else if ( hasCallback ) {
+			s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /javascript|ecmascript/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+		s.global = false;
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+
+		var script,
+			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+		return {
+
+			send: function( _, callback ) {
+
+				script = document.createElement( "script" );
+
+				script.async = "async";
+
+				if ( s.scriptCharset ) {
+					script.charset = s.scriptCharset;
+				}
+
+				script.src = s.url;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+
+						// Remove the script
+						if ( head && script.parentNode ) {
+							head.removeChild( script );
+						}
+
+						// Dereference the script
+						script = undefined;
+
+						// Callback if not abort
+						if ( !isAbort ) {
+							callback( 200, "success" );
+						}
+					}
+				};
+				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+				// This arises when a base node is used (#2709 and #4378).
+				head.insertBefore( script, head.firstChild );
+			},
+
+			abort: function() {
+				if ( script ) {
+					script.onload( 0, 1 );
+				}
+			}
+		};
+	}
+});
+var xhrCallbacks,
+	// #5280: Internet Explorer will keep connections alive if we don't abort on unload
+	xhrOnUnloadAbort = window.ActiveXObject ? function() {
+		// Abort all pending requests
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]( 0, 1 );
+		}
+	} : false,
+	xhrId = 0;
+
+// Functions to create xhrs
+function createStandardXHR() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch( e ) {}
+}
+
+function createActiveXHR() {
+	try {
+		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+	} catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+	/* Microsoft failed to properly
+	 * implement the XMLHttpRequest in IE7 (can't request local files),
+	 * so we use the ActiveXObject when it is available
+	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+	 * we need a fallback.
+	 */
+	function() {
+		return !this.isLocal && createStandardXHR() || createActiveXHR();
+	} :
+	// For all other browsers, use the standard XMLHttpRequest object
+	createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+	jQuery.extend( jQuery.support, {
+		ajax: !!xhr,
+		cors: !!xhr && ( "withCredentials" in xhr )
+	});
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+	jQuery.ajaxTransport(function( s ) {
+		// Cross domain only allowed if supported through XMLHttpRequest
+		if ( !s.crossDomain || jQuery.support.cors ) {
+
+			var callback;
+
+			return {
+				send: function( headers, complete ) {
+
+					// Get a new xhr
+					var handle, i,
+						xhr = s.xhr();
+
+					// Open the socket
+					// Passing null username, generates a login popup on Opera (#2865)
+					if ( s.username ) {
+						xhr.open( s.type, s.url, s.async, s.username, s.password );
+					} else {
+						xhr.open( s.type, s.url, s.async );
+					}
+
+					// Apply custom fields if provided
+					if ( s.xhrFields ) {
+						for ( i in s.xhrFields ) {
+							xhr[ i ] = s.xhrFields[ i ];
+						}
+					}
+
+					// Override mime type if needed
+					if ( s.mimeType && xhr.overrideMimeType ) {
+						xhr.overrideMimeType( s.mimeType );
+					}
+
+					// X-Requested-With header
+					// For cross-domain requests, seeing as conditions for a preflight are
+					// akin to a jigsaw puzzle, we simply never set it to be sure.
+					// (it can always be set on a per-request basis or even using ajaxSetup)
+					// For same-domain requests, won't change header if already provided.
+					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+						headers[ "X-Requested-With" ] = "XMLHttpRequest";
+					}
+
+					// Need an extra try/catch for cross domain requests in Firefox 3
+					try {
+						for ( i in headers ) {
+							xhr.setRequestHeader( i, headers[ i ] );
+						}
+					} catch( _ ) {}
+
+					// Do send the request
+					// This may raise an exception which is actually
+					// handled in jQuery.ajax (so no try/catch here)
+					xhr.send( ( s.hasContent && s.data ) || null );
+
+					// Listener
+					callback = function( _, isAbort ) {
+
+						var status,
+							statusText,
+							responseHeaders,
+							responses,
+							xml;
+
+						// Firefox throws exceptions when accessing properties
+						// of an xhr when a network error occurred
+						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+						try {
+
+							// Was never called and is aborted or complete
+							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+								// Only called once
+								callback = undefined;
+
+								// Do not keep as active anymore
+								if ( handle ) {
+									xhr.onreadystatechange = jQuery.noop;
+									if ( xhrOnUnloadAbort ) {
+										delete xhrCallbacks[ handle ];
+									}
+								}
+
+								// If it's an abort
+								if ( isAbort ) {
+									// Abort it manually if needed
+									if ( xhr.readyState !== 4 ) {
+										xhr.abort();
+									}
+								} else {
+									status = xhr.status;
+									responseHeaders = xhr.getAllResponseHeaders();
+									responses = {};
+									xml = xhr.responseXML;
+
+									// Construct response list
+									if ( xml && xml.documentElement /* #4958 */ ) {
+										responses.xml = xml;
+									}
+
+									// When requesting binary data, IE6-9 will throw an exception
+									// on any attempt to access responseText (#11426)
+									try {
+										responses.text = xhr.responseText;
+									} catch( _ ) {
+									}
+
+									// Firefox throws an exception when accessing
+									// statusText for faulty cross-domain requests
+									try {
+										statusText = xhr.statusText;
+									} catch( e ) {
+										// We normalize with Webkit giving an empty statusText
+										statusText = "";
+									}
+
+									// Filter status for non standard behaviors
+
+									// If the request is local and we have data: assume a success
+									// (success with no data won't get notified, that's the best we
+									// can do given current implementations)
+									if ( !status && s.isLocal && !s.crossDomain ) {
+										status = responses.text ? 200 : 404;
+									// IE - #1450: sometimes returns 1223 when it should be 204
+									} else if ( status === 1223 ) {
+										status = 204;
+									}
+								}
+							}
+						} catch( firefoxAccessException ) {
+							if ( !isAbort ) {
+								complete( -1, firefoxAccessException );
+							}
+						}
+
+						// Call complete if needed
+						if ( responses ) {
+							complete( status, statusText, responses, responseHeaders );
+						}
+					};
+
+					if ( !s.async ) {
+						// if we're in sync mode we fire the callback
+						callback();
+					} else if ( xhr.readyState === 4 ) {
+						// (IE6 & IE7) if it's in cache and has been
+						// retrieved directly we need to fire the callback
+						setTimeout( callback, 0 );
+					} else {
+						handle = ++xhrId;
+						if ( xhrOnUnloadAbort ) {
+							// Create the active xhrs callbacks list if needed
+							// and attach the unload handler
+							if ( !xhrCallbacks ) {
+								xhrCallbacks = {};
+								jQuery( window ).unload( xhrOnUnloadAbort );
+							}
+							// Add to list of active xhrs callbacks
+							xhrCallbacks[ handle ] = callback;
+						}
+						xhr.onreadystatechange = callback;
+					}
+				},
+
+				abort: function() {
+					if ( callback ) {
+						callback(0,1);
+					}
+				}
+			};
+		}
+	});
+}
+var fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [function( prop, value ) {
+			var end, unit,
+				tween = this.createTween( prop, value ),
+				parts = rfxnum.exec( value ),
+				target = tween.cur(),
+				start = +target || 0,
+				scale = 1,
+				maxIterations = 20;
+
+			if ( parts ) {
+				end = +parts[2];
+				unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+				// We need to compute starting value
+				if ( unit !== "px" && start ) {
+					// Iteratively approximate from a nonzero starting point
+					// Prefer the current property, because this process will be trivial if it uses the same units
+					// Fallback to end or a simple constant
+					start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+					do {
+						// If previous iteration zeroed out, double until we get *something*
+						// Use a string for doubling factor so we don't accidentally see scale as unchanged below
+						scale = scale || ".5";
+
+						// Adjust and apply
+						start = start / scale;
+						jQuery.style( tween.elem, prop, start + unit );
+
+					// Update scale, tolerating zero or NaN from tween.cur()
+					// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+					} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+				}
+
+				tween.unit = unit;
+				tween.start = start;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+			}
+			return tween;
+		}]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	}, 0 );
+	return ( fxNow = jQuery.now() );
+}
+
+function createTweens( animation, props ) {
+	jQuery.each( props, function( prop, value ) {
+		var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+			index = 0,
+			length = collection.length;
+		for ( ; index < length; index++ ) {
+			if ( collection[ index ].call( animation, prop, value ) ) {
+
+				// we're done with this property
+				return;
+			}
+		}
+	});
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		index = 0,
+		tweenerIndex = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				percent = 1 - ( remaining / animation.duration || 0 ),
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end, easing ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// if we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// resolve when we played the last frame
+				// otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	createTweens( animation, props );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			anim: animation,
+			queue: animation.opts.queue,
+			elem: elem
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// not quite $.extend, this wont overwrite keys already present.
+			// also - reusing 'index' from above because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+function defaultPrefilter( elem, props, opts ) {
+	var index, prop, value, length, dataShow, tween, hooks, oldfire,
+		anim = this,
+		style = elem.style,
+		orig = {},
+		handled = [],
+		hidden = elem.nodeType && isHidden( elem );
+
+	// handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// doing this makes sure that the complete handler will be called
+			// before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE does not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		if ( jQuery.css( elem, "display" ) === "inline" &&
+				jQuery.css( elem, "float" ) === "none" ) {
+
+			// inline-level elements accept inline-block;
+			// block-level elements need to be inline with layout
+			if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+				style.display = "inline-block";
+
+			} else {
+				style.zoom = 1;
+			}
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		if ( !jQuery.support.shrinkWrapBlocks ) {
+			anim.done(function() {
+				style.overflow = opts.overflow[ 0 ];
+				style.overflowX = opts.overflow[ 1 ];
+				style.overflowY = opts.overflow[ 2 ];
+			});
+		}
+	}
+
+
+	// show/hide pass
+	for ( index in props ) {
+		value = props[ index ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ index ];
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+				continue;
+			}
+			handled.push( index );
+		}
+	}
+
+	length = handled.length;
+	if ( length ) {
+		dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+			jQuery.removeData( elem, "fxshow", true );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( index = 0 ; index < length ; index++ ) {
+			prop = handled[ index ];
+			tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+			orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+	}
+}
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// passing any value as a 4th parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails
+			// so, simple values such as "10px" are parsed to Float.
+			// complex values such as "rotate(1rad)" are returned as is.
+			result = jQuery.css( tween.elem, tween.prop, false, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// use step hook for back compat - use cssHook if its there - use .style if its
+			// available and use plain properties where available
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ||
+			// special check for .toggle( handler, handler, ... )
+			( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations resolve immediately
+				if ( empty ) {
+					anim.stop( true );
+				}
+			};
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = jQuery._data( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// start the next in the queue if the last step wasn't forced
+			// timers currently will call their complete callbacks, which will dequeue
+			// but only if they were gotoEnd
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	}
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		attrs = { height: type },
+		i = 0;
+
+	// if we include width, step value is 1 to do all cssExpand values,
+	// if we don't include width, step value is 2 to skip over Left and Right
+	includeWidth = includeWidth? 1 : 0;
+	for( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p*Math.PI ) / 2;
+	}
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+	var timer,
+		timers = jQuery.timers,
+		i = 0;
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+};
+
+jQuery.fx.timer = function( timer ) {
+	if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.animated = function( elem ) {
+		return jQuery.grep(jQuery.timers, function( fn ) {
+			return elem === fn.elem;
+		}).length;
+	};
+}
+var rroot = /^(?:body|html)$/i;
+
+jQuery.fn.offset = function( options ) {
+	if ( arguments.length ) {
+		return options === undefined ?
+			this :
+			this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+	}
+
+	var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,
+		box = { top: 0, left: 0 },
+		elem = this[ 0 ],
+		doc = elem && elem.ownerDocument;
+
+	if ( !doc ) {
+		return;
+	}
+
+	if ( (body = doc.body) === elem ) {
+		return jQuery.offset.bodyOffset( elem );
+	}
+
+	docElem = doc.documentElement;
+
+	// Make sure it's not a disconnected DOM node
+	if ( !jQuery.contains( docElem, elem ) ) {
+		return box;
+	}
+
+	// If we don't have gBCR, just use 0,0 rather than error
+	// BlackBerry 5, iOS 3 (original iPhone)
+	if ( typeof elem.getBoundingClientRect !== "undefined" ) {
+		box = elem.getBoundingClientRect();
+	}
+	win = getWindow( doc );
+	clientTop  = docElem.clientTop  || body.clientTop  || 0;
+	clientLeft = docElem.clientLeft || body.clientLeft || 0;
+	scrollTop  = win.pageYOffset || docElem.scrollTop;
+	scrollLeft = win.pageXOffset || docElem.scrollLeft;
+	return {
+		top: box.top  + scrollTop  - clientTop,
+		left: box.left + scrollLeft - clientLeft
+	};
+};
+
+jQuery.offset = {
+
+	bodyOffset: function( body ) {
+		var top = body.offsetTop,
+			left = body.offsetLeft;
+
+		if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+		}
+
+		return { top: top, left: left };
+	},
+
+	setOffset: function( elem, options, i ) {
+		var position = jQuery.css( elem, "position" );
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		var curElem = jQuery( elem ),
+			curOffset = curElem.offset(),
+			curCSSTop = jQuery.css( elem, "top" ),
+			curCSSLeft = jQuery.css( elem, "left" ),
+			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+			props = {}, curPosition = {}, curTop, curLeft;
+
+		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+
+jQuery.fn.extend({
+
+	position: function() {
+		if ( !this[0] ) {
+			return;
+		}
+
+		var elem = this[0],
+
+		// Get *real* offsetParent
+		offsetParent = this.offsetParent(),
+
+		// Get correct offsets
+		offset       = this.offset(),
+		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+		// Subtract element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+		// Add offsetParent borders
+		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+		// Subtract the two offsets
+		return {
+			top:  offset.top  - parentOffset.top,
+			left: offset.left - parentOffset.left
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || document.body;
+			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent || document.body;
+		});
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+	var top = /Y/.test( prop );
+
+	jQuery.fn[ method ] = function( val ) {
+		return jQuery.access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? (prop in win) ? win[ prop ] :
+					win.document.documentElement[ method ] :
+					elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : jQuery( win ).scrollLeft(),
+					 top ? val : jQuery( win ).scrollTop()
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return jQuery.access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, value, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+	define( "jquery", [], function () { return jQuery; } );
+}
+
+})( window );
diff --git a/src/main/webapp/lib/jquery/jquery-ui-1.8.6.custom.min.js b/src/main/webapp/lib/jquery/jquery-ui-1.8.6.custom.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..312c0199450c4aad9ef35cd75213a0001a1a3456
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery-ui-1.8.6.custom.min.js
@@ -0,0 +1,778 @@
+/*!
+ * jQuery UI 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.6",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,
+NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,
+"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");
+if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,
+"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,
+d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}});
+c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&
+b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
+;/*!
+ * jQuery UI Widget 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,
+a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.charAt(0)==="_")return h;
+e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,
+this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},
+widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},
+enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
+;/*!
+ * jQuery UI Mouse 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ *	jquery.ui.widget.js
+ */
+(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
+this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
+return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
+this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
+a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
+;/*
+ * jQuery UI Position 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY,
+left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+=
+k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+parseInt(c.curCSS(this,"marginRight",true))||0,w=m+q+parseInt(c.curCSS(this,"marginBottom",true))||0,i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-=m/2;
+i.left=parseInt(i.left);i.top=parseInt(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left=d>0?
+b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+=
+a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b),
+g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery);
+;/*
+ * jQuery UI Draggable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
+"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
+this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
+this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
+d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
+this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
+b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
+a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
+0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
+"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
+a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
+10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
+f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
+Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
+this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
+this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.6"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
+if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
+c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
+1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
+this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
+this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
+d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
+if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
+"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
+b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
+c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
+width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
+o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
+p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
+(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
+10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
+;/*
+ * jQuery UI Droppable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.draggable.js
+ */
+(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
+a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
+this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
+this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
+d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
+a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.6"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
+switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
+i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
+"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
+a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
+d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
+;/*
+ * jQuery UI Resizable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(e){e.widget("ui.resizable",e.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");e.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
+_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&e.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
+top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
+this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
+nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d<c.length;d++){var f=e.trim(c[d]),g=e('<div class="ui-resizable-handle '+("ui-resizable-"+f)+'"></div>');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
+String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),k=0;k=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,k);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection();
+this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){e(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
+if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
+d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=
+this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
+this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis];if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
+b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;
+f={width:c.size.width-(f?0:c.sizeDiff.width),height:c.size.height-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f,{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
+b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(l(b.left))this.position.left=b.left;if(l(b.top))this.position.top=b.top;if(l(b.height))this.size.height=b.height;if(l(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top=
+a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,d=l(b.width)&&a.maxWidth&&a.maxWidth<b.width,f=l(b.height)&&a.maxHeight&&a.maxHeight<b.height,g=l(b.width)&&a.minWidth&&a.minWidth>b.width,h=l(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
+k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minWidth;if(d&&k)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var d=[c.css("borderTopWidth"),
+c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],f=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=e.map(d,function(g,h){g=parseInt(g,10)||0;h=parseInt(f[h],10)||0;return g+h})}e.browser.msie&&(e(b).is(":hidden")||e(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
+this.element.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,
+arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,
+{version:"1.8.6"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,
+function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=
+(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=
+false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-
+a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",
+b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top",
+"Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset;var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,
+f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left:a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=
+a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top-d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+
+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition,f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&
+e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",
+height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=
+d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
+;/*
+ * jQuery UI Selectable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),
+selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX,
+c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting",
+c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d=
+this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");
+a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&
+!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=
+e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.6"})})(jQuery);
+;/*
+ * jQuery UI Sortable 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
+this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
+arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
+c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
+{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
+if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
+a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
+if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
+c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
+document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
+null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
+d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||
+"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+
+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?
+2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},
+_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=
+this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=
+this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");
+if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=
+0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=
+this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},
+update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=
+null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));
+this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,
+null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||
+d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a==
+"string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition==
+"absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==
+"relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},
+_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-
+this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),
+10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?
+this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=
+this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+
+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?
+g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():
+e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==
+f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",
+f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",
+g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=
+0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});
+d.extend(d.ui.sortable,{version:"1.8.6"})})(jQuery);
+;/*
+ * jQuery UI Accordion 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ */
+(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix");
+a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var f=d.closest(".ui-accordion-header");a.active=f.length?f:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion",
+function(g){return a._keydown(g)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(g){a._clickHandler.call(a,g,this);g.preventDefault()})},_createIcons:function(){var a=this.options;if(a.icons){c("<span></span>").addClass("ui-icon "+
+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");
+this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();
+b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target);
+a.preventDefault()}if(g){c(a.target).attr("tabIndex",-1);c(g).attr("tabIndex",0);g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+
+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options;
+if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);
+a.next().addClass("ui-accordion-content-active")}h=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):h,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(h,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);
+this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},h=this.active=c([]);this._toggle(h,f,g)}},_toggle:function(a,b,d,f,g){var h=this,e=h.options;h.toShow=a;h.toHide=b;h.data=d;var j=function(){if(h)return h._completed.apply(h,arguments)};h._trigger("changestart",null,h.data);h.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),toHide:b,complete:j,
+down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!f[k]&&!c.easing[k])k="slide";f[k]||(f[k]=function(l){this.slide(l,{easing:k,duration:i||700})});
+f[k](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.6",animations:{slide:function(a,
+b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},h={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){h[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/);g[i]={value:j[1],
+unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(h,{step:function(j,i){if(i.prop=="height")f=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=f*g[i.prop].value+g[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide",paddingTop:"hide",
+paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
+;/*
+ * jQuery UI Autocomplete 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ *	jquery.ui.position.js
+ */
+(function(e){e.widget("ui.autocomplete",{options:{appendTo:"body",delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},_create:function(){var a=this,b=this.element[0].ownerDocument,f;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.attr("readonly"))){f=false;var d=e.ui.keyCode;switch(c.keyCode){case d.PAGE_UP:a._move("previousPage",
+c);break;case d.PAGE_DOWN:a._move("nextPage",c);break;case d.UP:a._move("previous",c);c.preventDefault();break;case d.DOWN:a._move("next",c);c.preventDefault();break;case d.ENTER:case d.NUMPAD_ENTER:if(a.menu.active){f=true;c.preventDefault()}case d.TAB:if(!a.menu.active)return;a.menu.select(c);break;case d.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);
+break}}}).bind("keypress.autocomplete",function(c){if(f){f=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo(e(this.options.appendTo||
+"body",b)[0]).mousedown(function(c){var d=a.menu.element[0];e(c.target).closest(".ui-menu-item").length||setTimeout(function(){e(document).one("mousedown",function(g){g.target!==a.element[0]&&g.target!==d&&!e.ui.contains(d,g.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:d})&&/^key/.test(c.originalEvent.type)&&a.element.val(d.value)},selected:function(c,d){d=d.item.data("item.autocomplete");
+var g=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=g;setTimeout(function(){a.previous=g},1)}false!==a._trigger("select",c,{item:d})&&a.element.val(d.value);a.term=a.element.val();a.close(c);a.selectedItem=d},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");
+this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a,b){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(e(b||"body",this.element[0].ownerDocument)[0])},_initSource:function(){var a=this,b,f;if(e.isArray(this.options.source)){b=this.options.source;this.source=function(c,d){d(e.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){f=this.options.source;this.source=
+function(c,d){a.xhr&&a.xhr.abort();a.xhr=e.getJSON(f,c,function(g,i,h){h===a.xhr&&d(g);a.xhr=null})}}else this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)!==false)return this._search(a)},_search:function(a){this.element.addClass("ui-autocomplete-loading");this.source({term:a},this.response)},_response:function(a){if(a&&a.length){a=
+this._normalize(a);this._suggest(a);this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(b){if(typeof b===
+"string")return{label:b,value:b};return e.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(a){this._renderMenu(this.menu.element.empty().zIndex(this.element.zIndex()+1),a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position(e.extend({of:this.element},this.options.position));this._resizeMenu()},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth(),this.element.outerWidth()))},_renderMenu:function(a,b){var f=
+this;e.each(b,function(c,d){f._renderItem(a,d)})},_renderItem:function(a,b){return e("<li></li>").data("item.autocomplete",b).append(e("<a></a>").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,
+"\\$&")},filter:function(a,b){var f=new RegExp(e.ui.autocomplete.escapeRegex(b),"i");return e.grep(a,function(c){return f.test(c.label||c.value||c)})}})})(jQuery);
+(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(b){if(e(b.target).closest(".ui-menu-item a").length){b.preventDefault();a.select(b)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
+-1).mouseenter(function(b){a.activate(b,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var f=b.offset().top-this.element.offset().top,c=this.element.attr("scrollTop"),d=this.element.height();if(f<0)this.element.attr("scrollTop",c+f);else f>=d&&this.element.attr("scrollTop",c+f-d+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:b})},
+deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,f){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);
+a.length?this.activate(f,a):this.activate(f,this.element.children(b))}else this.activate(f,this.element.children(b))},nextPage:function(a){if(this.hasScroll())if(!this.active||this.last())this.activate(a,this.element.children(".ui-menu-item:first"));else{var b=this.active.offset().top,f=this.element.height(),c=this.element.children(".ui-menu-item").filter(function(){var d=e(this).offset().top-b-f+e(this).height();return d<10&&d>-10});c.length||(c=this.element.children(".ui-menu-item:last"));this.activate(a,
+c)}else this.activate(a,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(".ui-menu-item:last"));else{var b=this.active.offset().top,f=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var c=e(this).offset().top-b+f-e(this).height();return c<10&&c>-10});result.length||(result=this.element.children(".ui-menu-item:first"));
+this.activate(a,result)}else this.activate(a,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})})(jQuery);
+;/*
+ * jQuery UI Button 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ */
+(function(a){var g,i=function(b){a(":ui-button",b.target.form).each(function(){var c=a(this).data("button");setTimeout(function(){c.refresh()},1)})},h=function(b){var c=b.name,d=b.form,e=a([]);if(c)e=d?a(d).find("[name='"+c+"']"):a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form});return e};a.widget("ui.button",{options:{disabled:null,text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",
+i);if(typeof this.options.disabled!=="boolean")this.options.disabled=this.element.attr("disabled");this._determineButtonType();this.hasTitle=!!this.buttonElement.attr("title");var b=this,c=this.options,d=this.type==="checkbox"||this.type==="radio",e="ui-state-hover"+(!d?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",
+function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",function(){c.disabled||a(this).removeClass(e)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");
+b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var f=b.element[0];h(f).not(f).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");
+g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(f){if(c.disabled)return false;if(f.keyCode==a.ui.keyCode.SPACE||f.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(f){f.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",
+c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("label[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=
+this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());this.hasTitle||
+this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
+true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"),
+c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary"));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary");
+this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":visible").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end().end()},
+destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
+;/*
+ * jQuery UI Dialog 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ *  jquery.ui.button.js
+ *	jquery.ui.draggable.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.position.js
+ *	jquery.ui.resizable.js
+ */
+(function(c,j){var k={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},l={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:{my:"center",at:"center",of:window,collision:"fit",using:function(a){var b=c(this).css(a).offset().top;
+b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||"&#160;",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",
+-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role",
+"button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id",e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=
+b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");a.uiDialog.remove();a.originalTitle&&
+a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});
+c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);
+d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target===f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();
+a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;f=c('<button type="button"></button>').attr(h,true).unbind("click").click(function(){h.click.apply(b.element[0],
+arguments)}).appendTo(g);c.fn.button&&f.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,
+h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===j?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";
+d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",
+g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,
+a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(a);e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f);if(g in k)e=true;if(g in l)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);
+break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");
+g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||"&#160;"));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a=this.options,b,d;this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,
+height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height-b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.6",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});
+c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()<c.ui.dialog.overlay.maxZ)return false})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&
+d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");
+a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,
+document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,function(){a=a.add(this)});a.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
+;/*
+ * jQuery UI Slider 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.mouse.js
+ *	jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
+this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
+if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
+else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),h,g,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
+false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");h=a._start(c,f);if(h===false)return}break}i=a.options.step;h=a.options.values&&a.options.values.length?(g=a.values(f)):(g=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:g=a._valueMin();break;case d.ui.keyCode.END:g=a._valueMax();break;case d.ui.keyCode.PAGE_UP:g=a._trimAlignValue(h+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:g=a._trimAlignValue(h-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(h===
+a._valueMax())return;g=a._trimAlignValue(h+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(h===a._valueMin())return;g=a._trimAlignValue(h-i);break}a._slide(c,f,g);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
+this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,h,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});e=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(i){var j=Math.abs(c-h.values(i));if(e>j){e=j;f=d(this);g=i}});if(b.range===true&&this.values(1)===b.min){g+=1;f=d(this.handles[g])}if(this._start(a,
+g)===false)return false;this._mouseSliding=true;h._handleIndex=g;f.addClass("ui-state-active").focus();b=f.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-f.width()/2,top:a.pageY-b.top-f.height()/2-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b=
+this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b=
+this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);
+c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],value:c});
+a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
+this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
+else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
+this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
+return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
+this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,h={},g,i,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(k){f=(c.values(k)-c._valueMin())/(c._valueMax()-c._valueMin())*100;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](h,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({width:f-
+g+"%"},{queue:false,duration:b.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:b.animate})}g=f});else{i=this.value();j=this._valueMin();l=this._valueMax();f=l!==j?(i-j)/(l-j)*100:0;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](h,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
+b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.6"})})(jQuery);
+;/*
+ * jQuery UI Tabs 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ */
+(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&&
+e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=
+d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]||
+(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a._sanitizeSelector(i));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=d("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");
+this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected=
+this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");
+if(c.selected>=0&&this.anchors.length){d(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],d(a._sanitizeSelector(a.anchors[c.selected].hash))))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));
+this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+
+g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",
+function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};
+this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected=-1;c.cookie&&
+a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";
+d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=
+d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b,
+e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=d("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);
+j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();
+if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=b}),function(h){return h>=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null,
+this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this},
+load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c,"cache.tabs",
+true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(b,
+e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.6"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k<a.anchors.length?k:0)},b);j&&j.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(j){j.clientX&&a.rotate(null)}:
+function(){t=c.selected;h()});if(b){this.element.bind("tabsshow",h);this.anchors.bind(c.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(c.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
+;/*
+ * jQuery UI Datepicker 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ */
+(function(d,G){function K(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
+"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
+"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
+minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
+b);for(var c in b)if(b[c]==null||b[c]==G)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.6"}});var y=(new Date).getTime();d.extend(K.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
+f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
+_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
+b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
+""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
+c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
+true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==
+Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
+d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
+_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
+d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
+for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
+this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
+!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
+return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
+a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
+a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
+var c=String.fromCharCode(a.charCode==G?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
+a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
+d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
+d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
+h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
+this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
+this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
+a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
+k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
+a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
+"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
+!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
+b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){var b=
+this._getInst(d(a)[0]);b.input&&b._selectingMonthYear&&setTimeout(function(){b.input.focus()},0);b._selectingMonthYear=!b._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=
+d(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,
+"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b==
+"object"?b.toString():b+"";if(b=="")return null;for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?
+3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,H){p=o(p)?H:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length).toLowerCase()==p[w].toLowerCase()){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");
+break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>
+-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*
+60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)==
+"'"&&!i("'"))u=false;else l+=a.charAt(j);else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+=
+"'";else u=true;break;default:l+=a.charAt(j)}return l},_possibleChars:function(a){for(var b="",c=false,e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==G?a.settings[b]:this._defaults[b]},
+_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,
+this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=
+parseInt(j[1],10);break;case "w":case "W":g+=parseInt(j[1],10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},
+_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?
+"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=
+this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,
+"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+
+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+
+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
+y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var L=this._getDefaultDate(a),I="",C=0;C<i[0];C++){for(var M=
+"",D=0;D<i[1];D++){var N=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
+f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
+A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var O=0;O<A;O++){x+="<tr>";var P=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,J=B&&!H||!F[0]||j&&q<j||o&&q>o;P+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==N.getTime()&&g==a.selectedMonth&&
+a._keyEvent||L.getTime()==q.getTime()&&L.getTime()==N.getTime()?" "+this._dayOverClass:"")+(J?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(J?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":J?'<span class="ui-state-default">'+q.getDate()+
+"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=P+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");M+=x}I+=M}I+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
+"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
+a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
+i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
+a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
+"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
+c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
+"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
+function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
+return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new K;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.6";window["DP_jQuery_"+y]=d})(jQuery);
+;/*
+ * jQuery UI Progressbar 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   jquery.ui.core.js
+ *   jquery.ui.widget.js
+ */
+(function(b,c){b.widget("ui.progressbar",{options:{value:0},min:0,max:100,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
+this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===c)return this._value();this._setOption("value",a);return this},_setOption:function(a,d){if(a==="value"){this.options.value=d;this._refreshValue();this._trigger("change");this._value()===this.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.max,Math.max(this.min,a))},_refreshValue:function(){var a=
+this.value();this.valueDiv.toggleClass("ui-corner-right",a===this.max).width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.6"})})(jQuery);
+;/*
+ * jQuery UI Effects 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1],
+16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,
+a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d=
+a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor",
+"borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,
+0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],
+lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=
+b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("className");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("className",v);e.animate(u(h,r),a,b,function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?
+f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,
+[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.6",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=
+0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,
+{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=
+k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=
+k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,
+a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*
+(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,
+a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,
+a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+
+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==
+j)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*
+(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
+;/*
+ * jQuery UI Effects Blind 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","left"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,g);b.effects.removeWrapper(a);
+c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
+;/*
+ * jQuery UI Effects Bounce 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","left"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/
+3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
+b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Clip 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","left","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,c/2)}var h={};h[g.size]=
+f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Drop 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","left","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e=="show"?1:
+0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Explode 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f=
+0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
+e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
+;/*
+ * jQuery UI Effects Fade 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fade
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Fold 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100*
+f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
+;/*
+ * jQuery UI Effects Highlight 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
+this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Pulsate 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
+a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Scale 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a,
+b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity=
+1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","left","width","height","overflow","opacity"],g=["position","top","left","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=c.effects.setMode(a,
+b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}};if(m=="box"||m=="both"){if(d.from.y!=
+d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a);a.css("overflow","hidden").css(a.from);
+if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from);child.to=c.effects.setTransition(child,
+f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,n?e:g);c.effects.removeWrapper(a);b.callback&&
+b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Shake 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","left"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=(h=="pos"?"-=":"+=")+
+e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Slide 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","left"],e=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(e=="show")a.css(f,b=="pos"?-g:g);var i={};i[f]=(e=="show"?b=="pos"?
+"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Transfer 1.8.6
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *	jquery.effects.core.js
+ */
+(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
+b.dequeue()})})}})(jQuery);
+;
\ No newline at end of file
diff --git a/src/main/webapp/lib/jquery/jquery-ui-timepicker-addon.js b/src/main/webapp/lib/jquery/jquery-ui-timepicker-addon.js
new file mode 100644
index 0000000000000000000000000000000000000000..63d2efab6f5cc38ff31ef19efd3f7f93cd7af6a0
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery-ui-timepicker-addon.js
@@ -0,0 +1,682 @@
+/*
+* jQuery timepicker addon
+* By: Trent Richardson [http://trentrichardson.com]
+* Version 0.7
+* Last Modified: 10/7/2010
+* 
+* Copyright 2010 Trent Richardson
+* Dual licensed under the MIT and GPL licenses.
+* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
+* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
+* 
+* HERES THE CSS:
+* .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }
+* .ui-timepicker-div dl{ text-align: left; }
+* .ui-timepicker-div dl dt{ height: 25px; }
+* .ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }
+* .ui-timepicker-div .ui_tpicker_hour div { padding-right: 2px; }
+* .ui-timepicker-div .ui_tpicker_minute div { padding-right: 6px; }
+* .ui-timepicker-div .ui_tpicker_second div { padding-right: 6px; }
+* .ui-timepicker-div td { font-size: 90%; }
+*/
+
+(function($) {
+	function Timepicker(singleton) {
+		if(typeof(singleton) === 'boolean' && singleton == true) {
+			this.regional = []; // Available regional settings, indexed by language code
+			this.regional[''] = { // Default regional settings
+				currentText: 'Now',
+				ampm: false,
+				timeFormat: 'hh:mm tt',
+				timeOnlyTitle: 'Choose Time',
+				timeText: 'Time',
+				hourText: 'Hour',
+				minuteText: 'Minute',
+				secondText: 'Second'
+			};
+			this.defaults = { // Global defaults for all the datetime picker instances
+				showButtonPanel: true,
+				timeOnly: false,
+				showHour: true,
+				showMinute: true,
+				showSecond: false,
+				showTime: true,
+				stepHour: 0.05,
+				stepMinute: 0.05,
+				stepSecond: 0.05,
+				hour: 0,
+				minute: 0,
+				second: 0,
+				hourMin: 0,
+				minuteMin: 0,
+				secondMin: 0,
+				hourMax: 23,
+				minuteMax: 59,
+				secondMax: 59,
+				hourGrid: 0,
+				minuteGrid: 0,
+				secondGrid: 0,
+				alwaysSetTime: true
+			};
+			$.extend(this.defaults, this.regional['']);
+		} else {
+			this.defaults = $.extend({}, $.timepicker.defaults);
+		}
+
+	};
+
+	Timepicker.prototype = {
+		$input: null,
+		$altInput: null,
+		$timeObj: null,
+		inst: null,
+		hour_slider: null,
+		minute_slider: null,
+		second_slider: null,
+		hour: 0,
+		minute: 0,
+		second: 0,
+		ampm: '',
+		formattedDate: '',
+		formattedTime: '',
+		formattedDateTime: '',
+
+		//########################################################################
+		// add our sliders to the calendar
+		//########################################################################
+		addTimePicker: function(dp_inst) {
+			var tp_inst = this;
+			var currDT;
+			if ((this.$altInput) && this.$altInput != null)
+			{
+				currDT = this.$input.val() + ' ' + this.$altInput.val();
+			}
+			else
+			{
+				currDT = this.$input.val();
+			}
+			var regstr = this.defaults.timeFormat.toString()
+				.replace(/h{1,2}/ig, '(\\d?\\d)')
+				.replace(/m{1,2}/ig, '(\\d?\\d)')
+				.replace(/s{1,2}/ig, '(\\d?\\d)')
+				.replace(/t{1,2}/ig, '(am|pm|a|p)?')
+				.replace(/\s/g, '\\s?') + '$';
+
+			if (!this.defaults.timeOnly) {
+				//the time should come after x number of characters and a space.  x = at least the length of text specified by the date format
+				var dp_dateFormat = $.datepicker._get(dp_inst, 'dateFormat');
+				regstr = '.{' + dp_dateFormat.length + ',}\\s+' + regstr;
+			}
+
+			var order = this.getFormatPositions();
+			var treg = currDT.match(new RegExp(regstr, 'i'));
+
+			if (treg) {
+				if (order.t !== -1) {
+					this.ampm = ((treg[order.t] === undefined || treg[order.t].length === 0) ? '' : (treg[order.t].charAt(0).toUpperCase() == 'A') ? 'AM' : 'PM').toUpperCase();
+				}
+
+				if (order.h !== -1) {
+					if (this.ampm == 'AM' && treg[order.h] == '12') {
+						// 12am = 0 hour
+						this.hour = 0;
+					} else if (this.ampm == 'PM' && treg[order.h] != '12') {
+						// 12pm = 12 hour, any other pm = hour + 12
+						this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0);
+					} else {
+						this.hour = treg[order.h];
+					}
+				}
+
+				if (order.m !== -1) {
+					this.minute = treg[order.m];
+				}
+
+				if (order.s !== -1) {
+					this.second = treg[order.s];
+				}
+			}
+
+			tp_inst.timeDefined = (treg) ? true : false;
+
+			if (typeof(dp_inst.stay_open) !== 'boolean' || dp_inst.stay_open === false) {
+			// wait for datepicker to create itself.. 60% of the time it works every time..
+				setTimeout(function() {
+					tp_inst.injectTimePicker(dp_inst, tp_inst);
+				}, 10);
+			} else {
+				tp_inst.injectTimePicker(dp_inst, tp_inst);
+			}
+
+		},
+
+		//########################################################################
+		// figure out position of time elements.. cause js cant do named captures
+		//########################################################################
+		getFormatPositions: function() {
+			var finds = this.defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|t{1,2})/g);
+			var orders = { h: -1, m: -1, s: -1, t: -1 };
+
+			if (finds) {
+				for (var i = 0; i < finds.length; i++) {
+					if (orders[finds[i].toString().charAt(0)] == -1) {
+						orders[finds[i].toString().charAt(0)] = i + 1;
+					}
+				}
+			}
+
+			return orders;
+		},
+
+		//########################################################################
+		// generate and inject html for timepicker into ui datepicker
+		//########################################################################
+		injectTimePicker: function(dp_inst, tp_inst) {
+			var $dp = dp_inst.dpDiv;
+			var opts = tp_inst.defaults;
+
+			// Added by Peter Medeiros:
+			// - Figure out what the hour/minute/second max should be based on the step values.
+			// - Example: if stepMinute is 15, then minMax is 45.
+			var hourMax = opts.hourMax - (opts.hourMax % opts.stepHour);
+			var minMax  = opts.minuteMax - (opts.minuteMax % opts.stepMinute);
+			var secMax  = opts.secondMax - (opts.secondMax % opts.stepSecond);
+
+			// Prevent displaying twice
+			if ($dp.find("div#ui-timepicker-div-"+ dp_inst.id).length === 0) {
+				var noDisplay = ' style="display:none;"';
+				var html =
+					'<div class="ui-timepicker-div" id="ui-timepicker-div-' + dp_inst.id + '"><dl>' +
+						'<dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_' + dp_inst.id + '"'	+ ((opts.showTime)   ? '' : noDisplay) + '>' + opts.timeText + '</dt>' +
+						'<dd class="ui_tpicker_time" id="ui_tpicker_time_' + dp_inst.id + '"'	+ ((opts.showTime)   ? '' : noDisplay) + '></dd>' +
+						'<dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_' + dp_inst.id + '"'   + ((opts.showHour)   ? '' : noDisplay) + '>' + opts.hourText + '</dt>';
+						
+				if (opts.hourGrid > 0)
+				{
+					html += '<dd class="ui_tpicker_hour ui_tpicker_hour_' + opts.hourGrid + '">' +
+							'<div id="ui_tpicker_hour_' + dp_inst.id + '"' + ((opts.showHour)   ? '' : noDisplay) + '></div>' +
+							'<div><table><tr>';
+							
+					for (var h = 0; h < hourMax; h += opts.hourGrid)
+					{
+						var tmph = h;
+						if(opts.ampm && h > 12)
+							tmph = h-12;
+						else tmph = h;
+
+						if(tmph < 10)
+							tmph = '0' + tmph;
+						if(opts.ampm)
+						{
+							if(h == 0)
+								tmph = 12 +'a';
+							else if(h < 12)
+								tmph += 'a';
+							else tmph += 'p';
+						}
+						html += '<td>' + tmph + '</td>';
+					}
+								
+					html += '</tr></table></div>' +
+							'</dd>';
+				}
+				else
+				{
+					html += '<dd class="ui_tpicker_hour" id="ui_tpicker_hour_' + dp_inst.id + '"'	+ ((opts.showHour)   ? '' : noDisplay) + '></dd>';
+				}
+						
+				html += '<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_' + dp_inst.id + '"'	+ ((opts.showMinute) ? '' : noDisplay) + '>' + opts.minuteText + '</dt>';
+				
+				if (opts.minuteGrid > 0)
+				{
+					html += '<dd class="ui_tpicker_minute ui_tpicker_minute_' + opts.minuteGrid + '">' +
+							'<div id="ui_tpicker_minute_' + dp_inst.id + '"' + ((opts.showMinute) ? '' : noDisplay) + '></div>' +
+							'<div><table><tr>';
+							
+					for (var m = 0; m < minMax; m += opts.minuteGrid)
+					{
+						html += '<td>' + ((m < 10) ? '0' : '') + m + '</td>';
+					}
+								
+					html += '</tr></table></div>' +
+							'</dd>';
+				}
+				else
+				{
+					html += '<dd class="ui_tpicker_minute" id="ui_tpicker_minute_' + dp_inst.id + '"'	+ ((opts.showMinute) ? '' : noDisplay) + '></dd>'
+				}
+				
+				html += '<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_' + dp_inst.id + '"'	+ ((opts.showSecond) ? '' : noDisplay) + '>' + opts.secondText + '</dt>';
+				
+				if (opts.secondGrid > 0)
+				{
+					html += '<dd class="ui_tpicker_second ui_tpicker_second_' + opts.secondGrid + '">' +
+							'<div id="ui_tpicker_second_' + dp_inst.id + '"' + ((opts.showSecond) ? '' : noDisplay) + '></div>' +
+							'<table><table><tr>';
+							
+					for (var s = 0; s < secMax; s += opts.secondGrid)
+					{
+						html += '<td>' + ((s < 10) ? '0' : '') + s + '</td>';
+					}
+								
+					html += '</tr></table></table>' +
+							'</dd>';
+				}
+				else
+				{
+					html += '<dd class="ui_tpicker_second" id="ui_tpicker_second_' + dp_inst.id + '"'	+ ((opts.showSecond) ? '' : noDisplay) + '></dd>';
+				}
+				
+				html += '</dl></div>';
+				$tp = $(html);
+
+				// if we only want time picker...
+				if (opts.timeOnly === true) {
+					$tp.prepend(
+						'<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' +
+							'<div class="ui-datepicker-title">'+ opts.timeOnlyTitle +'</div>' +
+						'</div>');
+					$dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
+				}
+
+				tp_inst.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_inst.id).slider({
+					orientation: "horizontal",
+					value: tp_inst.hour,
+					min: opts.hourMin,
+					max: hourMax,
+					step: opts.stepHour,
+					slide: function(event, ui) {
+						tp_inst.hour_slider.slider( "option", "value", ui.value );
+						tp_inst.onTimeChange(dp_inst, tp_inst);
+					}
+				});
+
+				// Updated by Peter Medeiros:
+				// - Pass in Event and UI instance into slide function
+				tp_inst.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_inst.id).slider({
+					orientation: "horizontal",
+					value: tp_inst.minute,
+					min: opts.minuteMin,
+					max: minMax,
+					step: opts.stepMinute,
+					slide: function(event, ui) {
+						// update the global minute slider instance value with the current slider value
+						tp_inst.minute_slider.slider( "option", "value", ui.value );
+						tp_inst.onTimeChange(dp_inst, tp_inst);
+					}
+				});
+
+				tp_inst.second_slider = $tp.find('#ui_tpicker_second_'+ dp_inst.id).slider({
+					orientation: "horizontal",
+					value: tp_inst.second,
+					min: opts.secondMin,
+					max: secMax,
+					step: opts.stepSecond,
+					slide: function(event, ui) {
+						tp_inst.second_slider.slider( "option", "value", ui.value );
+						tp_inst.onTimeChange(dp_inst, tp_inst);
+					}
+				});
+
+				// Add grid functionality
+				$tp.find(".ui_tpicker_hour td").each(
+						function(index)
+						{
+							$(this).click(
+									function()
+									{
+										var h = $(this).html();
+										if(opts.ampm)
+										{
+											var ap = h.substring(2).toLowerCase();
+											var aph = new Number(h.substring(0,2));
+
+											if(ap == 'a'){
+												if(aph == 12)
+													h = 0;
+												else h = aph;
+											}else{
+												if(aph == 12)
+													h = 12;
+												else h = aph + 12;
+											}
+										}
+										tp_inst.hour_slider.slider("option", "value", h);
+										tp_inst.onTimeChange(dp_inst, tp_inst);
+									}
+								);
+							
+							$(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
+						}
+					);
+				$tp.find(".ui_tpicker_minute td").each(
+						function(index)
+						{
+							$(this).click(
+									function()
+									{
+										tp_inst.minute_slider.slider("option", "value", $(this).html());
+										tp_inst.onTimeChange(dp_inst, tp_inst);
+									}
+								);
+							
+							$(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
+						}
+					);
+				$tp.find(".ui_tpicker_second td").each(
+						function(index)
+						{
+							$(this).click(
+									function()
+									{
+										tp_inst.second_slider.slider("option", "value", $(this).html());
+										tp_inst.onTimeChange(dp_inst, tp_inst);
+									}
+								);
+							$(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
+						}
+					);
+					
+				$dp.find('.ui-datepicker-calendar').after($tp);
+				
+				tp_inst.$timeObj = $('#ui_tpicker_time_'+ dp_inst.id);
+
+				if (dp_inst !== null) {
+					var timeDefined = tp_inst.timeDefined;
+					tp_inst.onTimeChange(dp_inst, tp_inst);
+					tp_inst.timeDefined = timeDefined;
+				}
+			}
+		},
+
+		//########################################################################
+		// when a slider moves..
+		// on time change is also called when the time is updated in the text field
+		//########################################################################
+		onTimeChange: function(dp_inst, tp_inst) {
+			var hour   = tp_inst.hour_slider.slider('value');
+			var minute = tp_inst.minute_slider.slider('value');
+			var second = tp_inst.second_slider.slider('value');
+			var ampm = (hour < 11.5) ? 'AM' : 'PM';
+			hour = (hour >= 11.5 && hour < 12) ? 12 : hour;
+			var hasChanged = false;
+
+			// If the update was done in the input field, this field should not be updated.
+			// If the update was done using the sliders, update the input field.
+			if (tp_inst.hour != hour || tp_inst.minute != minute || tp_inst.second != second || (tp_inst.ampm.length > 0 && tp_inst.ampm != ampm)) {
+				hasChanged = true;
+			}
+
+			tp_inst.hour = parseFloat(hour).toFixed(0);
+			tp_inst.minute = parseFloat(minute).toFixed(0);
+			tp_inst.second = parseFloat(second).toFixed(0);
+			tp_inst.ampm = ampm;
+
+			tp_inst.formatTime(tp_inst);
+			tp_inst.$timeObj.text(tp_inst.formattedTime);
+
+			if (hasChanged) {
+				tp_inst.updateDateTime(dp_inst, tp_inst);
+				tp_inst.timeDefined = true;
+			}
+		},
+
+		//########################################################################
+		// format the time all pretty...
+		//########################################################################
+		formatTime: function(tp_inst) {
+			var tmptime = tp_inst.defaults.timeFormat.toString();
+			var hour12 = ((tp_inst.ampm == 'AM') ? (tp_inst.hour) : (tp_inst.hour % 12));
+			hour12 = (Number(hour12) === 0) ? 12 : hour12;
+
+			if (tp_inst.defaults.ampm === true) {
+				tmptime = tmptime.toString()
+					.replace(/hh/g, ((hour12 < 10) ? '0' : '') + hour12)
+					.replace(/h/g, hour12)
+					.replace(/mm/g, ((tp_inst.minute < 10) ? '0' : '') + tp_inst.minute)
+					.replace(/m/g, tp_inst.minute)
+					.replace(/ss/g, ((tp_inst.second < 10) ? '0' : '') + tp_inst.second)
+					.replace(/s/g, tp_inst.second)
+					.replace(/TT/g, tp_inst.ampm.toUpperCase())
+					.replace(/tt/g, tp_inst.ampm.toLowerCase())
+					.replace(/T/g, tp_inst.ampm.charAt(0).toUpperCase())
+					.replace(/t/g, tp_inst.ampm.charAt(0).toLowerCase());
+
+			} else {
+				tmptime = tmptime.toString()
+					.replace(/hh/g, ((tp_inst.hour < 10) ? '0' : '') + tp_inst.hour)
+					.replace(/h/g, tp_inst.hour)
+					.replace(/mm/g, ((tp_inst.minute < 10) ? '0' : '') + tp_inst.minute)
+					.replace(/m/g, tp_inst.minute)
+					.replace(/ss/g, ((tp_inst.second < 10) ? '0' : '') + tp_inst.second)
+					.replace(/s/g, tp_inst.second);
+				tmptime = $.trim(tmptime.replace(/t/gi, ''));
+			}
+
+			tp_inst.formattedTime = tmptime;
+			return tp_inst.formattedTime;
+		},
+
+		//########################################################################
+		// update our input with the new date time..
+		//########################################################################
+		updateDateTime: function(dp_inst, tp_inst) {
+			var dt = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
+			var dateFmt = $.datepicker._get(dp_inst, 'dateFormat');
+			var formatCfg = $.datepicker._getFormatConfig(dp_inst);
+			this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
+			var formattedDateTime = this.formattedDate;
+			var timeAvailable = dt !== null && tp_inst.timeDefined;
+
+			if(this.defaults.timeOnly === true){
+				formattedDateTime = this.formattedTime;
+			}
+			else if (this.defaults.timeOnly !== true && (this.defaults.alwaysSetTime || timeAvailable)) {
+				if ((this.$altInput) && this.$altInput != null)
+				{
+					this.$altInput.val(this.formattedTime);
+				}
+				else{
+					formattedDateTime += ' ' + this.formattedTime;
+				}
+			}
+			
+			this.formattedDateTime = formattedDateTime;
+			this.$input.val(formattedDateTime);
+			this.$input.trigger("change");
+		},
+		
+		setDefaults: function(settings) {
+			extendRemove(this.defaults, settings || {});
+			return this;
+		}
+	};
+
+	//########################################################################
+	// extend timepicker to datepicker
+	//########################################################################		
+	jQuery.fn.datetimepicker = function(o) {
+		var opts = (o === undefined ? {} : o);
+		var input = $(this);
+		var tp = new Timepicker();
+		var inlineSettings = {};
+
+		for (var attrName in tp.defaults) {
+			var attrValue = input.attr('time:' + attrName);
+			if (attrValue) {
+				try {
+					inlineSettings[attrName] = eval(attrValue);
+				} catch (err) {
+					inlineSettings[attrName] = attrValue;
+				}
+			}
+		}
+		tp.defaults = $.extend(tp.defaults, inlineSettings);
+
+		var beforeShowFunc = function(input, inst) {
+			tp.hour = tp.defaults.hour;
+			tp.minute = tp.defaults.minute;
+			tp.second = tp.defaults.second;
+			tp.ampm = '';
+			tp.$input = $(input);
+			if(opts.altField != undefined && opts.altField != '')
+				tp.$altInput = $($.datepicker._get(inst, 'altField'));
+			tp.inst = inst;
+			tp.addTimePicker(inst);
+			if ($.isFunction(opts.beforeShow)) {
+				opts.beforeShow(input, inst);
+			}
+		};
+
+		var onChangeMonthYearFunc = function(year, month, inst) {
+			// Update the time as well : this prevents the time from disappearing from the input field.
+			tp.updateDateTime(inst, tp);
+			if ($.isFunction(opts.onChangeMonthYear)) {
+				opts.onChangeMonthYear(year, month, inst);
+			}
+		};
+
+		var onCloseFunc = function(dateText, inst) {
+			if(tp.timeDefined === true && input.val() != '') {
+				tp.updateDateTime(inst, tp);
+			}
+			if ($.isFunction(opts.onClose)) {
+				opts.onClose(dateText, inst);
+			}
+		};
+
+		tp.defaults = $.extend({}, tp.defaults, opts, {
+			beforeShow: beforeShowFunc,
+			onChangeMonthYear: onChangeMonthYearFunc,
+			onClose: onCloseFunc,
+			timepicker: tp // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
+		});
+
+		$(this).datepicker(tp.defaults);
+
+	};
+
+	//########################################################################
+	// shorthand just to use timepicker..
+	//########################################################################
+	jQuery.fn.timepicker = function(opts) {
+		opts = $.extend(opts, { timeOnly: true });
+		$(this).datetimepicker(opts);
+	};
+
+	//########################################################################
+	// the bad hack :/ override datepicker so it doesnt close on select
+	// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
+	//########################################################################
+	$.datepicker._base_selectDate = $.datepicker._selectDate;
+	$.datepicker._selectDate = function (id, dateStr) {
+		var target = $(id);
+		var inst = this._getInst(target[0]);
+		var tp_inst = $.datepicker._get(inst, 'timepicker');
+		
+		if(tp_inst){
+			inst.inline = true;
+			inst.stay_open = true;
+			$.datepicker._base_selectDate(id, dateStr);
+			inst.stay_open = false;
+			inst.inline = false;
+			this._notifyChange(inst);
+			this._updateDatepicker(inst);
+		}
+		else{
+			$.datepicker._base_selectDate(id, dateStr);
+		}
+	};
+
+	//#############################################################################################
+	// second bad hack :/ override datepicker so it triggers an event when changing the input field
+	// and does not redraw the datepicker on every selectDate event
+	//#############################################################################################
+	$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
+	$.datepicker._updateDatepicker = function(inst) {
+		if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
+			this._base_updateDatepicker(inst);
+			// Reload the time control when changing something in the input text field.
+			this._beforeShow(inst.input, inst);
+		}
+	};
+
+	$.datepicker._beforeShow = function(input, inst) {
+		var beforeShow = this._get(inst, 'beforeShow');
+		if (beforeShow) {
+			inst.stay_open = true;
+			beforeShow.apply((inst.input ? inst.input[0] : null), [inst.input, inst]);
+			inst.stay_open = false;
+		}
+	};
+
+	//#######################################################################################
+	// third bad hack :/ override datepicker so it allows spaces and colan in the input field
+	//#######################################################################################
+	$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
+	$.datepicker._doKeyPress = function(event) {
+		var inst = $.datepicker._getInst(event.target);
+		var tp_inst = $.datepicker._get(inst, 'timepicker');
+
+		if(tp_inst){
+			if ($.datepicker._get(inst, 'constrainInput')) {
+				var dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
+				var chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
+				var chrl = chr.toLowerCase();
+				// keyCode == 58 => ":"
+				// keyCode == 32 => " "
+				return event.ctrlKey || (chr < ' ' || !dateChars || dateChars.indexOf(chr) > -1 || event.keyCode == 58 || event.keyCode == 32 || chr == ':' || chr == ' ' || chrl == 'a' || chrl == 'p' || chrl == 'm');
+			}
+		}
+		else{
+			return $.datepicker._base_doKeyPress(event);
+		}
+
+	};
+
+	//#######################################################################################
+	// override "Today" button to also grab the time.
+	//#######################################################################################
+	$.datepicker._base_gotoToday = $.datepicker._gotoToday;
+	$.datepicker._gotoToday = function(id) {
+		$.datepicker._base_gotoToday(id);
+		
+		var target = $(id);
+		var dp_inst = this._getInst(target[0]);
+		var tp_inst = $.datepicker._get(dp_inst, 'timepicker');
+
+		if(tp_inst){
+			var date = new Date();
+			var hour = date.getHours();
+			var minute = date.getMinutes();
+			var second = date.getSeconds();
+
+			//check if within min/max times..
+			if( (hour < tp_inst.defaults.hourMin || hour > tp_inst.defaults.hourMax) || (minute < tp_inst.defaults.minuteMin || minute > tp_inst.defaults.minuteMax) || (second < tp_inst.defaults.secondMin || second > tp_inst.defaults.secondMax) ){					
+				hour = tp_inst.defaults.hourMin;
+				minute = tp_inst.defaults.minuteMin;
+				second = tp_inst.defaults.secondMin;				
+			}
+			
+			tp_inst.hour_slider.slider('value', hour );
+			tp_inst.minute_slider.slider('value', minute );
+			tp_inst.second_slider.slider('value', second );
+
+			tp_inst.onTimeChange(dp_inst, tp_inst);
+		}
+	};
+
+	//#######################################################################################
+	// jQuery extend now ignores nulls!
+	//#######################################################################################
+	function extendRemove(target, props) {
+		$.extend(target, props);
+		for (var name in props)
+			if (props[name] == null || props[name] == undefined)
+				target[name] = props[name];
+		return target;
+	};
+
+	$.timepicker = new Timepicker(true); // singleton instance
+})(jQuery);
+
diff --git a/src/main/webapp/lib/jquery/jquery.cometd-reload.js b/src/main/webapp/lib/jquery/jquery.cometd-reload.js
new file mode 100644
index 0000000000000000000000000000000000000000..07982ee3609579b3658b9ff29c4c8b064fb73a3e
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery.cometd-reload.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function($)
+{
+    function bind(org_cometd, cookie, ReloadExtension, cometd)
+    {
+        // Remap cometd COOKIE functions to jquery cookie functions
+        // Avoid to set to undefined if the jquery cookie plugin is not present
+        if (cookie)
+        {
+            org_cometd.COOKIE.set = cookie;
+            org_cometd.COOKIE.get = cookie;
+        }
+
+        var result = new ReloadExtension();
+        cometd.registerExtension('reload', result);
+        return result;
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd', 'jquery.cookie', 'org/cometd/ReloadExtension', 'jquery.cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd, $.cookie, org.cometd.ReloadExtension, $.cometd);
+    }
+})(jQuery);
diff --git a/src/main/webapp/lib/jquery/jquery.cometd.js b/src/main/webapp/lib/jquery/jquery.cometd.js
new file mode 100644
index 0000000000000000000000000000000000000000..39e800316be613b7fd47aaaebea8b1c8c16bde1b
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery.cometd.js
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function($)
+{
+    function bind($, org_cometd)
+    {
+        // Remap cometd JSON functions to jquery JSON functions
+        org_cometd.JSON.toJSON = JSON.stringify;
+        org_cometd.JSON.fromJSON = JSON.parse;
+
+        function _setHeaders(xhr, headers)
+        {
+            if (headers)
+            {
+                for (var headerName in headers)
+                {
+                    if (headerName.toLowerCase() === 'content-type')
+                    {
+                        continue;
+                    }
+                    xhr.setRequestHeader(headerName, headers[headerName]);
+                }
+            }
+        }
+
+        // Remap toolkit-specific transport calls
+        function LongPollingTransport()
+        {
+            var _super = new org_cometd.LongPollingTransport();
+            var that = org_cometd.Transport.derive(_super);
+
+            that.xhrSend = function(packet)
+            {
+                return $.ajax({
+                    url: packet.url,
+                    async: packet.sync !== true,
+                    type: 'POST',
+                    contentType: 'application/json;charset=UTF-8',
+                    data: packet.body,
+                    xhrFields: {
+                        // Has no effect if the request is not cross domain
+                        // but if it is, allows cookies to be sent to the server
+                        withCredentials: true
+                    },
+                    beforeSend: function(xhr)
+                    {
+                        _setHeaders(xhr, packet.headers);
+                        // Returning false will abort the XHR send
+                        return true;
+                    },
+                    success: packet.onSuccess,
+                    error: function(xhr, reason, exception)
+                    {
+                        packet.onError(reason, exception);
+                    }
+                });
+            };
+
+            return that;
+        }
+
+        function CallbackPollingTransport()
+        {
+            var _super = new org_cometd.CallbackPollingTransport();
+            var that = org_cometd.Transport.derive(_super);
+
+            that.jsonpSend = function(packet)
+            {
+                $.ajax({
+                    url: packet.url,
+                    async: packet.sync !== true,
+                    type: 'GET',
+                    dataType: 'jsonp',
+                    jsonp: 'jsonp',
+                    data: {
+                        // In callback-polling, the content must be sent via the 'message' parameter
+                        message: packet.body
+                    },
+                    beforeSend: function(xhr)
+                    {
+                        _setHeaders(xhr, packet.headers);
+                        // Returning false will abort the XHR send
+                        return true;
+                    },
+                    success: packet.onSuccess,
+                    error: function(xhr, reason, exception)
+                    {
+                        packet.onError(reason, exception);
+                    }
+                });
+            };
+
+            return that;
+        }
+
+        $.Cometd = function(name)
+        {
+            var cometd = new org_cometd.Cometd(name);
+
+            // Registration order is important
+            if (org_cometd.WebSocket)
+            {
+                cometd.registerTransport('websocket', new org_cometd.WebSocketTransport());
+            }
+            cometd.registerTransport('long-polling', new LongPollingTransport());
+            cometd.registerTransport('callback-polling', new CallbackPollingTransport());
+
+            return cometd;
+        };
+
+        // The default cometd instance
+        $.cometd = new $.Cometd();
+
+        return $.cometd;
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['jquery', 'org/cometd'], bind);
+    }
+    else
+    {
+        bind($, org.cometd);
+    }
+})(jQuery);
diff --git a/src/main/webapp/lib/jquery/jquery.cookie.js b/src/main/webapp/lib/jquery/jquery.cookie.js
new file mode 100644
index 0000000000000000000000000000000000000000..0c022916dbbc5d78cf8fd40b6d14c4e5a2d57424
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery.cookie.js
@@ -0,0 +1,56 @@
+/*!
+* jQuery Cookie Plugin
+* https://github.com/carhartl/jquery-cookie
+*
+* Copyright 2011, Klaus Hartl
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://www.opensource.org/licenses/mit-license.php
+* http://www.opensource.org/licenses/GPL-2.0
+*/
+(function($) {
+    $.cookie = function(key, value, options) {
+
+        // key and at least value given, set cookie...
+        if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) {
+            options = $.extend({}, options);
+
+            if (value === null || value === undefined) {
+                options.expires = -1;
+            }
+
+            if (typeof options.expires === 'number') {
+                var days = options.expires, t = options.expires = new Date();
+                t.setDate(t.getDate() + days);
+            }
+
+            value = String(value);
+
+            return (document.cookie = [
+                encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
+                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+                options.path    ? '; path=' + options.path : '',
+                options.domain  ? '; domain=' + options.domain : '',
+                options.secure  ? '; secure' : ''
+            ].join(''));
+        }
+
+        // key and possibly options given, get cookie...
+        options = value || {};
+        var decode = options.raw ? function(s) { return s; } : decodeURIComponent;
+
+        var pairs = document.cookie.split('; ');
+        for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
+            if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
+        }
+        return null;
+    };
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['jquery'], function($)
+        {
+            return $.cookie;
+        });
+    }
+
+})(jQuery);
diff --git a/src/main/webapp/lib/jquery/jquery.json-2.2.js b/src/main/webapp/lib/jquery/jquery.json-2.2.js
new file mode 100644
index 0000000000000000000000000000000000000000..87f5d0157c801ea16929f8452cde507e9c5f5bcd
--- /dev/null
+++ b/src/main/webapp/lib/jquery/jquery.json-2.2.js
@@ -0,0 +1,178 @@
+/*
+ * jQuery JSON Plugin
+ * version: 2.1 (2009-08-14)
+ *
+ * This document is licensed as free software under the terms of the
+ * MIT License: http://www.opensource.org/licenses/mit-license.php
+ *
+ * Brantley Harris wrote this plugin. It is based somewhat on the JSON.org 
+ * website's http://www.json.org/json2.js, which proclaims:
+ * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
+ * I uphold.
+ *
+ * It is also influenced heavily by MochiKit's serializeJSON, which is 
+ * copyrighted 2005 by Bob Ippolito.
+ */
+ 
+(function($) {
+    /** jQuery.toJSON( json-serializble )
+        Converts the given argument into a JSON respresentation.
+
+        If an object has a "toJSON" function, that will be used to get the representation.
+        Non-integer/string keys are skipped in the object, as are keys that point to a function.
+
+        json-serializble:
+            The *thing* to be converted.
+     **/
+    $.toJSON = function(o)
+    {
+        if (typeof(JSON) == 'object' && JSON.stringify)
+            return JSON.stringify(o);
+        
+        var type = typeof(o);
+    
+        if (o === null)
+            return "null";
+    
+        if (type == "undefined")
+            return undefined;
+        
+        if (type == "number" || type == "boolean")
+            return o + "";
+    
+        if (type == "string")
+            return $.quoteString(o);
+    
+        if (type == 'object')
+        {
+            if (typeof o.toJSON == "function") 
+                return $.toJSON( o.toJSON() );
+            
+            if (o.constructor === Date)
+            {
+                var month = o.getUTCMonth() + 1;
+                if (month < 10) month = '0' + month;
+
+                var day = o.getUTCDate();
+                if (day < 10) day = '0' + day;
+
+                var year = o.getUTCFullYear();
+                
+                var hours = o.getUTCHours();
+                if (hours < 10) hours = '0' + hours;
+                
+                var minutes = o.getUTCMinutes();
+                if (minutes < 10) minutes = '0' + minutes;
+                
+                var seconds = o.getUTCSeconds();
+                if (seconds < 10) seconds = '0' + seconds;
+                
+                var milli = o.getUTCMilliseconds();
+                if (milli < 100) milli = '0' + milli;
+                if (milli < 10) milli = '0' + milli;
+
+                return '"' + year + '-' + month + '-' + day + 'T' +
+                             hours + ':' + minutes + ':' + seconds + 
+                             '.' + milli + 'Z"'; 
+            }
+
+            if (o.constructor === Array) 
+            {
+                var ret = [];
+                for (var i = 0; i < o.length; i++)
+                    ret.push( $.toJSON(o[i]) || "null" );
+
+                return "[" + ret.join(",") + "]";
+            }
+        
+            var pairs = [];
+            for (var k in o) {
+                var name;
+                var type = typeof k;
+
+                if (type == "number")
+                    name = '"' + k + '"';
+                else if (type == "string")
+                    name = $.quoteString(k);
+                else
+                    continue;  //skip non-string or number keys
+            
+                if (typeof o[k] == "function") 
+                    continue;  //skip pairs where the value is a function.
+            
+                var val = $.toJSON(o[k]);
+            
+                pairs.push(name + ":" + val);
+            }
+
+            return "{" + pairs.join(", ") + "}";
+        }
+    };
+
+    /** jQuery.evalJSON(src)
+        Evaluates a given piece of json source.
+     **/
+    $.evalJSON = function(src)
+    {
+        if (typeof(JSON) == 'object' && JSON.parse)
+            return JSON.parse(src);
+        return eval("(" + src + ")");
+    };
+    
+    /** jQuery.secureEvalJSON(src)
+        Evals JSON in a way that is *more* secure.
+    **/
+    $.secureEvalJSON = function(src)
+    {
+        if (typeof(JSON) == 'object' && JSON.parse)
+            return JSON.parse(src);
+        
+        var filtered = src;
+        filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
+        filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
+        filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
+        
+        if (/^[\],:{}\s]*$/.test(filtered))
+            return eval("(" + src + ")");
+        else
+            throw new SyntaxError("Error parsing JSON, source is not valid.");
+    };
+
+    /** jQuery.quoteString(string)
+        Returns a string-repr of a string, escaping quotes intelligently.  
+        Mostly a support function for toJSON.
+    
+        Examples:
+            >>> jQuery.quoteString("apple")
+            "apple"
+        
+            >>> jQuery.quoteString('"Where are we going?", she asked.')
+            "\"Where are we going?\", she asked."
+     **/
+    $.quoteString = function(string)
+    {
+        if (string.match(_escapeable))
+        {
+            return '"' + string.replace(_escapeable, function (a) 
+            {
+                var c = _meta[a];
+                if (typeof c === 'string') return c;
+                c = a.charCodeAt();
+                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
+            }) + '"';
+        }
+        return '"' + string + '"';
+    };
+    
+    var _escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
+    
+    var _meta = {
+        '\b': '\\b',
+        '\t': '\\t',
+        '\n': '\\n',
+        '\f': '\\f',
+        '\r': '\\r',
+        '"' : '\\"',
+        '\\': '\\\\'
+    };
+})(jQuery);
diff --git a/src/main/webapp/lib/jquery/org/cometd.js b/src/main/webapp/lib/jquery/org/cometd.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba924d6a6f9556729e7480a61f0d3c52b1231acd
--- /dev/null
+++ b/src/main/webapp/lib/jquery/org/cometd.js
@@ -0,0 +1,3039 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Namespaces for the cometd implementation
+this.org = this.org || {};
+org.cometd = {};
+
+org.cometd.JSON = {};
+org.cometd.JSON.toJSON = org.cometd.JSON.fromJSON = function(object)
+{
+    throw 'Abstract';
+};
+
+org.cometd.Utils = {};
+
+org.cometd.Utils.isString = function(value)
+{
+    if (value === undefined || value === null)
+    {
+        return false;
+    }
+    return typeof value === 'string' ||  value instanceof String;
+};
+
+org.cometd.Utils.isArray = function(value)
+{
+    if (value === undefined || value === null)
+    {
+        return false;
+    }
+    return value instanceof Array;
+};
+
+/**
+ * Returns whether the given element is contained into the given array.
+ * @param element the element to check presence for
+ * @param array the array to check for the element presence
+ * @return the index of the element, if present, or a negative index if the element is not present
+ */
+org.cometd.Utils.inArray = function(element, array)
+{
+    for (var i = 0; i < array.length; ++i)
+    {
+        if (element === array[i])
+        {
+            return i;
+        }
+    }
+    return -1;
+};
+
+org.cometd.Utils.setTimeout = function(cometd, funktion, delay)
+{
+    return window.setTimeout(function()
+    {
+        try
+        {
+            funktion();
+        }
+        catch (x)
+        {
+            cometd._debug('Exception invoking timed function', funktion, x);
+        }
+    }, delay);
+};
+
+org.cometd.Utils.clearTimeout = function(timeoutHandle)
+{
+    window.clearTimeout(timeoutHandle);
+};
+
+/**
+ * A registry for transports used by the Cometd object.
+ */
+org.cometd.TransportRegistry = function()
+{
+    var _types = [];
+    var _transports = {};
+
+    this.getTransportTypes = function()
+    {
+        return _types.slice(0);
+    };
+
+    this.findTransportTypes = function(version, crossDomain, url)
+    {
+        var result = [];
+        for (var i = 0; i < _types.length; ++i)
+        {
+            var type = _types[i];
+            if (_transports[type].accept(version, crossDomain, url) === true)
+            {
+                result.push(type);
+            }
+        }
+        return result;
+    };
+
+    this.negotiateTransport = function(types, version, crossDomain, url)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            var type = _types[i];
+            for (var j = 0; j < types.length; ++j)
+            {
+                if (type === types[j])
+                {
+                    var transport = _transports[type];
+                    if (transport.accept(version, crossDomain, url) === true)
+                    {
+                        return transport;
+                    }
+                }
+            }
+        }
+        return null;
+    };
+
+    this.add = function(type, transport, index)
+    {
+        var existing = false;
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                existing = true;
+                break;
+            }
+        }
+
+        if (!existing)
+        {
+            if (typeof index !== 'number')
+            {
+                _types.push(type);
+            }
+            else
+            {
+                _types.splice(index, 0, type);
+            }
+            _transports[type] = transport;
+        }
+
+        return !existing;
+    };
+
+    this.find = function(type)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                return _transports[type];
+            }
+        }
+        return null;
+    };
+
+    this.remove = function(type)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                _types.splice(i, 1);
+                var transport = _transports[type];
+                delete _transports[type];
+                return transport;
+            }
+        }
+        return null;
+    };
+
+    this.clear = function()
+    {
+        _types = [];
+        _transports = {};
+    };
+
+    this.reset = function()
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            _transports[_types[i]].reset();
+        }
+    };
+};
+
+/**
+ * Base object with the common functionality for transports.
+ */
+org.cometd.Transport = function()
+{
+    var _type;
+    var _cometd;
+
+    /**
+     * Function invoked just after a transport has been successfully registered.
+     * @param type the type of transport (for example 'long-polling')
+     * @param cometd the cometd object this transport has been registered to
+     * @see #unregistered()
+     */
+    this.registered = function(type, cometd)
+    {
+        _type = type;
+        _cometd = cometd;
+    };
+
+    /**
+     * Function invoked just after a transport has been successfully unregistered.
+     * @see #registered(type, cometd)
+     */
+    this.unregistered = function()
+    {
+        _type = null;
+        _cometd = null;
+    };
+
+    this._debug = function()
+    {
+        _cometd._debug.apply(_cometd, arguments);
+    };
+
+    this._mixin = function()
+    {
+        return _cometd._mixin.apply(_cometd, arguments);
+    };
+
+    this.getConfiguration = function()
+    {
+        return _cometd.getConfiguration();
+    };
+
+    this.getAdvice = function()
+    {
+        return _cometd.getAdvice();
+    };
+
+    this.setTimeout = function(funktion, delay)
+    {
+        return org.cometd.Utils.setTimeout(_cometd, funktion, delay);
+    };
+
+    this.clearTimeout = function(handle)
+    {
+        org.cometd.Utils.clearTimeout(handle);
+    };
+
+    /**
+     * Converts the given response into an array of bayeux messages
+     * @param response the response to convert
+     * @return an array of bayeux messages obtained by converting the response
+     */
+    this.convertToMessages = function (response)
+    {
+        if (org.cometd.Utils.isString(response))
+        {
+            try
+            {
+                return org.cometd.JSON.fromJSON(response);
+            }
+            catch(x)
+            {
+                this._debug('Could not convert to JSON the following string', '"' + response + '"');
+                throw x;
+            }
+        }
+        if (org.cometd.Utils.isArray(response))
+        {
+            return response;
+        }
+        if (response === undefined || response === null)
+        {
+            return [];
+        }
+        if (response instanceof Object)
+        {
+            return [response];
+        }
+        throw 'Conversion Error ' + response + ', typeof ' + (typeof response);
+    };
+
+    /**
+     * Returns whether this transport can work for the given version and cross domain communication case.
+     * @param version a string indicating the transport version
+     * @param crossDomain a boolean indicating whether the communication is cross domain
+     * @return true if this transport can work for the given version and cross domain communication case,
+     * false otherwise
+     */
+    this.accept = function(version, crossDomain, url)
+    {
+        throw 'Abstract';
+    };
+
+    /**
+     * Returns the type of this transport.
+     * @see #registered(type, cometd)
+     */
+    this.getType = function()
+    {
+        return _type;
+    };
+
+    this.send = function(envelope, metaConnect)
+    {
+        throw 'Abstract';
+    };
+
+    this.reset = function()
+    {
+        this._debug('Transport', _type, 'reset');
+    };
+
+    this.abort = function()
+    {
+        this._debug('Transport', _type, 'aborted');
+    };
+
+    this.toString = function()
+    {
+        return this.getType();
+    };
+};
+
+org.cometd.Transport.derive = function(baseObject)
+{
+    function F() {}
+    F.prototype = baseObject;
+    return new F();
+};
+
+/**
+ * Base object with the common functionality for transports based on requests.
+ * The key responsibility is to allow at most 2 outstanding requests to the server,
+ * to avoid that requests are sent behind a long poll.
+ * To achieve this, we have one reserved request for the long poll, and all other
+ * requests are serialized one after the other.
+ */
+org.cometd.RequestTransport = function()
+{
+    var _super = new org.cometd.Transport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _requestIds = 0;
+    var _metaConnectRequest = null;
+    var _requests = [];
+    var _envelopes = [];
+
+    function _coalesceEnvelopes(envelope)
+    {
+        while (_envelopes.length > 0)
+        {
+            var envelopeAndRequest = _envelopes[0];
+            var newEnvelope = envelopeAndRequest[0];
+            var newRequest = envelopeAndRequest[1];
+            if (newEnvelope.url === envelope.url &&
+                    newEnvelope.sync === envelope.sync)
+            {
+                _envelopes.shift();
+                envelope.messages = envelope.messages.concat(newEnvelope.messages);
+                this._debug('Coalesced', newEnvelope.messages.length, 'messages from request', newRequest.id);
+                continue;
+            }
+            break;
+        }
+    }
+
+    function _transportSend(envelope, request)
+    {
+        this.transportSend(envelope, request);
+        request.expired = false;
+
+        if (!envelope.sync)
+        {
+            var maxDelay = this.getConfiguration().maxNetworkDelay;
+            var delay = maxDelay;
+            if (request.metaConnect === true)
+            {
+                delay += this.getAdvice().timeout;
+            }
+
+            this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for the response, maxNetworkDelay', maxDelay);
+
+            var self = this;
+            request.timeout = this.setTimeout(function()
+            {
+                request.expired = true;
+                if (request.xhr)
+                {
+                    request.xhr.abort();
+                }
+                var errorMessage = 'Request ' + request.id + ' of transport ' + self.getType() + ' exceeded ' + delay + ' ms max network delay';
+                self._debug(errorMessage);
+                self.complete(request, false, request.metaConnect);
+                envelope.onFailure(request.xhr, envelope.messages, 'timeout', errorMessage);
+            }, delay);
+        }
+    }
+
+    function _queueSend(envelope)
+    {
+        var requestId = ++_requestIds;
+        var request = {
+            id: requestId,
+            metaConnect: false
+        };
+
+        // Consider the metaConnect requests which should always be present
+        if (_requests.length < this.getConfiguration().maxConnections - 1)
+        {
+            _requests.push(request);
+            _transportSend.call(this, envelope, request);
+        }
+        else
+        {
+            this._debug('Transport', this.getType(), 'queueing request', requestId, 'envelope', envelope);
+            _envelopes.push([envelope, request]);
+        }
+    }
+
+    function _metaConnectComplete(request)
+    {
+        var requestId = request.id;
+        this._debug('Transport', this.getType(), 'metaConnect complete, request', requestId);
+        if (_metaConnectRequest !== null && _metaConnectRequest.id !== requestId)
+        {
+            throw 'Longpoll request mismatch, completing request ' + requestId;
+        }
+
+        // Reset metaConnect request
+        _metaConnectRequest = null;
+    }
+
+    function _complete(request, success)
+    {
+        var index = org.cometd.Utils.inArray(request, _requests);
+        // The index can be negative if the request has been aborted
+        if (index >= 0)
+        {
+            _requests.splice(index, 1);
+        }
+
+        if (_envelopes.length > 0)
+        {
+            var envelopeAndRequest = _envelopes.shift();
+            var nextEnvelope = envelopeAndRequest[0];
+            var nextRequest = envelopeAndRequest[1];
+            this._debug('Transport dequeued request', nextRequest.id);
+            if (success)
+            {
+                if (this.getConfiguration().autoBatch)
+                {
+                    _coalesceEnvelopes.call(this, nextEnvelope);
+                }
+                _queueSend.call(this, nextEnvelope);
+                this._debug('Transport completed request', request.id, nextEnvelope);
+            }
+            else
+            {
+                // Keep the semantic of calling response callbacks asynchronously after the request
+                var self = this;
+                this.setTimeout(function()
+                {
+                    self.complete(nextRequest, false, nextRequest.metaConnect);
+                    nextEnvelope.onFailure(nextRequest.xhr, nextEnvelope.messages, 'error', 'Previous request failed');
+                }, 0);
+            }
+        }
+    }
+
+    _self.complete = function(request, success, metaConnect)
+    {
+        if (metaConnect)
+        {
+            _metaConnectComplete.call(this, request);
+        }
+        else
+        {
+            _complete.call(this, request, success);
+        }
+    };
+
+    /**
+     * Performs the actual send depending on the transport type details.
+     * @param envelope the envelope to send
+     * @param request the request information
+     */
+    _self.transportSend = function(envelope, request)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSuccess = function(envelope, request, responses)
+    {
+        if (!request.expired)
+        {
+            this.clearTimeout(request.timeout);
+            this.complete(request, true, request.metaConnect);
+            if (responses && responses.length > 0)
+            {
+                envelope.onSuccess(responses);
+            }
+            else
+            {
+                envelope.onFailure(request.xhr, envelope.messages, 'Empty HTTP response');
+            }
+        }
+    };
+
+    _self.transportFailure = function(envelope, request, reason, exception)
+    {
+        if (!request.expired)
+        {
+            this.clearTimeout(request.timeout);
+            this.complete(request, false, request.metaConnect);
+            envelope.onFailure(request.xhr, envelope.messages, reason, exception);
+        }
+    };
+
+    function _metaConnectSend(envelope)
+    {
+        if (_metaConnectRequest !== null)
+        {
+            throw 'Concurrent metaConnect requests not allowed, request id=' + _metaConnectRequest.id + ' not yet completed';
+        }
+
+        var requestId = ++_requestIds;
+        this._debug('Transport', this.getType(), 'metaConnect send, request', requestId, 'envelope', envelope);
+        var request = {
+            id: requestId,
+            metaConnect: true
+        };
+        _transportSend.call(this, envelope, request);
+        _metaConnectRequest = request;
+    }
+
+    _self.send = function(envelope, metaConnect)
+    {
+        if (metaConnect)
+        {
+            _metaConnectSend.call(this, envelope);
+        }
+        else
+        {
+            _queueSend.call(this, envelope);
+        }
+    };
+
+    _self.abort = function()
+    {
+        _super.abort();
+        for (var i = 0; i < _requests.length; ++i)
+        {
+            var request = _requests[i];
+            this._debug('Aborting request', request);
+            if (request.xhr)
+            {
+                request.xhr.abort();
+            }
+        }
+        if (_metaConnectRequest)
+        {
+            this._debug('Aborting metaConnect request', _metaConnectRequest);
+            if (_metaConnectRequest.xhr)
+            {
+                _metaConnectRequest.xhr.abort();
+            }
+        }
+        this.reset();
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        _metaConnectRequest = null;
+        _requests = [];
+        _envelopes = [];
+    };
+
+    return _self;
+};
+
+org.cometd.LongPollingTransport = function()
+{
+    var _super = new org.cometd.RequestTransport();
+    var _self = org.cometd.Transport.derive(_super);
+    // By default, support cross domain
+    var _supportsCrossDomain = true;
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        return _supportsCrossDomain || !crossDomain;
+    };
+
+    _self.xhrSend = function(packet)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSend = function(envelope, request)
+    {
+        this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelope);
+
+        var self = this;
+        try
+        {
+            var sameStack = true;
+            request.xhr = this.xhrSend({
+                transport: this,
+                url: envelope.url,
+                sync: envelope.sync,
+                headers: this.getConfiguration().requestHeaders,
+                body: org.cometd.JSON.toJSON(envelope.messages),
+                onSuccess: function(response)
+                {
+                    self._debug('Transport', self.getType(), 'received response', response);
+                    var success = false;
+                    try
+                    {
+                        var received = self.convertToMessages(response);
+                        if (received.length === 0)
+                        {
+                            _supportsCrossDomain = false;
+                            self.transportFailure(envelope, request, 'no response', null);
+                        }
+                        else
+                        {
+                            success = true;
+                            self.transportSuccess(envelope, request, received);
+                        }
+                    }
+                    catch(x)
+                    {
+                        self._debug(x);
+                        if (!success)
+                        {
+                            _supportsCrossDomain = false;
+                            self.transportFailure(envelope, request, 'bad response', x);
+                        }
+                    }
+                },
+                onError: function(reason, exception)
+                {
+                    _supportsCrossDomain = false;
+                    if (sameStack)
+                    {
+                        // Keep the semantic of calling response callbacks asynchronously after the request
+                        self.setTimeout(function()
+                        {
+                            self.transportFailure(envelope, request, reason, exception);
+                        }, 0);
+                    }
+                    else
+                    {
+                        self.transportFailure(envelope, request, reason, exception);
+                    }
+                }
+            });
+            sameStack = false;
+        }
+        catch (x)
+        {
+            _supportsCrossDomain = false;
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                self.transportFailure(envelope, request, 'error', x);
+            }, 0);
+        }
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        _supportsCrossDomain = true;
+    };
+
+    return _self;
+};
+
+org.cometd.CallbackPollingTransport = function()
+{
+    var _super = new org.cometd.RequestTransport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _maxLength = 2000;
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        return true;
+    };
+
+    _self.jsonpSend = function(packet)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSend = function(envelope, request)
+    {
+        var self = this;
+
+        // Microsoft Internet Explorer has a 2083 URL max length
+        // We must ensure that we stay within that length
+        var start = 0;
+        var length = envelope.messages.length;
+        var lengths = [];
+        while (length > 0)
+        {
+            // Encode the messages because all brackets, quotes, commas, colons, etc
+            // present in the JSON will be URL encoded, taking many more characters
+            var json = org.cometd.JSON.toJSON(envelope.messages.slice(start, start + length));
+            var urlLength = envelope.url.length + encodeURI(json).length;
+
+            // Let's stay on the safe side and use 2000 instead of 2083
+            // also because we did not count few characters among which
+            // the parameter name 'message' and the parameter 'jsonp',
+            // which sum up to about 50 chars
+            if (urlLength > _maxLength)
+            {
+                if (length === 1)
+                {
+                    var x = 'Bayeux message too big (' + urlLength + ' bytes, max is ' + _maxLength + ') ' +
+                            'for transport ' + this.getType();
+                    // Keep the semantic of calling response callbacks asynchronously after the request
+                    this.setTimeout(function()
+                    {
+                        self.transportFailure(envelope, request, 'error', x);
+                    }, 0);
+                    return;
+                }
+
+                --length;
+                continue;
+            }
+
+            lengths.push(length);
+            start += length;
+            length = envelope.messages.length - start;
+        }
+
+        // Here we are sure that the messages can be sent within the URL limit
+
+        var envelopeToSend = envelope;
+        if (lengths.length > 1)
+        {
+            var begin = 0;
+            var end = lengths[0];
+            this._debug('Transport', this.getType(), 'split', envelope.messages.length, 'messages into', lengths.join(' + '));
+            envelopeToSend = this._mixin(false, {}, envelope);
+            envelopeToSend.messages = envelope.messages.slice(begin, end);
+            envelopeToSend.onSuccess = envelope.onSuccess;
+            envelopeToSend.onFailure = envelope.onFailure;
+
+            for (var i = 1; i < lengths.length; ++i)
+            {
+                var nextEnvelope = this._mixin(false, {}, envelope);
+                begin = end;
+                end += lengths[i];
+                nextEnvelope.messages = envelope.messages.slice(begin, end);
+                nextEnvelope.onSuccess = envelope.onSuccess;
+                nextEnvelope.onFailure = envelope.onFailure;
+                this.send(nextEnvelope, request.metaConnect);
+            }
+        }
+
+        this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelopeToSend);
+
+        try
+        {
+            var sameStack = true;
+            this.jsonpSend({
+                transport: this,
+                url: envelopeToSend.url,
+                sync: envelopeToSend.sync,
+                headers: this.getConfiguration().requestHeaders,
+                body: org.cometd.JSON.toJSON(envelopeToSend.messages),
+                onSuccess: function(responses)
+                {
+                    var success = false;
+                    try
+                    {
+                        var received = self.convertToMessages(responses);
+                        if (received.length === 0)
+                        {
+                            self.transportFailure(envelopeToSend, request, 'no response');
+                        }
+                        else
+                        {
+                            success=true;
+                            self.transportSuccess(envelopeToSend, request, received);
+                        }
+                    }
+                    catch (x)
+                    {
+                        self._debug(x);
+                        if (!success)
+                        {
+                            self.transportFailure(envelopeToSend, request, 'bad response', x);
+                        }
+                    }
+                },
+                onError: function(reason, exception)
+                {
+                    if (sameStack)
+                    {
+                        // Keep the semantic of calling response callbacks asynchronously after the request
+                        self.setTimeout(function()
+                        {
+                            self.transportFailure(envelopeToSend, request, reason, exception);
+                        }, 0);
+                    }
+                    else
+                    {
+                        self.transportFailure(envelopeToSend, request, reason, exception);
+                    }
+                }
+            });
+            sameStack = false;
+        }
+        catch (xx)
+        {
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                self.transportFailure(envelopeToSend, request, 'error', xx);
+            }, 0);
+        }
+    };
+
+    return _self;
+};
+
+org.cometd.WebSocketTransport = function()
+{
+    var _super = new org.cometd.Transport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _cometd;
+    // By default, support WebSocket
+    var _supportsWebSocket = true;
+    // Whether we were able to establish a WebSocket connection
+    var _webSocketSupported = false;
+    // Envelopes that have been sent
+    var _envelopes = {};
+    // Timeouts for messages that have been sent
+    var _timeouts = {};
+    var _webSocket = null;
+    var _opened = false;
+    var _connected = false;
+    var _successCallback;
+
+    function _websocketConnect()
+    {
+        // Mangle the URL, changing the scheme from 'http' to 'ws'
+        var url = _cometd.getURL().replace(/^http/, 'ws');
+        this._debug('Transport', this.getType(), 'connecting to URL', url);
+
+        var self = this;
+        var connectTimer = null;
+
+        var connectTimeout = _cometd.getConfiguration().connectTimeout;
+        if (connectTimeout > 0)
+        {
+            connectTimer = this.setTimeout(function()
+            {
+                connectTimer = null;
+                if (!_opened)
+                {
+                    self._debug('Transport', self.getType(), 'timed out while connecting to URL', url, ':', connectTimeout, 'ms');
+                    self.onClose(1002, 'Connect Timeout');
+                }
+            }, connectTimeout);
+        }
+
+        var webSocket = new org.cometd.WebSocket(url);
+        webSocket.onopen = function()
+        {
+            self._debug('WebSocket opened', webSocket);
+            if (connectTimer)
+            {
+                self.clearTimeout(connectTimer);
+                connectTimer = null;
+            }
+            if (webSocket !== _webSocket)
+            {
+                // It's possible that the onopen callback is invoked
+                // with a delay so that we have already reconnected
+                self._debug('Ignoring open event, WebSocket', _webSocket);
+                return;
+            }
+            self.onOpen();
+        };
+        webSocket.onclose = function(event)
+        {
+            var code = event ? event.code : 1000;
+            var reason = event ? event.reason : undefined;
+            self._debug('WebSocket closed', code, '/', reason, webSocket);
+            if (connectTimer)
+            {
+                self.clearTimeout(connectTimer);
+                connectTimer = null;
+            }
+            if (webSocket !== _webSocket)
+            {
+                // The onclose callback may be invoked when the server sends
+                // the close message reply, but after we have already reconnected
+                self._debug('Ignoring close event, WebSocket', _webSocket);
+                return;
+            }
+            self.onClose(code, reason);
+        };
+        webSocket.onerror = function()
+        {
+            webSocket.onclose({ code: 1002 });
+        };
+        webSocket.onmessage = function(message)
+        {
+            self._debug('WebSocket message', message, webSocket);
+            if (webSocket !== _webSocket)
+            {
+                self._debug('Ignoring message event, WebSocket', _webSocket);
+                return;
+            }
+            self.onMessage(message);
+        };
+
+        _webSocket = webSocket;
+        this._debug('Transport', this.getType(), 'configured callbacks on', webSocket);
+    }
+
+    function _webSocketSend(envelope, metaConnect)
+    {
+        var json = org.cometd.JSON.toJSON(envelope.messages);
+
+        _webSocket.send(json);
+        this._debug('Transport', this.getType(), 'sent', envelope, 'metaConnect =', metaConnect);
+
+        // Manage the timeout waiting for the response
+        var maxDelay = this.getConfiguration().maxNetworkDelay;
+        var delay = maxDelay;
+        if (metaConnect)
+        {
+            delay += this.getAdvice().timeout;
+            _connected = true;
+        }
+
+        var messageIds = [];
+        for (var i = 0; i < envelope.messages.length; ++i)
+        {
+            var message = envelope.messages[i];
+            if (message.id)
+            {
+                messageIds.push(message.id);
+                var self = this;
+                _timeouts[message.id] = this.setTimeout(function()
+                {
+                    if (_webSocket)
+                    {
+                        _webSocket.close(1000, 'Timeout');
+                    }
+                }, delay);
+            }
+        }
+
+        this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for messages', messageIds, 'maxNetworkDelay', maxDelay, ', timeouts:', _timeouts);
+    }
+
+    function _send(envelope, metaConnect)
+    {
+        try
+        {
+            if (_webSocket === null)
+            {
+                _websocketConnect.call(this);
+            }
+            // We may have a non-null _webSocket, but not be open yet so
+            // to avoid out of order deliveries, we check if we are open
+            else if (_opened)
+            {
+                _webSocketSend.call(this, envelope, metaConnect);
+            }
+        }
+        catch (x)
+        {
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                envelope.onFailure(_webSocket, envelope.messages, 'error', x);
+            }, 0);
+        }
+    }
+
+    _self.onOpen = function()
+    {
+        this._debug('Transport', this.getType(), 'opened', _webSocket);
+        _opened = true;
+        _webSocketSupported = true;
+
+        this._debug('Sending pending messages', _envelopes);
+        for (var key in _envelopes)
+        {
+            var element = _envelopes[key];
+            var envelope = element[0];
+            var metaConnect = element[1];
+            // Store the success callback, which is independent from the envelope,
+            // so that it can be used to notify arrival of messages.
+            _successCallback = envelope.onSuccess;
+            _webSocketSend.call(this, envelope, metaConnect);
+        }
+    };
+
+    _self.onMessage = function(wsMessage)
+    {
+        this._debug('Transport', this.getType(), 'received websocket message', wsMessage, _webSocket);
+
+        var close = false;
+        var messages = this.convertToMessages(wsMessage.data);
+        var messageIds = [];
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+
+            // Detect if the message is a response to a request we made.
+            // If it's a meta message, for sure it's a response;
+            // otherwise it's a publish message and publish responses lack the data field
+            if (/^\/meta\//.test(message.channel) || message.data === undefined)
+            {
+                if (message.id)
+                {
+                    messageIds.push(message.id);
+
+                    var timeout = _timeouts[message.id];
+                    if (timeout)
+                    {
+                        this.clearTimeout(timeout);
+                        delete _timeouts[message.id];
+                        this._debug('Transport', this.getType(), 'removed timeout for message', message.id, ', timeouts', _timeouts);
+                    }
+                }
+            }
+
+            if ('/meta/connect' === message.channel)
+            {
+                _connected = false;
+            }
+            if ('/meta/disconnect' === message.channel && !_connected)
+            {
+                close = true;
+            }
+        }
+
+        // Remove the envelope corresponding to the messages
+        var removed = false;
+        for (var j = 0; j < messageIds.length; ++j)
+        {
+            var id = messageIds[j];
+            for (var key in _envelopes)
+            {
+                var ids = key.split(',');
+                var index = org.cometd.Utils.inArray(id, ids);
+                if (index >= 0)
+                {
+                    removed = true;
+                    ids.splice(index, 1);
+                    var envelope = _envelopes[key][0];
+                    var metaConnect = _envelopes[key][1];
+                    delete _envelopes[key];
+                    if (ids.length > 0)
+                    {
+                        _envelopes[ids.join(',')] = [envelope, metaConnect];
+                    }
+                    break;
+                }
+            }
+        }
+        if (removed)
+        {
+            this._debug('Transport', this.getType(), 'removed envelope, envelopes', _envelopes);
+        }
+
+        _successCallback.call(this, messages);
+
+        if (close)
+        {
+            _webSocket.close(1000, 'Disconnect');
+        }
+    };
+
+    _self.onClose = function(code, reason)
+    {
+        this._debug('Transport', this.getType(), 'closed', code, reason, _webSocket);
+
+        // Remember if we were able to connect
+        // This close event could be due to server shutdown, and if it restarts we want to try websocket again
+        _supportsWebSocket = _webSocketSupported;
+
+        for (var id in _timeouts)
+        {
+            this.clearTimeout(_timeouts[id]);
+        }
+        _timeouts = {};
+
+        for (var key in _envelopes)
+        {
+            var envelope = _envelopes[key][0];
+            var metaConnect = _envelopes[key][1];
+            if (metaConnect)
+            {
+                _connected = false;
+            }
+            envelope.onFailure(_webSocket, envelope.messages, 'closed ' + code + '/' + reason);
+        }
+        _envelopes = {};
+
+        if (_webSocket !== null && _opened)
+        {
+            _webSocket.close(1000, 'Close');
+        }
+        _opened = false;
+        _webSocket = null;
+    };
+
+    _self.registered = function(type, cometd)
+    {
+        _super.registered(type, cometd);
+        _cometd = cometd;
+    };
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        // Using !! to return a boolean (and not the WebSocket object)
+        return _supportsWebSocket && !!org.cometd.WebSocket && _cometd.websocketEnabled !== false;
+    };
+
+    _self.send = function(envelope, metaConnect)
+    {
+        this._debug('Transport', this.getType(), 'sending', envelope, 'metaConnect =', metaConnect);
+
+        // Store the envelope in any case; if the websocket cannot be opened, we fail it in close()
+        var messageIds = [];
+        for (var i = 0; i < envelope.messages.length; ++i)
+        {
+            var message = envelope.messages[i];
+            if (message.id)
+            {
+                messageIds.push(message.id);
+            }
+        }
+        _envelopes[messageIds.join(',')] = [envelope, metaConnect];
+        this._debug('Transport', this.getType(), 'stored envelope, envelopes', _envelopes);
+
+        _send.call(this, envelope, metaConnect);
+    };
+
+    _self.abort = function()
+    {
+        _super.abort();
+        if (_webSocket !== null)
+        {
+            try
+            {
+                _webSocket.close(1001);
+            }
+            catch (x)
+            {
+                // Firefox may throw, just ignore
+                this._debug(x);
+            }
+        }
+        this.reset();
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        if (_webSocket !== null && _opened)
+        {
+            _webSocket.close(1000, 'Reset');
+        }
+        _supportsWebSocket = true;
+        _webSocketSupported = false;
+        _timeouts = {};
+        _envelopes = {};
+        _webSocket = null;
+        _opened = false;
+        _successCallback = null;
+    };
+
+    return _self;
+};
+
+/**
+ * The constructor for a Cometd object, identified by an optional name.
+ * The default name is the string 'default'.
+ * In the rare case a page needs more than one Bayeux conversation,
+ * a new instance can be created via:
+ * <pre>
+ * var bayeuxUrl2 = ...;
+ *
+ * // Dojo style
+ * var cometd2 = new dojox.Cometd('another_optional_name');
+ *
+ * // jQuery style
+ * var cometd2 = new $.Cometd('another_optional_name');
+ *
+ * cometd2.init({url: bayeuxUrl2});
+ * </pre>
+ * @param name the optional name of this cometd object
+ */
+// IMPLEMENTATION NOTES:
+// Be very careful in not changing the function order and pass this file every time through JSLint (http://jslint.com)
+// The only implied globals must be "dojo", "org" and "window", and check that there are no "unused" warnings
+// Failing to pass JSLint may result in shrinkers/minifiers to create an unusable file.
+org.cometd.Cometd = function(name)
+{
+    var _cometd = this;
+    var _name = name || 'default';
+    var _crossDomain = false;
+    var _transports = new org.cometd.TransportRegistry();
+    var _transport;
+    var _status = 'disconnected';
+    var _messageId = 0;
+    var _clientId = null;
+    var _batch = 0;
+    var _messageQueue = [];
+    var _internalBatch = false;
+    var _listeners = {};
+    var _backoff = 0;
+    var _scheduledSend = null;
+    var _extensions = [];
+    var _advice = {};
+    var _handshakeProps;
+    var _publishCallbacks = {};
+    var _reestablish = false;
+    var _connected = false;
+    var _config = {
+        connectTimeout: 0,
+        maxConnections: 2,
+        backoffIncrement: 1000,
+        maxBackoff: 60000,
+        logLevel: 'info',
+        reverseIncomingExtensions: true,
+        maxNetworkDelay: 10000,
+        requestHeaders: {},
+        appendMessageTypeToURL: true,
+        autoBatch: false,
+        advice: {
+            timeout: 60000,
+            interval: 0,
+            reconnect: 'retry'
+        }
+    };
+
+    /**
+     * Mixes in the given objects into the target object by copying the properties.
+     * @param deep if the copy must be deep
+     * @param target the target object
+     * @param objects the objects whose properties are copied into the target
+     */
+    this._mixin = function(deep, target, objects)
+    {
+        var result = target || {};
+
+        // Skip first 2 parameters (deep and target), and loop over the others
+        for (var i = 2; i < arguments.length; ++i)
+        {
+            var object = arguments[i];
+
+            if (object === undefined || object === null)
+            {
+                continue;
+            }
+
+            for (var propName in object)
+            {
+                var prop = object[propName];
+                var targ = result[propName];
+
+                // Avoid infinite loops
+                if (prop === target)
+                {
+                    continue;
+                }
+                // Do not mixin undefined values
+                if (prop === undefined)
+                {
+                    continue;
+                }
+
+                if (deep && typeof prop === 'object' && prop !== null)
+                {
+                    if (prop instanceof Array)
+                    {
+                        result[propName] = this._mixin(deep, targ instanceof Array ? targ : [], prop);
+                    }
+                    else
+                    {
+                        var source = typeof targ === 'object' && !(targ instanceof Array) ? targ : {};
+                        result[propName] = this._mixin(deep, source, prop);
+                    }
+                }
+                else
+                {
+                    result[propName] = prop;
+                }
+            }
+        }
+
+        return result;
+    };
+
+    function _isString(value)
+    {
+        return org.cometd.Utils.isString(value);
+    }
+
+    function _isFunction(value)
+    {
+        if (value === undefined || value === null)
+        {
+            return false;
+        }
+        return typeof value === 'function';
+    }
+
+    function _log(level, args)
+    {
+        if (window.console)
+        {
+            var logger = window.console[level];
+            if (_isFunction(logger))
+            {
+                logger.apply(window.console, args);
+            }
+        }
+    }
+
+    this._warn = function()
+    {
+        _log('warn', arguments);
+    };
+
+    this._info = function()
+    {
+        if (_config.logLevel !== 'warn')
+        {
+            _log('info', arguments);
+        }
+    };
+
+    this._debug = function()
+    {
+        if (_config.logLevel === 'debug')
+        {
+            _log('debug', arguments);
+        }
+    };
+
+    /**
+     * Returns whether the given hostAndPort is cross domain.
+     * The default implementation checks against window.location.host
+     * but this function can be overridden to make it work in non-browser
+     * environments.
+     *
+     * @param hostAndPort the host and port in format host:port
+     * @return whether the given hostAndPort is cross domain
+     */
+    this._isCrossDomain = function(hostAndPort)
+    {
+        return hostAndPort && hostAndPort !== window.location.host;
+    };
+
+    function _configure(configuration)
+    {
+        _cometd._debug('Configuring cometd object with', configuration);
+        // Support old style param, where only the Bayeux server URL was passed
+        if (_isString(configuration))
+        {
+            configuration = { url: configuration };
+        }
+        if (!configuration)
+        {
+            configuration = {};
+        }
+
+        _config = _cometd._mixin(false, _config, configuration);
+
+        if (!_config.url)
+        {
+            throw 'Missing required configuration parameter \'url\' specifying the Bayeux server URL';
+        }
+
+        // Check if we're cross domain
+        // [1] = protocol://, [2] = host:port, [3] = host, [4] = IPv6_host, [5] = IPv4_host, [6] = :port, [7] = port, [8] = uri, [9] = rest
+        var urlParts = /(^https?:\/\/)?(((\[[^\]]+\])|([^:\/\?#]+))(:(\d+))?)?([^\?#]*)(.*)?/.exec(_config.url);
+        var hostAndPort = urlParts[2];
+        var uri = urlParts[8];
+        var afterURI = urlParts[9];
+        _crossDomain = _cometd._isCrossDomain(hostAndPort);
+
+        // Check if appending extra path is supported
+        if (_config.appendMessageTypeToURL)
+        {
+            if (afterURI !== undefined && afterURI.length > 0)
+            {
+                _cometd._info('Appending message type to URI ' + uri + afterURI + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
+                _config.appendMessageTypeToURL = false;
+            }
+            else
+            {
+                var uriSegments = uri.split('/');
+                var lastSegmentIndex = uriSegments.length - 1;
+                if (uri.match(/\/$/))
+                {
+                    lastSegmentIndex -= 1;
+                }
+                if (uriSegments[lastSegmentIndex].indexOf('.') >= 0)
+                {
+                    // Very likely the CometD servlet's URL pattern is mapped to an extension, such as *.cometd
+                    // It will be difficult to add the extra path in this case
+                    _cometd._info('Appending message type to URI ' + uri + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
+                    _config.appendMessageTypeToURL = false;
+                }
+            }
+        }
+    }
+
+    function _clearSubscriptions()
+    {
+        for (var channel in _listeners)
+        {
+            var subscriptions = _listeners[channel];
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                var subscription = subscriptions[i];
+                if (subscription && !subscription.listener)
+                {
+                    delete subscriptions[i];
+                    _cometd._debug('Removed subscription', subscription, 'for channel', channel);
+                }
+            }
+        }
+    }
+
+    function _setStatus(newStatus)
+    {
+        if (_status !== newStatus)
+        {
+            _cometd._debug('Status', _status, '->', newStatus);
+            _status = newStatus;
+        }
+    }
+
+    function _isDisconnected()
+    {
+        return _status === 'disconnecting' || _status === 'disconnected';
+    }
+
+    function _nextMessageId()
+    {
+        return ++_messageId;
+    }
+
+    function _applyExtension(scope, callback, name, message, outgoing)
+    {
+        try
+        {
+            return callback.call(scope, message);
+        }
+        catch (x)
+        {
+            _cometd._debug('Exception during execution of extension', name, x);
+            var exceptionCallback = _cometd.onExtensionException;
+            if (_isFunction(exceptionCallback))
+            {
+                _cometd._debug('Invoking extension exception callback', name, x);
+                try
+                {
+                    exceptionCallback.call(_cometd, x, name, outgoing, message);
+                }
+                catch(xx)
+                {
+                    _cometd._info('Exception during execution of exception callback in extension', name, xx);
+                }
+            }
+            return message;
+        }
+    }
+
+    function _applyIncomingExtensions(message)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            if (message === undefined || message === null)
+            {
+                break;
+            }
+
+            var index = _config.reverseIncomingExtensions ? _extensions.length - 1 - i : i;
+            var extension = _extensions[index];
+            var callback = extension.extension.incoming;
+            if (_isFunction(callback))
+            {
+                var result = _applyExtension(extension.extension, callback, extension.name, message, false);
+                message = result === undefined ? message : result;
+            }
+        }
+        return message;
+    }
+
+    function _applyOutgoingExtensions(message)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            if (message === undefined || message === null)
+            {
+                break;
+            }
+
+            var extension = _extensions[i];
+            var callback = extension.extension.outgoing;
+            if (_isFunction(callback))
+            {
+                var result = _applyExtension(extension.extension, callback, extension.name, message, true);
+                message = result === undefined ? message : result;
+            }
+        }
+        return message;
+    }
+
+    function _notify(channel, message)
+    {
+        var subscriptions = _listeners[channel];
+        if (subscriptions && subscriptions.length > 0)
+        {
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                var subscription = subscriptions[i];
+                // Subscriptions may come and go, so the array may have 'holes'
+                if (subscription)
+                {
+                    try
+                    {
+                        subscription.callback.call(subscription.scope, message);
+                    }
+                    catch (x)
+                    {
+                        _cometd._debug('Exception during notification', subscription, message, x);
+                        var listenerCallback = _cometd.onListenerException;
+                        if (_isFunction(listenerCallback))
+                        {
+                            _cometd._debug('Invoking listener exception callback', subscription, x);
+                            try
+                            {
+                                listenerCallback.call(_cometd, x, subscription.handle, subscription.listener, message);
+                            }
+                            catch (xx)
+                            {
+                                _cometd._info('Exception during execution of listener callback', subscription, xx);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    function _notifyListeners(channel, message)
+    {
+        // Notify direct listeners
+        _notify(channel, message);
+
+        // Notify the globbing listeners
+        var channelParts = channel.split('/');
+        var last = channelParts.length - 1;
+        for (var i = last; i > 0; --i)
+        {
+            var channelPart = channelParts.slice(0, i).join('/') + '/*';
+            // We don't want to notify /foo/* if the channel is /foo/bar/baz,
+            // so we stop at the first non recursive globbing
+            if (i === last)
+            {
+                _notify(channelPart, message);
+            }
+            // Add the recursive globber and notify
+            channelPart += '*';
+            _notify(channelPart, message);
+        }
+    }
+
+    function _cancelDelayedSend()
+    {
+        if (_scheduledSend !== null)
+        {
+            org.cometd.Utils.clearTimeout(_scheduledSend);
+        }
+        _scheduledSend = null;
+    }
+
+    function _delayedSend(operation)
+    {
+        _cancelDelayedSend();
+        var delay = _advice.interval + _backoff;
+        _cometd._debug('Function scheduled in', delay, 'ms, interval =', _advice.interval, 'backoff =', _backoff, operation);
+        _scheduledSend = org.cometd.Utils.setTimeout(_cometd, operation, delay);
+    }
+
+    // Needed to break cyclic dependencies between function definitions
+    var _handleMessages;
+    var _handleFailure;
+
+    /**
+     * Delivers the messages to the CometD server
+     * @param messages the array of messages to send
+     * @param longpoll true if this send is a long poll
+     */
+    function _send(sync, messages, longpoll, extraPath)
+    {
+        // We must be sure that the messages have a clientId.
+        // This is not guaranteed since the handshake may take time to return
+        // (and hence the clientId is not known yet) and the application
+        // may create other messages.
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+            message.id = '' + _nextMessageId();
+
+            if (_clientId)
+            {
+                message.clientId = _clientId;
+            }
+
+            var callback = undefined;
+            if (_isFunction(message._callback))
+            {
+                callback = message._callback;
+                // Remove the publish callback before calling the extensions
+                delete message._callback;
+            }
+
+            message = _applyOutgoingExtensions(message);
+            if (message !== undefined && message !== null)
+            {
+                messages[i] = message;
+                if (callback)
+                    _publishCallbacks[message.id] = callback;
+            }
+            else
+            {
+                messages.splice(i--, 1);
+            }
+        }
+
+        if (messages.length === 0)
+        {
+            return;
+        }
+
+        var url = _config.url;
+        if (_config.appendMessageTypeToURL)
+        {
+            // If url does not end with '/', then append it
+            if (!url.match(/\/$/))
+            {
+                url = url + '/';
+            }
+            if (extraPath)
+            {
+                url = url + extraPath;
+            }
+        }
+
+        var envelope = {
+            url: url,
+            sync: sync,
+            messages: messages,
+            onSuccess: function(rcvdMessages)
+            {
+                try
+                {
+                    _handleMessages.call(_cometd, rcvdMessages);
+                }
+                catch (x)
+                {
+                    _cometd._debug('Exception during handling of messages', x);
+                }
+            },
+            onFailure: function(conduit, messages, reason, exception)
+            {
+                try
+                {
+                    _handleFailure.call(_cometd, conduit, messages, reason, exception);
+                }
+                catch (x)
+                {
+                    _cometd._debug('Exception during handling of failure', x);
+                }
+            }
+        };
+        _cometd._debug('Send', envelope);
+        _transport.send(envelope, longpoll);
+    }
+
+    function _queueSend(message)
+    {
+        if (_batch > 0 || _internalBatch === true)
+        {
+            _messageQueue.push(message);
+        }
+        else
+        {
+            _send(false, [message], false);
+        }
+    }
+
+    /**
+     * Sends a complete bayeux message.
+     * This method is exposed as a public so that extensions may use it
+     * to send bayeux message directly, for example in case of re-sending
+     * messages that have already been sent but that for some reason must
+     * be resent.
+     */
+    this.send = _queueSend;
+
+    function _resetBackoff()
+    {
+        _backoff = 0;
+    }
+
+    function _increaseBackoff()
+    {
+        if (_backoff < _config.maxBackoff)
+        {
+            _backoff += _config.backoffIncrement;
+        }
+    }
+
+    /**
+     * Starts a the batch of messages to be sent in a single request.
+     * @see #_endBatch(sendMessages)
+     */
+    function _startBatch()
+    {
+        ++_batch;
+    }
+
+    function _flushBatch()
+    {
+        var messages = _messageQueue;
+        _messageQueue = [];
+        if (messages.length > 0)
+        {
+            _send(false, messages, false);
+        }
+    }
+
+    /**
+     * Ends the batch of messages to be sent in a single request,
+     * optionally sending messages present in the message queue depending
+     * on the given argument.
+     * @see #_startBatch()
+     */
+    function _endBatch()
+    {
+        --_batch;
+        if (_batch < 0)
+        {
+            throw 'Calls to startBatch() and endBatch() are not paired';
+        }
+
+        if (_batch === 0 && !_isDisconnected() && !_internalBatch)
+        {
+            _flushBatch();
+        }
+    }
+
+    /**
+     * Sends the connect message
+     */
+    function _connect()
+    {
+        if (!_isDisconnected())
+        {
+            var message = {
+                channel: '/meta/connect',
+                connectionType: _transport.getType()
+            };
+
+            // In case of reload or temporary loss of connection
+            // we want the next successful connect to return immediately
+            // instead of being held by the server, so that connect listeners
+            // can be notified that the connection has been re-established
+            if (!_connected)
+            {
+                message.advice = { timeout: 0 };
+            }
+
+            _setStatus('connecting');
+            _cometd._debug('Connect sent', message);
+            _send(false, [message], true, 'connect');
+            _setStatus('connected');
+        }
+    }
+
+    function _delayedConnect()
+    {
+        _setStatus('connecting');
+        _delayedSend(function()
+        {
+            _connect();
+        });
+    }
+
+    function _updateAdvice(newAdvice)
+    {
+        if (newAdvice)
+        {
+            _advice = _cometd._mixin(false, {}, _config.advice, newAdvice);
+            _cometd._debug('New advice', _advice);
+        }
+    }
+
+    function _disconnect(abort)
+    {
+        _cancelDelayedSend();
+        if (abort)
+        {
+            _transport.abort();
+        }
+        _clientId = null;
+        _setStatus('disconnected');
+        _batch = 0;
+        _resetBackoff();
+
+        // Fail any existing queued message
+        if (_messageQueue.length > 0)
+        {
+            _handleFailure.call(_cometd, undefined, _messageQueue, 'error', 'Disconnected');
+            _messageQueue = [];
+        }
+    }
+
+    /**
+     * Sends the initial handshake message
+     */
+    function _handshake(handshakeProps)
+    {
+        _clientId = null;
+
+        _clearSubscriptions();
+
+        // Reset the transports if we're not retrying the handshake
+        if (_isDisconnected())
+        {
+            _transports.reset();
+            _updateAdvice(_config.advice);
+        }
+        else
+        {
+            // We are retrying the handshake, either because another handshake failed
+            // and we're backing off, or because the server timed us out and asks us to
+            // re-handshake: in both cases, make sure that if the handshake succeeds
+            // the next action is a connect.
+            _updateAdvice(_cometd._mixin(false, _advice, {reconnect: 'retry'}));
+        }
+
+        _batch = 0;
+
+        // Mark the start of an internal batch.
+        // This is needed because handshake and connect are async.
+        // It may happen that the application calls init() then subscribe()
+        // and the subscribe message is sent before the connect message, if
+        // the subscribe message is not held until the connect message is sent.
+        // So here we start a batch to hold temporarily any message until
+        // the connection is fully established.
+        _internalBatch = true;
+
+        // Save the properties provided by the user, so that
+        // we can reuse them during automatic re-handshake
+        _handshakeProps = handshakeProps;
+
+        var version = '1.0';
+
+        // Figure out the transports to send to the server
+        var transportTypes = _transports.findTransportTypes(version, _crossDomain, _config.url);
+
+        var bayeuxMessage = {
+            version: version,
+            minimumVersion: '0.9',
+            channel: '/meta/handshake',
+            supportedConnectionTypes: transportTypes,
+            advice: {
+                timeout: _advice.timeout,
+                interval: _advice.interval
+            }
+        };
+        // Do not allow the user to mess with the required properties,
+        // so merge first the user properties and *then* the bayeux message
+        var message = _cometd._mixin(false, {}, _handshakeProps, bayeuxMessage);
+
+        // Pick up the first available transport as initial transport
+        // since we don't know if the server supports it
+        _transport = _transports.negotiateTransport(transportTypes, version, _crossDomain, _config.url);
+        _cometd._debug('Initial transport is', _transport.getType());
+
+        // We started a batch to hold the application messages,
+        // so here we must bypass it and send immediately.
+        _setStatus('handshaking');
+        _cometd._debug('Handshake sent', message);
+        _send(false, [message], false, 'handshake');
+    }
+
+    function _delayedHandshake()
+    {
+        _setStatus('handshaking');
+
+        // We will call _handshake() which will reset _clientId, but we want to avoid
+        // that between the end of this method and the call to _handshake() someone may
+        // call publish() (or other methods that call _queueSend()).
+        _internalBatch = true;
+
+        _delayedSend(function()
+        {
+            _handshake(_handshakeProps);
+        });
+    }
+
+    function _failHandshake(message)
+    {
+        _notifyListeners('/meta/handshake', message);
+        _notifyListeners('/meta/unsuccessful', message);
+
+        // Only try again if we haven't been disconnected and
+        // the advice permits us to retry the handshake
+        var retry = !_isDisconnected() && _advice.reconnect !== 'none';
+        if (retry)
+        {
+            _increaseBackoff();
+            _delayedHandshake();
+        }
+        else
+        {
+            _disconnect(false);
+        }
+    }
+
+    function _handshakeResponse(message)
+    {
+        if (message.successful)
+        {
+            // Save clientId, figure out transport, then follow the advice to connect
+            _clientId = message.clientId;
+
+            var newTransport = _transports.negotiateTransport(message.supportedConnectionTypes, message.version, _crossDomain, _config.url);
+            if (newTransport === null)
+            {
+                throw 'Could not negotiate transport with server; client ' +
+                      _transports.findTransportTypes(message.version, _crossDomain, _config.url) +
+                      ', server ' + message.supportedConnectionTypes;
+            }
+            else if (_transport !== newTransport)
+            {
+                _cometd._debug('Transport', _transport, '->', newTransport);
+                _transport = newTransport;
+            }
+
+            // End the internal batch and allow held messages from the application
+            // to go to the server (see _handshake() where we start the internal batch).
+            _internalBatch = false;
+            _flushBatch();
+
+            // Here the new transport is in place, as well as the clientId, so
+            // the listeners can perform a publish() if they want.
+            // Notify the listeners before the connect below.
+            message.reestablish = _reestablish;
+            _reestablish = true;
+            _notifyListeners('/meta/handshake', message);
+
+            var action = _isDisconnected() ? 'none' : _advice.reconnect;
+            switch (action)
+            {
+                case 'retry':
+                    _resetBackoff();
+                    _delayedConnect();
+                    break;
+                case 'none':
+                    _disconnect(false);
+                    break;
+                default:
+                    throw 'Unrecognized advice action ' + action;
+            }
+        }
+        else
+        {
+            _failHandshake(message);
+        }
+    }
+
+    function _handshakeFailure(xhr, message)
+    {
+        _failHandshake({
+            successful: false,
+            failure: true,
+            channel: '/meta/handshake',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'retry',
+                interval: _backoff
+            }
+        });
+    }
+
+    function _failConnect(message)
+    {
+        // Notify the listeners after the status change but before the next action
+        _notifyListeners('/meta/connect', message);
+        _notifyListeners('/meta/unsuccessful', message);
+
+        // This may happen when the server crashed, the current clientId
+        // will be invalid, and the server will ask to handshake again
+        // Listeners can call disconnect(), so check the state after they run
+        var action = _isDisconnected() ? 'none' : _advice.reconnect;
+        switch (action)
+        {
+            case 'retry':
+                _delayedConnect();
+                _increaseBackoff();
+                break;
+            case 'handshake':
+                // The current transport may be failed (e.g. network disconnection)
+                // Reset the transports so the new handshake picks up the right one
+                _transports.reset();
+                _resetBackoff();
+                _delayedHandshake();
+                break;
+            case 'none':
+                _disconnect(false);
+                break;
+            default:
+                throw 'Unrecognized advice action' + action;
+        }
+    }
+
+    function _connectResponse(message)
+    {
+        _connected = message.successful;
+
+        if (_connected)
+        {
+            _notifyListeners('/meta/connect', message);
+
+            // Normally, the advice will say "reconnect: 'retry', interval: 0"
+            // and the server will hold the request, so when a response returns
+            // we immediately call the server again (long polling)
+            // Listeners can call disconnect(), so check the state after they run
+            var action = _isDisconnected() ? 'none' : _advice.reconnect;
+            switch (action)
+            {
+                case 'retry':
+                    _resetBackoff();
+                    _delayedConnect();
+                    break;
+                case 'none':
+                    _disconnect(false);
+                    break;
+                default:
+                    throw 'Unrecognized advice action ' + action;
+            }
+        }
+        else
+        {
+            _failConnect(message);
+        }
+    }
+
+    function _connectFailure(xhr, message)
+    {
+        _connected = false;
+        _failConnect({
+            successful: false,
+            failure: true,
+            channel: '/meta/connect',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'retry',
+                interval: _backoff
+            }
+        });
+    }
+
+    function _failDisconnect(message)
+    {
+        _disconnect(true);
+        _notifyListeners('/meta/disconnect', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _disconnectResponse(message)
+    {
+        if (message.successful)
+        {
+            _disconnect(false);
+            _notifyListeners('/meta/disconnect', message);
+        }
+        else
+        {
+            _failDisconnect(message);
+        }
+    }
+
+    function _disconnectFailure(xhr, message)
+    {
+        _failDisconnect({
+            successful: false,
+            failure: true,
+            channel: '/meta/disconnect',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _failSubscribe(message)
+    {
+        _notifyListeners('/meta/subscribe', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _subscribeResponse(message)
+    {
+        if (message.successful)
+        {
+            _notifyListeners('/meta/subscribe', message);
+        }
+        else
+        {
+            _failSubscribe(message);
+        }
+    }
+
+    function _subscribeFailure(xhr, message)
+    {
+        _failSubscribe({
+            successful: false,
+            failure: true,
+            channel: '/meta/subscribe',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _failUnsubscribe(message)
+    {
+        _notifyListeners('/meta/unsubscribe', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _unsubscribeResponse(message)
+    {
+        if (message.successful)
+        {
+            _notifyListeners('/meta/unsubscribe', message);
+        }
+        else
+        {
+            _failUnsubscribe(message);
+        }
+    }
+
+    function _unsubscribeFailure(xhr, message)
+    {
+        _failUnsubscribe({
+            successful: false,
+            failure: true,
+            channel: '/meta/unsubscribe',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _handlePublishCallback(message)
+    {
+        var callback = _publishCallbacks[message.id];
+        if (_isFunction(callback))
+        {
+            delete _publishCallbacks[message.id];
+            callback.call(_cometd, message);
+        }
+    }
+
+    function _failMessage(message)
+    {
+        _handlePublishCallback(message);
+        _notifyListeners('/meta/publish', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _messageResponse(message)
+    {
+        if (message.successful === undefined)
+        {
+            if (message.data)
+            {
+                // It is a plain message, and not a bayeux meta message
+                _notifyListeners(message.channel, message);
+            }
+            else
+            {
+                _cometd._debug('Unknown message', message);
+            }
+        }
+        else
+        {
+            if (message.successful)
+            {
+                _handlePublishCallback(message);
+                _notifyListeners('/meta/publish', message);
+            }
+            else
+            {
+                _failMessage(message);
+            }
+        }
+    }
+
+    function _messageFailure(xhr, message)
+    {
+        _failMessage({
+            successful: false,
+            failure: true,
+            channel: message.channel,
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _receive(message)
+    {
+        message = _applyIncomingExtensions(message);
+        if (message === undefined || message === null)
+        {
+            return;
+        }
+
+        _updateAdvice(message.advice);
+
+        var channel = message.channel;
+        switch (channel)
+        {
+            case '/meta/handshake':
+                _handshakeResponse(message);
+                break;
+            case '/meta/connect':
+                _connectResponse(message);
+                break;
+            case '/meta/disconnect':
+                _disconnectResponse(message);
+                break;
+            case '/meta/subscribe':
+                _subscribeResponse(message);
+                break;
+            case '/meta/unsubscribe':
+                _unsubscribeResponse(message);
+                break;
+            default:
+                _messageResponse(message);
+                break;
+        }
+    }
+
+    /**
+     * Receives a message.
+     * This method is exposed as a public so that extensions may inject
+     * messages simulating that they had been received.
+     */
+    this.receive = _receive;
+
+    _handleMessages = function(rcvdMessages)
+    {
+        _cometd._debug('Received', rcvdMessages);
+
+        for (var i = 0; i < rcvdMessages.length; ++i)
+        {
+            var message = rcvdMessages[i];
+            _receive(message);
+        }
+    };
+
+    _handleFailure = function(conduit, messages, reason, exception)
+    {
+        _cometd._debug('handleFailure', conduit, messages, reason, exception);
+
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+            var channel = message.channel;
+            switch (channel)
+            {
+                case '/meta/handshake':
+                    _handshakeFailure(conduit, message);
+                    break;
+                case '/meta/connect':
+                    _connectFailure(conduit, message);
+                    break;
+                case '/meta/disconnect':
+                    _disconnectFailure(conduit, message);
+                    break;
+                case '/meta/subscribe':
+                    _subscribeFailure(conduit, message);
+                    break;
+                case '/meta/unsubscribe':
+                    _unsubscribeFailure(conduit, message);
+                    break;
+                default:
+                    _messageFailure(conduit, message);
+                    break;
+            }
+        }
+    };
+
+    function _hasSubscriptions(channel)
+    {
+        var subscriptions = _listeners[channel];
+        if (subscriptions)
+        {
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                if (subscriptions[i])
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    function _resolveScopedCallback(scope, callback)
+    {
+        var delegate = {
+            scope: scope,
+            method: callback
+        };
+        if (_isFunction(scope))
+        {
+            delegate.scope = undefined;
+            delegate.method = scope;
+        }
+        else
+        {
+            if (_isString(callback))
+            {
+                if (!scope)
+                {
+                    throw 'Invalid scope ' + scope;
+                }
+                delegate.method = scope[callback];
+                if (!_isFunction(delegate.method))
+                {
+                    throw 'Invalid callback ' + callback + ' for scope ' + scope;
+                }
+            }
+            else if (!_isFunction(callback))
+            {
+                throw 'Invalid callback ' + callback;
+            }
+        }
+        return delegate;
+    }
+
+    function _addListener(channel, scope, callback, isListener)
+    {
+        // The data structure is a map<channel, subscription[]>, where each subscription
+        // holds the callback to be called and its scope.
+
+        var delegate = _resolveScopedCallback(scope, callback);
+        _cometd._debug('Adding listener on', channel, 'with scope', delegate.scope, 'and callback', delegate.method);
+
+        var subscription = {
+            channel: channel,
+            scope: delegate.scope,
+            callback: delegate.method,
+            listener: isListener
+        };
+
+        var subscriptions = _listeners[channel];
+        if (!subscriptions)
+        {
+            subscriptions = [];
+            _listeners[channel] = subscriptions;
+        }
+
+        // Pushing onto an array appends at the end and returns the id associated with the element increased by 1.
+        // Note that if:
+        // a.push('a'); var hb=a.push('b'); delete a[hb-1]; var hc=a.push('c');
+        // then:
+        // hc==3, a.join()=='a',,'c', a.length==3
+        var subscriptionID = subscriptions.push(subscription) - 1;
+        subscription.id = subscriptionID;
+        subscription.handle = [channel, subscriptionID];
+
+        _cometd._debug('Added listener', subscription, 'for channel', channel, 'having id =', subscriptionID);
+
+        // The subscription to allow removal of the listener is made of the channel and the index
+        return subscription.handle;
+    }
+
+    function _removeListener(subscription)
+    {
+        var subscriptions = _listeners[subscription[0]];
+        if (subscriptions)
+        {
+            delete subscriptions[subscription[1]];
+            _cometd._debug('Removed listener', subscription);
+        }
+    }
+
+    //
+    // PUBLIC API
+    //
+
+    /**
+     * Registers the given transport under the given transport type.
+     * The optional index parameter specifies the "priority" at which the
+     * transport is registered (where 0 is the max priority).
+     * If a transport with the same type is already registered, this function
+     * does nothing and returns false.
+     * @param type the transport type
+     * @param transport the transport object
+     * @param index the index at which this transport is to be registered
+     * @return true if the transport has been registered, false otherwise
+     * @see #unregisterTransport(type)
+     */
+    this.registerTransport = function(type, transport, index)
+    {
+        var result = _transports.add(type, transport, index);
+        if (result)
+        {
+            this._debug('Registered transport', type);
+
+            if (_isFunction(transport.registered))
+            {
+                transport.registered(type, this);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @return an array of all registered transport types
+     */
+    this.getTransportTypes = function()
+    {
+        return _transports.getTransportTypes();
+    };
+
+    /**
+     * Unregisters the transport with the given transport type.
+     * @param type the transport type to unregister
+     * @return the transport that has been unregistered,
+     * or null if no transport was previously registered under the given transport type
+     */
+    this.unregisterTransport = function(type)
+    {
+        var transport = _transports.remove(type);
+        if (transport !== null)
+        {
+            this._debug('Unregistered transport', type);
+
+            if (_isFunction(transport.unregistered))
+            {
+                transport.unregistered();
+            }
+        }
+        return transport;
+    };
+
+    this.unregisterTransports = function()
+    {
+        _transports.clear();
+    };
+
+    this.findTransport = function(name)
+    {
+        return _transports.find(name);
+    };
+
+    /**
+     * Configures the initial Bayeux communication with the Bayeux server.
+     * Configuration is passed via an object that must contain a mandatory field <code>url</code>
+     * of type string containing the URL of the Bayeux server.
+     * @param configuration the configuration object
+     */
+    this.configure = function(configuration)
+    {
+        _configure.call(this, configuration);
+    };
+
+    /**
+     * Configures and establishes the Bayeux communication with the Bayeux server
+     * via a handshake and a subsequent connect.
+     * @param configuration the configuration object
+     * @param handshakeProps an object to be merged with the handshake message
+     * @see #configure(configuration)
+     * @see #handshake(handshakeProps)
+     */
+    this.init = function(configuration, handshakeProps)
+    {
+        this.configure(configuration);
+        this.handshake(handshakeProps);
+    };
+
+    /**
+     * Establishes the Bayeux communication with the Bayeux server
+     * via a handshake and a subsequent connect.
+     * @param handshakeProps an object to be merged with the handshake message
+     */
+    this.handshake = function(handshakeProps)
+    {
+        _setStatus('disconnected');
+        _reestablish = false;
+        _handshake(handshakeProps);
+    };
+
+    /**
+     * Disconnects from the Bayeux server.
+     * It is possible to suggest to attempt a synchronous disconnect, but this feature
+     * may only be available in certain transports (for example, long-polling may support
+     * it, callback-polling certainly does not).
+     * @param sync whether attempt to perform a synchronous disconnect
+     * @param disconnectProps an object to be merged with the disconnect message
+     */
+    this.disconnect = function(sync, disconnectProps)
+    {
+        if (_isDisconnected())
+        {
+            return;
+        }
+
+        if (disconnectProps === undefined)
+        {
+            if (typeof sync !== 'boolean')
+            {
+                disconnectProps = sync;
+                sync = false;
+            }
+        }
+
+        var bayeuxMessage = {
+            channel: '/meta/disconnect'
+        };
+        var message = this._mixin(false, {}, disconnectProps, bayeuxMessage);
+        _setStatus('disconnecting');
+        _send(sync === true, [message], false, 'disconnect');
+    };
+
+    /**
+     * Marks the start of a batch of application messages to be sent to the server
+     * in a single request, obtaining a single response containing (possibly) many
+     * application reply messages.
+     * Messages are held in a queue and not sent until {@link #endBatch()} is called.
+     * If startBatch() is called multiple times, then an equal number of endBatch()
+     * calls must be made to close and send the batch of messages.
+     * @see #endBatch()
+     */
+    this.startBatch = function()
+    {
+        _startBatch();
+    };
+
+    /**
+     * Marks the end of a batch of application messages to be sent to the server
+     * in a single request.
+     * @see #startBatch()
+     */
+    this.endBatch = function()
+    {
+        _endBatch();
+    };
+
+    /**
+     * Executes the given callback in the given scope, surrounded by a {@link #startBatch()}
+     * and {@link #endBatch()} calls.
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to be executed within {@link #startBatch()} and {@link #endBatch()} calls
+     */
+    this.batch = function(scope, callback)
+    {
+        var delegate = _resolveScopedCallback(scope, callback);
+        this.startBatch();
+        try
+        {
+            delegate.method.call(delegate.scope);
+            this.endBatch();
+        }
+        catch (x)
+        {
+            this._debug('Exception during execution of batch', x);
+            this.endBatch();
+            throw x;
+        }
+    };
+
+    /**
+     * Adds a listener for bayeux messages, performing the given callback in the given scope
+     * when a message for the given channel arrives.
+     * @param channel the channel the listener is interested to
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to call when a message is sent to the channel
+     * @returns the subscription handle to be passed to {@link #removeListener(object)}
+     * @see #removeListener(subscription)
+     */
+    this.addListener = function(channel, scope, callback)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+
+        return _addListener(channel, scope, callback, true);
+    };
+
+    /**
+     * Removes the subscription obtained with a call to {@link #addListener(string, object, function)}.
+     * @param subscription the subscription to unsubscribe.
+     * @see #addListener(channel, scope, callback)
+     */
+    this.removeListener = function(subscription)
+    {
+        if (!org.cometd.Utils.isArray(subscription))
+        {
+            throw 'Invalid argument: expected subscription, not ' + subscription;
+        }
+
+        _removeListener(subscription);
+    };
+
+    /**
+     * Removes all listeners registered with {@link #addListener(channel, scope, callback)} or
+     * {@link #subscribe(channel, scope, callback)}.
+     */
+    this.clearListeners = function()
+    {
+        _listeners = {};
+    };
+
+    /**
+     * Subscribes to the given channel, performing the given callback in the given scope
+     * when a message for the channel arrives.
+     * @param channel the channel to subscribe to
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to call when a message is sent to the channel
+     * @param subscribeProps an object to be merged with the subscribe message
+     * @return the subscription handle to be passed to {@link #unsubscribe(object)}
+     */
+    this.subscribe = function(channel, scope, callback, subscribeProps)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        // Normalize arguments
+        if (_isFunction(scope))
+        {
+            subscribeProps = callback;
+            callback = scope;
+            scope = undefined;
+        }
+
+        // Only send the message to the server if this client has not yet subscribed to the channel
+        var send = !_hasSubscriptions(channel);
+
+        var subscription = _addListener(channel, scope, callback, false);
+
+        if (send)
+        {
+            // Send the subscription message after the subscription registration to avoid
+            // races where the server would send a message to the subscribers, but here
+            // on the client the subscription has not been added yet to the data structures
+            var bayeuxMessage = {
+                channel: '/meta/subscribe',
+                subscription: channel
+            };
+            var message = this._mixin(false, {}, subscribeProps, bayeuxMessage);
+            _queueSend(message);
+        }
+
+        return subscription;
+    };
+
+    /**
+     * Unsubscribes the subscription obtained with a call to {@link #subscribe(string, object, function)}.
+     * @param subscription the subscription to unsubscribe.
+     */
+    this.unsubscribe = function(subscription, unsubscribeProps)
+    {
+        if (arguments.length < 1)
+        {
+            throw 'Illegal arguments number: required 1, got ' + arguments.length;
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        // Remove the local listener before sending the message
+        // This ensures that if the server fails, this client does not get notifications
+        this.removeListener(subscription);
+
+        var channel = subscription[0];
+        // Only send the message to the server if this client unsubscribes the last subscription
+        if (!_hasSubscriptions(channel))
+        {
+            var bayeuxMessage = {
+                channel: '/meta/unsubscribe',
+                subscription: channel
+            };
+            var message = this._mixin(false, {}, unsubscribeProps, bayeuxMessage);
+            _queueSend(message);
+        }
+    };
+
+    /**
+     * Removes all subscriptions added via {@link #subscribe(channel, scope, callback, subscribeProps)},
+     * but does not remove the listeners added via {@link addListener(channel, scope, callback)}.
+     */
+    this.clearSubscriptions = function()
+    {
+        _clearSubscriptions();
+    };
+
+    /**
+     * Publishes a message on the given channel, containing the given content.
+     * @param channel the channel to publish the message to
+     * @param content the content of the message
+     * @param publishProps an object to be merged with the publish message
+     */
+    this.publish = function(channel, content, publishProps, publishCallback)
+    {
+        if (arguments.length < 1)
+        {
+            throw 'Illegal arguments number: required 1, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        if (_isFunction(content))
+        {
+            publishCallback = content;
+            content = publishProps = {};
+        }
+        else if (_isFunction(publishProps))
+        {
+            publishCallback = publishProps;
+            publishProps = {};
+        }
+
+        var bayeuxMessage = {
+            channel: channel,
+            data: content,
+            _callback: publishCallback
+        };
+        var message = this._mixin(false, {}, publishProps, bayeuxMessage);
+        _queueSend(message);
+    };
+
+    /**
+     * Returns a string representing the status of the bayeux communication with the Bayeux server.
+     */
+    this.getStatus = function()
+    {
+        return _status;
+    };
+
+    /**
+     * Returns whether this instance has been disconnected.
+     */
+    this.isDisconnected = _isDisconnected;
+
+    /**
+     * Sets the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
+     * Default value is 1 second, which means if there is a persistent failure the retries will happen
+     * after 1 second, then after 2 seconds, then after 3 seconds, etc. So for example with 15 seconds of
+     * elapsed time, there will be 5 retries (at 1, 3, 6, 10 and 15 seconds elapsed).
+     * @param period the backoff period to set
+     * @see #getBackoffIncrement()
+     */
+    this.setBackoffIncrement = function(period)
+    {
+        _config.backoffIncrement = period;
+    };
+
+    /**
+     * Returns the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
+     * @see #setBackoffIncrement(period)
+     */
+    this.getBackoffIncrement = function()
+    {
+        return _config.backoffIncrement;
+    };
+
+    /**
+     * Returns the backoff period to wait before retrying an unsuccessful or failed message.
+     */
+    this.getBackoffPeriod = function()
+    {
+        return _backoff;
+    };
+
+    /**
+     * Sets the log level for console logging.
+     * Valid values are the strings 'error', 'warn', 'info' and 'debug', from
+     * less verbose to more verbose.
+     * @param level the log level string
+     */
+    this.setLogLevel = function(level)
+    {
+        _config.logLevel = level;
+    };
+
+    /**
+     * Registers an extension whose callbacks are called for every incoming message
+     * (that comes from the server to this client implementation) and for every
+     * outgoing message (that originates from this client implementation for the
+     * server).
+     * The format of the extension object is the following:
+     * <pre>
+     * {
+     *     incoming: function(message) { ... },
+     *     outgoing: function(message) { ... }
+     * }
+     * </pre>
+     * Both properties are optional, but if they are present they will be called
+     * respectively for each incoming message and for each outgoing message.
+     * @param name the name of the extension
+     * @param extension the extension to register
+     * @return true if the extension was registered, false otherwise
+     * @see #unregisterExtension(name)
+     */
+    this.registerExtension = function(name, extension)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(name))
+        {
+            throw 'Illegal argument type: extension name must be a string';
+        }
+
+        var existing = false;
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var existingExtension = _extensions[i];
+            if (existingExtension.name === name)
+            {
+                existing = true;
+                break;
+            }
+        }
+        if (!existing)
+        {
+            _extensions.push({
+                name: name,
+                extension: extension
+            });
+            this._debug('Registered extension', name);
+
+            // Callback for extensions
+            if (_isFunction(extension.registered))
+            {
+                extension.registered(name, this);
+            }
+
+            return true;
+        }
+        else
+        {
+            this._info('Could not register extension with name', name, 'since another extension with the same name already exists');
+            return false;
+        }
+    };
+
+    /**
+     * Unregister an extension previously registered with
+     * {@link #registerExtension(name, extension)}.
+     * @param name the name of the extension to unregister.
+     * @return true if the extension was unregistered, false otherwise
+     */
+    this.unregisterExtension = function(name)
+    {
+        if (!_isString(name))
+        {
+            throw 'Illegal argument type: extension name must be a string';
+        }
+
+        var unregistered = false;
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var extension = _extensions[i];
+            if (extension.name === name)
+            {
+                _extensions.splice(i, 1);
+                unregistered = true;
+                this._debug('Unregistered extension', name);
+
+                // Callback for extensions
+                var ext = extension.extension;
+                if (_isFunction(ext.unregistered))
+                {
+                    ext.unregistered();
+                }
+
+                break;
+            }
+        }
+        return unregistered;
+    };
+
+    /**
+     * Find the extension registered with the given name.
+     * @param name the name of the extension to find
+     * @return the extension found or null if no extension with the given name has been registered
+     */
+    this.getExtension = function(name)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var extension = _extensions[i];
+            if (extension.name === name)
+            {
+                return extension.extension;
+            }
+        }
+        return null;
+    };
+
+    /**
+     * Returns the name assigned to this Cometd object, or the string 'default'
+     * if no name has been explicitly passed as parameter to the constructor.
+     */
+    this.getName = function()
+    {
+        return _name;
+    };
+
+    /**
+     * Returns the clientId assigned by the Bayeux server during handshake.
+     */
+    this.getClientId = function()
+    {
+        return _clientId;
+    };
+
+    /**
+     * Returns the URL of the Bayeux server.
+     */
+    this.getURL = function()
+    {
+        return _config.url;
+    };
+
+    this.getTransport = function()
+    {
+        return _transport;
+    };
+
+    this.getConfiguration = function()
+    {
+        return this._mixin(true, {}, _config);
+    };
+
+    this.getAdvice = function()
+    {
+        return this._mixin(true, {}, _advice);
+    };
+
+    // WebSocket handling for Firefox, which deploys WebSocket
+    // under the name of MozWebSocket in Firefox 6, 7, 8 and 9
+    org.cometd.WebSocket = window.WebSocket;
+    if (!org.cometd.WebSocket)
+    {
+        org.cometd.WebSocket = window.MozWebSocket;
+    }
+};
+
+if (typeof define === 'function' && define.amd)
+{
+    define(function()
+    {
+        return org.cometd;
+    });
+}
+
diff --git a/src/main/webapp/lib/jquery/org/cometd/AckExtension.js b/src/main/webapp/lib/jquery/org/cometd/AckExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..3b547a67ca45410eb46036691a8aa495941f121e
--- /dev/null
+++ b/src/main/webapp/lib/jquery/org/cometd/AckExtension.js
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * This client-side extension enables the client to acknowledge to the server
+         * the messages that the client has received.
+         * For the acknowledgement to work, the server must be configured with the
+         * correspondent server-side ack extension. If both client and server support
+         * the ack extension, then the ack functionality will take place automatically.
+         * By enabling this extension, all messages arriving from the server will arrive
+         * via the long poll, so the comet communication will be slightly chattier.
+         * The fact that all messages will return via long poll means also that the
+         * messages will arrive with total order, which is not guaranteed if messages
+         * can arrive via both long poll and normal response.
+         * Messages are not acknowledged one by one, but instead a group of messages is
+         * acknowledged when long poll returns.
+         */
+        return org_cometd.AckExtension = function()
+        {
+            var _cometd;
+            var _serverSupportsAcks = false;
+            var _ackId = -1;
+
+            function _debug(text, args)
+            {
+                _cometd._debug(text, args);
+            }
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _debug('AckExtension: executing registration callback');
+            };
+
+            this.unregistered = function()
+            {
+                _debug('AckExtension: executing unregistration callback');
+                _cometd = null;
+            };
+
+            this.incoming = function(message)
+            {
+                var channel = message.channel;
+                if (channel == '/meta/handshake')
+                {
+                    _serverSupportsAcks = message.ext && message.ext.ack;
+                    _debug('AckExtension: server supports acks', _serverSupportsAcks);
+                }
+                else if (_serverSupportsAcks && channel == '/meta/connect' && message.successful)
+                {
+                    var ext = message.ext;
+                    if (ext && typeof ext.ack === 'number')
+                    {
+                        _ackId = ext.ack;
+                        _debug('AckExtension: server sent ack id', _ackId);
+                    }
+                }
+                return message;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+                if (channel == '/meta/handshake')
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.ack = _cometd && _cometd.ackEnabled !== false;
+                    _ackId = -1;
+                }
+                else if (_serverSupportsAcks && channel == '/meta/connect')
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.ack = _ackId;
+                    _debug('AckExtension: client sending ack id', _ackId);
+                }
+                return message;
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/jquery/org/cometd/ReloadExtension.js b/src/main/webapp/lib/jquery/org/cometd/ReloadExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef6de781554f6a9067666b85e2d32966871068eb
--- /dev/null
+++ b/src/main/webapp/lib/jquery/org/cometd/ReloadExtension.js
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        if (!org_cometd.COOKIE)
+        {
+            org_cometd.COOKIE = {};
+            org_cometd.COOKIE.set = function(name, value, options)
+            {
+                throw 'Abstract';
+            };
+            org_cometd.COOKIE.get = function(name)
+            {
+                throw 'Abstract';
+            };
+        }
+
+        /**
+         * The reload extension allows a page to be loaded (or reloaded)
+         * without having to re-handshake in the new (or reloaded) page,
+         * therefore resuming the existing cometd connection.
+         *
+         * When the reload() method is called, the state of the cometd
+         * connection and of the cometd subscriptions is stored in a cookie
+         * with a short max-age.
+         * The reload() method must therefore be called by page unload
+         * handlers, often provided by JavaScript toolkits.
+         *
+         * When the page is (re)loaded, this extension checks the cookie
+         * and restores the cometd connection and the cometd subscriptions.
+         */
+        return org_cometd.ReloadExtension = function(configuration)
+        {
+            var _cometd;
+            var _debug;
+            var _state = null;
+            var _cookieName = 'org.cometd.reload';
+            var _cookiePath = '/';
+            var _cookieMaxAge = 5;
+            var _batch = false;
+
+            function _reload(config)
+            {
+                if (_state && _state.handshakeResponse !== null)
+                {
+                    _configure(config);
+                    _state.cookiePath = _cookiePath;
+                    var cookie = org_cometd.JSON.toJSON(_state);
+                    _debug('Reload extension saving cookie value', cookie);
+                    org_cometd.COOKIE.set(_cookieName, cookie, {
+                        'max-age': _cookieMaxAge,
+                        path: _cookiePath,
+                        expires: new Date(new Date().getTime() + _cookieMaxAge * 1000)
+                    });
+                }
+            }
+
+            function _similarState(oldState)
+            {
+                // We want to check here that the CometD object
+                // did not change much between reloads.
+                // We just check the URL for now, but in future
+                // further checks may involve the transport type
+                // and other configuration parameters.
+                return _state.url == oldState.url;
+            }
+
+            function _configure(config)
+            {
+                if (config)
+                {
+                    if (typeof config.cookieMaxAge === 'number')
+                    {
+                        _cookieMaxAge = config.cookieMaxAge;
+                    }
+                    if (typeof config.cookieName === 'string')
+                    {
+                        _cookieName = config.cookieName;
+                    }
+                    if (typeof config.cookiePath === 'string')
+                    {
+                        _cookiePath = config.cookiePath;
+                    }
+                }
+            }
+
+            this.configure = _configure;
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _cometd.reload = _reload;
+                _debug = _cometd._debug;
+            };
+
+            this.unregistered = function()
+            {
+                delete _cometd.reload;
+                _cometd = null;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+
+                if (channel == '/meta/handshake')
+                {
+                    _state = {};
+                    _state.url = _cometd.getURL();
+
+                    var cookie = org_cometd.COOKIE.get(_cookieName);
+                    _debug('Reload extension found cookie value', cookie);
+                    // Is there a saved handshake response from a prior load ?
+                    if (cookie)
+                    {
+                        try
+                        {
+                            var oldState = org_cometd.JSON.fromJSON(cookie);
+
+                            // Remove the cookie, not needed anymore
+                            org_cometd.COOKIE.set(_cookieName, '', {
+                                'max-age': -1,
+                                path: oldState.cookiePath,
+                                expires: -1
+                            });
+
+                            if (oldState.handshakeResponse && _similarState(oldState))
+                            {
+                                _debug('Reload extension restoring state', oldState);
+                                setTimeout(function()
+                                {
+                                    _debug('Reload extension replaying handshake response', oldState.handshakeResponse);
+                                    _state.handshakeResponse = oldState.handshakeResponse;
+                                    _state.transportType = oldState.transportType;
+                                    _state.reloading = true;
+                                    var response = _cometd._mixin(true, {}, _state.handshakeResponse, {ext: {reload: true}});
+                                    response.supportedConnectionTypes = [_state.transportType];
+                                    _cometd.receive(response);
+                                    _debug('Reload extension replayed handshake response', response);
+                                }, 0);
+
+                                // delay any sends until first connect is complete.
+                                if (!_batch)
+                                {
+                                    _batch = true;
+                                    _cometd.startBatch();
+                                }
+                                // This handshake is aborted, as we will replay the prior handshake response
+                                return null;
+                            }
+                            else
+                            {
+                                _debug('Reload extension could not restore state', oldState);
+                            }
+                        }
+                        catch(x)
+                        {
+                            _debug('Reload extension error while trying to restore cookie', x);
+                        }
+                    }
+                }
+                else if (channel == '/meta/connect')
+                {
+                    if (!_state.transportType)
+                    {
+                        _state.transportType = message.connectionType;
+                        _debug('Reload extension tracked transport type', _state.transportType);
+                    }
+                }
+                return message;
+            };
+
+            this.incoming = function(message)
+            {
+                if (message.successful)
+                {
+                    switch (message.channel)
+                    {
+                        case '/meta/handshake':
+                            // If the handshake response is already present, then we're replaying it.
+                            // Since the replay may have modified the handshake response, do not record it here.
+                            if (!_state.handshakeResponse)
+                            {
+                                // Save successful handshake response
+                                _state.handshakeResponse = message;
+                                _debug('Reload extension tracked handshake response', message);
+                            }
+                            break;
+                        case '/meta/disconnect':
+                            _state = null;
+                            break;
+                        case '/meta/connect':
+                            if (_batch)
+                            {
+                                _cometd.endBatch();
+                                _batch = false;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                return message;
+            };
+
+            _configure(configuration);
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/jquery/org/cometd/TimeStampExtension.js b/src/main/webapp/lib/jquery/org/cometd/TimeStampExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..8011a3a68e54ed9dae65583400421637a649cabf
--- /dev/null
+++ b/src/main/webapp/lib/jquery/org/cometd/TimeStampExtension.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * The timestamp extension adds the optional timestamp field to all outgoing messages.
+         */
+        return org_cometd.TimeStampExtension = function()
+        {
+            this.outgoing = function(message)
+            {
+                message.timestamp = new Date().toUTCString();
+                return message;
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+}());
diff --git a/src/main/webapp/lib/jquery/org/cometd/TimeSyncExtension.js b/src/main/webapp/lib/jquery/org/cometd/TimeSyncExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..506329830f9d486ceeb38a90b7054bfbf28d1dc3
--- /dev/null
+++ b/src/main/webapp/lib/jquery/org/cometd/TimeSyncExtension.js
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * With each handshake or connect, the extension sends timestamps within the
+         * ext field like: <code>{ext:{timesync:{tc:12345567890,l:23,o:4567},...},...}</code>
+         * where:<ul>
+         *  <li>tc is the client timestamp in ms since 1970 of when the message was sent.
+         *  <li>l is the network lag that the client has calculated.
+         *  <li>o is the clock offset that the client has calculated.
+         * </ul>
+         *
+         * <p>
+         * A cometd server that supports timesync, can respond with an ext
+         * field like: <code>{ext:{timesync:{tc:12345567890,ts:1234567900,p:123,a:3},...},...}</code>
+         * where:<ul>
+         *  <li>tc is the client timestamp of when the message was sent,
+         *  <li>ts is the server timestamp of when the message was received
+         *  <li>p is the poll duration in ms - ie the time the server took before sending the response.
+         *  <li>a is the measured accuracy of the calculated offset and lag sent by the client
+         * </ul>
+         *
+         * <p>
+         * The relationship between tc, ts & l is given by <code>ts=tc+o+l</code> (the
+         * time the server received the messsage is the client time plus the offset plus the
+         * network lag).   Thus the accuracy of the o and l settings can be determined with
+         * <code>a=(tc+o+l)-ts</code>.
+         * </p>
+         * <p>
+         * When the client has received the response, it can make a more accurate estimate
+         * of the lag as <code>l2=(now-tc-p)/2</code> (assuming symmetric lag).
+         * A new offset can then be calculated with the relationship on the client
+         * that <code>ts=tc+o2+l2</code>, thus <code>o2=ts-tc-l2</code>.
+         * </p>
+         * <p>
+         * Since the client also receives the a value calculated on the server, it
+         * should be possible to analyse this and compensate for some asymmetry
+         * in the lag. But the current client does not do this.
+         * </p>
+         *
+         * @param configuration
+         */
+        return org_cometd.TimeSyncExtension = function(configuration)
+        {
+            var _cometd;
+            var _maxSamples = configuration && configuration.maxSamples || 10;
+            var _lags = [];
+            var _offsets = [];
+            var _lag = 0;
+            var _offset = 0;
+
+            function _debug(text, args)
+            {
+                _cometd._debug(text, args);
+            }
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _debug('TimeSyncExtension: executing registration callback');
+            };
+
+            this.unregistered = function()
+            {
+                _debug('TimeSyncExtension: executing unregistration callback');
+                _cometd = null;
+                _lags = [];
+                _offsets = [];
+            };
+
+            this.incoming = function(message)
+            {
+                var channel = message.channel;
+                if (channel && channel.indexOf('/meta/') === 0)
+                {
+                    if (message.ext && message.ext.timesync)
+                    {
+                        var timesync = message.ext.timesync;
+                        _debug('TimeSyncExtension: server sent timesync', timesync);
+
+                        var now = new Date().getTime();
+                        var l2 = (now - timesync.tc - timesync.p) / 2;
+                        var o2 = timesync.ts - timesync.tc - l2;
+
+                        _lags.push(l2);
+                        _offsets.push(o2);
+                        if (_offsets.length > _maxSamples)
+                        {
+                            _offsets.shift();
+                            _lags.shift();
+                        }
+
+                        var samples = _offsets.length;
+                        var lagsSum = 0;
+                        var offsetsSum = 0;
+                        for (var i = 0; i < samples; ++i)
+                        {
+                            lagsSum += _lags[i];
+                            offsetsSum += _offsets[i];
+                        }
+                        _lag = parseInt((lagsSum / samples).toFixed());
+                        _offset = parseInt((offsetsSum / samples).toFixed());
+                        _debug('TimeSyncExtension: network lag', _lag, 'ms, time offset with server', _offset, 'ms', _lag, _offset);
+                    }
+                }
+                return message;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+                if (channel && channel.indexOf('/meta/') === 0)
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.timesync = {
+                        tc: new Date().getTime(),
+                        l: _lag,
+                        o: _offset
+                    };
+                    _debug('TimeSyncExtension: client sending timesync', org_cometd.JSON.toJSON(message.ext.timesync));
+                }
+                return message;
+            };
+
+            /**
+             * Get the estimated offset in ms from the clients clock to the
+             * servers clock.  The server time is the client time plus the offset.
+             */
+            this.getTimeOffset = function()
+            {
+                return _offset;
+            };
+
+            /**
+             * Get an array of multiple offset samples used to calculate
+             * the offset.
+             */
+            this.getTimeOffsetSamples = function()
+            {
+                return _offsets;
+            };
+
+            /**
+             * Get the estimated network lag in ms from the client to the server.
+             */
+            this.getNetworkLag = function()
+            {
+                return _lag;
+            };
+
+            /**
+             * Get the estimated server time in ms since the epoch.
+             */
+            this.getServerTime = function()
+            {
+                return new Date().getTime() + _offset;
+            };
+
+            /**
+             *
+             * Get the estimated server time as a Date object
+             */
+            this.getServerDate = function()
+            {
+                return new Date(this.getServerTime());
+            };
+
+            /**
+             * Set a timeout to expire at given time on the server.
+             * @param callback The function to call when the timer expires
+             * @param atServerTimeOrDate a js Time or Date object representing the
+             * server time at which the timeout should expire
+             */
+            this.setTimeout = function(callback, atServerTimeOrDate)
+            {
+                var ts = (atServerTimeOrDate instanceof Date) ? atServerTimeOrDate.getTime() : (0 + atServerTimeOrDate);
+                var tc = ts - _offset;
+                var interval = tc - new Date().getTime();
+                if (interval <= 0)
+                {
+                    interval = 1;
+                }
+                return org_cometd.Utils.setTimeout(_cometd, callback, interval);
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/openlayers/LoadingPanel.js b/src/main/webapp/lib/openlayers/LoadingPanel.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c4ca1886009bb9479f2d89043edb9f8c0168725
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/LoadingPanel.js
@@ -0,0 +1,220 @@
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ *
+ * Class: OpenLayers.Control.LoadingPanel
+ * In some applications, it makes sense to alert the user that something is 
+ * happening while tiles are loading. This control displays a div across the 
+ * map when this is going on.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.LoadingPanel = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: counter
+     * {Integer} A counter for the number of layers loading
+     */ 
+    counter: 0,
+
+    /**
+     * Property: maximized
+     * {Boolean} A boolean indicating whether or not the control is maximized
+    */
+    maximized: false,
+
+    /**
+     * Property: visible
+     * {Boolean} A boolean indicating whether or not the control is visible
+    */
+    visible: true,
+
+    /**
+     * Constructor: OpenLayers.Control.LoadingPanel
+     * Display a panel across the map that says 'loading'. 
+     *
+     * Parameters:
+     * options - {Object} additional options.
+     */
+    initialize: function(options) {
+         OpenLayers.Control.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Function: setVisible
+     * Set the visibility of this control
+     *
+     * Parameters:
+     * visible - {Boolean} should the control be visible or not?
+    */
+    setVisible: function(visible) {
+        this.visible = visible;
+        if (visible) {
+            OpenLayers.Element.show(this.div);
+        } else {
+            OpenLayers.Element.hide(this.div);
+        }
+    },
+
+    /**
+     * Function: getVisible
+     * Get the visibility of this control
+     *
+     * Returns:
+     * {Boolean} the current visibility of this control
+    */
+    getVisible: function() {
+        return this.visible;
+    },
+
+    /**
+     * APIMethod: hide
+     * Hide the loading panel control
+    */
+    hide: function() {
+        this.setVisible(false);
+    },
+
+    /**
+     * APIMethod: show
+     * Show the loading panel control
+    */
+    show: function() {
+        this.setVisible(true);
+    },
+
+    /**
+     * APIMethod: toggle
+     * Toggle the visibility of the loading panel control
+    */
+    toggle: function() {
+        this.setVisible(!this.getVisible());
+    },
+
+    /**
+     * Method: addLayer
+     * Attach event handlers when new layer gets added to the map
+     *
+     * Parameters:
+     * evt - {Event}
+    */
+    addLayer: function(evt) {
+        if (evt.layer) {
+            evt.layer.events.register('loadstart', this, this.increaseCounter);
+            evt.layer.events.register('loadend', this, this.decreaseCounter);
+        }
+    },
+
+    /**
+     * Method: setMap
+     * Set the map property for the control and all handlers.
+     *
+     * Parameters: 
+     * map - {<OpenLayers.Map>} The control's map.
+     */
+    setMap: function(map) {
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+        this.map.events.register('preaddlayer', this, this.addLayer);
+        for (var i = 0; i < this.map.layers.length; i++) {
+            var layer = this.map.layers[i];
+            layer.events.register('loadstart', this, this.increaseCounter);
+            layer.events.register('loadend', this, this.decreaseCounter);
+        }
+    },
+
+    /**
+     * Method: increaseCounter
+     * Increase the counter and show control
+    */
+    increaseCounter: function() {
+        this.counter++;
+        if (this.counter > 0) { 
+            if (!this.maximized && this.visible) {
+                this.maximizeControl(); 
+            }
+        }
+    },
+    
+    /**
+     * Method: decreaseCounter
+     * Decrease the counter and hide the control if finished
+    */
+    decreaseCounter: function() {
+        if (this.counter > 0) {
+            this.counter--;
+        }
+        if (this.counter == 0) {
+            if (this.maximized && this.visible) {
+                this.minimizeControl();
+            }
+        }
+    },
+
+    /**
+     * Method: draw
+     * Create and return the element to be splashed over the map.
+     */
+    draw: function () {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        return this.div;
+    },
+     
+    /**
+     * Method: minimizeControl
+     * Set the display properties of the control to make it disappear.
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    minimizeControl: function(evt) {
+        this.div.style.display = "none"; 
+        this.maximized = false;
+    
+        if (evt != null) {
+            OpenLayers.Event.stop(evt);
+        }
+    },
+    
+    /**
+     * Method: maximizeControl
+     * Make the control visible.
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    maximizeControl: function(evt) {
+        this.div.style.display = "block";
+        this.maximized = true;
+    
+        if (evt != null) {
+            OpenLayers.Event.stop(evt);
+        }
+    },
+
+    /** 
+     * Method: destroy
+     * Destroy control.
+     */
+    destroy: function() {
+        if (this.map) {
+            this.map.events.unregister('preaddlayer', this, this.addLayer);
+            if (this.map.layers) {
+                for (var i = 0; i < this.map.layers.length; i++) {
+                    var layer = this.map.layers[i];
+                    layer.events.unregister('loadstart', this, 
+                        this.increaseCounter);
+                    layer.events.unregister('loadend', this, 
+                        this.decreaseCounter);
+                }
+            }
+        }
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },     
+
+    CLASS_NAME: "OpenLayers.Control.LoadingPanel"
+
+});
diff --git a/src/main/webapp/lib/openlayers/OpenLayers.js b/src/main/webapp/lib/openlayers/OpenLayers.js
new file mode 100644
index 0000000000000000000000000000000000000000..7089c4dc7a9b12927e76c2c936bba65710fb31de
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/OpenLayers.js
@@ -0,0 +1,85105 @@
+/*
+
+  OpenLayers.js -- OpenLayers Map Viewer Library
+
+  Copyright 2005-2011 OpenLayers Contributors, released under the FreeBSD
+  license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt
+  for the full text of the license.
+
+  Includes compressed code under the following licenses:
+
+  (For uncompressed versions of the code used please see the
+  OpenLayers SVN repository: <http://openlayers.org/>)
+
+*/
+
+/* Contains portions of Prototype.js:
+ *
+ * Prototype JavaScript framework, version 1.4.0
+ *  (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+ *--------------------------------------------------------------------------*/
+
+/**  
+*  
+*  Contains portions of Rico <http://openrico.org/>
+* 
+*  Copyright 2005 Sabre Airline Solutions  
+*  
+*  Licensed under the Apache License, Version 2.0 (the "License"); you
+*  may not use this file except in compliance with the License. You
+*  may obtain a copy of the License at
+*  
+*         http://www.apache.org/licenses/LICENSE-2.0  
+*  
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+*  implied. See the License for the specific language governing
+*  permissions and limitations under the License. 
+*
+**/
+
+/**
+ * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
+ * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/**
+ * Contains portions of Gears <http://code.google.com/apis/gears/>
+ *
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. Neither the name of Google Inc. nor the names of its contributors may be
+ *     used to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sets up google.gears.*, which is *the only* supported way to access Gears.
+ *
+ * Circumvent this file at your own risk!
+ *
+ * In the future, Gears may automatically define google.gears.* without this
+ * file. Gears may use these objects to transparently fix bugs and compatibility
+ * issues. Applications that use the code below will continue to work seamlessly
+ * when that happens.
+ */
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *//* ======================================================================
+    Gears/gears_init.js
+   ====================================================================== */
+
+/*
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. Neither the name of Google Inc. nor the names of its contributors may be
+ *     used to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sets up google.gears.*, which is *the only* supported way to access Gears.
+ *
+ * Circumvent this file at your own risk!
+ *
+ * In the future, Gears may automatically define google.gears.* without this
+ * file. Gears may use these objects to transparently fix bugs and compatibility
+ * issues. Applications that use the code below will continue to work seamlessly
+ * when that happens.
+ */
+
+(function() {
+  // We are already defined. Hooray!
+  if (window.google && google.gears) {
+    return;
+  }
+
+  var factory = null;
+
+  // Firefox
+  if (typeof GearsFactory != 'undefined') {
+    factory = new GearsFactory();
+  } else {
+    // IE
+    try {
+      factory = new ActiveXObject('Gears.Factory');
+      // privateSetGlobalObject is only required and supported on WinCE.
+      if (factory.getBuildInfo().indexOf('ie_mobile') != -1) {
+        factory.privateSetGlobalObject(this);
+      }
+    } catch (e) {
+      // Safari
+      if ((typeof navigator.mimeTypes != 'undefined')
+           && navigator.mimeTypes["application/x-googlegears"]) {
+        factory = document.createElement("object");
+        factory.style.display = "none";
+        factory.width = 0;
+        factory.height = 0;
+        factory.type = "application/x-googlegears";
+        document.documentElement.appendChild(factory);
+      }
+    }
+  }
+
+  // *Do not* define any objects if Gears is not installed. This mimics the
+  // behavior of Gears defining the objects in the future.
+  if (!factory) {
+    return;
+  }
+
+  // Now set up the objects, being careful not to overwrite anything.
+  //
+  // Note: In Internet Explorer for Windows Mobile, you can't add properties to
+  // the window object. However, global objects are automatically added as
+  // properties of the window object in all browsers.
+  if (!window.google) {
+    google = {};
+  }
+
+  if (!google.gears) {
+    google.gears = {factory: factory};
+  }
+})();
+/* ======================================================================
+    OpenLayers/SingleFile.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+var OpenLayers = {
+    /**
+     * Constant: VERSION_NUMBER
+     */
+    VERSION_NUMBER: "Release 2.11",
+
+    /**
+     * Constant: singleFile
+     * TODO: remove this in 3.0 when we stop supporting build profiles that
+     * include OpenLayers.js
+     */
+    singleFile: true,
+
+    /**
+     * Method: _getScriptLocation
+     * Return the path to this script. This is also implemented in
+     * OpenLayers.js
+     *
+     * Returns:
+     * {String} Path to this script
+     */
+    _getScriptLocation: (function() {
+        var r = new RegExp("(^|(.*?\\/))(OpenLayers\.js)(\\?|$)"),
+            s = document.getElementsByTagName('script'),
+            src, m, l = "";
+        for(var i=0, len=s.length; i<len; i++) {
+            src = s[i].getAttribute('src');
+            if(src) {
+                var m = src.match(r);
+                if(m) {
+                    l = m[1];
+                    break;
+                }
+            }
+        }
+        return (function() { return l; });
+    })()
+};
+/* ======================================================================
+    OpenLayers/BaseTypes/Class.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/SingleFile.js
+ */
+
+/**
+ * Constructor: OpenLayers.Class
+ * Base class used to construct all other classes. Includes support for 
+ *     multiple inheritance. 
+ *     
+ * This constructor is new in OpenLayers 2.5.  At OpenLayers 3.0, the old 
+ *     syntax for creating classes and dealing with inheritance 
+ *     will be removed.
+ * 
+ * To create a new OpenLayers-style class, use the following syntax:
+ * (code)
+ *     var MyClass = OpenLayers.Class(prototype);
+ * (end)
+ *
+ * To create a new OpenLayers-style class with multiple inheritance, use the
+ *     following syntax:
+ * (code)
+ *     var MyClass = OpenLayers.Class(Class1, Class2, prototype);
+ * (end)
+ * 
+ * Note that instanceof reflection will only reveal Class1 as superclass.
+ *
+ */
+OpenLayers.Class = function() {
+    var len = arguments.length;
+    var P = arguments[0];
+    var F = arguments[len-1];
+
+    var C = typeof F.initialize == "function" ?
+        F.initialize :
+        function(){ P.prototype.initialize.apply(this, arguments); };
+
+    if (len > 1) {
+        var newArgs = [C, P].concat(
+                Array.prototype.slice.call(arguments).slice(1, len-1), F);
+        OpenLayers.inherit.apply(null, newArgs);
+    } else {
+        C.prototype = F;
+    }
+    return C;
+};
+
+/**
+ * Property: isPrototype
+ * *Deprecated*.  This is no longer needed and will be removed at 3.0.
+ */
+OpenLayers.Class.isPrototype = function () {};
+
+/**
+ * APIFunction: OpenLayers.create
+ * *Deprecated*.  Old method to create an OpenLayers style class.  Use the
+ *     <OpenLayers.Class> constructor instead.
+ *
+ * Returns:
+ * An OpenLayers class
+ */
+OpenLayers.Class.create = function() {
+    return function() {
+        if (arguments && arguments[0] != OpenLayers.Class.isPrototype) {
+            this.initialize.apply(this, arguments);
+        }
+    };
+};
+
+/**
+ * APIFunction: inherit
+ * *Deprecated*.  Old method to inherit from one or more OpenLayers style
+ *     classes.  Use the <OpenLayers.Class> constructor instead.
+ *
+ * Parameters:
+ * class - One or more classes can be provided as arguments
+ *
+ * Returns:
+ * An object prototype
+ */
+OpenLayers.Class.inherit = function (P) {
+    var C = function() {
+       P.call(this);
+    };
+    var newArgs = [C].concat(Array.prototype.slice.call(arguments));
+    OpenLayers.inherit.apply(null, newArgs);
+    return C.prototype;
+};
+
+/**
+ * Function: OpenLayers.inherit
+ *
+ * Parameters:
+ * C - {Object} the class that inherits
+ * P - {Object} the superclass to inherit from
+ *
+ * In addition to the mandatory C and P parameters, an arbitrary number of
+ * objects can be passed, which will extend C.
+ */
+OpenLayers.inherit = function(C, P) {
+   var F = function() {};
+   F.prototype = P.prototype;
+   C.prototype = new F;
+   var i, l, o;
+   for(i=2, l=arguments.length; i<l; i++) {
+       o = arguments[i];
+       if(typeof o === "function") {
+           o = o.prototype;
+       }
+       OpenLayers.Util.extend(C.prototype, o);
+   }
+};
+
+/**
+ * APIFunction: extend
+ * Copy all properties of a source object to a destination object.  Modifies
+ *     the passed in destination object.  Any properties on the source object
+ *     that are set to undefined will not be (re)set on the destination object.
+ *
+ * Parameters:
+ * destination - {Object} The object that will be modified
+ * source - {Object} The object with properties to be set on the destination
+ *
+ * Returns:
+ * {Object} The destination object.
+ */
+OpenLayers.Util = OpenLayers.Util || {};
+OpenLayers.Util.extend = function(destination, source) {
+    destination = destination || {};
+    if (source) {
+        for (var property in source) {
+            var value = source[property];
+            if (value !== undefined) {
+                destination[property] = value;
+            }
+        }
+
+        /**
+         * IE doesn't include the toString property when iterating over an object's
+         * properties with the for(property in object) syntax.  Explicitly check if
+         * the source has its own toString property.
+         */
+
+        /*
+         * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
+         * prototype object" when calling hawOwnProperty if the source object
+         * is an instance of window.Event.
+         */
+
+        var sourceIsEvt = typeof window.Event == "function"
+                          && source instanceof window.Event;
+
+        if (!sourceIsEvt
+           && source.hasOwnProperty && source.hasOwnProperty("toString")) {
+            destination.toString = source.toString;
+        }
+    }
+    return destination;
+};
+/* ======================================================================
+    OpenLayers/Protocol.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol
+ * Abstract vector layer protocol class.  Not to be instantiated directly.  Use
+ *     one of the protocol subclasses instead.
+ */
+OpenLayers.Protocol = OpenLayers.Class({
+    
+    /**
+     * Property: format
+     * {<OpenLayers.Format>} The format used by this protocol.
+     */
+    format: null,
+    
+    /**
+     * Property: options
+     * {Object} Any options sent to the constructor.
+     */
+    options: null,
+
+    /**
+     * Property: autoDestroy
+     * {Boolean} The creator of the protocol can set autoDestroy to false
+     *      to fully control when the protocol is destroyed. Defaults to
+     *      true.
+     */
+    autoDestroy: true,
+   
+    /**
+     * Property: defaultFilter
+     * {OpenLayers.Filter} Optional default filter to read requests
+     */
+    defaultFilter: null,
+    
+    /**
+     * Constructor: OpenLayers.Protocol
+     * Abstract class for vector protocols.  Create instances of a subclass.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        options = options || {};
+        OpenLayers.Util.extend(this, options);
+        this.options = options;
+    },
+
+    /**
+     * Method: mergeWithDefaultFilter
+     * Merge filter passed to the read method with the default one
+     *
+     * Parameters:
+     * filter - {OpenLayers.Filter}
+     */
+    mergeWithDefaultFilter: function(filter) {
+        var merged;
+        if (filter && this.defaultFilter) {
+            merged = new OpenLayers.Filter.Logical({
+                type: OpenLayers.Filter.Logical.AND,
+                filters: [this.defaultFilter, filter]
+            });
+        } else {
+            merged = filter || this.defaultFilter || undefined;
+        }
+        return merged;
+    },
+
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        this.options = null;
+        this.format = null;
+    },
+    
+    /**
+     * APIMethod: read
+     * Construct a request for reading new features.
+     *
+     * Parameters:
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     * object, the same object will be passed to the callback function passed
+     * if one exists in the options object.
+     */
+    read: function(options) {
+        options = options || {};
+        options.filter = this.mergeWithDefaultFilter(options.filter);
+    },
+    
+    
+    /**
+     * APIMethod: create
+     * Construct a request for writing newly created features.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *            {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     * object, the same object will be passed to the callback function passed
+     * if one exists in the options object.
+     */
+    create: function() {
+    },
+    
+    /**
+     * APIMethod: update
+     * Construct a request updating modified features.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *            {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     * object, the same object will be passed to the callback function passed
+     * if one exists in the options object.
+     */
+    update: function() {
+    },
+    
+    /**
+     * APIMethod: delete
+     * Construct a request deleting a removed feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     * object, the same object will be passed to the callback function passed
+     * if one exists in the options object.
+     */
+    "delete": function() {
+    },
+
+    /**
+     * APIMethod: commit
+     * Go over the features and for each take action
+     * based on the feature state. Possible actions are create,
+     * update and delete.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})}
+     * options - {Object} Object whose possible keys are "create", "update",
+     *      "delete", "callback" and "scope", the values referenced by the
+     *      first three are objects as passed to the "create", "update", and
+     *      "delete" methods, the value referenced by the "callback" key is
+     *      a function which is called when the commit operation is complete
+     *      using the scope referenced by the "scope" key.
+     *
+     * Returns:
+     * {Array({<OpenLayers.Protocol.Response>})} An array of
+     * <OpenLayers.Protocol.Response> objects.
+     */
+    commit: function() {
+    },
+
+    /**
+     * Method: abort
+     * Abort an ongoing request.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>}
+     */
+    abort: function(response) {
+    },
+   
+    /**
+     * Method: createCallback
+     * Returns a function that applies the given public method with resp and
+     *     options arguments.
+     *
+     * Parameters:
+     * method - {Function} The method to be applied by the callback.
+     * response - {<OpenLayers.Protocol.Response>} The protocol response object.
+     * options - {Object} Options sent to the protocol method
+     */
+    createCallback: function(method, response, options) {
+        return OpenLayers.Function.bind(function() {
+            method.apply(this, [response, options]);
+        }, this);
+    },
+   
+    CLASS_NAME: "OpenLayers.Protocol" 
+});
+
+/**
+ * Class: OpenLayers.Protocol.Response
+ * Protocols return Response objects to their users.
+ */
+OpenLayers.Protocol.Response = OpenLayers.Class({
+    /**
+     * Property: code
+     * {Number} - OpenLayers.Protocol.Response.SUCCESS or
+     *            OpenLayers.Protocol.Response.FAILURE
+     */
+    code: null,
+
+    /**
+     * Property: requestType
+     * {String} The type of request this response corresponds to. Either
+     *      "create", "read", "update" or "delete".
+     */
+    requestType: null,
+
+    /**
+     * Property: last
+     * {Boolean} - true if this is the last response expected in a commit,
+     * false otherwise, defaults to true.
+     */
+    last: true,
+
+    /**
+     * Property: features
+     * {Array({<OpenLayers.Feature.Vector>})} or {<OpenLayers.Feature.Vector>}
+     * The features returned in the response by the server.
+     */
+    features: null,
+
+    /**
+     * Property: reqFeatures
+     * {Array({<OpenLayers.Feature.Vector>})} or {<OpenLayers.Feature.Vector>}
+     * The features provided by the user and placed in the request by the
+     *      protocol.
+     */
+    reqFeatures: null,
+
+    /**
+     * Property: priv
+     */
+    priv: null,
+
+    /**
+     * Property: error
+     * {Object} The error object in case a service exception was encountered.
+     */
+    error: null,
+
+    /**
+     * Constructor: OpenLayers.Protocol.Response
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+    },
+
+    /**
+     * Method: success
+     *
+     * Returns:
+     * {Boolean} - true on success, false otherwise
+     */
+    success: function() {
+        return this.code > 0;
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.Response"
+});
+
+OpenLayers.Protocol.Response.SUCCESS = 1;
+OpenLayers.Protocol.Response.FAILURE = 0;
+/* ======================================================================
+    OpenLayers/Protocol/SQL.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.SQL
+ * Abstract SQL protocol class.  Not to be instantiated directly.  Use
+ *     one of the SQL protocol subclasses instead.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+OpenLayers.Protocol.SQL = OpenLayers.Class(OpenLayers.Protocol, {
+
+    /**
+     * APIProperty: databaseName
+     * {String}
+     */
+    databaseName: 'ol',
+
+    /**
+     * APIProperty: tableName
+     * Name of the database table into which Features should be saved.
+     */
+    tableName: "ol_vector_features",
+
+    /**
+     * Property: postReadFiltering
+     * {Boolean} Whether the filter (if there's one) must be applied after
+     *      the features have been read from the database; for example the
+     *      BBOX strategy passes the read method a BBOX spatial filter, if
+     *      postReadFiltering is true every feature read from the database
+     *      will go through the BBOX spatial filter, which can be costly;
+     *      defaults to true.
+     */
+    postReadFiltering: true,
+
+    /**
+     * Constructor: OpenLayers.Protocol.SQL
+     */
+    initialize: function(options) {
+        OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: supported
+     * This should be overridden by specific subclasses
+     *
+     * Returns:
+     * {Boolean} Whether or not the browser supports the SQL backend
+     */
+    supported: function() {
+        return false;
+    },
+
+    /**
+     * Method: evaluateFilter
+     * If postReadFiltering is true evaluate the filter against the feature
+     * and return the result of the evaluation, otherwise return true.
+     *
+     * Parameters:
+     * {<OpenLayers.Feature.Vector>} The feature.
+     * {<OpenLayers.Filter>} The filter.
+     *
+     * Returns:
+     * {Boolean} true if postReadFiltering if false, the result of the
+     * filter evaluation otherwise.
+     */
+    evaluateFilter: function(feature, filter) {
+        return filter && this.postReadFiltering ?
+            filter.evaluate(feature) : true;
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.SQL"
+});
+/* ======================================================================
+    OpenLayers/Console.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Namespace: OpenLayers.Console
+ * The OpenLayers.Console namespace is used for debugging and error logging.
+ * If the Firebug Lite (../Firebug/firebug.js) is included before this script,
+ * calls to OpenLayers.Console methods will get redirected to window.console.
+ * This makes use of the Firebug extension where available and allows for
+ * cross-browser debugging Firebug style.
+ *
+ * Note:
+ * Note that behavior will differ with the Firebug extention and Firebug Lite.
+ * Most notably, the Firebug Lite console does not currently allow for
+ * hyperlinks to code or for clicking on object to explore their properties.
+ * 
+ */
+OpenLayers.Console = {
+    /**
+     * Create empty functions for all console methods.  The real value of these
+     * properties will be set if Firebug Lite (../Firebug/firebug.js script) is
+     * included.  We explicitly require the Firebug Lite script to trigger
+     * functionality of the OpenLayers.Console methods.
+     */
+    
+    /**
+     * APIFunction: log
+     * Log an object in the console.  The Firebug Lite console logs string
+     * representation of objects.  Given multiple arguments, they will
+     * be cast to strings and logged with a space delimiter.  If the first
+     * argument is a string with printf-like formatting, subsequent arguments
+     * will be used in string substitution.  Any additional arguments (beyond
+     * the number substituted in a format string) will be appended in a space-
+     * delimited line.
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    log: function() {},
+
+    /**
+     * APIFunction: debug
+     * Writes a message to the console, including a hyperlink to the line
+     * where it was called.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    debug: function() {},
+
+    /**
+     * APIFunction: info
+     * Writes a message to the console with the visual "info" icon and color
+     * coding and a hyperlink to the line where it was called.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    info: function() {},
+
+    /**
+     * APIFunction: warn
+     * Writes a message to the console with the visual "warning" icon and
+     * color coding and a hyperlink to the line where it was called.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    warn: function() {},
+
+    /**
+     * APIFunction: error
+     * Writes a message to the console with the visual "error" icon and color
+     * coding and a hyperlink to the line where it was called.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    error: function() {},
+    
+    /**
+     * APIFunction: userError
+     * A single interface for showing error messages to the user. The default
+     * behavior is a Javascript alert, though this can be overridden by
+     * reassigning OpenLayers.Console.userError to a different function.
+     *
+     * Expects a single error message
+     * 
+     * Parameters:
+     * error - {Object}
+     */
+    userError: function(error) {
+        alert(error);
+    },
+
+    /**
+     * APIFunction: assert
+     * Tests that an expression is true. If not, it will write a message to
+     * the console and throw an exception.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    assert: function() {},
+
+    /**
+     * APIFunction: dir
+     * Prints an interactive listing of all properties of the object. This
+     * looks identical to the view that you would see in the DOM tab.
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    dir: function() {},
+
+    /**
+     * APIFunction: dirxml
+     * Prints the XML source tree of an HTML or XML element. This looks
+     * identical to the view that you would see in the HTML tab. You can click
+     * on any node to inspect it in the HTML tab.
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    dirxml: function() {},
+
+    /**
+     * APIFunction: trace
+     * Prints an interactive stack trace of JavaScript execution at the point
+     * where it is called.  The stack trace details the functions on the stack,
+     * as well as the values that were passed as arguments to each function.
+     * You can click each function to take you to its source in the Script tab,
+     * and click each argument value to inspect it in the DOM or HTML tabs.
+     * 
+     */
+    trace: function() {},
+
+    /**
+     * APIFunction: group
+     * Writes a message to the console and opens a nested block to indent all
+     * future messages sent to the console. Call OpenLayers.Console.groupEnd()
+     * to close the block.
+     *
+     * May be called with multiple arguments as with OpenLayers.Console.log().
+     * 
+     * Parameters:
+     * object - {Object}
+     */
+    group: function() {},
+
+    /**
+     * APIFunction: groupEnd
+     * Closes the most recently opened block created by a call to
+     * OpenLayers.Console.group
+     */
+    groupEnd: function() {},
+    
+    /**
+     * APIFunction: time
+     * Creates a new timer under the given name. Call
+     * OpenLayers.Console.timeEnd(name)
+     * with the same name to stop the timer and print the time elapsed.
+     *
+     * Parameters:
+     * name - {String}
+     */
+    time: function() {},
+
+    /**
+     * APIFunction: timeEnd
+     * Stops a timer created by a call to OpenLayers.Console.time(name) and
+     * writes the time elapsed.
+     *
+     * Parameters:
+     * name - {String}
+     */
+    timeEnd: function() {},
+
+    /**
+     * APIFunction: profile
+     * Turns on the JavaScript profiler. The optional argument title would
+     * contain the text to be printed in the header of the profile report.
+     *
+     * This function is not currently implemented in Firebug Lite.
+     * 
+     * Parameters:
+     * title - {String} Optional title for the profiler
+     */
+    profile: function() {},
+
+    /**
+     * APIFunction: profileEnd
+     * Turns off the JavaScript profiler and prints its report.
+     * 
+     * This function is not currently implemented in Firebug Lite.
+     */
+    profileEnd: function() {},
+
+    /**
+     * APIFunction: count
+     * Writes the number of times that the line of code where count was called
+     * was executed. The optional argument title will print a message in
+     * addition to the number of the count.
+     *
+     * This function is not currently implemented in Firebug Lite.
+     *
+     * Parameters:
+     * title - {String} Optional title to be printed with count
+     */
+    count: function() {},
+
+    CLASS_NAME: "OpenLayers.Console"
+};
+
+/**
+ * Execute an anonymous function to extend the OpenLayers.Console namespace
+ * if the firebug.js script is included.  This closure is used so that the
+ * "scripts" and "i" variables don't pollute the global namespace.
+ */
+(function() {
+    /**
+     * If Firebug Lite is included (before this script), re-route all
+     * OpenLayers.Console calls to the console object.
+     */
+    var scripts = document.getElementsByTagName("script");
+    for(var i=0, len=scripts.length; i<len; ++i) {
+        if(scripts[i].src.indexOf("firebug.js") != -1) {
+            if(console) {
+                OpenLayers.Util.extend(OpenLayers.Console, console);
+                break;
+            }
+        }
+    }
+})();
+/* ======================================================================
+    OpenLayers/Lang.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang
+ * Internationalization namespace.  Contains dictionaries in various languages
+ *     and methods to set and get the current language.
+ */
+OpenLayers.Lang = {
+    
+    /** 
+     * Property: code
+     * {String}  Current language code to use in OpenLayers.  Use the
+     *     <setCode> method to set this value and the <getCode> method to
+     *     retrieve it.
+     */
+    code: null,
+
+    /** 
+     * APIProperty: defaultCode
+     * {String} Default language to use when a specific language can't be
+     *     found.  Default is "en".
+     */
+    defaultCode: "en",
+        
+    /**
+     * APIFunction: getCode
+     * Get the current language code.
+     *
+     * Returns:
+     * The current language code.
+     */
+    getCode: function() {
+        if(!OpenLayers.Lang.code) {
+            OpenLayers.Lang.setCode();
+        }
+        return OpenLayers.Lang.code;
+    },
+    
+    /**
+     * APIFunction: setCode
+     * Set the language code for string translation.  This code is used by
+     *     the <OpenLayers.Lang.translate> method.
+     *
+     * Parameters-
+     * code - {String} These codes follow the IETF recommendations at
+     *     http://www.ietf.org/rfc/rfc3066.txt.  If no value is set, the
+     *     browser's language setting will be tested.  If no <OpenLayers.Lang>
+     *     dictionary exists for the code, the <OpenLayers.String.defaultLang>
+     *     will be used.
+     */
+    setCode: function(code) {
+        var lang;
+        if(!code) {
+            code = (OpenLayers.BROWSER_NAME == "msie") ?
+                navigator.userLanguage : navigator.language;
+        }
+        var parts = code.split('-');
+        parts[0] = parts[0].toLowerCase();
+        if(typeof OpenLayers.Lang[parts[0]] == "object") {
+            lang = parts[0];
+        }
+
+        // check for regional extensions
+        if(parts[1]) {
+            var testLang = parts[0] + '-' + parts[1].toUpperCase();
+            if(typeof OpenLayers.Lang[testLang] == "object") {
+                lang = testLang;
+            }
+        }
+        if(!lang) {
+            OpenLayers.Console.warn(
+                'Failed to find OpenLayers.Lang.' + parts.join("-") +
+                ' dictionary, falling back to default language'
+            );
+            lang = OpenLayers.Lang.defaultCode;
+        }
+        
+        OpenLayers.Lang.code = lang;
+    },
+
+    /**
+     * APIMethod: translate
+     * Looks up a key from a dictionary based on the current language string.
+     *     The value of <getCode> will be used to determine the appropriate
+     *     dictionary.  Dictionaries are stored in <OpenLayers.Lang>.
+     *
+     * Parameters:
+     * key - {String} The key for an i18n string value in the dictionary.
+     * context - {Object} Optional context to be used with
+     *     <OpenLayers.String.format>.
+     * 
+     * Returns:
+     * {String} A internationalized string.
+     */
+    translate: function(key, context) {
+        var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()];
+        var message = dictionary && dictionary[key];
+        if(!message) {
+            // Message not found, fall back to message key
+            message = key;
+        }
+        if(context) {
+            message = OpenLayers.String.format(message, context);
+        }
+        return message;
+    }
+    
+};
+
+
+/**
+ * APIMethod: OpenLayers.i18n
+ * Alias for <OpenLayers.Lang.translate>.  Looks up a key from a dictionary
+ *     based on the current language string. The value of
+ *     <OpenLayers.Lang.getCode> will be used to determine the appropriate
+ *     dictionary.  Dictionaries are stored in <OpenLayers.Lang>.
+ *
+ * Parameters:
+ * key - {String} The key for an i18n string value in the dictionary.
+ * context - {Object} Optional context to be used with
+ *     <OpenLayers.String.format>.
+ * 
+ * Returns:
+ * {String} A internationalized string.
+ */
+OpenLayers.i18n = OpenLayers.Lang.translate;
+/* ======================================================================
+    OpenLayers/BaseTypes.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Lang.js
+ * @requires OpenLayers/Console.js
+ */
+ 
+/** 
+ * Header: OpenLayers Base Types
+ * OpenLayers custom string, number and function functions are described here.
+ */
+
+/**
+ * Namespace: OpenLayers.String
+ * Contains convenience functions for string manipulation.
+ */
+OpenLayers.String = {
+
+    /**
+     * APIFunction: startsWith
+     * Test whether a string starts with another string. 
+     * 
+     * Parameters:
+     * str - {String} The string to test.
+     * sub - {String} The substring to look for.
+     *  
+     * Returns:
+     * {Boolean} The first string starts with the second.
+     */
+    startsWith: function(str, sub) {
+        return (str.indexOf(sub) == 0);
+    },
+
+    /**
+     * APIFunction: contains
+     * Test whether a string contains another string.
+     * 
+     * Parameters:
+     * str - {String} The string to test.
+     * sub - {String} The substring to look for.
+     * 
+     * Returns:
+     * {Boolean} The first string contains the second.
+     */
+    contains: function(str, sub) {
+        return (str.indexOf(sub) != -1);
+    },
+    
+    /**
+     * APIFunction: trim
+     * Removes leading and trailing whitespace characters from a string.
+     * 
+     * Parameters:
+     * str - {String} The (potentially) space padded string.  This string is not
+     *     modified.
+     * 
+     * Returns:
+     * {String} A trimmed version of the string with all leading and 
+     *     trailing spaces removed.
+     */
+    trim: function(str) {
+        return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+    },
+    
+    /**
+     * APIFunction: camelize
+     * Camel-case a hyphenated string. 
+     *     Ex. "chicken-head" becomes "chickenHead", and
+     *     "-chicken-head" becomes "ChickenHead".
+     *
+     * Parameters:
+     * str - {String} The string to be camelized.  The original is not modified.
+     * 
+     * Returns:
+     * {String} The string, camelized
+     */
+    camelize: function(str) {
+        var oStringList = str.split('-');
+        var camelizedString = oStringList[0];
+        for (var i=1, len=oStringList.length; i<len; i++) {
+            var s = oStringList[i];
+            camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+        }
+        return camelizedString;
+    },
+    
+    /**
+     * APIFunction: format
+     * Given a string with tokens in the form ${token}, return a string
+     *     with tokens replaced with properties from the given context
+     *     object.  Represent a literal "${" by doubling it, e.g. "${${".
+     *
+     * Parameters:
+     * template - {String} A string with tokens to be replaced.  A template
+     *     has the form "literal ${token}" where the token will be replaced
+     *     by the value of context["token"].
+     * context - {Object} An optional object with properties corresponding
+     *     to the tokens in the format string.  If no context is sent, the
+     *     window object will be used.
+     * args - {Array} Optional arguments to pass to any functions found in
+     *     the context.  If a context property is a function, the token
+     *     will be replaced by the return from the function called with
+     *     these arguments.
+     *
+     * Returns:
+     * {String} A string with tokens replaced from the context object.
+     */
+    format: function(template, context, args) {
+        if(!context) {
+            context = window;
+        }
+
+        // Example matching: 
+        // str   = ${foo.bar}
+        // match = foo.bar
+        var replacer = function(str, match) {
+            var replacement;
+
+            // Loop through all subs. Example: ${a.b.c}
+            // 0 -> replacement = context[a];
+            // 1 -> replacement = context[a][b];
+            // 2 -> replacement = context[a][b][c];
+            var subs = match.split(/\.+/);
+            for (var i=0; i< subs.length; i++) {
+                if (i == 0) {
+                    replacement = context;
+                }
+
+                replacement = replacement[subs[i]];
+            }
+
+            if(typeof replacement == "function") {
+                replacement = args ?
+                    replacement.apply(null, args) :
+                    replacement();
+            }
+
+            // If replacement is undefined, return the string 'undefined'.
+            // This is a workaround for a bugs in browsers not properly 
+            // dealing with non-participating groups in regular expressions:
+            // http://blog.stevenlevithan.com/archives/npcg-javascript
+            if (typeof replacement == 'undefined') {
+                return 'undefined';
+            } else {
+                return replacement; 
+            }
+        };
+
+        return template.replace(OpenLayers.String.tokenRegEx, replacer);
+    },
+
+    /**
+     * Property: tokenRegEx
+     * Used to find tokens in a string.
+     * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
+     */
+    tokenRegEx:  /\$\{([\w.]+?)\}/g,
+    
+    /**
+     * Property: numberRegEx
+     * Used to test strings as numbers.
+     */
+    numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
+    
+    /**
+     * APIFunction: isNumeric
+     * Determine whether a string contains only a numeric value.
+     *
+     * Examples:
+     * (code)
+     * OpenLayers.String.isNumeric("6.02e23") // true
+     * OpenLayers.String.isNumeric("12 dozen") // false
+     * OpenLayers.String.isNumeric("4") // true
+     * OpenLayers.String.isNumeric(" 4 ") // false
+     * (end)
+     *
+     * Returns:
+     * {Boolean} String contains only a number.
+     */
+    isNumeric: function(value) {
+        return OpenLayers.String.numberRegEx.test(value);
+    },
+    
+    /**
+     * APIFunction: numericIf
+     * Converts a string that appears to be a numeric value into a number.
+     * 
+     * Returns
+     * {Number|String} a Number if the passed value is a number, a String
+     *     otherwise. 
+     */
+    numericIf: function(value) {
+        return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value;
+    }
+
+};
+
+if (!String.prototype.startsWith) {
+    /**
+     * APIMethod: String.startsWith
+     * *Deprecated*. Whether or not a string starts with another string. 
+     * 
+     * Parameters:
+     * sStart - {String} The string we're testing for.
+     *  
+     * Returns:
+     * {Boolean} Whether or not this string starts with the string passed in.
+     */
+    String.prototype.startsWith = function(sStart) {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                                {'newMethod':'OpenLayers.String.startsWith'}));
+        return OpenLayers.String.startsWith(this, sStart);
+    };
+}
+
+if (!String.prototype.contains) {
+    /**
+     * APIMethod: String.contains
+     * *Deprecated*. Whether or not a string contains another string.
+     * 
+     * Parameters:
+     * str - {String} The string that we're testing for.
+     * 
+     * Returns:
+     * {Boolean} Whether or not this string contains with the string passed in.
+     */
+    String.prototype.contains = function(str) {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                                  {'newMethod':'OpenLayers.String.contains'}));
+        return OpenLayers.String.contains(this, str);
+    };
+}
+
+if (!String.prototype.trim) {
+    /**
+     * APIMethod: String.trim
+     * *Deprecated*. Removes leading and trailing whitespace characters from a string.
+     * 
+     * Returns:
+     * {String} A trimmed version of the string - all leading and 
+     *          trailing spaces removed
+     */
+    String.prototype.trim = function() {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                                      {'newMethod':'OpenLayers.String.trim'}));
+        return OpenLayers.String.trim(this);
+    };
+}
+
+if (!String.prototype.camelize) {
+    /**
+     * APIMethod: String.camelize
+     * *Deprecated*. Camel-case a hyphenated string. 
+     *     Ex. "chicken-head" becomes "chickenHead", and
+     *     "-chicken-head" becomes "ChickenHead".
+     * 
+     * Returns:
+     * {String} The string, camelized
+     */
+    String.prototype.camelize = function() {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                                  {'newMethod':'OpenLayers.String.camelize'}));
+        return OpenLayers.String.camelize(this);
+    };
+}
+
+/**
+ * Namespace: OpenLayers.Number
+ * Contains convenience functions for manipulating numbers.
+ */
+OpenLayers.Number = {
+
+    /**
+     * Property: decimalSeparator
+     * Decimal separator to use when formatting numbers.
+     */
+    decimalSeparator: ".",
+    
+    /**
+     * Property: thousandsSeparator
+     * Thousands separator to use when formatting numbers.
+     */
+    thousandsSeparator: ",",
+    
+    /**
+     * APIFunction: limitSigDigs
+     * Limit the number of significant digits on a float.
+     * 
+     * Parameters:
+     * num - {Float}
+     * sig - {Integer}
+     * 
+     * Returns:
+     * {Float} The number, rounded to the specified number of significant
+     *     digits.
+     */
+    limitSigDigs: function(num, sig) {
+        var fig = 0;
+        if (sig > 0) {
+            fig = parseFloat(num.toPrecision(sig));
+        }
+        return fig;
+    },
+    
+    /**
+     * APIFunction: format
+     * Formats a number for output.
+     * 
+     * Parameters:
+     * num  - {Float}
+     * dec  - {Integer} Number of decimal places to round to.
+     *        Defaults to 0. Set to null to leave decimal places unchanged.
+     * tsep - {String} Thousands separator.
+     *        Default is ",".
+     * dsep - {String} Decimal separator.
+     *        Default is ".".
+     *
+     * Returns:
+     * {String} A string representing the formatted number.
+     */
+    format: function(num, dec, tsep, dsep) {
+        dec = (typeof dec != "undefined") ? dec : 0; 
+        tsep = (typeof tsep != "undefined") ? tsep :
+            OpenLayers.Number.thousandsSeparator; 
+        dsep = (typeof dsep != "undefined") ? dsep :
+            OpenLayers.Number.decimalSeparator;
+
+        if (dec != null) {
+            num = parseFloat(num.toFixed(dec));
+        }
+
+        var parts = num.toString().split(".");
+        if (parts.length == 1 && dec == null) {
+            // integer where we do not want to touch the decimals
+            dec = 0;
+        }
+        
+        var integer = parts[0];
+        if (tsep) {
+            var thousands = /(-?[0-9]+)([0-9]{3})/; 
+            while(thousands.test(integer)) { 
+                integer = integer.replace(thousands, "$1" + tsep + "$2"); 
+            }
+        }
+        
+        var str;
+        if (dec == 0) {
+            str = integer;
+        } else {
+            var rem = parts.length > 1 ? parts[1] : "0";
+            if (dec != null) {
+                rem = rem + new Array(dec - rem.length + 1).join("0");
+            }
+            str = integer + dsep + rem;
+        }
+        return str;
+    }
+};
+
+if (!Number.prototype.limitSigDigs) {
+    /**
+     * APIMethod: Number.limitSigDigs
+     * *Deprecated*. Limit the number of significant digits on an integer. Does *not*
+     *     work with floats!
+     * 
+     * Parameters:
+     * sig - {Integer}
+     * 
+     * Returns:
+     * {Integer} The number, rounded to the specified number of significant digits.
+     *           If null, 0, or negative value passed in, returns 0
+     */
+    Number.prototype.limitSigDigs = function(sig) {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                              {'newMethod':'OpenLayers.Number.limitSigDigs'}));
+        return OpenLayers.Number.limitSigDigs(this, sig);
+    };
+}
+
+/**
+ * Namespace: OpenLayers.Function
+ * Contains convenience functions for function manipulation.
+ */
+OpenLayers.Function = {
+    /**
+     * APIFunction: bind
+     * Bind a function to an object.  Method to easily create closures with
+     *     'this' altered.
+     * 
+     * Parameters:
+     * func - {Function} Input function.
+     * object - {Object} The object to bind to the input function (as this).
+     * 
+     * Returns:
+     * {Function} A closure with 'this' set to the passed in object.
+     */
+    bind: function(func, object) {
+        // create a reference to all arguments past the second one
+        var args = Array.prototype.slice.apply(arguments, [2]);
+        return function() {
+            // Push on any additional arguments from the actual function call.
+            // These will come after those sent to the bind call.
+            var newArgs = args.concat(
+                Array.prototype.slice.apply(arguments, [0])
+            );
+            return func.apply(object, newArgs);
+        };
+    },
+    
+    /**
+     * APIFunction: bindAsEventListener
+     * Bind a function to an object, and configure it to receive the event
+     *     object as first parameter when called. 
+     * 
+     * Parameters:
+     * func - {Function} Input function to serve as an event listener.
+     * object - {Object} A reference to this.
+     * 
+     * Returns:
+     * {Function}
+     */
+    bindAsEventListener: function(func, object) {
+        return function(event) {
+            return func.call(object, event || window.event);
+        };
+    },
+    
+    /**
+     * APIFunction: False
+     * A simple function to that just does "return false". We use this to 
+     * avoid attaching anonymous functions to DOM event handlers, which 
+     * causes "issues" on IE<8.
+     * 
+     * Usage:
+     * document.onclick = OpenLayers.Function.False;
+     * 
+     * Returns:
+     * {Boolean}
+     */
+    False : function() {
+        return false;
+    },
+
+    /**
+     * APIFunction: True
+     * A simple function to that just does "return true". We use this to 
+     * avoid attaching anonymous functions to DOM event handlers, which 
+     * causes "issues" on IE<8.
+     * 
+     * Usage:
+     * document.onclick = OpenLayers.Function.True;
+     * 
+     * Returns:
+     * {Boolean}
+     */
+    True : function() {
+        return true;
+    },
+    
+    /**
+     * APIFunction: Void
+     * A reusable function that returns ``undefined``.
+     *
+     * Returns:
+     * {undefined}
+     */
+    Void: function() {}
+
+};
+
+if (!Function.prototype.bind) {
+    /**
+     * APIMethod: Function.bind
+     * *Deprecated*. Bind a function to an object. 
+     * Method to easily create closures with 'this' altered.
+     * 
+     * Parameters:
+     * object - {Object} the this parameter
+     * 
+     * Returns:
+     * {Function} A closure with 'this' altered to the first
+     *            argument.
+     */
+    Function.prototype.bind = function() {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                                {'newMethod':'OpenLayers.Function.bind'}));
+        // new function takes the same arguments with this function up front
+        Array.prototype.unshift.apply(arguments, [this]);
+        return OpenLayers.Function.bind.apply(null, arguments);
+    };
+}
+
+if (!Function.prototype.bindAsEventListener) {
+    /**
+     * APIMethod: Function.bindAsEventListener
+     * *Deprecated*. Bind a function to an object, and configure it to receive the
+     *     event object as first parameter when called. 
+     * 
+     * Parameters:
+     * object - {Object} A reference to this.
+     * 
+     * Returns:
+     * {Function}
+     */
+    Function.prototype.bindAsEventListener = function(object) {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
+                        {'newMethod':'OpenLayers.Function.bindAsEventListener'}));
+        return OpenLayers.Function.bindAsEventListener(this, object);
+    };
+}
+
+/**
+ * Namespace: OpenLayers.Array
+ * Contains convenience functions for array manipulation.
+ */
+OpenLayers.Array = {
+
+    /**
+     * APIMethod: filter
+     * Filter an array.  Provides the functionality of the
+     *     Array.prototype.filter extension to the ECMA-262 standard.  Where
+     *     available, Array.prototype.filter will be used.
+     *
+     * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
+     *
+     * Parameters:
+     * array - {Array} The array to be filtered.  This array is not mutated.
+     *     Elements added to this array by the callback will not be visited.
+     * callback - {Function} A function that is called for each element in
+     *     the array.  If this function returns true, the element will be
+     *     included in the return.  The function will be called with three
+     *     arguments: the element in the array, the index of that element, and
+     *     the array itself.  If the optional caller parameter is specified
+     *     the callback will be called with this set to caller.
+     * caller - {Object} Optional object to be set as this when the callback
+     *     is called.
+     *
+     * Returns:
+     * {Array} An array of elements from the passed in array for which the
+     *     callback returns true.
+     */
+    filter: function(array, callback, caller) {
+        var selected = [];
+        if (Array.prototype.filter) {
+            selected = array.filter(callback, caller);
+        } else {
+            var len = array.length;
+            if (typeof callback != "function") {
+                throw new TypeError();
+            }
+            for(var i=0; i<len; i++) {
+                if (i in array) {
+                    var val = array[i];
+                    if (callback.call(caller, val, i, array)) {
+                        selected.push(val);
+                    }
+                }
+            }        
+        }
+        return selected;
+    }
+    
+};
+/* ======================================================================
+    OpenLayers/BaseTypes/Bounds.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Bounds
+ * Instances of this class represent bounding boxes.  Data stored as left,
+ * bottom, right, top floats. All values are initialized to null, however,
+ * you should make sure you set them before using the bounds for anything.
+ * 
+ * Possible use case:
+ * (code)
+ *     bounds = new OpenLayers.Bounds();
+ *     bounds.extend(new OpenLayers.LonLat(4,5));
+ *     bounds.extend(new OpenLayers.LonLat(5,6));
+ *     bounds.toBBOX(); // returns 4,5,5,6
+ * (end)
+ */
+OpenLayers.Bounds = OpenLayers.Class({
+
+    /**
+     * Property: left
+     * {Number} Minimum horizontal coordinate.
+     */
+    left: null,
+
+    /**
+     * Property: bottom
+     * {Number} Minimum vertical coordinate.
+     */
+    bottom: null,
+
+    /**
+     * Property: right
+     * {Number} Maximum horizontal coordinate.
+     */
+    right: null,
+
+    /**
+     * Property: top
+     * {Number} Maximum vertical coordinate.
+     */
+    top: null,
+    
+    /**
+     * Property: centerLonLat
+     * {<OpenLayers.LonLat>} A cached center location.  This should not be
+     *     accessed directly.  Use <getCenterLonLat> instead.
+     */
+    centerLonLat: null,
+
+    /**
+     * Constructor: OpenLayers.Bounds
+     * Construct a new bounds object.
+     *
+     * Parameters:
+     * left - {Number} The left bounds of the box.  Note that for width
+     *        calculations, this is assumed to be less than the right value.
+     * bottom - {Number} The bottom bounds of the box.  Note that for height
+     *          calculations, this is assumed to be more than the top value.
+     * right - {Number} The right bounds.
+     * top - {Number} The top bounds.
+     */
+    initialize: function(left, bottom, right, top) {
+        if (left != null) {
+            this.left = OpenLayers.Util.toFloat(left);
+        }
+        if (bottom != null) {
+            this.bottom = OpenLayers.Util.toFloat(bottom);
+        }
+        if (right != null) {
+            this.right = OpenLayers.Util.toFloat(right);
+        }
+        if (top != null) {
+            this.top = OpenLayers.Util.toFloat(top);
+        }
+    },
+
+    /**
+     * Method: clone
+     * Create a cloned instance of this bounds.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} A fresh copy of the bounds
+     */
+    clone:function() {
+        return new OpenLayers.Bounds(this.left, this.bottom, 
+                                     this.right, this.top);
+    },
+
+    /**
+     * Method: equals
+     * Test a two bounds for equivalence.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {Boolean} The passed-in bounds object has the same left,
+     *           right, top, bottom components as this.  Note that if bounds 
+     *           passed in is null, returns false.
+     */
+    equals:function(bounds) {
+        var equals = false;
+        if (bounds != null) {
+            equals = ((this.left == bounds.left) && 
+                      (this.right == bounds.right) &&
+                      (this.top == bounds.top) && 
+                      (this.bottom == bounds.bottom));
+        }
+        return equals;
+    },
+
+    /** 
+     * APIMethod: toString
+     * 
+     * Returns:
+     * {String} String representation of bounds object. 
+     */
+    toString:function() {
+        return [this.left, this.bottom, this.right, this.top].join(",");
+    },
+
+    /**
+     * APIMethod: toArray
+     *
+     * Parameters:
+     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
+     *
+     * Returns:
+     * {Array} array of left, bottom, right, top
+     */
+    toArray: function(reverseAxisOrder) {
+        if (reverseAxisOrder === true) {
+            return [this.bottom, this.left, this.top, this.right];
+        } else {
+            return [this.left, this.bottom, this.right, this.top];
+        }
+    },    
+
+    /** 
+     * APIMethod: toBBOX
+     * 
+     * Parameters:
+     * decimal - {Integer} How many significant digits in the bbox coords?
+     *                     Default is 6
+     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
+     * 
+     * Returns:
+     * {String} Simple String representation of bounds object.
+     *          (e.g. <i>"5,42,10,45"</i>)
+     */
+    toBBOX:function(decimal, reverseAxisOrder) {
+        if (decimal== null) {
+            decimal = 6; 
+        }
+        var mult = Math.pow(10, decimal);
+        var xmin = Math.round(this.left * mult) / mult;
+        var ymin = Math.round(this.bottom * mult) / mult;
+        var xmax = Math.round(this.right * mult) / mult;
+        var ymax = Math.round(this.top * mult) / mult;
+        if (reverseAxisOrder === true) {
+            return ymin + "," + xmin + "," + ymax + "," + xmax;
+        } else {
+            return xmin + "," + ymin + "," + xmax + "," + ymax;
+        }
+    },
+ 
+    /**
+     * APIMethod: toGeometry
+     * Create a new polygon geometry based on this bounds.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Polygon>} A new polygon with the coordinates
+     *     of this bounds.
+     */
+    toGeometry: function() {
+        return new OpenLayers.Geometry.Polygon([
+            new OpenLayers.Geometry.LinearRing([
+                new OpenLayers.Geometry.Point(this.left, this.bottom),
+                new OpenLayers.Geometry.Point(this.right, this.bottom),
+                new OpenLayers.Geometry.Point(this.right, this.top),
+                new OpenLayers.Geometry.Point(this.left, this.top)
+            ])
+        ]);
+    },
+    
+    /**
+     * APIMethod: getWidth
+     * 
+     * Returns:
+     * {Float} The width of the bounds
+     */
+    getWidth:function() {
+        return (this.right - this.left);
+    },
+
+    /**
+     * APIMethod: getHeight
+     * 
+     * Returns:
+     * {Float} The height of the bounds (top minus bottom).
+     */
+    getHeight:function() {
+        return (this.top - this.bottom);
+    },
+
+    /**
+     * APIMethod: getSize
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} The size of the box.
+     */
+    getSize:function() {
+        return new OpenLayers.Size(this.getWidth(), this.getHeight());
+    },
+
+    /**
+     * APIMethod: getCenterPixel
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} The center of the bounds in pixel space.
+     */
+    getCenterPixel:function() {
+        return new OpenLayers.Pixel( (this.left + this.right) / 2,
+                                     (this.bottom + this.top) / 2);
+    },
+
+    /**
+     * APIMethod: getCenterLonLat
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} The center of the bounds in map space.
+     */
+    getCenterLonLat:function() {
+        if(!this.centerLonLat) {
+            this.centerLonLat = new OpenLayers.LonLat(
+                (this.left + this.right) / 2, (this.bottom + this.top) / 2
+            );
+        }
+        return this.centerLonLat;
+    },
+
+    /**
+     * APIMethod: scale
+     * Scales the bounds around a pixel or lonlat. Note that the new 
+     *     bounds may return non-integer properties, even if a pixel
+     *     is passed. 
+     * 
+     * Parameters:
+     * ratio - {Float} 
+     * origin - {<OpenLayers.Pixel> or <OpenLayers.LonLat>}
+     *          Default is center.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} A new bounds that is scaled by ratio
+     *                      from origin.
+     */
+    scale: function(ratio, origin){
+        if(origin == null){
+            origin = this.getCenterLonLat();
+        }
+        
+        var origx,origy;
+
+        // get origin coordinates
+        if(origin.CLASS_NAME == "OpenLayers.LonLat"){
+            origx = origin.lon;
+            origy = origin.lat;
+        } else {
+            origx = origin.x;
+            origy = origin.y;
+        }
+
+        var left = (this.left - origx) * ratio + origx;
+        var bottom = (this.bottom - origy) * ratio + origy;
+        var right = (this.right - origx) * ratio + origx;
+        var top = (this.top - origy) * ratio + origy;
+        
+        return new OpenLayers.Bounds(left, bottom, right, top);
+    },
+
+    /**
+     * APIMethod: add
+     * 
+     * Parameters:
+     * x - {Float}
+     * y - {Float}
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A new bounds whose coordinates are the same as
+     *     this, but shifted by the passed-in x and y values.
+     */
+    add:function(x, y) {
+        if ( (x == null) || (y == null) ) {
+            var msg = OpenLayers.i18n("boundsAddError");
+            OpenLayers.Console.error(msg);
+            return null;
+        }
+        return new OpenLayers.Bounds(this.left + x, this.bottom + y,
+                                     this.right + x, this.top + y);
+    },
+    
+    /**
+     * APIMethod: extend
+     * Extend the bounds to include the point, lonlat, or bounds specified.
+     *     Note, this function assumes that left < right and bottom < top.
+     * 
+     * Parameters: 
+     * object - {Object} Can be LonLat, Point, or Bounds
+     */
+    extend:function(object) {
+        var bounds = null;
+        if (object) {
+            // clear cached center location
+            switch(object.CLASS_NAME) {
+                case "OpenLayers.LonLat":    
+                    bounds = new OpenLayers.Bounds(object.lon, object.lat,
+                                                    object.lon, object.lat);
+                    break;
+                case "OpenLayers.Geometry.Point":
+                    bounds = new OpenLayers.Bounds(object.x, object.y,
+                                                    object.x, object.y);
+                    break;
+                    
+                case "OpenLayers.Bounds":    
+                    bounds = object;
+                    break;
+            }
+    
+            if (bounds) {
+                this.centerLonLat = null;
+                if ( (this.left == null) || (bounds.left < this.left)) {
+                    this.left = bounds.left;
+                }
+                if ( (this.bottom == null) || (bounds.bottom < this.bottom) ) {
+                    this.bottom = bounds.bottom;
+                } 
+                if ( (this.right == null) || (bounds.right > this.right) ) {
+                    this.right = bounds.right;
+                }
+                if ( (this.top == null) || (bounds.top > this.top) ) { 
+                    this.top = bounds.top;
+                }
+            }
+        }
+    },
+
+    /**
+     * APIMethod: containsLonLat
+     * 
+     * Parameters:
+     * ll - {<OpenLayers.LonLat>}
+     * inclusive - {Boolean} Whether or not to include the border.
+     *     Default is true.
+     *
+     * Returns:
+     * {Boolean} The passed-in lonlat is within this bounds.
+     */
+    containsLonLat:function(ll, inclusive) {
+        return this.contains(ll.lon, ll.lat, inclusive);
+    },
+
+    /**
+     * APIMethod: containsPixel
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     * inclusive - {Boolean} Whether or not to include the border. Default is
+     *     true.
+     *
+     * Returns:
+     * {Boolean} The passed-in pixel is within this bounds.
+     */
+    containsPixel:function(px, inclusive) {
+        return this.contains(px.x, px.y, inclusive);
+    },
+    
+    /**
+     * APIMethod: contains
+     * 
+     * Parameters:
+     * x - {Float}
+     * y - {Float}
+     * inclusive - {Boolean} Whether or not to include the border. Default is
+     *     true.
+     *
+     * Returns:
+     * {Boolean} Whether or not the passed-in coordinates are within this
+     *     bounds.
+     */
+    contains:function(x, y, inclusive) {
+        //set default
+        if (inclusive == null) {
+            inclusive = true;
+        }
+
+        if (x == null || y == null) {
+            return false;
+        }
+
+        x = OpenLayers.Util.toFloat(x);
+        y = OpenLayers.Util.toFloat(y);
+
+        var contains = false;
+        if (inclusive) {
+            contains = ((x >= this.left) && (x <= this.right) && 
+                        (y >= this.bottom) && (y <= this.top));
+        } else {
+            contains = ((x > this.left) && (x < this.right) && 
+                        (y > this.bottom) && (y < this.top));
+        }              
+        return contains;
+    },
+
+    /**
+     * APIMethod: intersectsBounds
+     * Determine whether the target bounds intersects this bounds.  Bounds are
+     *     considered intersecting if any of their edges intersect or if one
+     *     bounds contains the other.
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} The target bounds.
+     * inclusive - {Boolean} Treat coincident borders as intersecting.  Default
+     *     is true.  If false, bounds that do not overlap but only touch at the
+     *     border will not be considered as intersecting.
+     *
+     * Returns:
+     * {Boolean} The passed-in bounds object intersects this bounds.
+     */
+    intersectsBounds:function(bounds, inclusive) {
+        if (inclusive == null) {
+            inclusive = true;
+        }
+        var intersects = false;
+        var mightTouch = (
+            this.left == bounds.right ||
+            this.right == bounds.left ||
+            this.top == bounds.bottom ||
+            this.bottom == bounds.top
+        );
+        
+        // if the two bounds only touch at an edge, and inclusive is false,
+        // then the bounds don't *really* intersect.
+        if (inclusive || !mightTouch) {
+            // otherwise, if one of the boundaries even partially contains another,
+            // inclusive of the edges, then they do intersect.
+            var inBottom = (
+                ((bounds.bottom >= this.bottom) && (bounds.bottom <= this.top)) ||
+                ((this.bottom >= bounds.bottom) && (this.bottom <= bounds.top))
+            );
+            var inTop = (
+                ((bounds.top >= this.bottom) && (bounds.top <= this.top)) ||
+                ((this.top > bounds.bottom) && (this.top < bounds.top))
+            );
+            var inLeft = (
+                ((bounds.left >= this.left) && (bounds.left <= this.right)) ||
+                ((this.left >= bounds.left) && (this.left <= bounds.right))
+            );
+            var inRight = (
+                ((bounds.right >= this.left) && (bounds.right <= this.right)) ||
+                ((this.right >= bounds.left) && (this.right <= bounds.right))
+            );
+            intersects = ((inBottom || inTop) && (inLeft || inRight));
+        }
+        return intersects;
+    },
+    
+    /**
+     * APIMethod: containsBounds
+     * Determine whether the target bounds is contained within this bounds.
+     * 
+     * bounds - {<OpenLayers.Bounds>} The target bounds.
+     * partial - {Boolean} If any of the target corners is within this bounds
+     *     consider the bounds contained.  Default is false.  If false, the
+     *     entire target bounds must be contained within this bounds.
+     * inclusive - {Boolean} Treat shared edges as contained.  Default is
+     *     true.
+     *
+     * Returns:
+     * {Boolean} The passed-in bounds object is contained within this bounds. 
+     */
+    containsBounds:function(bounds, partial, inclusive) {
+        if (partial == null) {
+            partial = false;
+        }
+        if (inclusive == null) {
+            inclusive = true;
+        }
+        var bottomLeft  = this.contains(bounds.left, bounds.bottom, inclusive);
+        var bottomRight = this.contains(bounds.right, bounds.bottom, inclusive);
+        var topLeft  = this.contains(bounds.left, bounds.top, inclusive);
+        var topRight = this.contains(bounds.right, bounds.top, inclusive);
+        
+        return (partial) ? (bottomLeft || bottomRight || topLeft || topRight)
+                         : (bottomLeft && bottomRight && topLeft && topRight);
+    },
+
+    /** 
+     * APIMethod: determineQuadrant
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {String} The quadrant ("br" "tr" "tl" "bl") of the bounds in which the
+     *     coordinate lies.
+     */
+    determineQuadrant: function(lonlat) {
+    
+        var quadrant = "";
+        var center = this.getCenterLonLat();
+        
+        quadrant += (lonlat.lat < center.lat) ? "b" : "t";
+        quadrant += (lonlat.lon < center.lon) ? "l" : "r";
+    
+        return quadrant; 
+    },
+    
+    /**
+     * APIMethod: transform
+     * Transform the Bounds object from source to dest. 
+     *
+     * Parameters: 
+     * source - {<OpenLayers.Projection>} Source projection. 
+     * dest   - {<OpenLayers.Projection>} Destination projection. 
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} Itself, for use in chaining operations.
+     */
+    transform: function(source, dest) {
+        // clear cached center location
+        this.centerLonLat = null;
+        var ll = OpenLayers.Projection.transform(
+            {'x': this.left, 'y': this.bottom}, source, dest);
+        var lr = OpenLayers.Projection.transform(
+            {'x': this.right, 'y': this.bottom}, source, dest);
+        var ul = OpenLayers.Projection.transform(
+            {'x': this.left, 'y': this.top}, source, dest);
+        var ur = OpenLayers.Projection.transform(
+            {'x': this.right, 'y': this.top}, source, dest);
+        this.left   = Math.min(ll.x, ul.x);
+        this.bottom = Math.min(ll.y, lr.y);
+        this.right  = Math.max(lr.x, ur.x);
+        this.top    = Math.max(ul.y, ur.y);
+        return this;
+    },
+
+    /**
+     * APIMethod: wrapDateLine
+     *  
+     * Parameters:
+     * maxExtent - {<OpenLayers.Bounds>}
+     * options - {Object} Some possible options are:
+     *
+     * Allowed Options:
+     *                    leftTolerance - {float} Allow for a margin of error 
+     *                                            with the 'left' value of this 
+     *                                            bound.
+     *                                            Default is 0.
+     *                    rightTolerance - {float} Allow for a margin of error 
+     *                                             with the 'right' value of 
+     *                                             this bound.
+     *                                             Default is 0.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A copy of this bounds, but wrapped around the 
+     *                       "dateline" (as specified by the borders of 
+     *                       maxExtent). Note that this function only returns 
+     *                       a different bounds value if this bounds is 
+     *                       *entirely* outside of the maxExtent. If this 
+     *                       bounds straddles the dateline (is part in/part 
+     *                       out of maxExtent), the returned bounds will be 
+     *                       merely a copy of this one.
+     */
+    wrapDateLine: function(maxExtent, options) {    
+        options = options || {};
+        
+        var leftTolerance = options.leftTolerance || 0;
+        var rightTolerance = options.rightTolerance || 0;
+
+        var newBounds = this.clone();
+    
+        if (maxExtent) {
+
+           //shift right?
+           while ( newBounds.left < maxExtent.left && 
+                   (newBounds.right - rightTolerance) <= maxExtent.left ) { 
+                newBounds = newBounds.add(maxExtent.getWidth(), 0);
+           }
+
+           //shift left?
+           while ( (newBounds.left + leftTolerance) >= maxExtent.right && 
+                   newBounds.right > maxExtent.right ) { 
+                newBounds = newBounds.add(-maxExtent.getWidth(), 0);
+           }
+        }
+                
+        return newBounds;
+    },
+
+    CLASS_NAME: "OpenLayers.Bounds"
+});
+
+/** 
+ * APIFunction: fromString
+ * Alternative constructor that builds a new OpenLayers.Bounds from a 
+ *     parameter string
+ * 
+ * Parameters: 
+ * str - {String}Comma-separated bounds string. (e.g. <i>"5,42,10,45"</i>)
+ * reverseAxisOrder - {Boolean} Does the string use reverse axis order?
+ * 
+ * Returns:
+ * {<OpenLayers.Bounds>} New bounds object built from the 
+ *                       passed-in String.
+ */
+OpenLayers.Bounds.fromString = function(str, reverseAxisOrder) {
+    var bounds = str.split(",");
+    return OpenLayers.Bounds.fromArray(bounds, reverseAxisOrder);
+};
+
+/** 
+ * APIFunction: fromArray
+ * Alternative constructor that builds a new OpenLayers.Bounds
+ *     from an array
+ * 
+ * Parameters:
+ * bbox - {Array(Float)} Array of bounds values (e.g. <i>[5,42,10,45]</i>)
+ * reverseAxisOrder - {Boolean} Does the array use reverse axis order?
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>} New bounds object built from the passed-in Array.
+ */
+OpenLayers.Bounds.fromArray = function(bbox, reverseAxisOrder) {
+    return reverseAxisOrder === true ?
+           new OpenLayers.Bounds(parseFloat(bbox[1]),
+                                 parseFloat(bbox[0]),
+                                 parseFloat(bbox[3]),
+                                 parseFloat(bbox[2])) :
+           new OpenLayers.Bounds(parseFloat(bbox[0]),
+                                 parseFloat(bbox[1]),
+                                 parseFloat(bbox[2]),
+                                 parseFloat(bbox[3]));
+};
+
+/** 
+ * APIFunction: fromSize
+ * Alternative constructor that builds a new OpenLayers.Bounds
+ *     from a size
+ * 
+ * Parameters:
+ * size - {<OpenLayers.Size>} 
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>} New bounds object built from the passed-in size.
+ */
+OpenLayers.Bounds.fromSize = function(size) {
+    return new OpenLayers.Bounds(0,
+                                 size.h,
+                                 size.w,
+                                 0);
+};
+
+/**
+ * Function: oppositeQuadrant
+ * Get the opposite quadrant for a given quadrant string.
+ *
+ * Parameters:
+ * quadrant - {String} two character quadrant shortstring
+ *
+ * Returns:
+ * {String} The opposing quadrant ("br" "tr" "tl" "bl"). For Example, if 
+ *          you pass in "bl" it returns "tr", if you pass in "br" it 
+ *          returns "tl", etc.
+ */
+OpenLayers.Bounds.oppositeQuadrant = function(quadrant) {
+    var opp = "";
+    
+    opp += (quadrant.charAt(0) == 't') ? 'b' : 't';
+    opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l';
+    
+    return opp;
+};
+/* ======================================================================
+    OpenLayers/BaseTypes/Element.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/BaseTypes.js
+ */
+
+/**
+ * Namespace: OpenLayers.Element
+ */
+OpenLayers.Element = {
+
+    /**
+     * APIFunction: visible
+     * 
+     * Parameters: 
+     * element - {DOMElement}
+     * 
+     * Returns:
+     * {Boolean} Is the element visible?
+     */
+    visible: function(element) {
+        return OpenLayers.Util.getElement(element).style.display != 'none';
+    },
+
+    /**
+     * APIFunction: toggle
+     * Toggle the visibility of element(s) passed in
+     * 
+     * Parameters:
+     * element - {DOMElement} Actually user can pass any number of elements
+     */
+    toggle: function() {
+        for (var i=0, len=arguments.length; i<len; i++) {
+            var element = OpenLayers.Util.getElement(arguments[i]);
+            var display = OpenLayers.Element.visible(element) ? 'hide' 
+                                                              : 'show';
+            OpenLayers.Element[display](element);
+        }
+    },
+
+
+    /**
+     * APIFunction: hide
+     * *Deprecated*. Hide element(s) passed in
+     * 
+     * Parameters:
+     * element - {DOMElement} Actually user can pass any number of elements
+     */
+    hide: function() {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {
+            newMethod: "element.style.display = 'none';"
+        }));
+
+        for (var i=0, len=arguments.length; i<len; i++) {
+            var element = OpenLayers.Util.getElement(arguments[i]);
+            if (element) {
+                element.style.display = 'none';
+            }
+        }
+    },
+
+    /**
+     * APIFunction: show
+     * *Deprecated*. Show element(s) passed in
+     * 
+     * Parameters:
+     * element - {DOMElement} Actually user can pass any number of elements
+     */
+    show: function() {
+        OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {
+            newMethod: "element.style.display = '';"
+        }));
+
+        for (var i=0, len=arguments.length; i<len; i++) {
+            var element = OpenLayers.Util.getElement(arguments[i]);
+            if (element) {
+                element.style.display = '';
+            }
+        }
+    },
+
+    /**
+     * APIFunction: remove
+     * Remove the specified element from the DOM.
+     * 
+     * Parameters:
+     * element - {DOMElement}
+     */
+    remove: function(element) {
+        element = OpenLayers.Util.getElement(element);
+        element.parentNode.removeChild(element);
+    },
+
+    /**
+     * APIFunction: getHeight
+     *  
+     * Parameters:
+     * element - {DOMElement}
+     * 
+     * Returns:
+     * {Integer} The offset height of the element passed in
+     */
+    getHeight: function(element) {
+        element = OpenLayers.Util.getElement(element);
+        return element.offsetHeight;
+    },
+
+    /**
+     * APIFunction: getDimensions
+     * *Deprecated*. Returns dimensions of the element passed in.
+     *  
+     * Parameters:
+     * element - {DOMElement}
+     * 
+     * Returns:
+     * {Object} Object with 'width' and 'height' properties which are the 
+     *          dimensions of the element passed in.
+     */
+    getDimensions: function(element) {
+        element = OpenLayers.Util.getElement(element);
+        if (OpenLayers.Element.getStyle(element, 'display') != 'none') {
+            return {width: element.offsetWidth, height: element.offsetHeight};
+        }
+    
+        // All *Width and *Height properties give 0 on elements with display none,
+        // so enable the element temporarily
+        var els = element.style;
+        var originalVisibility = els.visibility;
+        var originalPosition = els.position;
+        var originalDisplay = els.display;
+        els.visibility = 'hidden';
+        els.position = 'absolute';
+        els.display = '';
+        var originalWidth = element.clientWidth;
+        var originalHeight = element.clientHeight;
+        els.display = originalDisplay;
+        els.position = originalPosition;
+        els.visibility = originalVisibility;
+        return {width: originalWidth, height: originalHeight};
+    },
+
+    /**
+     * Function: hasClass
+     * Tests if an element has the given CSS class name.
+     *
+     * Parameters:
+     * element - {DOMElement} A DOM element node.
+     * name - {String} The CSS class name to search for.
+     *
+     * Returns:
+     * {Boolean} The element has the given class name.
+     */
+    hasClass: function(element, name) {
+        var names = element.className;
+        return (!!names && new RegExp("(^|\\s)" + name + "(\\s|$)").test(names));
+    },
+    
+    /**
+     * Function: addClass
+     * Add a CSS class name to an element.  Safe where element already has
+     *     the class name.
+     *
+     * Parameters:
+     * element - {DOMElement} A DOM element node.
+     * name - {String} The CSS class name to add.
+     *
+     * Returns:
+     * {DOMElement} The element.
+     */
+    addClass: function(element, name) {
+        if(!OpenLayers.Element.hasClass(element, name)) {
+            element.className += (element.className ? " " : "") + name;
+        }
+        return element;
+    },
+
+    /**
+     * Function: removeClass
+     * Remove a CSS class name from an element.  Safe where element does not
+     *     have the class name.
+     *
+     * Parameters:
+     * element - {DOMElement} A DOM element node.
+     * name - {String} The CSS class name to remove.
+     *
+     * Returns:
+     * {DOMElement} The element.
+     */
+    removeClass: function(element, name) {
+        var names = element.className;
+        if(names) {
+            element.className = OpenLayers.String.trim(
+                names.replace(
+                    new RegExp("(^|\\s+)" + name + "(\\s+|$)"), " "
+                )
+            );
+        }
+        return element;
+    },
+
+    /**
+     * Function: toggleClass
+     * Remove a CSS class name from an element if it exists.  Add the class name
+     *     if it doesn't exist.
+     *
+     * Parameters:
+     * element - {DOMElement} A DOM element node.
+     * name - {String} The CSS class name to toggle.
+     *
+     * Returns:
+     * {DOMElement} The element.
+     */
+    toggleClass: function(element, name) {
+        if(OpenLayers.Element.hasClass(element, name)) {
+            OpenLayers.Element.removeClass(element, name);
+        } else {
+            OpenLayers.Element.addClass(element, name);
+        }
+        return element;
+    },
+
+    /**
+     * APIFunction: getStyle
+     * 
+     * Parameters:
+     * element - {DOMElement}
+     * style - {?}
+     * 
+     * Returns:
+     * {?}
+     */
+    getStyle: function(element, style) {
+        element = OpenLayers.Util.getElement(element);
+
+        var value = null;
+        if (element && element.style) {
+            value = element.style[OpenLayers.String.camelize(style)];
+            if (!value) {
+                if (document.defaultView && 
+                    document.defaultView.getComputedStyle) {
+                    
+                    var css = document.defaultView.getComputedStyle(element, null);
+                    value = css ? css.getPropertyValue(style) : null;
+                } else if (element.currentStyle) {
+                    value = element.currentStyle[OpenLayers.String.camelize(style)];
+                }
+            }
+        
+            var positions = ['left', 'top', 'right', 'bottom'];
+            if (window.opera &&
+                (OpenLayers.Util.indexOf(positions,style) != -1) &&
+                (OpenLayers.Element.getStyle(element, 'position') == 'static')) { 
+                value = 'auto';
+            }
+        }
+    
+        return value == 'auto' ? null : value;
+    }
+
+};
+/* ======================================================================
+    OpenLayers/BaseTypes/LonLat.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.LonLat
+ * This class represents a longitude and latitude pair
+ */
+OpenLayers.LonLat = OpenLayers.Class({
+
+    /** 
+     * APIProperty: lon
+     * {Float} The x-axis coodinate in map units
+     */
+    lon: 0.0,
+    
+    /** 
+     * APIProperty: lat
+     * {Float} The y-axis coordinate in map units
+     */
+    lat: 0.0,
+
+    /**
+     * Constructor: OpenLayers.LonLat
+     * Create a new map location.
+     *
+     * Parameters:
+     * lon - {Number} The x-axis coordinate in map units.  If your map is in
+     *     a geographic projection, this will be the Longitude.  Otherwise,
+     *     it will be the x coordinate of the map location in your map units.
+     * lat - {Number} The y-axis coordinate in map units.  If your map is in
+     *     a geographic projection, this will be the Latitude.  Otherwise,
+     *     it will be the y coordinate of the map location in your map units.
+     */
+    initialize: function(lon, lat) {
+        this.lon = OpenLayers.Util.toFloat(lon);
+        this.lat = OpenLayers.Util.toFloat(lat);
+    },
+    
+    /**
+     * Method: toString
+     * Return a readable string version of the lonlat
+     *
+     * Returns:
+     * {String} String representation of OpenLayers.LonLat object. 
+     *           (e.g. <i>"lon=5,lat=42"</i>)
+     */
+    toString:function() {
+        return ("lon=" + this.lon + ",lat=" + this.lat);
+    },
+
+    /** 
+     * APIMethod: toShortString
+     * 
+     * Returns:
+     * {String} Shortened String representation of OpenLayers.LonLat object. 
+     *         (e.g. <i>"5, 42"</i>)
+     */
+    toShortString:function() {
+        return (this.lon + ", " + this.lat);
+    },
+
+    /** 
+     * APIMethod: clone
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} New OpenLayers.LonLat object with the same lon 
+     *                       and lat values
+     */
+    clone:function() {
+        return new OpenLayers.LonLat(this.lon, this.lat);
+    },
+
+    /** 
+     * APIMethod: add
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} A new OpenLayers.LonLat object with the lon and 
+     *                       lat passed-in added to this's. 
+     */
+    add:function(lon, lat) {
+        if ( (lon == null) || (lat == null) ) {
+            var msg = OpenLayers.i18n("lonlatAddError");
+            OpenLayers.Console.error(msg);
+            return null;
+        }
+        return new OpenLayers.LonLat(this.lon + OpenLayers.Util.toFloat(lon), 
+                                     this.lat + OpenLayers.Util.toFloat(lat));
+    },
+
+    /** 
+     * APIMethod: equals
+     * 
+     * Parameters:
+     * ll - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {Boolean} Boolean value indicating whether the passed-in 
+     *           <OpenLayers.LonLat> object has the same lon and lat 
+     *           components as this.
+     *           Note: if ll passed in is null, returns false
+     */
+    equals:function(ll) {
+        var equals = false;
+        if (ll != null) {
+            equals = ((this.lon == ll.lon && this.lat == ll.lat) ||
+                      (isNaN(this.lon) && isNaN(this.lat) && isNaN(ll.lon) && isNaN(ll.lat)));
+        }
+        return equals;
+    },
+
+    /**
+     * APIMethod: transform
+     * Transform the LonLat object from source to dest. This transformation is
+     *    *in place*: if you want a *new* lonlat, use .clone() first.
+     *
+     * Parameters: 
+     * source - {<OpenLayers.Projection>} Source projection. 
+     * dest   - {<OpenLayers.Projection>} Destination projection. 
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} Itself, for use in chaining operations.
+     */
+    transform: function(source, dest) {
+        var point = OpenLayers.Projection.transform(
+            {'x': this.lon, 'y': this.lat}, source, dest);
+        this.lon = point.x;
+        this.lat = point.y;
+        return this;
+    },
+    
+    /**
+     * APIMethod: wrapDateLine
+     * 
+     * Parameters:
+     * maxExtent - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} A copy of this lonlat, but wrapped around the 
+     *                       "dateline" (as specified by the borders of 
+     *                       maxExtent)
+     */
+    wrapDateLine: function(maxExtent) {    
+
+        var newLonLat = this.clone();
+    
+        if (maxExtent) {
+            //shift right?
+            while (newLonLat.lon < maxExtent.left) {
+                newLonLat.lon +=  maxExtent.getWidth();
+            }    
+           
+            //shift left?
+            while (newLonLat.lon > maxExtent.right) {
+                newLonLat.lon -= maxExtent.getWidth();
+            }    
+        }
+                
+        return newLonLat;
+    },
+
+    CLASS_NAME: "OpenLayers.LonLat"
+});
+
+/** 
+ * Function: fromString
+ * Alternative constructor that builds a new <OpenLayers.LonLat> from a 
+ *     parameter string
+ * 
+ * Parameters:
+ * str - {String} Comma-separated Lon,Lat coordinate string. 
+ *                 (e.g. <i>"5,40"</i>)
+ * 
+ * Returns:
+ * {<OpenLayers.LonLat>} New <OpenLayers.LonLat> object built from the 
+ *                       passed-in String.
+ */
+OpenLayers.LonLat.fromString = function(str) {
+    var pair = str.split(",");
+    return new OpenLayers.LonLat(pair[0], pair[1]);
+};
+
+/** 
+ * Function: fromArray
+ * Alternative constructor that builds a new <OpenLayers.LonLat> from an 
+ *     array of two numbers that represent lon- and lat-values.
+ * 
+ * Parameters:
+ * arr - {Array(Float)} Array of lon/lat values (e.g. [5,-42])
+ * 
+ * Returns:
+ * {<OpenLayers.LonLat>} New <OpenLayers.LonLat> object built from the 
+ *                       passed-in array.
+ */
+OpenLayers.LonLat.fromArray = function(arr) {
+    var gotArr = OpenLayers.Util.isArray(arr),
+        lon = gotArr && arr[0],
+        lat = gotArr && arr[1];
+    return new OpenLayers.LonLat(lon, lat);
+};
+/* ======================================================================
+    OpenLayers/BaseTypes/Pixel.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Pixel
+ * This class represents a screen coordinate, in x and y coordinates
+ */
+OpenLayers.Pixel = OpenLayers.Class({
+    
+    /**
+     * APIProperty: x
+     * {Number} The x coordinate
+     */
+    x: 0.0,
+
+    /**
+     * APIProperty: y
+     * {Number} The y coordinate
+     */
+    y: 0.0,
+    
+    /**
+     * Constructor: OpenLayers.Pixel
+     * Create a new OpenLayers.Pixel instance
+     *
+     * Parameters:
+     * x - {Number} The x coordinate
+     * y - {Number} The y coordinate
+     *
+     * Returns:
+     * An instance of OpenLayers.Pixel
+     */
+    initialize: function(x, y) {
+        this.x = parseFloat(x);
+        this.y = parseFloat(y);
+    },
+    
+    /**
+     * Method: toString
+     * Cast this object into a string
+     *
+     * Returns:
+     * {String} The string representation of Pixel. ex: "x=200.4,y=242.2"
+     */
+    toString:function() {
+        return ("x=" + this.x + ",y=" + this.y);
+    },
+
+    /**
+     * APIMethod: clone
+     * Return a clone of this pixel object
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} A clone pixel
+     */
+    clone:function() {
+        return new OpenLayers.Pixel(this.x, this.y); 
+    },
+    
+    /**
+     * APIMethod: equals
+     * Determine whether one pixel is equivalent to another
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {Boolean} The point passed in as parameter is equal to this. Note that
+     * if px passed in is null, returns false.
+     */
+    equals:function(px) {
+        var equals = false;
+        if (px != null) {
+            equals = ((this.x == px.x && this.y == px.y) ||
+                      (isNaN(this.x) && isNaN(this.y) && isNaN(px.x) && isNaN(px.y)));
+        }
+        return equals;
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Returns the distance to the pixel point passed in as a parameter.
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {Float} The pixel point passed in as parameter to calculate the
+     *     distance to.
+     */
+    distanceTo:function(px) {
+        return Math.sqrt(
+            Math.pow(this.x - px.x, 2) +
+            Math.pow(this.y - px.y, 2)
+        );
+    },
+
+    /**
+     * APIMethod: add
+     *
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} A new Pixel with this pixel's x&y augmented by the 
+     * values passed in.
+     */
+    add:function(x, y) {
+        if ( (x == null) || (y == null) ) {
+            var msg = OpenLayers.i18n("pixelAddError");
+            OpenLayers.Console.error(msg);
+            return null;
+        }
+        return new OpenLayers.Pixel(this.x + x, this.y + y);
+    },
+
+    /**
+    * APIMethod: offset
+    * 
+    * Parameters
+    * px - {<OpenLayers.Pixel>}
+    * 
+    * Returns:
+    * {<OpenLayers.Pixel>} A new Pixel with this pixel's x&y augmented by the 
+    *                      x&y values of the pixel passed in.
+    */
+    offset:function(px) {
+        var newPx = this.clone();
+        if (px) {
+            newPx = this.add(px.x, px.y);
+        }
+        return newPx;
+    },
+
+    CLASS_NAME: "OpenLayers.Pixel"
+});
+/* ======================================================================
+    OpenLayers/BaseTypes/Size.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Size
+ * Instances of this class represent a width/height pair
+ */
+OpenLayers.Size = OpenLayers.Class({
+
+    /**
+     * APIProperty: w
+     * {Number} width
+     */
+    w: 0.0,
+    
+    /**
+     * APIProperty: h
+     * {Number} height
+     */
+    h: 0.0,
+
+
+    /**
+     * Constructor: OpenLayers.Size
+     * Create an instance of OpenLayers.Size
+     *
+     * Parameters:
+     * w - {Number} width
+     * h - {Number} height
+     */
+    initialize: function(w, h) {
+        this.w = parseFloat(w);
+        this.h = parseFloat(h);
+    },
+
+    /**
+     * Method: toString
+     * Return the string representation of a size object
+     *
+     * Returns:
+     * {String} The string representation of OpenLayers.Size object. 
+     * (e.g. <i>"w=55,h=66"</i>)
+     */
+    toString:function() {
+        return ("w=" + this.w + ",h=" + this.h);
+    },
+
+    /**
+     * APIMethod: clone
+     * Create a clone of this size object
+     *
+     * Returns:
+     * {<OpenLayers.Size>} A new OpenLayers.Size object with the same w and h
+     * values
+     */
+    clone:function() {
+        return new OpenLayers.Size(this.w, this.h);
+    },
+
+    /**
+     *
+     * APIMethod: equals
+     * Determine where this size is equal to another
+     *
+     * Parameters:
+     * sz - {<OpenLayers.Size>}
+     *
+     * Returns: 
+     * {Boolean} The passed in size has the same h and w properties as this one.
+     * Note that if sz passed in is null, returns false.
+     *
+     */
+    equals:function(sz) {
+        var equals = false;
+        if (sz != null) {
+            equals = ((this.w == sz.w && this.h == sz.h) ||
+                      (isNaN(this.w) && isNaN(this.h) && isNaN(sz.w) && isNaN(sz.h)));
+        }
+        return equals;
+    },
+
+    CLASS_NAME: "OpenLayers.Size"
+});
+/* ======================================================================
+    OpenLayers/Util.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes.js
+ * @requires OpenLayers/BaseTypes/Bounds.js
+ * @requires OpenLayers/BaseTypes/Element.js
+ * @requires OpenLayers/BaseTypes/LonLat.js
+ * @requires OpenLayers/BaseTypes/Pixel.js
+ * @requires OpenLayers/BaseTypes/Size.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: Util
+ */
+OpenLayers.Util = OpenLayers.Util || {};
+
+/** 
+ * Function: getElement
+ * This is the old $() from prototype
+ *
+ * Parameters:
+ * e - {String or DOMElement or Window}
+ * Return:
+ * {Array(DOMElement)}
+ */
+OpenLayers.Util.getElement = function() {
+    var elements = [];
+
+    for (var i=0, len=arguments.length; i<len; i++) {
+        var element = arguments[i];
+        if (typeof element == 'string') {
+            element = document.getElementById(element);
+        }
+        if (arguments.length == 1) {
+            return element;
+        }
+        elements.push(element);
+    }
+    return elements;
+};
+
+/**
+ * Function: isElement
+ * A cross-browser implementation of "e instanceof Element".
+ *
+ * Parameters:
+ * o - {Object} The object to test.
+ *
+ * Returns:
+ * {Boolean}
+ */
+OpenLayers.Util.isElement = function(o) {
+    return !!(o && o.nodeType === 1);
+};
+
+/**
+ * Function: isArray
+ * Tests that the provided object is an array.
+ * This test handles the cross-IFRAME case not caught
+ * by "a instanceof Array" and should be used instead.
+ * 
+ * Parameters:
+ * a - {Object} the object test.
+ * 
+ * Returns
+ * {Boolean} true if the object is an array.
+ */
+OpenLayers.Util.isArray = function(a) {
+	return (Object.prototype.toString.call(a) === '[object Array]');
+};
+
+/** 
+ * Maintain existing definition of $.
+ */
+if(typeof window.$  === "undefined") {
+    window.$ = OpenLayers.Util.getElement;
+}
+
+/** 
+ * Function: removeItem
+ * Remove an object from an array. Iterates through the array
+ *     to find the item, then removes it.
+ *
+ * Parameters:
+ * array - {Array}
+ * item - {Object}
+ * 
+ * Return
+ * {Array} A reference to the array
+ */
+OpenLayers.Util.removeItem = function(array, item) {
+    for(var i = array.length - 1; i >= 0; i--) {
+        if(array[i] == item) {
+            array.splice(i,1);
+            //break;more than once??
+        }
+    }
+    return array;
+};
+
+/**
+ * Function: clearArray
+ * *Deprecated*. This function will disappear in 3.0.
+ * Please use "array.length = 0" instead.
+ * 
+ * Parameters:
+ * array - {Array}
+ */
+OpenLayers.Util.clearArray = function(array) {
+    OpenLayers.Console.warn(
+        OpenLayers.i18n(
+            "methodDeprecated", {'newMethod': 'array = []'}
+        )
+    );
+    array.length = 0;
+};
+
+/** 
+ * Function: indexOf
+ * Seems to exist already in FF, but not in MOZ.
+ * 
+ * Parameters:
+ * array - {Array}
+ * obj - {*}
+ * 
+ * Returns:
+ * {Integer} The index at, which the first object was found in the array.
+ *           If not found, returns -1.
+ */
+OpenLayers.Util.indexOf = function(array, obj) {
+    // use the build-in function if available.
+    if (typeof array.indexOf == "function") {
+        return array.indexOf(obj);
+    } else {
+        for (var i = 0, len = array.length; i < len; i++) {
+            if (array[i] == obj) {
+                return i;
+            }
+        }
+        return -1;   
+    }
+};
+
+
+
+/**
+ * Function: modifyDOMElement
+ * 
+ * Modifies many properties of a DOM element all at once.  Passing in 
+ * null to an individual parameter will avoid setting the attribute.
+ *
+ * Parameters:
+ * element - {DOMElement} DOM element to modify.
+ * id - {String} The element id attribute to set.
+ * px - {<OpenLayers.Pixel>} The left and top style position.
+ * sz - {<OpenLayers.Size>}  The width and height style attributes.
+ * position - {String}       The position attribute.  eg: absolute, 
+ *                           relative, etc.
+ * border - {String}         The style.border attribute.  eg:
+ *                           solid black 2px
+ * overflow - {String}       The style.overview attribute.  
+ * opacity - {Float}         Fractional value (0.0 - 1.0)
+ */
+OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, 
+                                            border, overflow, opacity) {
+
+    if (id) {
+        element.id = id;
+    }
+    if (px) {
+        element.style.left = px.x + "px";
+        element.style.top = px.y + "px";
+    }
+    if (sz) {
+        element.style.width = sz.w + "px";
+        element.style.height = sz.h + "px";
+    }
+    if (position) {
+        element.style.position = position;
+    }
+    if (border) {
+        element.style.border = border;
+    }
+    if (overflow) {
+        element.style.overflow = overflow;
+    }
+    if (parseFloat(opacity) >= 0.0 && parseFloat(opacity) < 1.0) {
+        element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
+        element.style.opacity = opacity;
+    } else if (parseFloat(opacity) == 1.0) {
+        element.style.filter = '';
+        element.style.opacity = '';
+    }
+};
+
+/** 
+ * Function: createDiv
+ * Creates a new div and optionally set some standard attributes.
+ * Null may be passed to each parameter if you do not wish to
+ * set a particular attribute.
+ * Note - zIndex is NOT set on the resulting div.
+ * 
+ * Parameters:
+ * id - {String} An identifier for this element.  If no id is
+ *               passed an identifier will be created 
+ *               automatically.
+ * px - {<OpenLayers.Pixel>} The element left and top position. 
+ * sz - {<OpenLayers.Size>} The element width and height.
+ * imgURL - {String} A url pointing to an image to use as a 
+ *                   background image.
+ * position - {String} The style.position value. eg: absolute,
+ *                     relative etc.
+ * border - {String} The the style.border value. 
+ *                   eg: 2px solid black
+ * overflow - {String} The style.overflow value. Eg. hidden
+ * opacity - {Float} Fractional value (0.0 - 1.0)
+ * 
+ * Returns: 
+ * {DOMElement} A DOM Div created with the specified attributes.
+ */
+OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, 
+                                     border, overflow, opacity) {
+
+    var dom = document.createElement('div');
+
+    if (imgURL) {
+        dom.style.backgroundImage = 'url(' + imgURL + ')';
+    }
+
+    //set generic properties
+    if (!id) {
+        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
+    }
+    if (!position) {
+        position = "absolute";
+    }
+    OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, 
+                                     border, overflow, opacity);
+
+    return dom;
+};
+
+/**
+ * Function: createImage
+ * Creates an img element with specific attribute values.
+ *  
+ * Parameters:
+ * id - {String} The id field for the img.  If none assigned one will be
+ *               automatically generated.
+ * px - {<OpenLayers.Pixel>} The left and top positions.
+ * sz - {<OpenLayers.Size>} The style.width and style.height values.
+ * imgURL - {String} The url to use as the image source.
+ * position - {String} The style.position value.
+ * border - {String} The border to place around the image.
+ * opacity - {Float} Fractional value (0.0 - 1.0)
+ * delayDisplay - {Boolean} If true waits until the image has been
+ *                          loaded.
+ * 
+ * Returns:
+ * {DOMElement} A DOM Image created with the specified attributes.
+ */
+OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border,
+                                       opacity, delayDisplay) {
+
+    var image = document.createElement("img");
+
+    //set generic properties
+    if (!id) {
+        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
+    }
+    if (!position) {
+        position = "relative";
+    }
+    OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, 
+                                     border, null, opacity);
+
+    if(delayDisplay) {
+        image.style.display = "none";
+        OpenLayers.Event.observe(image, "load", 
+            OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, image));
+        OpenLayers.Event.observe(image, "error", 
+            OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, image));
+        
+    }
+    
+    //set special properties
+    image.style.alt = id;
+    image.galleryImg = "no";
+    if (imgURL) {
+        image.src = imgURL;
+    }
+
+
+        
+    return image;
+};
+
+/**
+ * Function: setOpacity
+ * *Deprecated*.  This function has been deprecated. Instead, please use 
+ *     <OpenLayers.Util.modifyDOMElement> 
+ *     or 
+ *     <OpenLayers.Util.modifyAlphaImageDiv>
+ * 
+ * Set the opacity of a DOM Element
+ *     Note that for this function to work in IE, elements must "have layout"
+ *     according to:
+ *     http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/haslayout.asp
+ *
+ * Parameters:
+ * element - {DOMElement} Set the opacity on this DOM element
+ * opacity - {Float} Opacity value (0.0 - 1.0)
+ */
+OpenLayers.Util.setOpacity = function(element, opacity) {
+    OpenLayers.Util.modifyDOMElement(element, null, null, null,
+                                     null, null, null, opacity);
+};
+
+/**
+ * Function: onImageLoad
+ * Bound to image load events.  For all images created with <createImage> or
+ *     <createAlphaImageDiv>, this function will be bound to the load event.
+ */
+OpenLayers.Util.onImageLoad = function() {
+    // The complex check here is to solve issues described in #480.
+    // Every time a map view changes, it increments the 'viewRequestID' 
+    // property. As the requests for the images for the new map view are sent
+    // out, they are tagged with this unique viewRequestID. 
+    // 
+    // If an image has no viewRequestID property set, we display it regardless, 
+    // but if it does have a viewRequestID property, we check that it matches 
+    // the viewRequestID set on the map.
+    // 
+    // If the viewRequestID on the map has changed, that means that the user
+    // has changed the map view since this specific request was sent out, and
+    // therefore this tile does not need to be displayed (so we do not execute
+    // this code that turns its display on).
+    //
+    if (!this.viewRequestID ||
+        (this.map && this.viewRequestID == this.map.viewRequestID)) { 
+        this.style.display = "";  
+    }
+    OpenLayers.Element.removeClass(this, "olImageLoadError");
+};
+
+/**
+ * Property: IMAGE_RELOAD_ATTEMPTS
+ * {Integer} How many times should we try to reload an image before giving up?
+ *           Default is 0
+ */
+OpenLayers.IMAGE_RELOAD_ATTEMPTS = 0;
+
+/**
+ * Function: onImageLoadError 
+ */
+OpenLayers.Util.onImageLoadError = function() {
+    this._attempts = (this._attempts) ? (this._attempts + 1) : 1;
+    if (this._attempts <= OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
+        var urls = this.urls;
+        if (urls && OpenLayers.Util.isArray(urls) && urls.length > 1){
+            var src = this.src.toString();
+            var current_url, k;
+            for (k = 0; current_url = urls[k]; k++){
+                if(src.indexOf(current_url) != -1){
+                    break;
+                }
+            }
+            var guess = Math.floor(urls.length * Math.random());
+            var new_url = urls[guess];
+            k = 0;
+            while(new_url == current_url && k++ < 4){
+                guess = Math.floor(urls.length * Math.random());
+                new_url = urls[guess];
+            }
+            this.src = src.replace(current_url, new_url);
+        } else {
+            this.src = this.src;
+        }
+    } else {
+        OpenLayers.Element.addClass(this, "olImageLoadError");
+    }
+    this.style.display = "";
+};
+
+/**
+ * Property: alphaHackNeeded
+ * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.
+ */
+OpenLayers.Util.alphaHackNeeded = null;
+
+/**
+ * Function: alphaHack
+ * Checks whether it's necessary (and possible) to use the png alpha
+ * hack which allows alpha transparency for png images under Internet
+ * Explorer.
+ * 
+ * Returns:
+ * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.
+ */
+OpenLayers.Util.alphaHack = function() {
+    if (OpenLayers.Util.alphaHackNeeded == null) {
+        var arVersion = navigator.appVersion.split("MSIE");
+        var version = parseFloat(arVersion[1]);
+        var filter = false;
+    
+        // IEs4Lin dies when trying to access document.body.filters, because 
+        // the property is there, but requires a DLL that can't be provided. This
+        // means that we need to wrap this in a try/catch so that this can
+        // continue.
+    
+        try { 
+            filter = !!(document.body.filters);
+        } catch (e) {}    
+    
+        OpenLayers.Util.alphaHackNeeded = (filter && 
+                                           (version >= 5.5) && (version < 7));
+    }
+    return OpenLayers.Util.alphaHackNeeded;
+};
+
+/** 
+ * Function: modifyAlphaImageDiv
+ * 
+ * Parameters:
+ * div - {DOMElement} Div containing Alpha-adjusted Image
+ * id - {String}
+ * px - {<OpenLayers.Pixel>}
+ * sz - {<OpenLayers.Size>}
+ * imgURL - {String}
+ * position - {String}
+ * border - {String}
+ * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale"
+ * opacity - {Float} Fractional value (0.0 - 1.0)
+ */ 
+OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, 
+                                               position, border, sizing, 
+                                               opacity) {
+
+    OpenLayers.Util.modifyDOMElement(div, id, px, sz, position,
+                                     null, null, opacity);
+
+    var img = div.childNodes[0];
+
+    if (imgURL) {
+        img.src = imgURL;
+    }
+    OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz, 
+                                     "relative", border);
+    
+    if (OpenLayers.Util.alphaHack()) {
+        if(div.style.display != "none") {
+            div.style.display = "inline-block";
+        }
+        if (sizing == null) {
+            sizing = "scale";
+        }
+        
+        div.style.filter = "progid:DXImageTransform.Microsoft" +
+                           ".AlphaImageLoader(src='" + img.src + "', " +
+                           "sizingMethod='" + sizing + "')";
+        if (parseFloat(div.style.opacity) >= 0.0 && 
+            parseFloat(div.style.opacity) < 1.0) {
+            div.style.filter += " alpha(opacity=" + div.style.opacity * 100 + ")";
+        }
+
+        img.style.filter = "alpha(opacity=0)";
+    }
+};
+
+/** 
+ * Function: createAlphaImageDiv
+ * 
+ * Parameters:
+ * id - {String}
+ * px - {<OpenLayers.Pixel>}
+ * sz - {<OpenLayers.Size>}
+ * imgURL - {String}
+ * position - {String}
+ * border - {String}
+ * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale"
+ * opacity - {Float} Fractional value (0.0 - 1.0)
+ * delayDisplay - {Boolean} If true waits until the image has been
+ *                          loaded.
+ * 
+ * Returns:
+ * {DOMElement} A DOM Div created with a DOM Image inside it. If the hack is 
+ *              needed for transparency in IE, it is added.
+ */ 
+OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, 
+                                               position, border, sizing, 
+                                               opacity, delayDisplay) {
+    
+    var div = OpenLayers.Util.createDiv();
+    var img = OpenLayers.Util.createImage(null, null, null, null, null, null, 
+                                          null, false);
+    div.appendChild(img);
+
+    if (delayDisplay) {
+        img.style.display = "none";
+        OpenLayers.Event.observe(img, "load",
+            OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, div));
+        OpenLayers.Event.observe(img, "error",
+            OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, div));
+    }
+
+    OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, 
+                                        border, sizing, opacity);
+    
+    return div;
+};
+
+
+/** 
+ * Function: upperCaseObject
+ * Creates a new hashtable and copies over all the keys from the 
+ *     passed-in object, but storing them under an uppercased
+ *     version of the key at which they were stored.
+ * 
+ * Parameters: 
+ * object - {Object}
+ * 
+ * Returns: 
+ * {Object} A new Object with all the same keys but uppercased
+ */
+OpenLayers.Util.upperCaseObject = function (object) {
+    var uObject = {};
+    for (var key in object) {
+        uObject[key.toUpperCase()] = object[key];
+    }
+    return uObject;
+};
+
+/** 
+ * Function: applyDefaults
+ * Takes an object and copies any properties that don't exist from
+ *     another properties, by analogy with OpenLayers.Util.extend() from
+ *     Prototype.js.
+ * 
+ * Parameters:
+ * to - {Object} The destination object.
+ * from - {Object} The source object.  Any properties of this object that
+ *     are undefined in the to object will be set on the to object.
+ *
+ * Returns:
+ * {Object} A reference to the to object.  Note that the to argument is modified
+ *     in place and returned by this function.
+ */
+OpenLayers.Util.applyDefaults = function (to, from) {
+    to = to || {};
+    /*
+     * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
+     * prototype object" when calling hawOwnProperty if the source object is an
+     * instance of window.Event.
+     */
+    var fromIsEvt = typeof window.Event == "function"
+                    && from instanceof window.Event;
+
+    for (var key in from) {
+        if (to[key] === undefined ||
+            (!fromIsEvt && from.hasOwnProperty
+             && from.hasOwnProperty(key) && !to.hasOwnProperty(key))) {
+            to[key] = from[key];
+        }
+    }
+    /**
+     * IE doesn't include the toString property when iterating over an object's
+     * properties with the for(property in object) syntax.  Explicitly check if
+     * the source has its own toString property.
+     */
+    if(!fromIsEvt && from && from.hasOwnProperty
+       && from.hasOwnProperty('toString') && !to.hasOwnProperty('toString')) {
+        to.toString = from.toString;
+    }
+    
+    return to;
+};
+
+/**
+ * Function: getParameterString
+ * 
+ * Parameters:
+ * params - {Object}
+ * 
+ * Returns:
+ * {String} A concatenation of the properties of an object in 
+ *          http parameter notation. 
+ *          (ex. <i>"key1=value1&key2=value2&key3=value3"</i>)
+ *          If a parameter is actually a list, that parameter will then
+ *          be set to a comma-seperated list of values (foo,bar) instead
+ *          of being URL escaped (foo%3Abar). 
+ */
+OpenLayers.Util.getParameterString = function(params) {
+    var paramsArray = [];
+    
+    for (var key in params) {
+      var value = params[key];
+      if ((value != null) && (typeof value != 'function')) {
+        var encodedValue;
+        if (typeof value == 'object' && value.constructor == Array) {
+          /* value is an array; encode items and separate with "," */
+          var encodedItemArray = [];
+          var item;
+          for (var itemIndex=0, len=value.length; itemIndex<len; itemIndex++) {
+            item = value[itemIndex];
+            encodedItemArray.push(encodeURIComponent(
+                (item === null || item === undefined) ? "" : item)
+            );
+          }
+          encodedValue = encodedItemArray.join(",");
+        }
+        else {
+          /* value is a string; simply encode */
+          encodedValue = encodeURIComponent(value);
+        }
+        paramsArray.push(encodeURIComponent(key) + "=" + encodedValue);
+      }
+    }
+    
+    return paramsArray.join("&");
+};
+
+/**
+ * Function: urlAppend
+ * Appends a parameter string to a url. This function includes the logic for
+ * using the appropriate character (none, & or ?) to append to the url before
+ * appending the param string.
+ * 
+ * Parameters:
+ * url - {String} The url to append to
+ * paramStr - {String} The param string to append
+ * 
+ * Returns:
+ * {String} The new url
+ */
+OpenLayers.Util.urlAppend = function(url, paramStr) {
+    var newUrl = url;
+    if(paramStr) {
+        var parts = (url + " ").split(/[?&]/);
+        newUrl += (parts.pop() === " " ?
+            paramStr :
+            parts.length ? "&" + paramStr : "?" + paramStr);
+    }
+    return newUrl;
+};
+
+/**
+ * Property: ImgPath
+ * {String} Default is ''.
+ */
+OpenLayers.ImgPath = '';
+
+/** 
+ * Function: getImagesLocation
+ * 
+ * Returns:
+ * {String} The fully formatted image location string
+ */
+OpenLayers.Util.getImagesLocation = function() {
+    return OpenLayers.ImgPath || (OpenLayers._getScriptLocation() + "img/");
+};
+
+
+/** 
+ * Function: Try
+ * Execute functions until one of them doesn't throw an error. 
+ *     Capitalized because "try" is a reserved word in JavaScript.
+ *     Taken directly from OpenLayers.Util.Try()
+ * 
+ * Parameters:
+ * [*] - {Function} Any number of parameters may be passed to Try()
+ *    It will attempt to execute each of them until one of them 
+ *    successfully executes. 
+ *    If none executes successfully, returns null.
+ * 
+ * Returns:
+ * {*} The value returned by the first successfully executed function.
+ */
+OpenLayers.Util.Try = function() {
+    var returnValue = null;
+
+    for (var i=0, len=arguments.length; i<len; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+};
+
+/**
+ * Function: getXmlNodeValue
+ * 
+ * Parameters:
+ * node - {XMLNode}
+ * 
+ * Returns:
+ * {String} The text value of the given node, without breaking in firefox or IE
+ */
+OpenLayers.Util.getXmlNodeValue = function(node) {
+    var val = null;
+    OpenLayers.Util.Try( 
+        function() {
+            val = node.text;
+            if (!val) {
+                val = node.textContent;
+            }
+            if (!val) {
+                val = node.firstChild.nodeValue;
+            }
+        }, 
+        function() {
+            val = node.textContent;
+        }); 
+    return val;
+};
+
+/** 
+ * Function: mouseLeft
+ * 
+ * Parameters:
+ * evt - {Event}
+ * div - {HTMLDivElement}
+ * 
+ * Returns:
+ * {Boolean}
+ */
+OpenLayers.Util.mouseLeft = function (evt, div) {
+    // start with the element to which the mouse has moved
+    var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;
+    // walk up the DOM tree.
+    while (target != div && target != null) {
+        target = target.parentNode;
+    }
+    // if the target we stop at isn't the div, then we've left the div.
+    return (target != div);
+};
+
+/**
+ * Property: precision
+ * {Number} The number of significant digits to retain to avoid
+ * floating point precision errors.
+ *
+ * We use 14 as a "safe" default because, although IEEE 754 double floats
+ * (standard on most modern operating systems) support up to about 16
+ * significant digits, 14 significant digits are sufficient to represent
+ * sub-millimeter accuracy in any coordinate system that anyone is likely to
+ * use with OpenLayers.
+ *
+ * If DEFAULT_PRECISION is set to 0, the original non-truncating behavior
+ * of OpenLayers <2.8 is preserved. Be aware that this will cause problems
+ * with certain projections, e.g. spherical Mercator.
+ *
+ */
+OpenLayers.Util.DEFAULT_PRECISION = 14;
+
+/**
+ * Function: toFloat
+ * Convenience method to cast an object to a Number, rounded to the
+ * desired floating point precision.
+ *
+ * Parameters:
+ * number    - {Number} The number to cast and round.
+ * precision - {Number} An integer suitable for use with
+ *      Number.toPrecision(). Defaults to OpenLayers.Util.DEFAULT_PRECISION.
+ *      If set to 0, no rounding is performed.
+ *
+ * Returns:
+ * {Number} The cast, rounded number.
+ */
+OpenLayers.Util.toFloat = function (number, precision) {
+    if (precision == null) {
+        precision = OpenLayers.Util.DEFAULT_PRECISION;
+    }
+    if (typeof number !== "number") {
+        number = parseFloat(number);
+    }
+    return precision === 0 ? number :
+                             parseFloat(number.toPrecision(precision));
+};
+
+/**
+ * Function: rad
+ * 
+ * Parameters:
+ * x - {Float}
+ * 
+ * Returns:
+ * {Float}
+ */
+OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
+
+/**
+ * Function: deg
+ *
+ * Parameters:
+ * x - {Float}
+ *
+ * Returns:
+ * {Float}
+ */
+OpenLayers.Util.deg = function(x) {return x*180/Math.PI;};
+
+/**
+ * Property: VincentyConstants
+ * {Object} Constants for Vincenty functions.
+ */
+OpenLayers.Util.VincentyConstants = {
+    a: 6378137,
+    b: 6356752.3142,
+    f: 1/298.257223563
+};
+
+/**
+ * APIFunction: distVincenty
+ * Given two objects representing points with geographic coordinates, this
+ *     calculates the distance between those points on the surface of an
+ *     ellipsoid.
+ *
+ * Parameters:
+ * p1 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
+ * p2 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
+ *
+ * Returns:
+ * {Float} The distance (in km) between the two input points as measured on an
+ *     ellipsoid.  Note that the input point objects must be in geographic
+ *     coordinates (decimal degrees) and the return distance is in kilometers.
+ */
+OpenLayers.Util.distVincenty = function(p1, p2) {
+    var ct = OpenLayers.Util.VincentyConstants;
+    var a = ct.a, b = ct.b, f = ct.f;
+
+    var L = OpenLayers.Util.rad(p2.lon - p1.lon);
+    var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
+    var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
+    var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
+    var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
+    var lambda = L, lambdaP = 2*Math.PI;
+    var iterLimit = 20;
+    while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
+        var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
+        var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
+        (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
+        if (sinSigma==0) {
+            return 0;  // co-incident points
+        }
+        var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
+        var sigma = Math.atan2(sinSigma, cosSigma);
+        var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
+        var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
+        var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
+        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
+        lambdaP = lambda;
+        lambda = L + (1-C) * f * Math.sin(alpha) *
+        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
+    }
+    if (iterLimit==0) {
+        return NaN;  // formula failed to converge
+    }
+    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
+    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
+    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
+    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
+    var s = b*A*(sigma-deltaSigma);
+    var d = s.toFixed(3)/1000; // round to 1mm precision
+    return d;
+};
+
+/**
+ * APIFunction: destinationVincenty
+ * Calculate destination point given start point lat/long (numeric degrees),
+ * bearing (numeric degrees) & distance (in m).
+ * Adapted from Chris Veness work, see
+ * http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html
+ *
+ * Parameters:
+ * lonlat  - {<OpenLayers.LonLat>} (or any object with both .lat, .lon
+ *     properties) The start point.
+ * brng     - {Float} The bearing (degrees).
+ * dist     - {Float} The ground distance (meters).
+ *
+ * Returns:
+ * {<OpenLayers.LonLat>} The destination point.
+ */
+OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {
+    var u = OpenLayers.Util;
+    var ct = u.VincentyConstants;
+    var a = ct.a, b = ct.b, f = ct.f;
+
+    var lon1 = lonlat.lon;
+    var lat1 = lonlat.lat;
+
+    var s = dist;
+    var alpha1 = u.rad(brng);
+    var sinAlpha1 = Math.sin(alpha1);
+    var cosAlpha1 = Math.cos(alpha1);
+
+    var tanU1 = (1-f) * Math.tan(u.rad(lat1));
+    var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
+    var sigma1 = Math.atan2(tanU1, cosAlpha1);
+    var sinAlpha = cosU1 * sinAlpha1;
+    var cosSqAlpha = 1 - sinAlpha*sinAlpha;
+    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
+    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
+    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
+
+    var sigma = s / (b*A), sigmaP = 2*Math.PI;
+    while (Math.abs(sigma-sigmaP) > 1e-12) {
+        var cos2SigmaM = Math.cos(2*sigma1 + sigma);
+        var sinSigma = Math.sin(sigma);
+        var cosSigma = Math.cos(sigma);
+        var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+            B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
+        sigmaP = sigma;
+        sigma = s / (b*A) + deltaSigma;
+    }
+
+    var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
+    var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
+        (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
+    var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
+    var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
+    var L = lambda - (1-C) * f * sinAlpha *
+        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
+
+    var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
+
+    return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
+};
+
+/**
+ * Function: getParameters
+ * Parse the parameters from a URL or from the current page itself into a 
+ *     JavaScript Object. Note that parameter values with commas are separated
+ *     out into an Array.
+ * 
+ * Parameters:
+ * url - {String} Optional url used to extract the query string.
+ *                If url is null or is not supplied, query string is taken 
+ *                from the page location.
+ * 
+ * Returns:
+ * {Object} An object of key/value pairs from the query string.
+ */
+OpenLayers.Util.getParameters = function(url) {
+    // if no url specified, take it from the location bar
+    url = (url === null || url === undefined) ? window.location.href : url;
+
+    //parse out parameters portion of url string
+    var paramsString = "";
+    if (OpenLayers.String.contains(url, '?')) {
+        var start = url.indexOf('?') + 1;
+        var end = OpenLayers.String.contains(url, "#") ?
+                    url.indexOf('#') : url.length;
+        paramsString = url.substring(start, end);
+    }
+
+    var parameters = {};
+    var pairs = paramsString.split(/[&;]/);
+    for(var i=0, len=pairs.length; i<len; ++i) {
+        var keyValue = pairs[i].split('=');
+        if (keyValue[0]) {
+
+            var key = keyValue[0];
+            try {
+                key = decodeURIComponent(key);
+            } catch (err) {
+                key = unescape(key);
+            }
+            
+            // being liberal by replacing "+" with " "
+            var value = (keyValue[1] || '').replace(/\+/g, " ");
+
+            try {
+                value = decodeURIComponent(value);
+            } catch (err) {
+                value = unescape(value);
+            }
+            
+            // follow OGC convention of comma delimited values
+            value = value.split(",");
+
+            //if there's only one value, do not return as array                    
+            if (value.length == 1) {
+                value = value[0];
+            }                
+            
+            parameters[key] = value;
+         }
+     }
+    return parameters;
+};
+
+/**
+ * Function: getArgs
+ * *Deprecated*.  Will be removed in 3.0.  Please use instead
+ *     <OpenLayers.Util.getParameters>
+ * 
+ * Parameters:
+ * url - {String} Optional url used to extract the query string.
+ *                If null, query string is taken from page location.
+ * 
+ * Returns:
+ * {Object} An object of key/value pairs from the query string.
+ */
+OpenLayers.Util.getArgs = function(url) {
+    OpenLayers.Console.warn(
+        OpenLayers.i18n(
+            "methodDeprecated", {'newMethod': 'OpenLayers.Util.getParameters'}
+        )
+    );
+    return OpenLayers.Util.getParameters(url);
+};
+
+/**
+ * Property: lastSeqID
+ * {Integer} The ever-incrementing count variable.
+ *           Used for generating unique ids.
+ */
+OpenLayers.Util.lastSeqID = 0;
+
+/**
+ * Function: createUniqueID
+ * Create a unique identifier for this session.  Each time this function
+ *     is called, a counter is incremented.  The return will be the optional
+ *     prefix (defaults to "id_") appended with the counter value.
+ * 
+ * Parameters:
+ * prefix {String} Optionsal string to prefix unique id. Default is "id_".
+ * 
+ * Returns:
+ * {String} A unique id string, built on the passed in prefix.
+ */
+OpenLayers.Util.createUniqueID = function(prefix) {
+    if (prefix == null) {
+        prefix = "id_";
+    }
+    OpenLayers.Util.lastSeqID += 1; 
+    return prefix + OpenLayers.Util.lastSeqID;        
+};
+
+/**
+ * Constant: INCHES_PER_UNIT
+ * {Object} Constant inches per unit -- borrowed from MapServer mapscale.c
+ * derivation of nautical miles from http://en.wikipedia.org/wiki/Nautical_mile
+ * Includes the full set of units supported by CS-MAP (http://trac.osgeo.org/csmap/)
+ * and PROJ.4 (http://trac.osgeo.org/proj/)
+ * The hardcoded table is maintain in a CS-MAP source code module named CSdataU.c
+ * The hardcoded table of PROJ.4 units are in pj_units.c.
+ */
+OpenLayers.INCHES_PER_UNIT = { 
+    'inches': 1.0,
+    'ft': 12.0,
+    'mi': 63360.0,
+    'm': 39.3701,
+    'km': 39370.1,
+    'dd': 4374754,
+    'yd': 36
+};
+OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches;
+OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
+OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;
+
+// Units from CS-Map
+OpenLayers.METERS_PER_INCH = 0.02540005080010160020;
+OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
+    "Inch": OpenLayers.INCHES_PER_UNIT.inches,
+    "Meter": 1.0 / OpenLayers.METERS_PER_INCH,   //EPSG:9001
+    "Foot": 0.30480060960121920243 / OpenLayers.METERS_PER_INCH,   //EPSG:9003
+    "IFoot": 0.30480000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9002
+    "ClarkeFoot": 0.3047972651151 / OpenLayers.METERS_PER_INCH,   //EPSG:9005
+    "SearsFoot": 0.30479947153867624624 / OpenLayers.METERS_PER_INCH,   //EPSG:9041
+    "GoldCoastFoot": 0.30479971018150881758 / OpenLayers.METERS_PER_INCH,   //EPSG:9094
+    "IInch": 0.02540000000000000000 / OpenLayers.METERS_PER_INCH,
+    "MicroInch": 0.00002540000000000000 / OpenLayers.METERS_PER_INCH,
+    "Mil": 0.00000002540000000000 / OpenLayers.METERS_PER_INCH,
+    "Centimeter": 0.01000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Kilometer": 1000.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9036
+    "Yard": 0.91440182880365760731 / OpenLayers.METERS_PER_INCH,
+    "SearsYard": 0.914398414616029 / OpenLayers.METERS_PER_INCH,   //EPSG:9040
+    "IndianYard": 0.91439853074444079983 / OpenLayers.METERS_PER_INCH,   //EPSG:9084
+    "IndianYd37": 0.91439523 / OpenLayers.METERS_PER_INCH,   //EPSG:9085
+    "IndianYd62": 0.9143988 / OpenLayers.METERS_PER_INCH,   //EPSG:9086
+    "IndianYd75": 0.9143985 / OpenLayers.METERS_PER_INCH,   //EPSG:9087
+    "IndianFoot": 0.30479951 / OpenLayers.METERS_PER_INCH,   //EPSG:9080
+    "IndianFt37": 0.30479841 / OpenLayers.METERS_PER_INCH,   //EPSG:9081
+    "IndianFt62": 0.3047996 / OpenLayers.METERS_PER_INCH,   //EPSG:9082
+    "IndianFt75": 0.3047995 / OpenLayers.METERS_PER_INCH,   //EPSG:9083
+    "Mile": 1609.34721869443738887477 / OpenLayers.METERS_PER_INCH,
+    "IYard": 0.91440000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9096
+    "IMile": 1609.34400000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9093
+    "NautM": 1852.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9030
+    "Lat-66": 110943.316488932731 / OpenLayers.METERS_PER_INCH,
+    "Lat-83": 110946.25736872234125 / OpenLayers.METERS_PER_INCH,
+    "Decimeter": 0.10000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Millimeter": 0.00100000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Dekameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Decameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Hectometer": 100.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "GermanMeter": 1.0000135965 / OpenLayers.METERS_PER_INCH,   //EPSG:9031
+    "CaGrid": 0.999738 / OpenLayers.METERS_PER_INCH,
+    "ClarkeChain": 20.1166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9038
+    "GunterChain": 20.11684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9033
+    "BenoitChain": 20.116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9062
+    "SearsChain": 20.11676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9042
+    "ClarkeLink": 0.201166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9039
+    "GunterLink": 0.2011684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9034
+    "BenoitLink": 0.20116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9063
+    "SearsLink": 0.2011676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9043
+    "Rod": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "IntnlChain": 20.1168 / OpenLayers.METERS_PER_INCH,   //EPSG:9097
+    "IntnlLink": 0.201168 / OpenLayers.METERS_PER_INCH,   //EPSG:9098
+    "Perch": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "Pole": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "Furlong": 201.1684023368046 / OpenLayers.METERS_PER_INCH,
+    "Rood": 3.778266898 / OpenLayers.METERS_PER_INCH,
+    "CapeFoot": 0.3047972615 / OpenLayers.METERS_PER_INCH,
+    "Brealey": 375.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "ModAmFt": 0.304812252984505969011938 / OpenLayers.METERS_PER_INCH,
+    "Fathom": 1.8288 / OpenLayers.METERS_PER_INCH,
+    "NautM-UK": 1853.184 / OpenLayers.METERS_PER_INCH,
+    "50kilometers": 50000.0 / OpenLayers.METERS_PER_INCH,
+    "150kilometers": 150000.0 / OpenLayers.METERS_PER_INCH
+});
+
+//unit abbreviations supported by PROJ.4
+OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
+    "mm": OpenLayers.INCHES_PER_UNIT["Meter"] / 1000.0,
+    "cm": OpenLayers.INCHES_PER_UNIT["Meter"] / 100.0,
+    "dm": OpenLayers.INCHES_PER_UNIT["Meter"] * 100.0,
+    "km": OpenLayers.INCHES_PER_UNIT["Meter"] * 1000.0,
+    "kmi": OpenLayers.INCHES_PER_UNIT["nmi"],    //International Nautical Mile
+    "fath": OpenLayers.INCHES_PER_UNIT["Fathom"], //International Fathom
+    "ch": OpenLayers.INCHES_PER_UNIT["IntnlChain"],  //International Chain
+    "link": OpenLayers.INCHES_PER_UNIT["IntnlLink"], //International Link
+    "us-in": OpenLayers.INCHES_PER_UNIT["inches"], //U.S. Surveyor's Inch
+    "us-ft": OpenLayers.INCHES_PER_UNIT["Foot"],	//U.S. Surveyor's Foot
+    "us-yd": OpenLayers.INCHES_PER_UNIT["Yard"],	//U.S. Surveyor's Yard
+    "us-ch": OpenLayers.INCHES_PER_UNIT["GunterChain"], //U.S. Surveyor's Chain
+    "us-mi": OpenLayers.INCHES_PER_UNIT["Mile"],   //U.S. Surveyor's Statute Mile
+    "ind-yd": OpenLayers.INCHES_PER_UNIT["IndianYd37"],  //Indian Yard
+    "ind-ft": OpenLayers.INCHES_PER_UNIT["IndianFt37"],  //Indian Foot
+    "ind-ch": 20.11669506 / OpenLayers.METERS_PER_INCH  //Indian Chain
+});
+
+/** 
+ * Constant: DOTS_PER_INCH
+ * {Integer} 72 (A sensible default)
+ */
+OpenLayers.DOTS_PER_INCH = 72;
+
+/**
+ * Function: normalizeScale
+ * 
+ * Parameters:
+ * scale - {float}
+ * 
+ * Returns:
+ * {Float} A normalized scale value, in 1 / X format. 
+ *         This means that if a value less than one ( already 1/x) is passed
+ *         in, it just returns scale directly. Otherwise, it returns 
+ *         1 / scale
+ */
+OpenLayers.Util.normalizeScale = function (scale) {
+    var normScale = (scale > 1.0) ? (1.0 / scale) 
+                                  : scale;
+    return normScale;
+};
+
+/**
+ * Function: getResolutionFromScale
+ * 
+ * Parameters:
+ * scale - {Float}
+ * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
+ *                  Default is degrees
+ * 
+ * Returns:
+ * {Float} The corresponding resolution given passed-in scale and unit 
+ *     parameters.  If the given scale is falsey, the returned resolution will
+ *     be undefined.
+ */
+OpenLayers.Util.getResolutionFromScale = function (scale, units) {
+    var resolution;
+    if (scale) {
+        if (units == null) {
+            units = "degrees";
+        }
+        var normScale = OpenLayers.Util.normalizeScale(scale);
+        resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
+                                        * OpenLayers.DOTS_PER_INCH);        
+    }
+    return resolution;
+};
+
+/**
+ * Function: getScaleFromResolution
+ * 
+ * Parameters:
+ * resolution - {Float}
+ * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
+ *                  Default is degrees
+ * 
+ * Returns:
+ * {Float} The corresponding scale given passed-in resolution and unit 
+ *         parameters.
+ */
+OpenLayers.Util.getScaleFromResolution = function (resolution, units) {
+
+    if (units == null) {
+        units = "degrees";
+    }
+
+    var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] *
+                    OpenLayers.DOTS_PER_INCH;
+    return scale;
+};
+
+/**
+ * Function: safeStopPropagation
+ * *Deprecated*. This function has been deprecated. Please use directly 
+ *     <OpenLayers.Event.stop> passing 'true' as the 2nd 
+ *     argument (preventDefault)
+ * 
+ * Safely stop the propagation of an event *without* preventing
+ *   the default browser action from occurring.
+ * 
+ * Parameter:
+ * evt - {Event}
+ */
+OpenLayers.Util.safeStopPropagation = function(evt) {
+    OpenLayers.Event.stop(evt, true);
+};
+
+/**
+ * Function: pagePosition
+ * Calculates the position of an element on the page (see
+ * http://code.google.com/p/doctype/wiki/ArticlePageOffset)
+ *
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Parameters:
+ * forElement - {DOMElement}
+ * 
+ * Returns:
+ * {Array} two item array, Left value then Top value.
+ */
+OpenLayers.Util.pagePosition =  function(forElement) {
+    // NOTE: If element is hidden (display none or disconnected or any the
+    // ancestors are hidden) we get (0,0) by default but we still do the
+    // accumulation of scroll position.
+
+    var pos = [0, 0];
+    var viewportElement = OpenLayers.Util.getViewportElement();
+    if (!forElement || forElement == window || forElement == viewportElement) {
+        // viewport is always at 0,0 as that defined the coordinate system for
+        // this function - this avoids special case checks in the code below
+        return pos;
+    }
+
+    // Gecko browsers normally use getBoxObjectFor to calculate the position.
+    // When invoked for an element with an implicit absolute position though it
+    // can be off by one. Therefore the recursive implementation is used in
+    // those (relatively rare) cases.
+    var BUGGY_GECKO_BOX_OBJECT =
+        OpenLayers.IS_GECKO && document.getBoxObjectFor &&
+        OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' &&
+        (forElement.style.top == '' || forElement.style.left == '');
+
+    var parent = null;
+    var box;
+
+    if (forElement.getBoundingClientRect) { // IE
+        box = forElement.getBoundingClientRect();
+        var scrollTop = viewportElement.scrollTop;
+        var scrollLeft = viewportElement.scrollLeft;
+
+        pos[0] = box.left + scrollLeft;
+        pos[1] = box.top + scrollTop;
+
+    } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko
+        // Gecko ignores the scroll values for ancestors, up to 1.9.  See:
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
+
+        box = document.getBoxObjectFor(forElement);
+        var vpBox = document.getBoxObjectFor(viewportElement);
+        pos[0] = box.screenX - vpBox.screenX;
+        pos[1] = box.screenY - vpBox.screenY;
+
+    } else { // safari/opera
+        pos[0] = forElement.offsetLeft;
+        pos[1] = forElement.offsetTop;
+        parent = forElement.offsetParent;
+        if (parent != forElement) {
+            while (parent) {
+                pos[0] += parent.offsetLeft;
+                pos[1] += parent.offsetTop;
+                parent = parent.offsetParent;
+            }
+        }
+
+        var browser = OpenLayers.BROWSER_NAME;
+
+        // opera & (safari absolute) incorrectly account for body offsetTop
+        if (browser == "opera" || (browser == "safari" &&
+              OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) {
+            pos[1] -= document.body.offsetTop;
+        }
+
+        // accumulate the scroll positions for everything but the body element
+        parent = forElement.offsetParent;
+        while (parent && parent != document.body) {
+            pos[0] -= parent.scrollLeft;
+            // see https://bugs.opera.com/show_bug.cgi?id=249965
+            if (browser != "opera" || parent.tagName != 'TR') {
+                pos[1] -= parent.scrollTop;
+            }
+            parent = parent.offsetParent;
+        }
+    }
+    
+    return pos;
+};
+
+/**
+ * Function: getViewportElement
+ * Returns die viewport element of the document. The viewport element is
+ * usually document.documentElement, except in IE,where it is either
+ * document.body or document.documentElement, depending on the document's
+ * compatibility mode (see
+ * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement)
+ */
+OpenLayers.Util.getViewportElement = function() {
+    var viewportElement = arguments.callee.viewportElement;
+    if (viewportElement == undefined) {
+        viewportElement = (OpenLayers.BROWSER_NAME == "msie" &&
+            document.compatMode != 'CSS1Compat') ? document.body :
+            document.documentElement;
+        arguments.callee.viewportElement = viewportElement;
+    }
+    return viewportElement;
+};
+
+/** 
+ * Function: isEquivalentUrl
+ * Test two URLs for equivalence. 
+ * 
+ * Setting 'ignoreCase' allows for case-independent comparison.
+ * 
+ * Comparison is based on: 
+ *  - Protocol
+ *  - Host (evaluated without the port)
+ *  - Port (set 'ignorePort80' to ignore "80" values)
+ *  - Hash ( set 'ignoreHash' to disable)
+ *  - Pathname (for relative <-> absolute comparison) 
+ *  - Arguments (so they can be out of order)
+ *  
+ * Parameters:
+ * url1 - {String}
+ * url2 - {String}
+ * options - {Object} Allows for customization of comparison:
+ *                    'ignoreCase' - Default is True
+ *                    'ignorePort80' - Default is True
+ *                    'ignoreHash' - Default is True
+ *
+ * Returns:
+ * {Boolean} Whether or not the two URLs are equivalent
+ */
+OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {
+    options = options || {};
+
+    OpenLayers.Util.applyDefaults(options, {
+        ignoreCase: true,
+        ignorePort80: true,
+        ignoreHash: true
+    });
+
+    var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
+    var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);
+
+    //compare all keys except for "args" (treated below)
+    for(var key in urlObj1) {
+        if(key !== "args") {
+            if(urlObj1[key] != urlObj2[key]) {
+                return false;
+            }
+        }
+    }
+
+    // compare search args - irrespective of order
+    for(var key in urlObj1.args) {
+        if(urlObj1.args[key] != urlObj2.args[key]) {
+            return false;
+        }
+        delete urlObj2.args[key];
+    }
+    // urlObj2 shouldn't have any args left
+    for(var key in urlObj2.args) {
+        return false;
+    }
+    
+    return true;
+};
+
+/**
+ * Function: createUrlObject
+ * 
+ * Parameters:
+ * url - {String}
+ * options - {Object} A hash of options.  Can be one of:
+ *            ignoreCase: lowercase url,
+ *            ignorePort80: don't include explicit port if port is 80,
+ *            ignoreHash: Don't include part of url after the hash (#).
+ * 
+ * Returns:
+ * {Object} An object with separate url, a, port, host, and args parsed out 
+ *          and ready for comparison
+ */
+OpenLayers.Util.createUrlObject = function(url, options) {
+    options = options || {};
+
+    // deal with relative urls first
+    if(!(/^\w+:\/\//).test(url)) {
+        var loc = window.location;
+        var port = loc.port ? ":" + loc.port : "";
+        var fullUrl = loc.protocol + "//" + loc.host.split(":").shift() + port;
+        if(url.indexOf("/") === 0) {
+            // full pathname
+            url = fullUrl + url;
+        } else {
+            // relative to current path
+            var parts = loc.pathname.split("/");
+            parts.pop();
+            url = fullUrl + parts.join("/") + "/" + url;
+        }
+    }
+  
+    if (options.ignoreCase) {
+        url = url.toLowerCase(); 
+    }
+
+    var a = document.createElement('a');
+    a.href = url;
+    
+    var urlObject = {};
+    
+    //host (without port)
+    urlObject.host = a.host.split(":").shift();
+
+    //protocol
+    urlObject.protocol = a.protocol;  
+
+    //port (get uniform browser behavior with port 80 here)
+    if(options.ignorePort80) {
+        urlObject.port = (a.port == "80" || a.port == "0") ? "" : a.port;
+    } else {
+        urlObject.port = (a.port == "" || a.port == "0") ? "80" : a.port;
+    }
+
+    //hash
+    urlObject.hash = (options.ignoreHash || a.hash === "#") ? "" : a.hash;  
+    
+    //args
+    var queryString = a.search;
+    if (!queryString) {
+        var qMark = url.indexOf("?");
+        queryString = (qMark != -1) ? url.substr(qMark) : "";
+    }
+    urlObject.args = OpenLayers.Util.getParameters(queryString);
+
+    //pathname (uniform browser behavior with leading "/")
+    urlObject.pathname = (a.pathname.charAt(0) == "/") ? a.pathname : "/" + a.pathname;
+    
+    return urlObject; 
+};
+ 
+/**
+ * Function: removeTail
+ * Takes a url and removes everything after the ? and #
+ * 
+ * Parameters:
+ * url - {String} The url to process
+ * 
+ * Returns:
+ * {String} The string with all queryString and Hash removed
+ */
+OpenLayers.Util.removeTail = function(url) {
+    var head = null;
+    
+    var qMark = url.indexOf("?");
+    var hashMark = url.indexOf("#");
+
+    if (qMark == -1) {
+        head = (hashMark != -1) ? url.substr(0,hashMark) : url;
+    } else {
+        head = (hashMark != -1) ? url.substr(0,Math.min(qMark, hashMark)) 
+                                  : url.substr(0, qMark);
+    }
+    return head;
+};
+
+/**
+ * Constant: IS_GECKO
+ * {Boolean} True if the userAgent reports the browser to use the Gecko engine
+ */
+OpenLayers.IS_GECKO = (function() {
+    var ua = navigator.userAgent.toLowerCase();
+    return ua.indexOf("webkit") == -1 && ua.indexOf("gecko") != -1;
+})();
+
+/**
+ * Constant: BROWSER_NAME
+ * {String}
+ * A substring of the navigator.userAgent property.  Depending on the userAgent
+ *     property, this will be the empty string or one of the following:
+ *     * "opera" -- Opera
+ *     * "msie"  -- Internet Explorer
+ *     * "safari" -- Safari
+ *     * "firefox" -- Firefox
+ *     * "mozilla" -- Mozilla
+ */
+OpenLayers.BROWSER_NAME = (function() {
+    var name = "";
+    var ua = navigator.userAgent.toLowerCase();
+    if (ua.indexOf("opera") != -1) {
+        name = "opera";
+    } else if (ua.indexOf("msie") != -1) {
+        name = "msie";
+    } else if (ua.indexOf("safari") != -1) {
+        name = "safari";
+    } else if (ua.indexOf("mozilla") != -1) {
+        if (ua.indexOf("firefox") != -1) {
+            name = "firefox";
+        } else {
+            name = "mozilla";
+        }
+    }
+    return name;
+})();
+
+/**
+ * Function: getBrowserName
+ * 
+ * Returns:
+ * {String} A string which specifies which is the current 
+ *          browser in which we are running. 
+ * 
+ *          Currently-supported browser detection and codes:
+ *           * 'opera' -- Opera
+ *           * 'msie'  -- Internet Explorer
+ *           * 'safari' -- Safari
+ *           * 'firefox' -- Firefox
+ *           * 'mozilla' -- Mozilla
+ * 
+ *          If we are unable to property identify the browser, we 
+ *           return an empty string.
+ */
+OpenLayers.Util.getBrowserName = function() {
+    return OpenLayers.BROWSER_NAME;
+};
+
+/**
+ * Method: getRenderedDimensions
+ * Renders the contentHTML offscreen to determine actual dimensions for
+ *     popup sizing. As we need layout to determine dimensions the content
+ *     is rendered -9999px to the left and absolute to ensure the 
+ *     scrollbars do not flicker
+ *     
+ * Parameters:
+ * contentHTML
+ * size - {<OpenLayers.Size>} If either the 'w' or 'h' properties is 
+ *     specified, we fix that dimension of the div to be measured. This is 
+ *     useful in the case where we have a limit in one dimension and must 
+ *     therefore meaure the flow in the other dimension.
+ * options - {Object}
+ *
+ * Allowed Options:
+ *     displayClass - {String} Optional parameter.  A CSS class name(s) string
+ *         to provide the CSS context of the rendered content.
+ *     containerElement - {DOMElement} Optional parameter. Insert the HTML to 
+ *         this node instead of the body root when calculating dimensions. 
+ * 
+ * Returns:
+ * {OpenLayers.Size}
+ */
+OpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) {
+    
+    var w, h;
+    
+    // create temp container div with restricted size
+    var container = document.createElement("div");
+    container.style.visibility = "hidden";
+        
+    var containerElement = (options && options.containerElement) 
+    	? options.containerElement : document.body;
+
+    //fix a dimension, if specified.
+    if (size) {
+        if (size.w) {
+            w = size.w;
+            container.style.width = w + "px";
+        } else if (size.h) {
+            h = size.h;
+            container.style.height = h + "px";
+        }
+    }
+
+    //add css classes, if specified
+    if (options && options.displayClass) {
+        container.className = options.displayClass;
+    }
+    
+    // create temp content div and assign content
+    var content = document.createElement("div");
+    content.innerHTML = contentHTML;
+    
+    // we need overflow visible when calculating the size
+    content.style.overflow = "visible";
+    if (content.childNodes) {
+        for (var i=0, l=content.childNodes.length; i<l; i++) {
+            if (!content.childNodes[i].style) continue;
+            content.childNodes[i].style.overflow = "visible";
+        }
+    }
+    
+    // add content to restricted container 
+    container.appendChild(content);
+    
+    // append container to body for rendering
+    containerElement.appendChild(container);
+    
+    // Opera and IE7 can't handle a node with position:aboslute if it inherits
+    // position:absolute from a parent.
+    var parentHasPositionAbsolute = false;
+    var parent = container.parentNode;
+    while (parent && parent.tagName.toLowerCase()!="body") {
+        var parentPosition = OpenLayers.Element.getStyle(parent, "position");
+        if(parentPosition == "absolute") {
+            parentHasPositionAbsolute = true;
+            break;
+        } else if (parentPosition && parentPosition != "static") {
+            break;
+        }
+        parent = parent.parentNode;
+    }
+
+    if(!parentHasPositionAbsolute) {
+        container.style.position = "absolute";
+    }
+    
+    // calculate scroll width of content and add corners and shadow width
+    if (!w) {
+        w = parseInt(content.scrollWidth);
+    
+        // update container width to allow height to adjust
+        container.style.width = w + "px";
+    }        
+    // capture height and add shadow and corner image widths
+    if (!h) {
+        h = parseInt(content.scrollHeight);
+    }
+
+    // remove elements
+    container.removeChild(content);
+    containerElement.removeChild(container);
+    
+    return new OpenLayers.Size(w, h);
+};
+
+/**
+ * APIFunction: getScrollbarWidth
+ * This function has been modified by the OpenLayers from the original version,
+ *     written by Matthew Eernisse and released under the Apache 2 
+ *     license here:
+ * 
+ *     http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
+ * 
+ *     It has been modified simply to cache its value, since it is physically 
+ *     impossible that this code could ever run in more than one browser at 
+ *     once. 
+ * 
+ * Returns:
+ * {Integer}
+ */
+OpenLayers.Util.getScrollbarWidth = function() {
+    
+    var scrollbarWidth = OpenLayers.Util._scrollbarWidth;
+    
+    if (scrollbarWidth == null) {
+        var scr = null;
+        var inn = null;
+        var wNoScroll = 0;
+        var wScroll = 0;
+    
+        // Outer scrolling div
+        scr = document.createElement('div');
+        scr.style.position = 'absolute';
+        scr.style.top = '-1000px';
+        scr.style.left = '-1000px';
+        scr.style.width = '100px';
+        scr.style.height = '50px';
+        // Start with no scrollbar
+        scr.style.overflow = 'hidden';
+    
+        // Inner content div
+        inn = document.createElement('div');
+        inn.style.width = '100%';
+        inn.style.height = '200px';
+    
+        // Put the inner div in the scrolling div
+        scr.appendChild(inn);
+        // Append the scrolling div to the doc
+        document.body.appendChild(scr);
+    
+        // Width of the inner div sans scrollbar
+        wNoScroll = inn.offsetWidth;
+    
+        // Add the scrollbar
+        scr.style.overflow = 'scroll';
+        // Width of the inner div width scrollbar
+        wScroll = inn.offsetWidth;
+    
+        // Remove the scrolling div from the doc
+        document.body.removeChild(document.body.lastChild);
+    
+        // Pixel width of the scroller
+        OpenLayers.Util._scrollbarWidth = (wNoScroll - wScroll);
+        scrollbarWidth = OpenLayers.Util._scrollbarWidth;
+    }
+
+    return scrollbarWidth;
+};
+
+/**
+ * APIFunction: getFormattedLonLat
+ * This function will return latitude or longitude value formatted as 
+ *
+ * Parameters:
+ * coordinate - {Float} the coordinate value to be formatted
+ * axis - {String} value of either 'lat' or 'lon' to indicate which axis is to
+ *          to be formatted (default = lat)
+ * dmsOption - {String} specify the precision of the output can be one of:
+ *           'dms' show degrees minutes and seconds
+ *           'dm' show only degrees and minutes
+ *           'd' show only degrees
+ * 
+ * Returns:
+ * {String} the coordinate value formatted as a string
+ */
+OpenLayers.Util.getFormattedLonLat = function(coordinate, axis, dmsOption) {
+    if (!dmsOption) {
+        dmsOption = 'dms';    //default to show degree, minutes, seconds
+    }
+	
+	coordinate = (coordinate+540)%360 - 180; // normalize for sphere being round
+	
+    var abscoordinate = Math.abs(coordinate);
+    var coordinatedegrees = Math.floor(abscoordinate);
+
+    var coordinateminutes = (abscoordinate - coordinatedegrees)/(1/60);
+    var tempcoordinateminutes = coordinateminutes;
+    coordinateminutes = Math.floor(coordinateminutes);
+    var coordinateseconds = (tempcoordinateminutes - coordinateminutes)/(1/60);
+    coordinateseconds =  Math.round(coordinateseconds*10);
+    coordinateseconds /= 10;
+
+    if( coordinateseconds >= 60) { 
+        coordinateseconds -= 60; 
+        coordinateminutes += 1; 
+        if( coordinateminutes >= 60) { 
+            coordinateminutes -= 60; 
+            coordinatedegrees += 1; 
+        } 
+    }
+    
+    if( coordinatedegrees < 10 ) {
+        coordinatedegrees = "0" + coordinatedegrees;
+    }
+    var str = coordinatedegrees + "\u00B0";
+
+    if (dmsOption.indexOf('dm') >= 0) {
+        if( coordinateminutes < 10 ) {
+            coordinateminutes = "0" + coordinateminutes;
+        }
+        str += coordinateminutes + "'";
+  
+        if (dmsOption.indexOf('dms') >= 0) {
+            if( coordinateseconds < 10 ) {
+                coordinateseconds = "0" + coordinateseconds;
+            }
+            str += coordinateseconds + '"';
+        }
+    }
+    
+    if (axis == "lon") {
+        str += coordinate < 0 ? OpenLayers.i18n("W") : OpenLayers.i18n("E");
+    } else {
+        str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N");
+    }
+    return str;
+};
+
+/* ======================================================================
+    OpenLayers/Format.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Format
+ * Base class for format reading/writing a variety of formats.  Subclasses
+ *     of OpenLayers.Format are expected to have read and write methods.
+ */
+OpenLayers.Format = OpenLayers.Class({
+    
+    /**
+     * Property: options
+     * {Object} A reference to options passed to the constructor.
+     */
+    options: null,
+    
+    /**
+     * APIProperty: externalProjection
+     * {<OpenLayers.Projection>} When passed a externalProjection and
+     *     internalProjection, the format will reproject the geometries it
+     *     reads or writes. The externalProjection is the projection used by
+     *     the content which is passed into read or which comes out of write.
+     *     In order to reproject, a projection transformation function for the
+     *     specified projections must be available. This support may be 
+     *     provided via proj4js or via a custom transformation function. See
+     *     {<OpenLayers.Projection.addTransform>} for more information on
+     *     custom transformations.
+     */
+    externalProjection: null,
+
+    /**
+     * APIProperty: internalProjection
+     * {<OpenLayers.Projection>} When passed a externalProjection and
+     *     internalProjection, the format will reproject the geometries it
+     *     reads or writes. The internalProjection is the projection used by
+     *     the geometries which are returned by read or which are passed into
+     *     write.  In order to reproject, a projection transformation function
+     *     for the specified projections must be available. This support may be
+     *     provided via proj4js or via a custom transformation function. See
+     *     {<OpenLayers.Projection.addTransform>} for more information on
+     *     custom transformations.
+     */
+    internalProjection: null,
+
+    /**
+     * APIProperty: data
+     * {Object} When <keepData> is true, this is the parsed string sent to
+     *     <read>.
+     */
+    data: null,
+
+    /**
+     * APIProperty: keepData
+     * {Object} Maintain a reference (<data>) to the most recently read data.
+     *     Default is false.
+     */
+    keepData: false,
+
+    /**
+     * Constructor: OpenLayers.Format
+     * Instances of this class are not useful.  See one of the subclasses.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           format
+     *
+     * Valid options:
+     * keepData - {Boolean} If true, upon <read>, the data property will be
+     *     set to the parsed object (e.g. the json or xml object).
+     *
+     * Returns:
+     * An instance of OpenLayers.Format
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+        this.options = options;
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up.
+     */
+    destroy: function() {
+    },
+
+    /**
+     * Method: read
+     * Read data from a string, and return an object whose type depends on the
+     * subclass. 
+     * 
+     * Parameters:
+     * data - {string} Data to read/parse.
+     *
+     * Returns:
+     * Depends on the subclass
+     */
+    read: function(data) {
+        OpenLayers.Console.userError(OpenLayers.i18n("readNotImplemented"));
+    },
+    
+    /**
+     * Method: write
+     * Accept an object, and return a string. 
+     *
+     * Parameters:
+     * object - {Object} Object to be serialized
+     *
+     * Returns:
+     * {String} A string representation of the object.
+     */
+    write: function(object) {
+        OpenLayers.Console.userError(OpenLayers.i18n("writeNotImplemented"));
+    },
+
+    CLASS_NAME: "OpenLayers.Format"
+});     
+/* ======================================================================
+    OpenLayers/Format/JSON.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * Note:
+ * This work draws heavily from the public domain JSON serializer/deserializer
+ *     at http://www.json.org/json.js. Rewritten so that it doesn't modify
+ *     basic data prototypes.
+ */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.JSON
+ * A parser to read/write JSON safely.  Create a new instance with the
+ *     <OpenLayers.Format.JSON> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, {
+    
+    /**
+     * APIProperty: indent
+     * {String} For "pretty" printing, the indent string will be used once for
+     *     each indentation level.
+     */
+    indent: "    ",
+    
+    /**
+     * APIProperty: space
+     * {String} For "pretty" printing, the space string will be used after
+     *     the ":" separating a name/value pair.
+     */
+    space: " ",
+    
+    /**
+     * APIProperty: newline
+     * {String} For "pretty" printing, the newline string will be used at the
+     *     end of each name/value pair or array item.
+     */
+    newline: "\n",
+    
+    /**
+     * Property: level
+     * {Integer} For "pretty" printing, this is incremented/decremented during
+     *     serialization.
+     */
+    level: 0,
+
+    /**
+     * Property: pretty
+     * {Boolean} Serialize with extra whitespace for structure.  This is set
+     *     by the <write> method.
+     */
+    pretty: false,
+
+    /**
+     * Property: nativeJSON
+     * {Boolean} Does the browser support native json?
+     */
+    nativeJSON: (function() {
+        return !!(window.JSON && typeof JSON.parse == "function" && typeof JSON.stringify == "function");
+    })(),
+
+    /**
+     * Constructor: OpenLayers.Format.JSON
+     * Create a new parser for JSON.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Deserialize a json string.
+     *
+     * Parameters:
+     * json - {String} A JSON string
+     * filter - {Function} A function which will be called for every key and
+     *     value at every level of the final result. Each value will be
+     *     replaced by the result of the filter function. This can be used to
+     *     reform generic objects into instances of classes, or to transform
+     *     date strings into Date objects.
+     *     
+     * Returns:
+     * {Object} An object, array, string, or number .
+     */
+    read: function(json, filter) {
+        var object;
+        if (this.nativeJSON) {
+            object = JSON.parse(json, filter);
+        } else try {
+            /**
+             * Parsing happens in three stages. In the first stage, we run the
+             *     text against a regular expression which looks for non-JSON
+             *     characters. We are especially concerned with '()' and 'new'
+             *     because they can cause invocation, and '=' because it can
+             *     cause mutation. But just to be safe, we will reject all
+             *     unexpected characters.
+             */
+            if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
+                                replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+                                replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+                /**
+                 * In the second stage we use the eval function to compile the
+                 *     text into a JavaScript structure. The '{' operator is
+                 *     subject to a syntactic ambiguity in JavaScript - it can
+                 *     begin a block or an object literal. We wrap the text in
+                 *     parens to eliminate the ambiguity.
+                 */
+                object = eval('(' + json + ')');
+
+                /**
+                 * In the optional third stage, we recursively walk the new
+                 *     structure, passing each name/value pair to a filter
+                 *     function for possible transformation.
+                 */
+                if(typeof filter === 'function') {
+                    function walk(k, v) {
+                        if(v && typeof v === 'object') {
+                            for(var i in v) {
+                                if(v.hasOwnProperty(i)) {
+                                    v[i] = walk(i, v[i]);
+                                }
+                            }
+                        }
+                        return filter(k, v);
+                    }
+                    object = walk('', object);
+                }
+            }
+        } catch(e) {
+            // Fall through if the regexp test fails.
+        }
+
+        if(this.keepData) {
+            this.data = object;
+        }
+
+        return object;
+    },
+
+    /**
+     * APIMethod: write
+     * Serialize an object into a JSON string.
+     *
+     * Parameters:
+     * value - {String} The object, array, string, number, boolean or date
+     *     to be serialized.
+     * pretty - {Boolean} Structure the output with newlines and indentation.
+     *     Default is false.
+     *
+     * Returns:
+     * {String} The JSON string representation of the input value.
+     */
+    write: function(value, pretty) {
+        this.pretty = !!pretty;
+        var json = null;
+        var type = typeof value;
+        if(this.serialize[type]) {
+            try {
+                json = (!this.pretty && this.nativeJSON) ?
+                    JSON.stringify(value) :
+                    this.serialize[type].apply(this, [value]);
+            } catch(err) {
+                OpenLayers.Console.error("Trouble serializing: " + err);
+            }
+        }
+        return json;
+    },
+    
+    /**
+     * Method: writeIndent
+     * Output an indentation string depending on the indentation level.
+     *
+     * Returns:
+     * {String} An appropriate indentation string.
+     */
+    writeIndent: function() {
+        var pieces = [];
+        if(this.pretty) {
+            for(var i=0; i<this.level; ++i) {
+                pieces.push(this.indent);
+            }
+        }
+        return pieces.join('');
+    },
+    
+    /**
+     * Method: writeNewline
+     * Output a string representing a newline if in pretty printing mode.
+     *
+     * Returns:
+     * {String} A string representing a new line.
+     */
+    writeNewline: function() {
+        return (this.pretty) ? this.newline : '';
+    },
+    
+    /**
+     * Method: writeSpace
+     * Output a string representing a space if in pretty printing mode.
+     *
+     * Returns:
+     * {String} A space.
+     */
+    writeSpace: function() {
+        return (this.pretty) ? this.space : '';
+    },
+
+    /**
+     * Property: serialize
+     * Object with properties corresponding to the serializable data types.
+     *     Property values are functions that do the actual serializing.
+     */
+    serialize: {
+        /**
+         * Method: serialize.object
+         * Transform an object into a JSON string.
+         *
+         * Parameters:
+         * object - {Object} The object to be serialized.
+         * 
+         * Returns:
+         * {String} A JSON string representing the object.
+         */
+        'object': function(object) {
+            // three special objects that we want to treat differently
+            if(object == null) {
+                return "null";
+            }
+            if(object.constructor == Date) {
+                return this.serialize.date.apply(this, [object]);
+            }
+            if(object.constructor == Array) {
+                return this.serialize.array.apply(this, [object]);
+            }
+            var pieces = ['{'];
+            this.level += 1;
+            var key, keyJSON, valueJSON;
+            
+            var addComma = false;
+            for(key in object) {
+                if(object.hasOwnProperty(key)) {
+                    // recursive calls need to allow for sub-classing
+                    keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+                                                    [key, this.pretty]);
+                    valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+                                                    [object[key], this.pretty]);
+                    if(keyJSON != null && valueJSON != null) {
+                        if(addComma) {
+                            pieces.push(',');
+                        }
+                        pieces.push(this.writeNewline(), this.writeIndent(),
+                                    keyJSON, ':', this.writeSpace(), valueJSON);
+                        addComma = true;
+                    }
+                }
+            }
+            
+            this.level -= 1;
+            pieces.push(this.writeNewline(), this.writeIndent(), '}');
+            return pieces.join('');
+        },
+        
+        /**
+         * Method: serialize.array
+         * Transform an array into a JSON string.
+         *
+         * Parameters:
+         * array - {Array} The array to be serialized
+         * 
+         * Returns:
+         * {String} A JSON string representing the array.
+         */
+        'array': function(array) {
+            var json;
+            var pieces = ['['];
+            this.level += 1;
+    
+            for(var i=0, len=array.length; i<len; ++i) {
+                // recursive calls need to allow for sub-classing
+                json = OpenLayers.Format.JSON.prototype.write.apply(this,
+                                                    [array[i], this.pretty]);
+                if(json != null) {
+                    if(i > 0) {
+                        pieces.push(',');
+                    }
+                    pieces.push(this.writeNewline(), this.writeIndent(), json);
+                }
+            }
+
+            this.level -= 1;    
+            pieces.push(this.writeNewline(), this.writeIndent(), ']');
+            return pieces.join('');
+        },
+        
+        /**
+         * Method: serialize.string
+         * Transform a string into a JSON string.
+         *
+         * Parameters:
+         * string - {String} The string to be serialized
+         * 
+         * Returns:
+         * {String} A JSON string representing the string.
+         */
+        'string': function(string) {
+            // If the string contains no control characters, no quote characters, and no
+            // backslash characters, then we can simply slap some quotes around it.
+            // Otherwise we must also replace the offending characters with safe
+            // sequences.    
+            var m = {
+                '\b': '\\b',
+                '\t': '\\t',
+                '\n': '\\n',
+                '\f': '\\f',
+                '\r': '\\r',
+                '"' : '\\"',
+                '\\': '\\\\'
+            };
+            if(/["\\\x00-\x1f]/.test(string)) {
+                return '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                    var c = m[b];
+                    if(c) {
+                        return c;
+                    }
+                    c = b.charCodeAt();
+                    return '\\u00' +
+                        Math.floor(c / 16).toString(16) +
+                        (c % 16).toString(16);
+                }) + '"';
+            }
+            return '"' + string + '"';
+        },
+
+        /**
+         * Method: serialize.number
+         * Transform a number into a JSON string.
+         *
+         * Parameters:
+         * number - {Number} The number to be serialized.
+         *
+         * Returns:
+         * {String} A JSON string representing the number.
+         */
+        'number': function(number) {
+            return isFinite(number) ? String(number) : "null";
+        },
+        
+        /**
+         * Method: serialize.boolean
+         * Transform a boolean into a JSON string.
+         *
+         * Parameters:
+         * bool - {Boolean} The boolean to be serialized.
+         * 
+         * Returns:
+         * {String} A JSON string representing the boolean.
+         */
+        'boolean': function(bool) {
+            return String(bool);
+        },
+        
+        /**
+         * Method: serialize.object
+         * Transform a date into a JSON string.
+         *
+         * Parameters:
+         * date - {Date} The date to be serialized.
+         * 
+         * Returns:
+         * {String} A JSON string representing the date.
+         */
+        'date': function(date) {    
+            function format(number) {
+                // Format integers to have at least two digits.
+                return (number < 10) ? '0' + number : number;
+            }
+            return '"' + date.getFullYear() + '-' +
+                    format(date.getMonth() + 1) + '-' +
+                    format(date.getDate()) + 'T' +
+                    format(date.getHours()) + ':' +
+                    format(date.getMinutes()) + ':' +
+                    format(date.getSeconds()) + '"';
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.JSON" 
+
+});     
+/* ======================================================================
+    OpenLayers/Feature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Class: OpenLayers.Feature
+ * Features are combinations of geography and attributes. The OpenLayers.Feature
+ *     class specifically combines a marker and a lonlat.
+ */
+OpenLayers.Feature = OpenLayers.Class({
+
+    /** 
+     * Property: layer 
+     * {<OpenLayers.Layer>} 
+     */
+    layer: null,
+
+    /** 
+     * Property: id 
+     * {String} 
+     */
+    id: null,
+    
+    /** 
+     * Property: lonlat 
+     * {<OpenLayers.LonLat>} 
+     */
+    lonlat: null,
+
+    /** 
+     * Property: data 
+     * {Object} 
+     */
+    data: null,
+
+    /** 
+     * Property: marker 
+     * {<OpenLayers.Marker>} 
+     */
+    marker: null,
+
+    /**
+     * APIProperty: popupClass
+     * {<OpenLayers.Class>} The class which will be used to instantiate
+     *     a new Popup. Default is <OpenLayers.Popup.AnchoredBubble>.
+     */
+    popupClass: null,
+
+    /** 
+     * Property: popup 
+     * {<OpenLayers.Popup>} 
+     */
+    popup: null,
+
+    /** 
+     * Constructor: OpenLayers.Feature
+     * Constructor for features.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} 
+     * lonlat - {<OpenLayers.LonLat>} 
+     * data - {Object} 
+     * 
+     * Returns:
+     * {<OpenLayers.Feature>}
+     */
+    initialize: function(layer, lonlat, data) {
+        this.layer = layer;
+        this.lonlat = lonlat;
+        this.data = (data != null) ? data : {};
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); 
+    },
+
+    /** 
+     * Method: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+
+        //remove the popup from the map
+        if ((this.layer != null) && (this.layer.map != null)) {
+            if (this.popup != null) {
+                this.layer.map.removePopup(this.popup);
+            }
+        }
+        // remove the marker from the layer
+        if (this.layer != null && this.marker != null) {
+            this.layer.removeMarker(this.marker);
+        }
+
+        this.layer = null;
+        this.id = null;
+        this.lonlat = null;
+        this.data = null;
+        if (this.marker != null) {
+            this.destroyMarker(this.marker);
+            this.marker = null;
+        }
+        if (this.popup != null) {
+            this.destroyPopup(this.popup);
+            this.popup = null;
+        }
+    },
+    
+    /**
+     * Method: onScreen
+     * 
+     * Returns:
+     * {Boolean} Whether or not the feature is currently visible on screen
+     *           (based on its 'lonlat' property)
+     */
+    onScreen:function() {
+        
+        var onScreen = false;
+        if ((this.layer != null) && (this.layer.map != null)) {
+            var screenBounds = this.layer.map.getExtent();
+            onScreen = screenBounds.containsLonLat(this.lonlat);
+        }    
+        return onScreen;
+    },
+    
+
+    /**
+     * Method: createMarker
+     * Based on the data associated with the Feature, create and return a marker object.
+     *
+     * Returns: 
+     * {<OpenLayers.Marker>} A Marker Object created from the 'lonlat' and 'icon' properties
+     *          set in this.data. If no 'lonlat' is set, returns null. If no
+     *          'icon' is set, OpenLayers.Marker() will load the default image.
+     *          
+     *          Note - this.marker is set to return value
+     * 
+     */
+    createMarker: function() {
+
+        if (this.lonlat != null) {
+            this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon);
+        }
+        return this.marker;
+    },
+
+    /**
+     * Method: destroyMarker
+     * Destroys marker.
+     * If user overrides the createMarker() function, s/he should be able
+     *   to also specify an alternative function for destroying it
+     */
+    destroyMarker: function() {
+        this.marker.destroy();  
+    },
+
+    /**
+     * Method: createPopup
+     * Creates a popup object created from the 'lonlat', 'popupSize',
+     *     and 'popupContentHTML' properties set in this.data. It uses
+     *     this.marker.icon as default anchor. 
+     *  
+     *  If no 'lonlat' is set, returns null. 
+     *  If no this.marker has been created, no anchor is sent.
+     *
+     *  Note - the returned popup object is 'owned' by the feature, so you
+     *      cannot use the popup's destroy method to discard the popup.
+     *      Instead, you must use the feature's destroyPopup
+     * 
+     *  Note - this.popup is set to return value
+     * 
+     * Parameters: 
+     * closeBox - {Boolean} create popup with closebox or not
+     * 
+     * Returns:
+     * {<OpenLayers.Popup>} Returns the created popup, which is also set
+     *     as 'popup' property of this feature. Will be of whatever type
+     *     specified by this feature's 'popupClass' property, but must be
+     *     of type <OpenLayers.Popup>.
+     * 
+     */
+    createPopup: function(closeBox) {
+
+        if (this.lonlat != null) {
+            if (!this.popup) {
+                var anchor = (this.marker) ? this.marker.icon : null;
+                var popupClass = this.popupClass ? 
+                    this.popupClass : OpenLayers.Popup.AnchoredBubble;
+                this.popup = new popupClass(this.id + "_popup", 
+                                            this.lonlat,
+                                            this.data.popupSize,
+                                            this.data.popupContentHTML,
+                                            anchor, 
+                                            closeBox); 
+            }    
+            if (this.data.overflow != null) {
+                this.popup.contentDiv.style.overflow = this.data.overflow;
+            }    
+            
+            this.popup.feature = this;
+        }        
+        return this.popup;
+    },
+
+    
+    /**
+     * Method: destroyPopup
+     * Destroys the popup created via createPopup.
+     *
+     * As with the marker, if user overrides the createPopup() function, s/he 
+     *   should also be able to override the destruction
+     */
+    destroyPopup: function() {
+        if (this.popup) {
+            this.popup.feature = null;
+            this.popup.destroy();
+            this.popup = null;
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Feature"
+});
+/* ======================================================================
+    OpenLayers/Feature/Vector.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+// TRASH THIS
+OpenLayers.State = {
+    /** states */
+    UNKNOWN: 'Unknown',
+    INSERT: 'Insert',
+    UPDATE: 'Update',
+    DELETE: 'Delete'
+};
+
+/**
+ * @requires OpenLayers/Feature.js
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Class: OpenLayers.Feature.Vector
+ * Vector features use the OpenLayers.Geometry classes as geometry description.
+ * They have an 'attributes' property, which is the data object, and a 'style'
+ * property, the default values of which are defined in the 
+ * <OpenLayers.Feature.Vector.style> objects.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Feature>
+ */
+OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {
+
+    /** 
+     * Property: fid 
+     * {String} 
+     */
+    fid: null,
+    
+    /** 
+     * APIProperty: geometry 
+     * {<OpenLayers.Geometry>} 
+     */
+    geometry: null,
+
+    /** 
+     * APIProperty: attributes 
+     * {Object} This object holds arbitrary, serializable properties that
+     *     describe the feature.
+     */
+    attributes: null,
+
+    /**
+     * Property: bounds
+     * {<OpenLayers.Bounds>} The box bounding that feature's geometry, that
+     *     property can be set by an <OpenLayers.Format> object when
+     *     deserializing the feature, so in most cases it represents an
+     *     information set by the server. 
+     */
+    bounds: null,
+
+    /** 
+     * Property: state 
+     * {String} 
+     */
+    state: null,
+    
+    /** 
+     * APIProperty: style 
+     * {Object} 
+     */
+    style: null,
+
+    /**
+     * APIProperty: url
+     * {String} If this property is set it will be taken into account by
+     *     {<OpenLayers.HTTP>} when upadting or deleting the feature.
+     */
+    url: null,
+    
+    /**
+     * Property: renderIntent
+     * {String} rendering intent currently being used
+     */
+    renderIntent: "default",
+    
+    /**
+     * APIProperty: modified
+     * {Object} An object with the originals of the geometry and attributes of
+     * the feature, if they were changed. Currently this property is only read
+     * by <OpenLayers.Format.WFST.v1>, and written by
+     * <OpenLayers.Control.ModifyFeature>, which sets the geometry property.
+     * Applications can set the originals of modified attributes in the
+     * attributes property. Note that applications have to check if this
+     * object and the attributes property is already created before using it.
+     * After a change made with ModifyFeature, this object could look like
+     *
+     * (code)
+     * {
+     *     geometry: >Object
+     * }
+     * (end)
+     *
+     * When an application has made changes to feature attributes, it could
+     * have set the attributes to something like this:
+     *
+     * (code)
+     * {
+     *     attributes: {
+     *         myAttribute: "original"
+     *     }
+     * }
+     * (end)
+     *
+     * Note that <OpenLayers.Format.WFST.v1> only checks for truthy values in
+     * *modified.geometry* and the attribute names in *modified.attributes*,
+     * but it is recommended to set the original values (and not just true) as
+     * attribute value, so applications could use this information to undo
+     * changes.
+     */
+    modified: null,
+
+    /** 
+     * Constructor: OpenLayers.Feature.Vector
+     * Create a vector feature. 
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The geometry that this feature
+     *     represents.
+     * attributes - {Object} An optional object that will be mapped to the
+     *     <attributes> property. 
+     * style - {Object} An optional style object.
+     */
+    initialize: function(geometry, attributes, style) {
+        OpenLayers.Feature.prototype.initialize.apply(this,
+                                                      [null, null, attributes]);
+        this.lonlat = null;
+        this.geometry = geometry ? geometry : null;
+        this.state = null;
+        this.attributes = {};
+        if (attributes) {
+            this.attributes = OpenLayers.Util.extend(this.attributes,
+                                                     attributes);
+        }
+        this.style = style ? style : null; 
+    },
+    
+    /** 
+     * Method: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        if (this.layer) {
+            this.layer.removeFeatures(this);
+            this.layer = null;
+        }
+            
+        this.geometry = null;
+        this.modified = null;
+        OpenLayers.Feature.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: clone
+     * Create a clone of this vector feature.  Does not set any non-standard
+     *     properties.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} An exact clone of this vector feature.
+     */
+    clone: function () {
+        return new OpenLayers.Feature.Vector(
+            this.geometry ? this.geometry.clone() : null,
+            this.attributes,
+            this.style);
+    },
+
+    /**
+     * Method: onScreen
+     * Determine whether the feature is within the map viewport.  This method
+     *     tests for an intersection between the geometry and the viewport
+     *     bounds.  If a more effecient but less precise geometry bounds
+     *     intersection is desired, call the method with the boundsOnly
+     *     parameter true.
+     *
+     * Parameters:
+     * boundsOnly - {Boolean} Only test whether a feature's bounds intersects
+     *     the viewport bounds.  Default is false.  If false, the feature's
+     *     geometry must intersect the viewport for onScreen to return true.
+     * 
+     * Returns:
+     * {Boolean} The feature is currently visible on screen (optionally
+     *     based on its bounds if boundsOnly is true).
+     */
+    onScreen:function(boundsOnly) {
+        var onScreen = false;
+        if(this.layer && this.layer.map) {
+            var screenBounds = this.layer.map.getExtent();
+            if(boundsOnly) {
+                var featureBounds = this.geometry.getBounds();
+                onScreen = screenBounds.intersectsBounds(featureBounds);
+            } else {
+                var screenPoly = screenBounds.toGeometry();
+                onScreen = screenPoly.intersects(this.geometry);
+            }
+        }    
+        return onScreen;
+    },
+
+    /**
+     * Method: getVisibility
+     * Determine whether the feature is displayed or not. It may not displayed
+     *     because:
+     *     - its style display property is set to 'none',
+     *     - it doesn't belong to any layer,
+     *     - the styleMap creates a symbolizer with display property set to 'none'
+     *          for it,
+     *     - the layer which it belongs to is not visible.
+     * 
+     * Returns:
+     * {Boolean} The feature is currently displayed.
+     */
+    getVisibility: function() {
+        return !(this.style && this.style.display == 'none' ||
+                 !this.layer ||
+                 this.layer && this.layer.styleMap &&
+                 this.layer.styleMap.createSymbolizer(this, this.renderIntent).display == 'none' ||
+                 this.layer && !this.layer.getVisibility());
+    },
+    
+    /**
+     * Method: createMarker
+     * HACK - we need to decide if all vector features should be able to
+     *     create markers
+     * 
+     * Returns:
+     * {<OpenLayers.Marker>} For now just returns null
+     */
+    createMarker: function() {
+        return null;
+    },
+
+    /**
+     * Method: destroyMarker
+     * HACK - we need to decide if all vector features should be able to
+     *     delete markers
+     * 
+     * If user overrides the createMarker() function, s/he should be able
+     *   to also specify an alternative function for destroying it
+     */
+    destroyMarker: function() {
+        // pass
+    },
+
+    /**
+     * Method: createPopup
+     * HACK - we need to decide if all vector features should be able to
+     *     create popups
+     * 
+     * Returns:
+     * {<OpenLayers.Popup>} For now just returns null
+     */
+    createPopup: function() {
+        return null;
+    },
+
+    /**
+     * Method: atPoint
+     * Determins whether the feature intersects with the specified location.
+     * 
+     * Parameters: 
+     * lonlat - {<OpenLayers.LonLat>} 
+     * toleranceLon - {float} Optional tolerance in Geometric Coords
+     * toleranceLat - {float} Optional tolerance in Geographic Coords
+     * 
+     * Returns:
+     * {Boolean} Whether or not the feature is at the specified location
+     */
+    atPoint: function(lonlat, toleranceLon, toleranceLat) {
+        var atPoint = false;
+        if(this.geometry) {
+            atPoint = this.geometry.atPoint(lonlat, toleranceLon, 
+                                                    toleranceLat);
+        }
+        return atPoint;
+    },
+
+    /**
+     * Method: destroyPopup
+     * HACK - we need to decide if all vector features should be able to
+     * delete popups
+     */
+    destroyPopup: function() {
+        // pass
+    },
+
+    /**
+     * Method: move
+     * Moves the feature and redraws it at its new location
+     *
+     * Parameters:
+     * state - {OpenLayers.LonLat or OpenLayers.Pixel} the
+     *         location to which to move the feature.
+     */
+    move: function(location) {
+
+        if(!this.layer || !this.geometry.move){
+            //do nothing if no layer or immoveable geometry
+            return undefined;
+        }
+
+        var pixel;
+        if (location.CLASS_NAME == "OpenLayers.LonLat") {
+            pixel = this.layer.getViewPortPxFromLonLat(location);
+        } else {
+            pixel = location;
+        }
+        
+        var lastPixel = this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());
+        var res = this.layer.map.getResolution();
+        this.geometry.move(res * (pixel.x - lastPixel.x),
+                           res * (lastPixel.y - pixel.y));
+        this.layer.drawFeature(this);
+        return lastPixel;
+    },
+    
+    /**
+     * Method: toState
+     * Sets the new state
+     *
+     * Parameters:
+     * state - {String} 
+     */
+    toState: function(state) {
+        if (state == OpenLayers.State.UPDATE) {
+            switch (this.state) {
+                case OpenLayers.State.UNKNOWN:
+                case OpenLayers.State.DELETE:
+                    this.state = state;
+                    break;
+                case OpenLayers.State.UPDATE:
+                case OpenLayers.State.INSERT:
+                    break;
+            }
+        } else if (state == OpenLayers.State.INSERT) {
+            switch (this.state) {
+                case OpenLayers.State.UNKNOWN:
+                    break;
+                default:
+                    this.state = state;
+                    break;
+            }
+        } else if (state == OpenLayers.State.DELETE) {
+            switch (this.state) {
+                case OpenLayers.State.INSERT:
+                    // the feature should be destroyed
+                    break;
+                case OpenLayers.State.DELETE:
+                    break;
+                case OpenLayers.State.UNKNOWN:
+                case OpenLayers.State.UPDATE:
+                    this.state = state;
+                    break;
+            }
+        } else if (state == OpenLayers.State.UNKNOWN) {
+            this.state = state;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Feature.Vector"
+});
+
+
+/**
+ * Constant: OpenLayers.Feature.Vector.style
+ * OpenLayers features can have a number of style attributes. The 'default' 
+ *     style will typically be used if no other style is specified. These
+ *     styles correspond for the most part, to the styling properties defined
+ *     by the SVG standard. 
+ *     Information on fill properties: http://www.w3.org/TR/SVG/painting.html#FillProperties
+ *     Information on stroke properties: http://www.w3.org/TR/SVG/painting.html#StrokeProperties
+ *
+ * Symbolizer properties:
+ * fill - {Boolean} Set to false if no fill is desired.
+ * fillColor - {String} Hex fill color.  Default is "#ee9900".
+ * fillOpacity - {Number} Fill opacity (0-1).  Default is 0.4 
+ * stroke - {Boolean} Set to false if no stroke is desired.
+ * strokeColor - {String} Hex stroke color.  Default is "#ee9900".
+ * strokeOpacity - {Number} Stroke opacity (0-1).  Default is 1.
+ * strokeWidth - {Number} Pixel stroke width.  Default is 1.
+ * strokeLinecap - {String} Stroke cap type.  Default is "round".  [butt | round | square]
+ * strokeDashstyle - {String} Stroke dash style.  Default is "solid". [dot | dash | dashdot | longdash | longdashdot | solid]
+ * graphic - {Boolean} Set to false if no graphic is desired.
+ * pointRadius - {Number} Pixel point radius.  Default is 6.
+ * pointerEvents - {String}  Default is "visiblePainted".
+ * cursor - {String} Default is "".
+ * externalGraphic - {String} Url to an external graphic that will be used for rendering points.
+ * graphicWidth - {Number} Pixel width for sizing an external graphic.
+ * graphicHeight - {Number} Pixel height for sizing an external graphic.
+ * graphicOpacity - {Number} Opacity (0-1) for an external graphic.
+ * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic.
+ * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic.
+ * rotation - {Number} For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point (or any point off center as specified by graphicXOffset and graphicYOffset).
+ * graphicZIndex - {Number} The integer z-index value to use in rendering.
+ * graphicName - {String} Named graphic to use when rendering points.  Supported values include "circle" (default),
+ *     "square", "star", "x", "cross", "triangle".
+ * graphicTitle - {String} Tooltip for an external graphic.
+ * backgroundGraphic - {String} Url to a graphic to be used as the background under an externalGraphic.
+ * backgroundGraphicZIndex - {Number} The integer z-index value to use in rendering the background graphic.
+ * backgroundXOffset - {Number} The x offset (in pixels) for the background graphic.
+ * backgroundYOffset - {Number} The y offset (in pixels) for the background graphic.
+ * backgroundHeight - {Number} The height of the background graphic.  If not provided, the graphicHeight will be used.
+ * backgroundWidth - {Number} The width of the background width.  If not provided, the graphicWidth will be used.
+ * label - {String} The text for an optional label. For browsers that use the canvas renderer, this requires either
+ *     fillText or mozDrawText to be available.
+ * labelAlign - {String} Label alignment. This specifies the insertion point relative to the text. It is a string
+ *     composed of two characters. The first character is for the horizontal alignment, the second for the vertical
+ *     alignment. Valid values for horizontal alignment: "l"=left, "c"=center, "r"=right. Valid values for vertical
+ *     alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb".
+ * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label. Not supported by the canvas renderer.
+ * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label. Not supported by the canvas renderer.
+ * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls.
+ *     Default is false.
+ * fontColor - {String} The font color for the label, to be provided like CSS.
+ * fontOpacity - {Number} Opacity (0-1) for the label
+ * fontFamily - {String} The font family for the label, to be provided like in CSS.
+ * fontSize - {String} The font size for the label, to be provided like in CSS.
+ * fontStyle - {String} The font style for the label, to be provided like in CSS.
+ * fontWeight - {String} The font weight for the label, to be provided like in CSS.
+ * display - {String} Symbolizers will have no effect if display is set to "none".  All other values have no effect.
+ */ 
+OpenLayers.Feature.Vector.style = {
+    'default': {
+        fillColor: "#ee9900",
+        fillOpacity: 0.4, 
+        hoverFillColor: "white",
+        hoverFillOpacity: 0.8,
+        strokeColor: "#ee9900",
+        strokeOpacity: 1,
+        strokeWidth: 1,
+        strokeLinecap: "round",
+        strokeDashstyle: "solid",
+        hoverStrokeColor: "red",
+        hoverStrokeOpacity: 1,
+        hoverStrokeWidth: 0.2,
+        pointRadius: 6,
+        hoverPointRadius: 1,
+        hoverPointUnit: "%",
+        pointerEvents: "visiblePainted",
+        cursor: "inherit"
+    },
+    'select': {
+        fillColor: "blue",
+        fillOpacity: 0.4, 
+        hoverFillColor: "white",
+        hoverFillOpacity: 0.8,
+        strokeColor: "blue",
+        strokeOpacity: 1,
+        strokeWidth: 2,
+        strokeLinecap: "round",
+        strokeDashstyle: "solid",
+        hoverStrokeColor: "red",
+        hoverStrokeOpacity: 1,
+        hoverStrokeWidth: 0.2,
+        pointRadius: 6,
+        hoverPointRadius: 1,
+        hoverPointUnit: "%",
+        pointerEvents: "visiblePainted",
+        cursor: "pointer"
+    },
+    'temporary': {
+        fillColor: "#66cccc",
+        fillOpacity: 0.2, 
+        hoverFillColor: "white",
+        hoverFillOpacity: 0.8,
+        strokeColor: "#66cccc",
+        strokeOpacity: 1,
+        strokeLinecap: "round",
+        strokeWidth: 2,
+        strokeDashstyle: "solid",
+        hoverStrokeColor: "red",
+        hoverStrokeOpacity: 1,
+        hoverStrokeWidth: 0.2,
+        pointRadius: 6,
+        hoverPointRadius: 1,
+        hoverPointUnit: "%",
+        pointerEvents: "visiblePainted",
+        cursor: "inherit"
+    },
+    'delete': {
+        display: "none"
+    }
+};    
+/* ======================================================================
+    OpenLayers/Format/WKT.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WKT
+ * Class for reading and writing Well-Known Text.  Create a new instance
+ * with the <OpenLayers.Format.WKT> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {
+    
+    /**
+     * Constructor: OpenLayers.Format.WKT
+     * Create a new parser for WKT
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *           this instance
+     *
+     * Returns:
+     * {<OpenLayers.Format.WKT>} A new WKT parser.
+     */
+    initialize: function(options) {
+        this.regExes = {
+            'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
+            'spaces': /\s+/,
+            'parenComma': /\)\s*,\s*\(/,
+            'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/,  // can't use {2} here
+            'trimParens': /^\s*\(?(.*?)\)?\s*$/
+        };
+        OpenLayers.Format.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Method: read
+     * Deserialize a WKT string and return a vector feature or an
+     * array of vector features.  Supports WKT for POINT, MULTIPOINT,
+     * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
+     * GEOMETRYCOLLECTION.
+     *
+     * Parameters:
+     * wkt - {String} A WKT string
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>|Array} A feature or array of features for
+     * GEOMETRYCOLLECTION WKT.
+     */
+    read: function(wkt) {
+        var features, type, str;
+        wkt = wkt.replace(/[\n\r]/g, " ");
+        var matches = this.regExes.typeStr.exec(wkt);
+        if(matches) {
+            type = matches[1].toLowerCase();
+            str = matches[2];
+            if(this.parse[type]) {
+                features = this.parse[type].apply(this, [str]);
+            }
+            if (this.internalProjection && this.externalProjection) {
+                if (features && 
+                    features.CLASS_NAME == "OpenLayers.Feature.Vector") {
+                    features.geometry.transform(this.externalProjection,
+                                                this.internalProjection);
+                } else if (features &&
+                           type != "geometrycollection" &&
+                           typeof features == "object") {
+                    for (var i=0, len=features.length; i<len; i++) {
+                        var component = features[i];
+                        component.geometry.transform(this.externalProjection,
+                                                     this.internalProjection);
+                    }
+                }
+            }
+        }    
+        return features;
+    },
+
+    /**
+     * Method: write
+     * Serialize a feature or array of features into a WKT string.
+     *
+     * Parameters:
+     * features - {<OpenLayers.Feature.Vector>|Array} A feature or array of
+     *            features
+     *
+     * Returns:
+     * {String} The WKT string representation of the input geometries
+     */
+    write: function(features) {
+        var collection, geometry, type, data, isCollection;
+        if (features.constructor == Array) {
+            collection = features;
+            isCollection = true;
+        } else {
+            collection = [features];
+            isCollection = false;
+        }
+        var pieces = [];
+        if (isCollection) {
+            pieces.push('GEOMETRYCOLLECTION(');
+        }
+        for (var i=0, len=collection.length; i<len; ++i) {
+            if (isCollection && i>0) {
+                pieces.push(',');
+            }
+            geometry = collection[i].geometry;
+            pieces.push(this.extractGeometry(geometry));
+        }
+        if (isCollection) {
+            pieces.push(')');
+        }
+        return pieces.join('');
+    },
+
+    /**
+     * Method: extractGeometry
+     * Entry point to construct the WKT for a single Geometry object.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry.Geometry>}
+     *
+     * Returns:
+     * {String} A WKT string of representing the geometry
+     */
+    extractGeometry: function(geometry) {
+        var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
+        if (!this.extract[type]) {
+            return null;
+        }
+        if (this.internalProjection && this.externalProjection) {
+            geometry = geometry.clone();
+            geometry.transform(this.internalProjection, this.externalProjection);
+        }                       
+        var wktType = type == 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase();
+        var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')';
+        return data;
+    },
+    
+    /**
+     * Object with properties corresponding to the geometry types.
+     * Property values are functions that do the actual data extraction.
+     */
+    extract: {
+        /**
+         * Return a space delimited string of point coordinates.
+         * @param {<OpenLayers.Geometry.Point>} point
+         * @returns {String} A string of coordinates representing the point
+         */
+        'point': function(point) {
+            return point.x + ' ' + point.y;
+        },
+
+        /**
+         * Return a comma delimited string of point coordinates from a multipoint.
+         * @param {<OpenLayers.Geometry.MultiPoint>} multipoint
+         * @returns {String} A string of point coordinate strings representing
+         *                  the multipoint
+         */
+        'multipoint': function(multipoint) {
+            var array = [];
+            for(var i=0, len=multipoint.components.length; i<len; ++i) {
+                array.push('(' +
+                           this.extract.point.apply(this, [multipoint.components[i]]) +
+                           ')');
+            }
+            return array.join(',');
+        },
+        
+        /**
+         * Return a comma delimited string of point coordinates from a line.
+         * @param {<OpenLayers.Geometry.LineString>} linestring
+         * @returns {String} A string of point coordinate strings representing
+         *                  the linestring
+         */
+        'linestring': function(linestring) {
+            var array = [];
+            for(var i=0, len=linestring.components.length; i<len; ++i) {
+                array.push(this.extract.point.apply(this, [linestring.components[i]]));
+            }
+            return array.join(',');
+        },
+
+        /**
+         * Return a comma delimited string of linestring strings from a multilinestring.
+         * @param {<OpenLayers.Geometry.MultiLineString>} multilinestring
+         * @returns {String} A string of of linestring strings representing
+         *                  the multilinestring
+         */
+        'multilinestring': function(multilinestring) {
+            var array = [];
+            for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+                array.push('(' +
+                           this.extract.linestring.apply(this, [multilinestring.components[i]]) +
+                           ')');
+            }
+            return array.join(',');
+        },
+        
+        /**
+         * Return a comma delimited string of linear ring arrays from a polygon.
+         * @param {<OpenLayers.Geometry.Polygon>} polygon
+         * @returns {String} An array of linear ring arrays representing the polygon
+         */
+        'polygon': function(polygon) {
+            var array = [];
+            for(var i=0, len=polygon.components.length; i<len; ++i) {
+                array.push('(' +
+                           this.extract.linestring.apply(this, [polygon.components[i]]) +
+                           ')');
+            }
+            return array.join(',');
+        },
+
+        /**
+         * Return an array of polygon arrays from a multipolygon.
+         * @param {<OpenLayers.Geometry.MultiPolygon>} multipolygon
+         * @returns {String} An array of polygon arrays representing
+         *                  the multipolygon
+         */
+        'multipolygon': function(multipolygon) {
+            var array = [];
+            for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+                array.push('(' +
+                           this.extract.polygon.apply(this, [multipolygon.components[i]]) +
+                           ')');
+            }
+            return array.join(',');
+        },
+
+        /**
+         * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an <OpenLayers.Geometry.Collection>
+         * @param {<OpenLayers.Geometry.Collection>} collection
+         * @returns {String} internal WKT representation of the collection
+         */
+        'collection': function(collection) {
+            var array = [];
+            for(var i=0, len=collection.components.length; i<len; ++i) {
+                array.push(this.extractGeometry.apply(this, [collection.components[i]]));
+            }
+            return array.join(',');
+        }
+
+    },
+
+    /**
+     * Object with properties corresponding to the geometry types.
+     * Property values are functions that do the actual parsing.
+     */
+    parse: {
+        /**
+         * Return point feature given a point WKT fragment.
+         * @param {String} str A WKT fragment representing the point
+         * @returns {<OpenLayers.Feature.Vector>} A point feature
+         * @private
+         */
+        'point': function(str) {
+            var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Point(coords[0], coords[1])
+            );
+        },
+
+        /**
+         * Return a multipoint feature given a multipoint WKT fragment.
+         * @param {String} A WKT fragment representing the multipoint
+         * @returns {<OpenLayers.Feature.Vector>} A multipoint feature
+         * @private
+         */
+        'multipoint': function(str) {
+            var point;
+            var points = OpenLayers.String.trim(str).split(',');
+            var components = [];
+            for(var i=0, len=points.length; i<len; ++i) {
+                point = points[i].replace(this.regExes.trimParens, '$1');
+                components.push(this.parse.point.apply(this, [point]).geometry);
+            }
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiPoint(components)
+            );
+        },
+        
+        /**
+         * Return a linestring feature given a linestring WKT fragment.
+         * @param {String} A WKT fragment representing the linestring
+         * @returns {<OpenLayers.Feature.Vector>} A linestring feature
+         * @private
+         */
+        'linestring': function(str) {
+            var points = OpenLayers.String.trim(str).split(',');
+            var components = [];
+            for(var i=0, len=points.length; i<len; ++i) {
+                components.push(this.parse.point.apply(this, [points[i]]).geometry);
+            }
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.LineString(components)
+            );
+        },
+
+        /**
+         * Return a multilinestring feature given a multilinestring WKT fragment.
+         * @param {String} A WKT fragment representing the multilinestring
+         * @returns {<OpenLayers.Feature.Vector>} A multilinestring feature
+         * @private
+         */
+        'multilinestring': function(str) {
+            var line;
+            var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
+            var components = [];
+            for(var i=0, len=lines.length; i<len; ++i) {
+                line = lines[i].replace(this.regExes.trimParens, '$1');
+                components.push(this.parse.linestring.apply(this, [line]).geometry);
+            }
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiLineString(components)
+            );
+        },
+        
+        /**
+         * Return a polygon feature given a polygon WKT fragment.
+         * @param {String} A WKT fragment representing the polygon
+         * @returns {<OpenLayers.Feature.Vector>} A polygon feature
+         * @private
+         */
+        'polygon': function(str) {
+            var ring, linestring, linearring;
+            var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
+            var components = [];
+            for(var i=0, len=rings.length; i<len; ++i) {
+                ring = rings[i].replace(this.regExes.trimParens, '$1');
+                linestring = this.parse.linestring.apply(this, [ring]).geometry;
+                linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
+                components.push(linearring);
+            }
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Polygon(components)
+            );
+        },
+
+        /**
+         * Return a multipolygon feature given a multipolygon WKT fragment.
+         * @param {String} A WKT fragment representing the multipolygon
+         * @returns {<OpenLayers.Feature.Vector>} A multipolygon feature
+         * @private
+         */
+        'multipolygon': function(str) {
+            var polygon;
+            var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
+            var components = [];
+            for(var i=0, len=polygons.length; i<len; ++i) {
+                polygon = polygons[i].replace(this.regExes.trimParens, '$1');
+                components.push(this.parse.polygon.apply(this, [polygon]).geometry);
+            }
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiPolygon(components)
+            );
+        },
+
+        /**
+         * Return an array of features given a geometrycollection WKT fragment.
+         * @param {String} A WKT fragment representing the geometrycollection
+         * @returns {Array} An array of OpenLayers.Feature.Vector
+         * @private
+         */
+        'geometrycollection': function(str) {
+            // separate components of the collection with |
+            str = str.replace(/,\s*([A-Za-z])/g, '|$1');
+            var wktArray = OpenLayers.String.trim(str).split('|');
+            var components = [];
+            for(var i=0, len=wktArray.length; i<len; ++i) {
+                components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));
+            }
+            return components;
+        }
+
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WKT" 
+});     
+/* ======================================================================
+    OpenLayers/Protocol/SQL/Gears.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires Gears/gears_init.js
+ * @requires OpenLayers/Protocol/SQL.js
+ * @requires OpenLayers/Format/JSON.js
+ * @requires OpenLayers/Format/WKT.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.SQL.Gears
+ * This Protocol stores feature in the browser via the Gears Database module 
+ * <http://code.google.com/apis/gears/api_database.html>.
+ *
+ * The main advantage is that all the read, create, update and delete operations 
+ * can be done offline.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol.SQL>
+ */
+OpenLayers.Protocol.SQL.Gears = OpenLayers.Class(OpenLayers.Protocol.SQL, {
+
+    /**
+     * Property: FID_PREFIX
+     * {String}
+     */
+    FID_PREFIX: '__gears_fid__',
+
+    /**
+     * Property: NULL_GEOMETRY
+     * {String}
+     */
+    NULL_GEOMETRY: '__gears_null_geometry__',
+
+    /**
+     * Property: NULL_FEATURE_STATE
+     * {String}
+     */
+    NULL_FEATURE_STATE: '__gears_null_feature_state__',
+
+    /**
+     * Property: jsonParser
+     * {<OpenLayers.Format.JSON>}
+     */
+    jsonParser: null,
+
+    /**
+     * Property: wktParser
+     * {<OpenLayers.Format.WKT>}
+     */
+    wktParser: null,
+
+    /**
+     * Property: fidRegExp
+     * {RegExp} Regular expression to know whether a feature was
+     *      created in offline mode.
+     */
+    fidRegExp: null,
+
+    /**
+     * Property: saveFeatureState
+     * {Boolean} Whether to save the feature state (<OpenLayers.State>)
+     *      into the database, defaults to true.
+     */    
+    saveFeatureState: true,
+
+    /**
+     * Property: typeOfFid
+     * {String} The type of the feature identifier, either "number" or
+     *      "string", defaults to "string".
+     */
+    typeOfFid: "string",
+
+    /**
+     * Property: db
+     * {GearsDatabase}
+     */
+    db: null,
+
+    /**
+     * Constructor: OpenLayers.Protocol.SQL.Gears
+     */
+    initialize: function(options) {
+        if (!this.supported()) {
+            return;
+        }
+        OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]);
+        this.jsonParser = new OpenLayers.Format.JSON();
+        this.wktParser = new OpenLayers.Format.WKT();
+
+        this.fidRegExp = new RegExp('^' + this.FID_PREFIX);
+        this.initializeDatabase();
+
+        
+    },
+
+    /**
+     * Method: initializeDatabase
+     */
+    initializeDatabase: function() {
+        this.db = google.gears.factory.create('beta.database');
+        this.db.open(this.databaseName);
+        this.db.execute(
+            "CREATE TABLE IF NOT EXISTS " + this.tableName +
+            " (fid TEXT UNIQUE, geometry TEXT, properties TEXT," +
+            "  state TEXT)");
+   },
+
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        this.db.close();
+        this.db = null;
+
+        this.jsonParser = null;
+        this.wktParser = null;
+
+        OpenLayers.Protocol.SQL.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: supported
+     * Determine whether a browser supports Gears
+     *
+     * Returns:
+     * {Boolean} The browser supports Gears
+     */
+    supported: function() {
+        return !!(window.google && google.gears);
+    },
+
+    /**
+     * APIMethod: read
+     * Read all features from the database and return a
+     * <OpenLayers.Protocol.Response> instance. If the options parameter
+     * contains a callback attribute, the function is called with the response
+     * as a parameter.
+     *
+     * Parameters:
+     * options - {Object} Optional object for configuring the request; it
+     *      can have the {Boolean} property "noFeatureStateReset" which
+     *      specifies if the state of features read from the Gears
+     *      database must be reset to null, if "noFeatureStateReset"
+     *      is undefined or false then each feature's state is reset
+     *      to null, if "noFeatureStateReset" is true the feature state
+     *      is preserved.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *      object.
+     */
+    read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var feature, features = [];
+        var rs = this.db.execute("SELECT * FROM " + this.tableName);
+        while (rs.isValidRow()) {
+            feature = this.unfreezeFeature(rs);
+            if (this.evaluateFilter(feature, options.filter)) {
+                if (!options.noFeatureStateReset) {
+                    feature.state = null;
+                }
+                features.push(feature);
+            }
+            rs.next();
+        }
+        rs.close();
+
+        var resp = new OpenLayers.Protocol.Response({
+            code: OpenLayers.Protocol.Response.SUCCESS,
+            requestType: "read",
+            features: features
+        });
+
+        if (options && options.callback) {
+            options.callback.call(options.scope, resp);
+        }
+
+        return resp;
+    },
+
+    /**
+     * Method: unfreezeFeature
+     *
+     * Parameters:
+     * row - {ResultSet}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    unfreezeFeature: function(row) {
+        var feature;
+        var wkt = row.fieldByName('geometry');
+        if (wkt == this.NULL_GEOMETRY) {
+            feature = new OpenLayers.Feature.Vector();
+        } else {
+            feature = this.wktParser.read(wkt);
+        }
+
+        feature.attributes = this.jsonParser.read(
+            row.fieldByName('properties'));
+
+        feature.fid = this.extractFidFromField(row.fieldByName('fid'));
+
+        var state = row.fieldByName('state');
+        if (state == this.NULL_FEATURE_STATE) {
+            state = null;
+        }
+        feature.state = state;
+
+        return feature;
+    },
+
+    /**
+     * Method: extractFidFromField
+     *
+     * Parameters:
+     * field - {String}
+     *
+     * Returns
+     * {String} or {Number} The fid.
+     */
+    extractFidFromField: function(field) {
+        if (!field.match(this.fidRegExp) && this.typeOfFid == "number") {
+            field = parseFloat(field);
+        }
+        return field;
+    },
+
+    /**
+     * APIMethod: create
+     * Create new features into the database.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *            {<OpenLayers.Feature.Vector>} The features to create in
+     *            the database.
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *          object.
+     */
+    create: function(features, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var resp = this.createOrUpdate(features);
+        resp.requestType = "create";
+
+        if (options && options.callback) {
+            options.callback.call(options.scope, resp);
+        }
+
+        return resp;
+    },
+
+    /**
+     * APIMethod: update
+     * Construct a request updating modified feature.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *            {<OpenLayers.Feature.Vector>} The features to update in
+     *            the database.
+     * options - {Object} Optional object for configuring the request.
+     *
+     * Returns:
+     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *          object.
+     */
+    update: function(features, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var resp = this.createOrUpdate(features);
+        resp.requestType = "update";
+
+        if (options && options.callback) {
+            options.callback.call(options.scope, resp);
+        }
+
+        return resp;
+    },
+
+    /**
+     * Method: createOrUpdate
+     * Construct a request for updating or creating features in the
+     * database.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *      {<OpenLayers.Feature.Vector>} The feature to create or update
+     *      in the database.
+     *
+     * Returns:
+     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *          object.
+     */
+    createOrUpdate: function(features) {
+        if (!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+
+        var i, len = features.length, feature;
+        var insertedFeatures = new Array(len);
+ 
+        for (i = 0; i < len; i++) {
+            feature = features[i];
+            var params = this.freezeFeature(feature);
+            this.db.execute(
+                "REPLACE INTO " + this.tableName + 
+                " (fid, geometry, properties, state)" + 
+                " VALUES (?, ?, ?, ?)",
+                params);
+
+            var clone = feature.clone();
+            clone.fid = this.extractFidFromField(params[0]);
+            insertedFeatures[i] = clone;
+        }
+
+        return new OpenLayers.Protocol.Response({
+            code: OpenLayers.Protocol.Response.SUCCESS,
+            features: insertedFeatures,
+            reqFeatures: features
+        });
+    },
+
+    /**
+     * Method: freezeFeature
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * state - {String} The feature state to store in the database.
+     *
+     * Returns:
+     * {Array}
+     */
+    freezeFeature: function(feature) {
+        // 2 notes:
+        // - fid might not be a string
+        // - getFeatureStateForFreeze needs the feature fid to it's stored
+        //   in the feature here
+        feature.fid = feature.fid != null ?
+            "" + feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX);
+
+        var geometry = feature.geometry != null ?
+            feature.geometry.toString() : this.NULL_GEOMETRY;
+
+        var properties = this.jsonParser.write(feature.attributes);
+
+        var state = this.getFeatureStateForFreeze(feature);
+
+        return [feature.fid, geometry, properties, state];
+    },
+
+    /**
+     * Method: getFeatureStateForFreeze
+     * Get the state of the feature to store into the database.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature.
+     *
+     * Returns
+     * {String} The state
+     */
+    getFeatureStateForFreeze: function(feature) {
+        var state;
+        if (!this.saveFeatureState) {
+            state = this.NULL_FEATURE_STATE;
+        } else if (this.createdOffline(feature)) {
+            // if the feature was created in offline mode, its
+            // state must remain INSERT
+            state = OpenLayers.State.INSERT;
+        } else {
+            state = feature.state;
+        }
+        return state;
+    },
+
+    /**
+     * APIMethod: delete
+     * Delete features from the database.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *            {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *       This object is modified and should not be reused.
+     *
+     * Returns:
+     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *          object.
+     */
+    "delete": function(features, options) {
+        if (!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var i, len, feature;
+        for (i = 0, len = features.length; i < len; i++) {
+            feature = features[i];
+
+            // if saveFeatureState is set to true and if the feature wasn't created
+            // in offline mode we don't delete it in the database but just update 
+            // it state column
+            if (this.saveFeatureState && !this.createdOffline(feature)) {
+                var toDelete = feature.clone();
+                toDelete.fid = feature.fid;
+                if (toDelete.geometry) {
+                    toDelete.geometry.destroy();
+                    toDelete.geometry = null;
+                }
+                toDelete.state = feature.state;
+                this.createOrUpdate(toDelete);
+            } else {
+                this.db.execute(
+                    "DELETE FROM " + this.tableName +
+                    " WHERE fid = ?", [feature.fid]);
+            }
+        }
+
+        var resp = new OpenLayers.Protocol.Response({
+            code: OpenLayers.Protocol.Response.SUCCESS,
+            requestType: "delete",
+            reqFeatures: features
+        });
+
+        if (options && options.callback) {
+            options.callback.call(options.scope, resp);
+        }
+
+        return resp;
+    },
+
+    /**
+     * Method: createdOffline
+     * Returns true if the feature had a feature id when it was created in
+     *      the Gears database, false otherwise; this is determined by
+     *      checking the form of the feature's fid value.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     *
+     * Returns:
+     * {Boolean}
+     */
+    createdOffline: function(feature) {
+        return (typeof feature.fid == "string" &&
+                !!(feature.fid.match(this.fidRegExp)));
+    },
+
+    /**
+     * APIMethod: commit
+     * Go over the features and for each take action
+     * based on the feature state. Possible actions are create,
+     * update and delete.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})}
+     * options - {Object} Object whose possible keys are "create", "update",
+     *      "delete", "callback" and "scope", the values referenced by the
+     *      first three are objects as passed to the "create", "update", and
+     *      "delete" methods, the value referenced by the "callback" key is
+     *      a function which is called when the commit operation is complete
+     *      using the scope referenced by the "scope" key.
+     *
+     * Returns:
+     * {Array({<OpenLayers.Protocol.Response>})} An array of
+     *       <OpenLayers.Protocol.Response> objects, one per request made
+     *       to the database.
+     */
+    commit: function(features, options) {
+        var opt, resp = [], nRequests = 0, nResponses = 0;
+
+        function callback(resp) {
+            if (++nResponses < nRequests) {
+                resp.last = false;
+            }
+            this.callUserCallback(options, resp);
+        }
+
+        var feature, toCreate = [], toUpdate = [], toDelete = [];
+        for (var i = features.length - 1; i >= 0; i--) {
+            feature = features[i];
+            switch (feature.state) {
+            case OpenLayers.State.INSERT:
+                toCreate.push(feature);
+                break;
+            case OpenLayers.State.UPDATE:
+                toUpdate.push(feature);
+                break;
+            case OpenLayers.State.DELETE:
+                toDelete.push(feature);
+                break;
+            }
+        }
+        if (toCreate.length > 0) {
+            nRequests++;
+            opt = OpenLayers.Util.applyDefaults(
+                {"callback": callback, "scope": this},
+                options.create
+            );
+            resp.push(this.create(toCreate, opt));
+        }
+        if (toUpdate.length > 0) {
+            nRequests++;
+            opt = OpenLayers.Util.applyDefaults(
+                {"callback": callback, "scope": this},
+                options.update
+            );
+            resp.push(this.update(toUpdate, opt));
+        }
+        if (toDelete.length > 0) {
+            nRequests++;
+            opt = OpenLayers.Util.applyDefaults(
+                {"callback": callback, "scope": this},
+                options["delete"]
+            );
+            resp.push(this["delete"](toDelete, opt));
+        }
+
+        return resp;
+    },
+
+    /**
+     * Method: clear
+     * Removes all rows of the table.
+     */
+    clear: function() {
+        this.db.execute("DELETE FROM " + this.tableName);
+    },
+
+    /**
+     * Method: callUserCallback
+     * This method is called from within commit each time a request is made
+     * to the database, it is responsible for calling the user-supplied
+     * callbacks.
+     *
+     * Parameters:
+     * options - {Object} The map of options passed to the commit call.
+     * resp - {<OpenLayers.Protocol.Response>}
+     */
+    callUserCallback: function(options, resp) {
+        var opt = options[resp.requestType];
+        if (opt && opt.callback) {
+            opt.callback.call(opt.scope, resp);
+        }
+        if (resp.last && options.callback) {
+            options.callback.call(options.scope);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.SQL.Gears"
+});
+/* ======================================================================
+    OpenLayers/Format/XML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XML
+ * Read and write XML.  For cross-browser XML generation, use methods on an
+ *     instance of the XML format class instead of on <code>document<end>.
+ *     The DOM creation and traversing methods exposed here all mimic the
+ *     W3C XML DOM methods.  Create a new parser with the
+ *     <OpenLayers.Format.XML> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.  Properties
+     *     of this object should not be set individually.  Read-only.  All
+     *     XML subclasses should have their own namespaces object.  Use
+     *     <setNamespace> to add or set a namespace alias after construction.
+     */
+    namespaces: null,
+    
+    /**
+     * Property: namespaceAlias
+     * {Object} Mapping of namespace URI to namespace alias.  This object
+     *     is read-only.  Use <setNamespace> to add or set a namespace alias.
+     */
+    namespaceAlias: null,
+    
+    /**
+     * Property: defaultPrefix
+     * {String} The default namespace alias for creating element nodes.
+     */
+    defaultPrefix: null,
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {},
+    
+    /**
+     * Property: writers
+     * As a compliment to the <readers> property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {},
+
+    /**
+     * Property: xmldom
+     * {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM
+     *     object.  It is not intended to be a browser sniffing property.
+     *     Instead, the xmldom property is used instead of <code>document<end>
+     *     where namespaced node creation methods are not supported. In all
+     *     other browsers, this remains null.
+     */
+    xmldom: null,
+
+    /**
+     * Constructor: OpenLayers.Format.XML
+     * Construct an XML parser.  The parser is used to read and write XML.
+     *     Reading XML from a string returns a DOM element.  Writing XML from
+     *     a DOM element returns a string.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on
+     *     the object.
+     */
+    initialize: function(options) {
+        if(window.ActiveXObject) {
+            this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
+        }
+        OpenLayers.Format.prototype.initialize.apply(this, [options]);
+        // clone the namespace object and set all namespace aliases
+        this.namespaces = OpenLayers.Util.extend({}, this.namespaces);
+        this.namespaceAlias = {};
+        for(var alias in this.namespaces) {
+            this.namespaceAlias[this.namespaces[alias]] = alias;
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up.
+     */
+    destroy: function() {
+        this.xmldom = null;
+        OpenLayers.Format.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: setNamespace
+     * Set a namespace alias and URI for the format.
+     *
+     * Parameters:
+     * alias - {String} The namespace alias (prefix).
+     * uri - {String} The namespace URI.
+     */
+    setNamespace: function(alias, uri) {
+        this.namespaces[alias] = uri;
+        this.namespaceAlias[uri] = alias;
+    },
+
+    /**
+     * APIMethod: read
+     * Deserialize a XML string and return a DOM node.
+     *
+     * Parameters:
+     * text - {String} A XML string
+     
+     * Returns:
+     * {DOMElement} A DOM node
+     */
+    read: function(text) {
+        var index = text.indexOf('<');
+        if(index > 0) {
+            text = text.substring(index);
+        }
+        var node = OpenLayers.Util.Try(
+            OpenLayers.Function.bind((
+                function() {
+                    var xmldom;
+                    /**
+                     * Since we want to be able to call this method on the prototype
+                     * itself, this.xmldom may not exist even if in IE.
+                     */
+                    if(window.ActiveXObject && !this.xmldom) {
+                        xmldom = new ActiveXObject("Microsoft.XMLDOM");
+                    } else {
+                        xmldom = this.xmldom;
+                        
+                    }
+                    xmldom.loadXML(text);
+                    return xmldom;
+                }
+            ), this),
+            function() {
+                return new DOMParser().parseFromString(text, 'text/xml');
+            },
+            function() {
+                var req = new XMLHttpRequest();
+                req.open("GET", "data:" + "text/xml" +
+                         ";charset=utf-8," + encodeURIComponent(text), false);
+                if(req.overrideMimeType) {
+                    req.overrideMimeType("text/xml");
+                }
+                req.send(null);
+                return req.responseXML;
+            }
+        );
+
+        if(this.keepData) {
+            this.data = node;
+        }
+
+        return node;
+    },
+
+    /**
+     * APIMethod: write
+     * Serialize a DOM node into a XML string.
+     * 
+     * Parameters:
+     * node - {DOMElement} A DOM node.
+     *
+     * Returns:
+     * {String} The XML string representation of the input node.
+     */
+    write: function(node) {
+        var data;
+        if(this.xmldom) {
+            data = node.xml;
+        } else {
+            var serializer = new XMLSerializer();
+            if (node.nodeType == 1) {
+                // Add nodes to a document before serializing. Everything else
+                // is serialized as is. This may need more work. See #1218 .
+                var doc = document.implementation.createDocument("", "", null);
+                if (doc.importNode) {
+                    node = doc.importNode(node, true);
+                }
+                doc.appendChild(node);
+                data = serializer.serializeToString(doc);
+            } else {
+                data = serializer.serializeToString(node);
+            }
+        }
+        return data;
+    },
+
+    /**
+     * APIMethod: createElementNS
+     * Create a new element with namespace.  This node can be appended to
+     *     another node with the standard node.appendChild method.  For
+     *     cross-browser support, this method must be used instead of
+     *     document.createElementNS.
+     *
+     * Parameters:
+     * uri - {String} Namespace URI for the element.
+     * name - {String} The qualified name of the element (prefix:localname).
+     * 
+     * Returns:
+     * {Element} A DOM element with namespace.
+     */
+    createElementNS: function(uri, name) {
+        var element;
+        if(this.xmldom) {
+            if(typeof uri == "string") {
+                element = this.xmldom.createNode(1, name, uri);
+            } else {
+                element = this.xmldom.createNode(1, name, "");
+            }
+        } else {
+            element = document.createElementNS(uri, name);
+        }
+        return element;
+    },
+
+    /**
+     * APIMethod: createTextNode
+     * Create a text node.  This node can be appended to another node with
+     *     the standard node.appendChild method.  For cross-browser support,
+     *     this method must be used instead of document.createTextNode.
+     * 
+     * Parameters:
+     * text - {String} The text of the node.
+     * 
+     * Returns: 
+     * {DOMElement} A DOM text node.
+     */
+    createTextNode: function(text) {
+        var node;
+        if (typeof text !== "string") {
+            text = String(text);
+        }
+        if(this.xmldom) {
+            node = this.xmldom.createTextNode(text);
+        } else {
+            node = document.createTextNode(text);
+        }
+        return node;
+    },
+
+    /**
+     * APIMethod: getElementsByTagNameNS
+     * Get a list of elements on a node given the namespace URI and local name.
+     *     To return all nodes in a given namespace, use '*' for the name
+     *     argument.  To return all nodes of a given (local) name, regardless
+     *     of namespace, use '*' for the uri argument.
+     * 
+     * Parameters:
+     * node - {Element} Node on which to search for other nodes.
+     * uri - {String} Namespace URI.
+     * name - {String} Local name of the tag (without the prefix).
+     * 
+     * Returns:
+     * {NodeList} A node list or array of elements.
+     */
+    getElementsByTagNameNS: function(node, uri, name) {
+        var elements = [];
+        if(node.getElementsByTagNameNS) {
+            elements = node.getElementsByTagNameNS(uri, name);
+        } else {
+            // brute force method
+            var allNodes = node.getElementsByTagName("*");
+            var potentialNode, fullName;
+            for(var i=0, len=allNodes.length; i<len; ++i) {
+                potentialNode = allNodes[i];
+                fullName = (potentialNode.prefix) ?
+                           (potentialNode.prefix + ":" + name) : name;
+                if((name == "*") || (fullName == potentialNode.nodeName)) {
+                    if((uri == "*") || (uri == potentialNode.namespaceURI)) {
+                        elements.push(potentialNode);
+                    }
+                }
+            }
+        }
+        return elements;
+    },
+
+    /**
+     * APIMethod: getAttributeNodeNS
+     * Get an attribute node given the namespace URI and local name.
+     * 
+     * Parameters:
+     * node - {Element} Node on which to search for attribute nodes.
+     * uri - {String} Namespace URI.
+     * name - {String} Local name of the attribute (without the prefix).
+     * 
+     * Returns:
+     * {DOMElement} An attribute node or null if none found.
+     */
+    getAttributeNodeNS: function(node, uri, name) {
+        var attributeNode = null;
+        if(node.getAttributeNodeNS) {
+            attributeNode = node.getAttributeNodeNS(uri, name);
+        } else {
+            var attributes = node.attributes;
+            var potentialNode, fullName;
+            for(var i=0, len=attributes.length; i<len; ++i) {
+                potentialNode = attributes[i];
+                if(potentialNode.namespaceURI == uri) {
+                    fullName = (potentialNode.prefix) ?
+                               (potentialNode.prefix + ":" + name) : name;
+                    if(fullName == potentialNode.nodeName) {
+                        attributeNode = potentialNode;
+                        break;
+                    }
+                }
+            }
+        }
+        return attributeNode;
+    },
+
+    /**
+     * APIMethod: getAttributeNS
+     * Get an attribute value given the namespace URI and local name.
+     * 
+     * Parameters:
+     * node - {Element} Node on which to search for an attribute.
+     * uri - {String} Namespace URI.
+     * name - {String} Local name of the attribute (without the prefix).
+     * 
+     * Returns:
+     * {String} An attribute value or and empty string if none found.
+     */
+    getAttributeNS: function(node, uri, name) {
+        var attributeValue = "";
+        if(node.getAttributeNS) {
+            attributeValue = node.getAttributeNS(uri, name) || "";
+        } else {
+            var attributeNode = this.getAttributeNodeNS(node, uri, name);
+            if(attributeNode) {
+                attributeValue = attributeNode.nodeValue;
+            }
+        }
+        return attributeValue;
+    },
+    
+    /**
+     * APIMethod: getChildValue
+     * Get the textual value of the node if it exists, or return an
+     *     optional default string.  Returns an empty string if no first child
+     *     exists and no default value is supplied.
+     *
+     * Parameters:
+     * node - {DOMElement} The element used to look for a first child value.
+     * def - {String} Optional string to return in the event that no
+     *     first child value exists.
+     *
+     * Returns:
+     * {String} The value of the first child of the given node.
+     */
+    getChildValue: function(node, def) {
+        var value = def || "";
+        if(node) {
+            for(var child=node.firstChild; child; child=child.nextSibling) {
+                switch(child.nodeType) {
+                    case 3: // text node
+                    case 4: // cdata section
+                        value += child.nodeValue;
+                }
+            }
+        }
+        return value;
+    },
+
+    /**
+     * APIMethod: concatChildValues
+     * *Deprecated*. Use <getChildValue> instead.
+     *
+     * Concatenate the value of all child nodes if any exist, or return an
+     *     optional default string.  Returns an empty string if no children
+     *     exist and no default value is supplied.  Not optimized for large
+     *     numbers of child nodes.
+     *
+     * Parameters:
+     * node - {DOMElement} The element used to look for child values.
+     * def - {String} Optional string to return in the event that no
+     *     child exist.
+     *
+     * Returns:
+     * {String} The concatenated value of all child nodes of the given node.
+     */
+    concatChildValues: function(node, def) {
+        var value = "";
+        var child = node.firstChild;
+        var childValue;
+        while(child) {
+            childValue = child.nodeValue;
+            if(childValue) {
+                value += childValue;
+            }
+            child = child.nextSibling;
+        }
+        if(value == "" && def != undefined) {
+            value = def;
+        }
+        return value;
+    },
+    
+    /**
+     * APIMethod: isSimpleContent
+     * Test if the given node has only simple content (i.e. no child element
+     *     nodes).
+     *
+     * Parameters:
+     * node - {DOMElement} An element node.
+     *
+     * Returns:
+     * {Boolean} The node has no child element nodes (nodes of type 1). 
+     */
+    isSimpleContent: function(node) {
+        var simple = true;
+        for(var child=node.firstChild; child; child=child.nextSibling) {
+            if(child.nodeType === 1) {
+                simple = false;
+                break;
+            }
+        }
+        return simple;
+    },
+    
+    /**
+     * APIMethod: contentType
+     * Determine the content type for a given node.
+     *
+     * Parameters:
+     * node - {DOMElement}
+     *
+     * Returns:
+     * {Integer} One of OpenLayers.Format.XML.CONTENT_TYPE.{EMPTY,SIMPLE,COMPLEX,MIXED}
+     *     if the node has no, simple, complex, or mixed content.
+     */
+    contentType: function(node) {
+        var simple = false,
+            complex = false;
+            
+        var type = OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;
+
+        for(var child=node.firstChild; child; child=child.nextSibling) {
+            switch(child.nodeType) {
+                case 1: // element
+                    complex = true;
+                    break;
+                case 8: // comment
+                    break;
+                default:
+                    simple = true;
+            }
+            if(complex && simple) {
+                break;
+            }
+        }
+        
+        if(complex && simple) {
+            type = OpenLayers.Format.XML.CONTENT_TYPE.MIXED;
+        } else if(complex) {
+            return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;
+        } else if(simple) {
+            return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;
+        }
+        return type;
+    },
+
+    /**
+     * APIMethod: hasAttributeNS
+     * Determine whether a node has a particular attribute matching the given
+     *     name and namespace.
+     * 
+     * Parameters:
+     * node - {Element} Node on which to search for an attribute.
+     * uri - {String} Namespace URI.
+     * name - {String} Local name of the attribute (without the prefix).
+     * 
+     * Returns:
+     * {Boolean} The node has an attribute matching the name and namespace.
+     */
+    hasAttributeNS: function(node, uri, name) {
+        var found = false;
+        if(node.hasAttributeNS) {
+            found = node.hasAttributeNS(uri, name);
+        } else {
+            found = !!this.getAttributeNodeNS(node, uri, name);
+        }
+        return found;
+    },
+    
+    /**
+     * APIMethod: setAttributeNS
+     * Adds a new attribute or changes the value of an attribute with the given
+     *     namespace and name.
+     *
+     * Parameters:
+     * node - {Element} Element node on which to set the attribute.
+     * uri - {String} Namespace URI for the attribute.
+     * name - {String} Qualified name (prefix:localname) for the attribute.
+     * value - {String} Attribute value.
+     */
+    setAttributeNS: function(node, uri, name, value) {
+        if(node.setAttributeNS) {
+            node.setAttributeNS(uri, name, value);
+        } else {
+            if(this.xmldom) {
+                if(uri) {
+                    var attribute = node.ownerDocument.createNode(
+                        2, name, uri
+                    );
+                    attribute.nodeValue = value;
+                    node.setAttributeNode(attribute);
+                } else {
+                    node.setAttribute(name, value);
+                }
+            } else {
+                throw "setAttributeNS not implemented";
+            }
+        }
+    },
+
+    /**
+     * Method: createElementNSPlus
+     * Shorthand for creating namespaced elements with optional attributes and
+     *     child text nodes.
+     *
+     * Parameters:
+     * name - {String} The qualified node name.
+     * options - {Object} Optional object for node configuration.
+     *
+     * Valid options:
+     * uri - {String} Optional namespace uri for the element - supply a prefix
+     *     instead if the namespace uri is a property of the format's namespace
+     *     object.
+     * attributes - {Object} Optional attributes to be set using the
+     *     <setAttributes> method.
+     * value - {String} Optional text to be appended as a text node.
+     *
+     * Returns:
+     * {Element} An element node.
+     */
+    createElementNSPlus: function(name, options) {
+        options = options || {};
+        // order of prefix preference
+        // 1. in the uri option
+        // 2. in the prefix option
+        // 3. in the qualified name
+        // 4. from the defaultPrefix
+        var uri = options.uri || this.namespaces[options.prefix];
+        if(!uri) {
+            var loc = name.indexOf(":");
+            uri = this.namespaces[name.substring(0, loc)];
+        }
+        if(!uri) {
+            uri = this.namespaces[this.defaultPrefix];
+        }
+        var node = this.createElementNS(uri, name);
+        if(options.attributes) {
+            this.setAttributes(node, options.attributes);
+        }
+        var value = options.value;
+        if(value != null) {
+            node.appendChild(this.createTextNode(value));
+        }
+        return node;
+    },
+    
+    /**
+     * Method: setAttributes
+     * Set multiple attributes given key value pairs from an object.
+     *
+     * Parameters:
+     * node - {Element} An element node.
+     * obj - {Object || Array} An object whose properties represent attribute
+     *     names and values represent attribute values.  If an attribute name
+     *     is a qualified name ("prefix:local"), the prefix will be looked up
+     *     in the parsers {namespaces} object.  If the prefix is found,
+     *     setAttributeNS will be used instead of setAttribute.
+     */
+    setAttributes: function(node, obj) {
+        var value, uri;
+        for(var name in obj) {
+            if(obj[name] != null && obj[name].toString) {
+                value = obj[name].toString();
+                // check for qualified attribute name ("prefix:local")
+                uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
+                this.setAttributeNS(node, uri, name, value);
+            }
+        }
+    },
+
+    /**
+     * Method: readNode
+     * Shorthand for applying one of the named readers given the node
+     *     namespace and local name.  Readers take two args (node, obj) and
+     *     generally extend or modify the second.
+     *
+     * Parameters:
+     * node - {DOMElement} The node to be read (required).
+     * obj - {Object} The object to be modified (optional).
+     *
+     * Returns:
+     * {Object} The input object, modified (or a new one if none was provided).
+     */
+    readNode: function(node, obj) {
+        if(!obj) {
+            obj = {};
+        }
+        var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix];
+        if(group) {
+            var local = node.localName || node.nodeName.split(":").pop();
+            var reader = group[local] || group["*"];
+            if(reader) {
+                reader.apply(this, [node, obj]);
+            }
+        }
+        return obj;
+    },
+
+    /**
+     * Method: readChildNodes
+     * Shorthand for applying the named readers to all children of a node.
+     *     For each child of type 1 (element), <readSelf> is called.
+     *
+     * Parameters:
+     * node - {DOMElement} The node to be read (required).
+     * obj - {Object} The object to be modified (optional).
+     *
+     * Returns:
+     * {Object} The input object, modified.
+     */
+    readChildNodes: function(node, obj) {
+        if(!obj) {
+            obj = {};
+        }
+        var children = node.childNodes;
+        var child;
+        for(var i=0, len=children.length; i<len; ++i) {
+            child = children[i];
+            if(child.nodeType == 1) {
+                this.readNode(child, obj);
+            }
+        }
+        return obj;
+    },
+
+    /**
+     * Method: writeNode
+     * Shorthand for applying one of the named writers and appending the
+     *     results to a node.  If a qualified name is not provided for the
+     *     second argument (and a local name is used instead), the namespace
+     *     of the parent node will be assumed.
+     *
+     * Parameters:
+     * name - {String} The name of a node to generate.  If a qualified name
+     *     (e.g. "pre:Name") is used, the namespace prefix is assumed to be
+     *     in the <writers> group.  If a local name is used (e.g. "Name") then
+     *     the namespace of the parent is assumed.  If a local name is used
+     *     and no parent is supplied, then the default namespace is assumed.
+     * obj - {Object} Structure containing data for the writer.
+     * parent - {DOMElement} Result will be appended to this node.  If no parent
+     *     is supplied, the node will not be appended to anything.
+     *
+     * Returns:
+     * {DOMElement} The child node.
+     */
+    writeNode: function(name, obj, parent) {
+        var prefix, local;
+        var split = name.indexOf(":");
+        if(split > 0) {
+            prefix = name.substring(0, split);
+            local = name.substring(split + 1);
+        } else {
+            if(parent) {
+                prefix = this.namespaceAlias[parent.namespaceURI];
+            } else {
+                prefix = this.defaultPrefix;
+            }
+            local = name;
+        }
+        var child = this.writers[prefix][local].apply(this, [obj]);
+        if(parent) {
+            parent.appendChild(child);
+        }
+        return child;
+    },
+
+    /**
+     * APIMethod: getChildEl
+     * Get the first child element.  Optionally only return the first child
+     *     if it matches the given name and namespace URI.
+     *
+     * Parameters:
+     * node - {DOMElement} The parent node.
+     * name - {String} Optional node name (local) to search for.
+     * uri - {String} Optional namespace URI to search for.
+     *
+     * Returns:
+     * {DOMElement} The first child.  Returns null if no element is found, if
+     *     something significant besides an element is found, or if the element
+     *     found does not match the optional name and uri.
+     */
+    getChildEl: function(node, name, uri) {
+        return node && this.getThisOrNextEl(node.firstChild, name, uri);
+    },
+    
+    /**
+     * APIMethod: getNextEl
+     * Get the next sibling element.  Optionally get the first sibling only
+     *     if it matches the given local name and namespace URI.
+     *
+     * Parameters:
+     * node - {DOMElement} The node.
+     * name - {String} Optional local name of the sibling to search for.
+     * uri - {String} Optional namespace URI of the sibling to search for.
+     *
+     * Returns:
+     * {DOMElement} The next sibling element.  Returns null if no element is
+     *     found, something significant besides an element is found, or the
+     *     found element does not match the optional name and uri.
+     */
+    getNextEl: function(node, name, uri) {
+        return node && this.getThisOrNextEl(node.nextSibling, name, uri);
+    },
+    
+    /**
+     * Method: getThisOrNextEl
+     * Return this node or the next element node.  Optionally get the first
+     *     sibling with the given local name or namespace URI.
+     *
+     * Parameters:
+     * node - {DOMElement} The node.
+     * name - {String} Optional local name of the sibling to search for.
+     * uri - {String} Optional namespace URI of the sibling to search for.
+     *
+     * Returns:
+     * {DOMElement} The next sibling element.  Returns null if no element is
+     *     found, something significant besides an element is found, or the
+     *     found element does not match the query.
+     */
+    getThisOrNextEl: function(node, name, uri) {
+        outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) {
+            switch(sibling.nodeType) {
+                case 1: // Element
+                    if((!name || name === (sibling.localName || sibling.nodeName.split(":").pop())) &&
+                       (!uri || uri === sibling.namespaceURI)) {
+                        // matches
+                        break outer;
+                    }
+                    sibling = null;
+                    break outer;
+                case 3: // Text
+                    if(/^\s*$/.test(sibling.nodeValue)) {
+                        break;
+                    }
+                case 4: // CDATA
+                case 6: // ENTITY_NODE
+                case 12: // NOTATION_NODE
+                case 10: // DOCUMENT_TYPE_NODE
+                case 11: // DOCUMENT_FRAGMENT_NODE
+                    sibling = null;
+                    break outer;
+            } // ignore comments and processing instructions
+        }
+        return sibling || null;
+    },
+    
+    /**
+     * APIMethod: lookupNamespaceURI
+     * Takes a prefix and returns the namespace URI associated with it on the given
+     *     node if found (and null if not). Supplying null for the prefix will
+     *     return the default namespace.
+     *
+     * For browsers that support it, this calls the native lookupNamesapceURI
+     *     function.  In other browsers, this is an implementation of
+     *     http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
+     *
+     * For browsers that don't support the attribute.ownerElement property, this
+     *     method cannot be called on attribute nodes.
+     *     
+     * Parameters:
+     * node - {DOMElement} The node from which to start looking.
+     * prefix - {String} The prefix to lookup or null to lookup the default namespace.
+     * 
+     * Returns:
+     * {String} The namespace URI for the given prefix.  Returns null if the prefix
+     *     cannot be found or the node is the wrong type.
+     */
+    lookupNamespaceURI: function(node, prefix) {
+        var uri = null;
+        if(node) {
+            if(node.lookupNamespaceURI) {
+                uri = node.lookupNamespaceURI(prefix);
+            } else {
+                outer: switch(node.nodeType) {
+                    case 1: // ELEMENT_NODE
+                        if(node.namespaceURI !== null && node.prefix === prefix) {
+                            uri = node.namespaceURI;
+                            break outer;
+                        }
+                        var len = node.attributes.length;
+                        if(len) {
+                            var attr;
+                            for(var i=0; i<len; ++i) {
+                                attr = node.attributes[i];
+                                if(attr.prefix === "xmlns" && attr.name === "xmlns:" + prefix) {
+                                    uri = attr.value || null;
+                                    break outer;
+                                } else if(attr.name === "xmlns" && prefix === null) {
+                                    uri = attr.value || null;
+                                    break outer;
+                                }
+                            }
+                        }
+                        uri = this.lookupNamespaceURI(node.parentNode, prefix);
+                        break outer;
+                    case 2: // ATTRIBUTE_NODE
+                        uri = this.lookupNamespaceURI(node.ownerElement, prefix);
+                        break outer;
+                    case 9: // DOCUMENT_NODE
+                        uri = this.lookupNamespaceURI(node.documentElement, prefix);
+                        break outer;
+                    case 6: // ENTITY_NODE
+                    case 12: // NOTATION_NODE
+                    case 10: // DOCUMENT_TYPE_NODE
+                    case 11: // DOCUMENT_FRAGMENT_NODE
+                        break outer;
+                    default: 
+                        // TEXT_NODE (3), CDATA_SECTION_NODE (4), ENTITY_REFERENCE_NODE (5),
+                        // PROCESSING_INSTRUCTION_NODE (7), COMMENT_NODE (8)
+                        uri =  this.lookupNamespaceURI(node.parentNode, prefix);
+                        break outer;
+                }
+            }
+        }
+        return uri;
+    },
+    
+    /**
+     * Method: getXMLDoc
+     * Get an XML document for nodes that are not supported in HTML (e.g.
+     * createCDATASection). On IE, this will either return an existing or
+     * create a new <xmldom> on the instance. On other browsers, this will
+     * either return an existing or create a new shared document (see
+     * <OpenLayers.Format.XML.document>).
+     *
+     * Returns:
+     * {XMLDocument}
+     */
+    getXMLDoc: function() {
+        if (!OpenLayers.Format.XML.document && !this.xmldom) {
+            if (document.implementation && document.implementation.createDocument) {
+                OpenLayers.Format.XML.document =
+                    document.implementation.createDocument("", "", null);
+            } else if (!this.xmldom && window.ActiveXObject) {
+                this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
+            }
+        }
+        return OpenLayers.Format.XML.document || this.xmldom;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.XML" 
+
+});     
+
+OpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3};
+
+/**
+ * APIFunction: OpenLayers.Format.XML.lookupNamespaceURI
+ * Takes a prefix and returns the namespace URI associated with it on the given
+ *     node if found (and null if not). Supplying null for the prefix will
+ *     return the default namespace.
+ *
+ * For browsers that support it, this calls the native lookupNamesapceURI
+ *     function.  In other browsers, this is an implementation of
+ *     http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
+ *
+ * For browsers that don't support the attribute.ownerElement property, this
+ *     method cannot be called on attribute nodes.
+ *     
+ * Parameters:
+ * node - {DOMElement} The node from which to start looking.
+ * prefix - {String} The prefix to lookup or null to lookup the default namespace.
+ * 
+ * Returns:
+ * {String} The namespace URI for the given prefix.  Returns null if the prefix
+ *     cannot be found or the node is the wrong type.
+ */
+OpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind(
+    OpenLayers.Format.XML.prototype.lookupNamespaceURI,
+    OpenLayers.Format.XML.prototype
+);
+
+/**
+ * Property: OpenLayers.Format.XML.document
+ * {XMLDocument} XML document to reuse for creating non-HTML compliant nodes,
+ * like document.createCDATASection.
+ */
+OpenLayers.Format.XML.document = null;
+/* ======================================================================
+    OpenLayers/BaseTypes/Date.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * Namespace: OpenLayers.Date
+ * Contains implementations of Date.parse and date.toISOString that match the
+ *     ECMAScript 5 specification for parsing RFC 3339 dates.
+ *     http://tools.ietf.org/html/rfc3339
+ */
+OpenLayers.Date = {
+
+    /**
+     * APIMethod: toISOString
+     * Generates a string representing a date.  The format of the string follows
+     *     the profile of ISO 8601 for date and time on the Internet (see
+     *     http://tools.ietf.org/html/rfc3339).  If the toISOString method is
+     *     available on the Date prototype, that is used.  The toISOString
+     *     method for Date instances is defined in ECMA-262.
+     *
+     * Parameters:
+     * date - {Date} A date object.
+     *
+     * Returns:
+     * {String} A string representing the date (e.g.
+     *     "2010-08-07T16:58:23.123Z").  If the date does not have a valid time
+     *     (i.e. isNaN(date.getTime())) this method returns the string "Invalid
+     *     Date".  The ECMA standard says the toISOString method should throw
+     *     RangeError in this case, but Firefox returns a string instead.  For
+     *     best results, use isNaN(date.getTime()) to determine date validity
+     *     before generating date strings.
+     */
+    toISOString: (function() {
+        if ("toISOString" in Date.prototype) {
+            return function(date) {
+                return date.toISOString();
+            };
+        } else {
+            function pad(num, len) {
+                var str = num + "";
+                while (str.length < len) {
+                    str = "0" + str;
+                }
+                return str;
+            }
+            return function(date) {
+                var str;
+                if (isNaN(date.getTime())) {
+                    // ECMA-262 says throw RangeError, Firefox returns
+                    // "Invalid Date"
+                    str = "Invalid Date";
+                } else {
+                    str =
+                        date.getUTCFullYear() + "-" +
+                        pad(date.getUTCMonth() + 1, 2) + "-" +
+                        pad(date.getUTCDate(), 2) + "T" +
+                        pad(date.getUTCHours(), 2) + ":" +
+                        pad(date.getUTCMinutes(), 2) + ":" +
+                        pad(date.getUTCSeconds(), 2) + "." +
+                        pad(date.getUTCMilliseconds(), 3) + "Z";
+                }
+                return str;
+            };
+        }
+
+    })(),
+
+    /**
+     * APIMethod: parse
+     * Generate a date object from a string.  The format for the string follows
+     *     the profile of ISO 8601 for date and time on the Internet (see
+     *     http://tools.ietf.org/html/rfc3339).  We don't call the native
+     *     Date.parse because of inconsistency between implmentations.  In
+     *     Chrome, calling Date.parse with a string that doesn't contain any
+     *     indication of the timezone (e.g. "2011"), the date is interpreted
+     *     in local time.  On Firefox, the assumption is UTC.
+     *
+     * Parameters:
+     * str - {String} A string representing the date (e.g.
+     *     "2010", "2010-08", "2010-08-07", "2010-08-07T16:58:23.123Z",
+     *     "2010-08-07T11:58:23.123-06").
+     *
+     * Returns:
+     * {Date} A date object.  If the string could not be parsed, an invalid
+     *     date is returned (i.e. isNaN(date.getTime())).
+     */
+    parse: function(str) {
+        var date;
+        var match = str.match(/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))?$/);
+        if (match && (match[1] || match[7])) { // must have at least year or time
+            var year = parseInt(match[1], 10) || 0;
+            var month = (parseInt(match[2], 10) - 1) || 0;
+            var day = parseInt(match[3], 10) || 1;
+            date = new Date(Date.UTC(year, month, day));
+            // optional time
+            var type = match[7];
+            if (type) {
+                var hours = parseInt(match[4], 10);
+                var minutes = parseInt(match[5], 10);
+                var secFrac = parseFloat(match[6]);
+                var seconds = secFrac | 0;
+                var milliseconds = Math.round(1000 * (secFrac - seconds));
+                date.setUTCHours(hours, minutes, seconds, milliseconds);
+                // check offset
+                if (type !== "Z") {
+                    var hoursOffset = parseInt(type, 10);
+                    var minutesOffset = parseInt(match[8], 10) || 0;
+                    var offset = -1000 * (60 * (hoursOffset * 60) + minutesOffset * 60);
+                    date = new Date(date.getTime() + offset);
+                }
+            }
+        } else {
+            date = new Date("invalid");
+        }
+        return date;
+    }
+};
+/* ======================================================================
+    OpenLayers/Geometry.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+ 
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Format/WKT.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry
+ * A Geometry is a description of a geographic object.  Create an instance of
+ * this class with the <OpenLayers.Geometry> constructor.  This is a base class,
+ * typical geometry types are described by subclasses of this class.
+ */
+OpenLayers.Geometry = OpenLayers.Class({
+
+    /**
+     * Property: id
+     * {String} A unique identifier for this geometry.
+     */
+    id: null,
+
+    /**
+     * Property: parent
+     * {<OpenLayers.Geometry>}This is set when a Geometry is added as component
+     * of another geometry
+     */
+    parent: null,
+
+    /**
+     * Property: bounds 
+     * {<OpenLayers.Bounds>} The bounds of this geometry
+     */
+    bounds: null,
+
+    /**
+     * Constructor: OpenLayers.Geometry
+     * Creates a geometry object.  
+     */
+    initialize: function() {
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME+ "_");
+    },
+    
+    /**
+     * Method: destroy
+     * Destroy this geometry.
+     */
+    destroy: function() {
+        this.id = null;
+        this.bounds = null;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Create a clone of this geometry.  Does not set any non-standard
+     *     properties of the cloned geometry.
+     * 
+     * Returns:
+     * {<OpenLayers.Geometry>} An exact clone of this geometry.
+     */
+    clone: function() {
+        return new OpenLayers.Geometry();
+    },
+    
+    /**
+     * Set the bounds for this Geometry.
+     * 
+     * Parameters:
+     * object - {<OpenLayers.Bounds>} 
+     */
+    setBounds: function(bounds) {
+        if (bounds) {
+            this.bounds = bounds.clone();
+        }
+    },
+    
+    /**
+     * Method: clearBounds
+     * Nullify this components bounds and that of its parent as well.
+     */
+    clearBounds: function() {
+        this.bounds = null;
+        if (this.parent) {
+            this.parent.clearBounds();
+        }    
+    },
+    
+    /**
+     * Method: extendBounds
+     * Extend the existing bounds to include the new bounds. 
+     * If geometry's bounds is not yet set, then set a new Bounds.
+     * 
+     * Parameters:
+     * newBounds - {<OpenLayers.Bounds>} 
+     */
+    extendBounds: function(newBounds){
+        var bounds = this.getBounds();
+        if (!bounds) {
+            this.setBounds(newBounds);
+        } else {
+            this.bounds.extend(newBounds);
+        }
+    },
+    
+    /**
+     * APIMethod: getBounds
+     * Get the bounds for this Geometry. If bounds is not set, it 
+     * is calculated again, this makes queries faster.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getBounds: function() {
+        if (this.bounds == null) {
+            this.calculateBounds();
+        }
+        return this.bounds;
+    },
+    
+    /** 
+     * APIMethod: calculateBounds
+     * Recalculate the bounds for the geometry. 
+     */
+    calculateBounds: function() {
+        //
+        // This should be overridden by subclasses.
+        //
+    },
+    
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries (on the x-y plane).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options depend on the specific geometry type.
+     * 
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+    },
+    
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+    },
+
+    /**
+     * Method: atPoint
+     * Note - This is only an approximation based on the bounds of the 
+     * geometry.
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>} 
+     * toleranceLon - {float} Optional tolerance in Geometric Coords
+     * toleranceLat - {float} Optional tolerance in Geographic Coords
+     * 
+     * Returns:
+     * {Boolean} Whether or not the geometry is at the specified location
+     */
+    atPoint: function(lonlat, toleranceLon, toleranceLat) {
+        var atPoint = false;
+        var bounds = this.getBounds();
+        if ((bounds != null) && (lonlat != null)) {
+
+            var dX = (toleranceLon != null) ? toleranceLon : 0;
+            var dY = (toleranceLat != null) ? toleranceLat : 0;
+    
+            var toleranceBounds = 
+                new OpenLayers.Bounds(this.bounds.left - dX,
+                                      this.bounds.bottom - dY,
+                                      this.bounds.right + dX,
+                                      this.bounds.top + dY);
+
+            atPoint = toleranceBounds.containsLonLat(lonlat);
+        }
+        return atPoint;
+    },
+    
+    /**
+     * Method: getLength
+     * Calculate the length of this geometry. This method is defined in
+     * subclasses.
+     * 
+     * Returns:
+     * {Float} The length of the collection by summing its parts
+     */
+    getLength: function() {
+        //to be overridden by geometries that actually have a length
+        //
+        return 0.0;
+    },
+
+    /**
+     * Method: getArea
+     * Calculate the area of this geometry. This method is defined in subclasses.
+     * 
+     * Returns:
+     * {Float} The area of the collection by summing its parts
+     */
+    getArea: function() {
+        //to be overridden by geometries that actually have an area
+        //
+        return 0.0;
+    },
+    
+    /**
+     * APIMethod: getCentroid
+     * Calculate the centroid of this geometry. This method is defined in subclasses.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Point>} The centroid of the collection
+     */
+    getCentroid: function() {
+        return null;
+    },
+
+    /**
+     * Method: toString
+     * Returns the Well-Known Text representation of a geometry
+     *
+     * Returns:
+     * {String} Well-Known Text
+     */
+    toString: function() {
+        return OpenLayers.Format.WKT.prototype.write(
+            new OpenLayers.Feature.Vector(this)
+        );
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry"
+});
+
+/**
+ * Function: OpenLayers.Geometry.fromWKT
+ * Generate a geometry given a Well-Known Text string.
+ *
+ * Parameters:
+ * wkt - {String} A string representing the geometry in Well-Known Text.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry of the appropriate class.
+ */
+OpenLayers.Geometry.fromWKT = function(wkt) {
+    var format = arguments.callee.format;
+    if(!format) {
+        format = new OpenLayers.Format.WKT();
+        arguments.callee.format = format;
+    }
+    var geom;
+    var result = format.read(wkt);
+    if(result instanceof OpenLayers.Feature.Vector) {
+        geom = result.geometry;
+    } else if(OpenLayers.Util.isArray(result)) {
+        var len = result.length;
+        var components = new Array(len);
+        for(var i=0; i<len; ++i) {
+            components[i] = result[i].geometry;
+        }
+        geom = new OpenLayers.Geometry.Collection(components);
+    }
+    return geom;
+};
+    
+/**
+ * Method: OpenLayers.Geometry.segmentsIntersect
+ * Determine whether two line segments intersect.  Optionally calculates
+ *     and returns the intersection point.  This function is optimized for
+ *     cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1.  In those
+ *     obvious cases where there is no intersection, the function should
+ *     not be called.
+ *
+ * Parameters:
+ * seg1 - {Object} Object representing a segment with properties x1, y1, x2,
+ *     and y2.  The start point is represented by x1 and y1.  The end point
+ *     is represented by x2 and y2.  Start and end are ordered so that x1 < x2.
+ * seg2 - {Object} Object representing a segment with properties x1, y1, x2,
+ *     and y2.  The start point is represented by x1 and y1.  The end point
+ *     is represented by x2 and y2.  Start and end are ordered so that x1 < x2.
+ * options - {Object} Optional properties for calculating the intersection.
+ *
+ * Valid options:
+ * point - {Boolean} Return the intersection point.  If false, the actual
+ *     intersection point will not be calculated.  If true and the segments
+ *     intersect, the intersection point will be returned.  If true and
+ *     the segments do not intersect, false will be returned.  If true and
+ *     the segments are coincident, true will be returned.
+ * tolerance - {Number} If a non-null value is provided, if the segments are
+ *     within the tolerance distance, this will be considered an intersection.
+ *     In addition, if the point option is true and the calculated intersection
+ *     is within the tolerance distance of an end point, the endpoint will be
+ *     returned instead of the calculated intersection.  Further, if the
+ *     intersection is within the tolerance of endpoints on both segments, or
+ *     if two segment endpoints are within the tolerance distance of eachother
+ *     (but no intersection is otherwise calculated), an endpoint on the
+ *     first segment provided will be returned.
+ *
+ * Returns:
+ * {Boolean | <OpenLayers.Geometry.Point>}  The two segments intersect.
+ *     If the point argument is true, the return will be the intersection
+ *     point or false if none exists.  If point is true and the segments
+ *     are coincident, return will be true (and the instersection is equal
+ *     to the shorter segment).
+ */
+OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {
+    var point = options && options.point;
+    var tolerance = options && options.tolerance;
+    var intersection = false;
+    var x11_21 = seg1.x1 - seg2.x1;
+    var y11_21 = seg1.y1 - seg2.y1;
+    var x12_11 = seg1.x2 - seg1.x1;
+    var y12_11 = seg1.y2 - seg1.y1;
+    var y22_21 = seg2.y2 - seg2.y1;
+    var x22_21 = seg2.x2 - seg2.x1;
+    var d = (y22_21 * x12_11) - (x22_21 * y12_11);
+    var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);
+    var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);
+    if(d == 0) {
+        // parallel
+        if(n1 == 0 && n2 == 0) {
+            // coincident
+            intersection = true;
+        }
+    } else {
+        var along1 = n1 / d;
+        var along2 = n2 / d;
+        if(along1 >= 0 && along1 <= 1 && along2 >=0 && along2 <= 1) {
+            // intersect
+            if(!point) {
+                intersection = true;
+            } else {
+                // calculate the intersection point
+                var x = seg1.x1 + (along1 * x12_11);
+                var y = seg1.y1 + (along1 * y12_11);
+                intersection = new OpenLayers.Geometry.Point(x, y);
+            }
+        }
+    }
+    if(tolerance) {
+        var dist;
+        if(intersection) {
+            if(point) {
+                var segs = [seg1, seg2];
+                var seg, x, y;
+                // check segment endpoints for proximity to intersection
+                // set intersection to first endpoint within the tolerance
+                outer: for(var i=0; i<2; ++i) {
+                    seg = segs[i];
+                    for(var j=1; j<3; ++j) {
+                        x = seg["x" + j];
+                        y = seg["y" + j];
+                        dist = Math.sqrt(
+                            Math.pow(x - intersection.x, 2) +
+                            Math.pow(y - intersection.y, 2)
+                        );
+                        if(dist < tolerance) {
+                            intersection.x = x;
+                            intersection.y = y;
+                            break outer;
+                        }
+                    }
+                }
+                
+            }
+        } else {
+            // no calculated intersection, but segments could be within
+            // the tolerance of one another
+            var segs = [seg1, seg2];
+            var source, target, x, y, p, result;
+            // check segment endpoints for proximity to intersection
+            // set intersection to first endpoint within the tolerance
+            outer: for(var i=0; i<2; ++i) {
+                source = segs[i];
+                target = segs[(i+1)%2];
+                for(var j=1; j<3; ++j) {
+                    p = {x: source["x"+j], y: source["y"+j]};
+                    result = OpenLayers.Geometry.distanceToSegment(p, target);
+                    if(result.distance < tolerance) {
+                        if(point) {
+                            intersection = new OpenLayers.Geometry.Point(p.x, p.y);
+                        } else {
+                            intersection = true;
+                        }
+                        break outer;
+                    }
+                }
+            }
+        }
+    }
+    return intersection;
+};
+
+/**
+ * Function: OpenLayers.Geometry.distanceToSegment
+ *
+ * Parameters:
+ * point - {Object} An object with x and y properties representing the
+ *     point coordinates.
+ * segment - {Object} An object with x1, y1, x2, and y2 properties
+ *     representing endpoint coordinates.
+ *
+ * Returns:
+ * {Object} An object with distance, x, and y properties.  The distance
+ *     will be the shortest distance between the input point and segment.
+ *     The x and y properties represent the coordinates along the segment
+ *     where the shortest distance meets the segment.
+ */
+OpenLayers.Geometry.distanceToSegment = function(point, segment) {
+    var x0 = point.x;
+    var y0 = point.y;
+    var x1 = segment.x1;
+    var y1 = segment.y1;
+    var x2 = segment.x2;
+    var y2 = segment.y2;
+    var dx = x2 - x1;
+    var dy = y2 - y1;
+    var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
+                (Math.pow(dx, 2) + Math.pow(dy, 2));
+    var x, y;
+    if(along <= 0.0) {
+        x = x1;
+        y = y1;
+    } else if(along >= 1.0) {
+        x = x2;
+        y = y2;
+    } else {
+        x = x1 + along * dx;
+        y = y1 + along * dy;
+    }
+    return {
+        distance: Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)),
+        x: x, y: y
+    };
+};
+/* ======================================================================
+    OpenLayers/Geometry/Point.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.Point
+ * Point geometry class. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Geometry> 
+ */
+OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, {
+
+    /** 
+     * APIProperty: x 
+     * {float} 
+     */
+    x: null,
+
+    /** 
+     * APIProperty: y 
+     * {float} 
+     */
+    y: null,
+
+    /**
+     * Constructor: OpenLayers.Geometry.Point
+     * Construct a point geometry.
+     *
+     * Parameters:
+     * x - {float} 
+     * y - {float}
+     * 
+     */
+    initialize: function(x, y) {
+        OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
+        
+        this.x = parseFloat(x);
+        this.y = parseFloat(y);
+    },
+
+    /**
+     * APIMethod: clone
+     * 
+     * Returns:
+     * {<OpenLayers.Geometry.Point>} An exact clone of this OpenLayers.Geometry.Point
+     */
+    clone: function(obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Geometry.Point(this.x, this.y);
+        }
+
+        // catch any randomly tagged-on properties
+        OpenLayers.Util.applyDefaults(obj, this);
+
+        return obj;
+    },
+
+    /** 
+     * Method: calculateBounds
+     * Create a new Bounds based on the lon/lat
+     */
+    calculateBounds: function () {
+        this.bounds = new OpenLayers.Bounds(this.x, this.y,
+                                            this.x, this.y);
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries (on the x-y plane).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var details = edge && options && options.details;
+        var distance, x0, y0, x1, y1, result;
+        if(geometry instanceof OpenLayers.Geometry.Point) {
+            x0 = this.x;
+            y0 = this.y;
+            x1 = geometry.x;
+            y1 = geometry.y;
+            distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
+            result = !details ?
+                distance : {x0: x0, y0: y0, x1: x1, y1: y1, distance: distance};
+        } else {
+            result = geometry.distanceTo(this, options);
+            if(details) {
+                // switch coord order since this geom is target
+                result = {
+                    x0: result.x1, y0: result.y1,
+                    x1: result.x0, y1: result.y0,
+                    distance: result.distance
+                };
+            }
+        }
+        return result;
+    },
+    
+    /** 
+     * APIMethod: equals
+     * Determine whether another geometry is equivalent to this one.  Geometries
+     *     are considered equivalent if all components have the same coordinates.
+     * 
+     * Parameters:
+     * geom - {<OpenLayers.Geometry.Point>} The geometry to test. 
+     *
+     * Returns:
+     * {Boolean} The supplied geometry is equivalent to this geometry.
+     */
+    equals: function(geom) {
+        var equals = false;
+        if (geom != null) {
+            equals = ((this.x == geom.x && this.y == geom.y) ||
+                      (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y)));
+        }
+        return equals;
+    },
+    
+    /**
+     * Method: toShortString
+     *
+     * Returns:
+     * {String} Shortened String representation of Point object. 
+     *         (ex. <i>"5, 42"</i>)
+     */
+    toShortString: function() {
+        return (this.x + ", " + this.y);
+    },
+    
+    /**
+     * APIMethod: move
+     * Moves a geometry by the given displacement along positive x and y axes.
+     *     This modifies the position of the geometry and clears the cached
+     *     bounds.
+     *
+     * Parameters:
+     * x - {Float} Distance to move geometry in positive x direction. 
+     * y - {Float} Distance to move geometry in positive y direction.
+     */
+    move: function(x, y) {
+        this.x = this.x + x;
+        this.y = this.y + y;
+        this.clearBounds();
+    },
+
+    /**
+     * APIMethod: rotate
+     * Rotate a point around another.
+     *
+     * Parameters:
+     * angle - {Float} Rotation angle in degrees (measured counterclockwise
+     *                 from the positive x-axis)
+     * origin - {<OpenLayers.Geometry.Point>} Center point for the rotation
+     */
+    rotate: function(angle, origin) {
+        angle *= Math.PI / 180;
+        var radius = this.distanceTo(origin);
+        var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x);
+        this.x = origin.x + (radius * Math.cos(theta));
+        this.y = origin.y + (radius * Math.sin(theta));
+        this.clearBounds();
+    },
+    
+    /**
+     * APIMethod: getCentroid
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Point>} The centroid of the collection
+     */
+    getCentroid: function() {
+        return new OpenLayers.Geometry.Point(this.x, this.y);
+    },
+
+    /**
+     * APIMethod: resize
+     * Resize a point relative to some origin.  For points, this has the effect
+     *     of scaling a vector (from the origin to the point).  This method is
+     *     more useful on geometry collection subclasses.
+     *
+     * Parameters:
+     * scale - {Float} Ratio of the new distance from the origin to the old
+     *                 distance from the origin.  A scale of 2 doubles the
+     *                 distance between the point and origin.
+     * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
+     * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
+     */
+    resize: function(scale, origin, ratio) {
+        ratio = (ratio == undefined) ? 1 : ratio;
+        this.x = origin.x + (scale * ratio * (this.x - origin.x));
+        this.y = origin.y + (scale * (this.y - origin.y));
+        this.clearBounds();
+        return this;
+    },
+    
+    /**
+     * APIMethod: intersects
+     * Determine if the input geometry intersects this one.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
+     *
+     * Returns:
+     * {Boolean} The input geometry intersects this one.
+     */
+    intersects: function(geometry) {
+        var intersect = false;
+        if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+            intersect = this.equals(geometry);
+        } else {
+            intersect = geometry.intersects(this);
+        }
+        return intersect;
+    },
+    
+    /**
+     * APIMethod: transform
+     * Translate the x,y properties of the point from source to dest.
+     * 
+     * Parameters:
+     * source - {<OpenLayers.Projection>} 
+     * dest - {<OpenLayers.Projection>}
+     * 
+     * Returns:
+     * {<OpenLayers.Geometry>} 
+     */
+    transform: function(source, dest) {
+        if ((source && dest)) {
+            OpenLayers.Projection.transform(
+                this, source, dest); 
+            this.bounds = null;
+        }       
+        return this;
+    },
+
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        return [this];
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.Point"
+});
+/* ======================================================================
+    OpenLayers/Geometry/Collection.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.Collection
+ * A Collection is exactly what it sounds like: A collection of different 
+ * Geometries. These are stored in the local parameter <components> (which
+ * can be passed as a parameter to the constructor). 
+ * 
+ * As new geometries are added to the collection, they are NOT cloned. 
+ * When removing geometries, they need to be specified by reference (ie you 
+ * have to pass in the *exact* geometry to be removed).
+ * 
+ * The <getArea> and <getLength> functions here merely iterate through
+ * the components, summing their respective areas and lengths.
+ *
+ * Create a new instance with the <OpenLayers.Geometry.Collection> constructor.
+ *
+ * Inerhits from:
+ *  - <OpenLayers.Geometry> 
+ */
+OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {
+
+    /**
+     * APIProperty: components
+     * {Array(<OpenLayers.Geometry>)} The component parts of this geometry
+     */
+    components: null,
+    
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of
+     * components that the collection can include.  A null value means the
+     * component types are not restricted.
+     */
+    componentTypes: null,
+
+    /**
+     * Constructor: OpenLayers.Geometry.Collection
+     * Creates a Geometry Collection -- a list of geoms.
+     *
+     * Parameters: 
+     * components - {Array(<OpenLayers.Geometry>)} Optional array of geometries
+     *
+     */
+    initialize: function (components) {
+        OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
+        this.components = [];
+        if (components != null) {
+            this.addComponents(components);
+        }
+    },
+
+    /**
+     * APIMethod: destroy
+     * Destroy this geometry.
+     */
+    destroy: function () {
+        this.components.length = 0;
+        this.components = null;
+        OpenLayers.Geometry.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: clone
+     * Clone this geometry.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Collection>} An exact clone of this collection
+     */
+    clone: function() {
+        var geometry = eval("new " + this.CLASS_NAME + "()");
+        for(var i=0, len=this.components.length; i<len; i++) {
+            geometry.addComponent(this.components[i].clone());
+        }
+        
+        // catch any randomly tagged-on properties
+        OpenLayers.Util.applyDefaults(geometry, this);
+        
+        return geometry;
+    },
+
+    /**
+     * Method: getComponentsString
+     * Get a string representing the components for this collection
+     * 
+     * Returns:
+     * {String} A string representation of the components of this geometry
+     */
+    getComponentsString: function(){
+        var strings = [];
+        for(var i=0, len=this.components.length; i<len; i++) {
+            strings.push(this.components[i].toShortString()); 
+        }
+        return strings.join(",");
+    },
+
+    /**
+     * APIMethod: calculateBounds
+     * Recalculate the bounds by iterating through the components and 
+     * calling calling extendBounds() on each item.
+     */
+    calculateBounds: function() {
+        this.bounds = null;
+        var bounds = new OpenLayers.Bounds();
+        var components = this.components;
+        if (components) {
+            for (var i=0, len=components.length; i<len; i++) {
+                bounds.extend(components[i].getBounds());
+            }
+        }
+        // to preserve old behavior, we only set bounds if non-null
+        // in the future, we could add bounds.isEmpty()
+        if (bounds.left != null && bounds.bottom != null && 
+            bounds.right != null && bounds.top != null) {
+            this.setBounds(bounds);
+        }
+    },
+
+    /**
+     * APIMethod: addComponents
+     * Add components to this geometry.
+     *
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry>)} An array of geometries to add
+     */
+    addComponents: function(components){
+        if(!(OpenLayers.Util.isArray(components))) {
+            components = [components];
+        }
+        for(var i=0, len=components.length; i<len; i++) {
+            this.addComponent(components[i]);
+        }
+    },
+
+    /**
+     * Method: addComponent
+     * Add a new component (geometry) to the collection.  If this.componentTypes
+     * is set, then the component class name must be in the componentTypes array.
+     *
+     * The bounds cache is reset.
+     * 
+     * Parameters:
+     * component - {<OpenLayers.Geometry>} A geometry to add
+     * index - {int} Optional index into the array to insert the component
+     *
+     * Returns:
+     * {Boolean} The component geometry was successfully added
+     */    
+    addComponent: function(component, index) {
+        var added = false;
+        if(component) {
+            if(this.componentTypes == null ||
+               (OpenLayers.Util.indexOf(this.componentTypes,
+                                        component.CLASS_NAME) > -1)) {
+
+                if(index != null && (index < this.components.length)) {
+                    var components1 = this.components.slice(0, index);
+                    var components2 = this.components.slice(index, 
+                                                           this.components.length);
+                    components1.push(component);
+                    this.components = components1.concat(components2);
+                } else {
+                    this.components.push(component);
+                }
+                component.parent = this;
+                this.clearBounds();
+                added = true;
+            }
+        }
+        return added;
+    },
+    
+    /**
+     * APIMethod: removeComponents
+     * Remove components from this geometry.
+     *
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry>)} The components to be removed
+     *
+     * Returns: 
+     * {Boolean} A component was removed.
+     */
+    removeComponents: function(components) {
+        var removed = false;
+
+        if(!(OpenLayers.Util.isArray(components))) {
+            components = [components];
+        }
+        for(var i=components.length-1; i>=0; --i) {
+            removed = this.removeComponent(components[i]) || removed;
+        }
+        return removed;
+    },
+    
+    /**
+     * Method: removeComponent
+     * Remove a component from this geometry.
+     *
+     * Parameters:
+     * component - {<OpenLayers.Geometry>} 
+     *
+     * Returns: 
+     * {Boolean} The component was removed.
+     */
+    removeComponent: function(component) {
+        
+        OpenLayers.Util.removeItem(this.components, component);
+        
+        // clearBounds() so that it gets recalculated on the next call
+        // to this.getBounds();
+        this.clearBounds();
+        return true;
+    },
+
+    /**
+     * APIMethod: getLength
+     * Calculate the length of this geometry
+     *
+     * Returns:
+     * {Float} The length of the geometry
+     */
+    getLength: function() {
+        var length = 0.0;
+        for (var i=0, len=this.components.length; i<len; i++) {
+            length += this.components[i].getLength();
+        }
+        return length;
+    },
+    
+    /**
+     * APIMethod: getArea
+     * Calculate the area of this geometry. Note how this function is overridden
+     * in <OpenLayers.Geometry.Polygon>.
+     *
+     * Returns:
+     * {Float} The area of the collection by summing its parts
+     */
+    getArea: function() {
+        var area = 0.0;
+        for (var i=0, len=this.components.length; i<len; i++) {
+            area += this.components[i].getArea();
+        }
+        return area;
+    },
+
+    /** 
+     * APIMethod: getGeodesicArea
+     * Calculate the approximate area of the polygon were it projected onto
+     *     the earth.
+     *
+     * Parameters:
+     * projection - {<OpenLayers.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Reference:
+     * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+     *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+     *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+     *
+     * Returns:
+     * {float} The approximate geodesic area of the geometry in square meters.
+     */
+    getGeodesicArea: function(projection) {
+        var area = 0.0;
+        for(var i=0, len=this.components.length; i<len; i++) {
+            area += this.components[i].getGeodesicArea(projection);
+        }
+        return area;
+    },
+    
+    /**
+     * APIMethod: getCentroid
+     *
+     * Compute the centroid for this geometry collection.
+     *
+     * Parameters:
+     * weighted - {Boolean} Perform the getCentroid computation recursively,
+     * returning an area weighted average of all geometries in this collection.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Point>} The centroid of the collection
+     */
+    getCentroid: function(weighted) {
+        if (!weighted) {
+            return this.components.length && this.components[0].getCentroid();
+        }
+        var len = this.components.length;
+        if (!len) {
+            return false;
+        }
+        
+        var areas = [];
+        var centroids = [];
+        var areaSum = 0;
+        var minArea = Number.MAX_VALUE;
+        var component;
+        for (var i=0; i<len; ++i) {
+            component = this.components[i];
+            var area = component.getArea();
+            var centroid = component.getCentroid(true);
+            if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) {
+                continue;
+            }
+            areas.push(area);
+            areaSum += area;
+            minArea = (area < minArea && area > 0) ? area : minArea;
+            centroids.push(centroid);
+        }
+        len = areas.length;
+        if (areaSum === 0) {
+            // all the components in this collection have 0 area
+            // probably a collection of points -- weight all the points the same
+            for (var i=0; i<len; ++i) {
+                areas[i] = 1;
+            }
+            areaSum = areas.length;
+        } else {
+            // normalize all the areas where the smallest area will get
+            // a value of 1
+            for (var i=0; i<len; ++i) {
+                areas[i] /= minArea;
+            }
+            areaSum /= minArea;
+        }
+        
+        var xSum = 0, ySum = 0, centroid, area;
+        for (var i=0; i<len; ++i) {
+            centroid = centroids[i];
+            area = areas[i];
+            xSum += centroid.x * area;
+            ySum += centroid.y * area;
+        }
+        
+        return new OpenLayers.Geometry.Point(xSum/areaSum, ySum/areaSum);
+    },
+
+    /**
+     * APIMethod: getGeodesicLength
+     * Calculate the approximate length of the geometry were it projected onto
+     *     the earth.
+     *
+     * projection - {<OpenLayers.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Returns:
+     * {Float} The appoximate geodesic length of the geometry in meters.
+     */
+    getGeodesicLength: function(projection) {
+        var length = 0.0;
+        for(var i=0, len=this.components.length; i<len; i++) {
+            length += this.components[i].getGeodesicLength(projection);
+        }
+        return length;
+    },
+
+    /**
+     * APIMethod: move
+     * Moves a geometry by the given displacement along positive x and y axes.
+     *     This modifies the position of the geometry and clears the cached
+     *     bounds.
+     *
+     * Parameters:
+     * x - {Float} Distance to move geometry in positive x direction. 
+     * y - {Float} Distance to move geometry in positive y direction.
+     */
+    move: function(x, y) {
+        for(var i=0, len=this.components.length; i<len; i++) {
+            this.components[i].move(x, y);
+        }
+    },
+
+    /**
+     * APIMethod: rotate
+     * Rotate a geometry around some origin
+     *
+     * Parameters:
+     * angle - {Float} Rotation angle in degrees (measured counterclockwise
+     *                 from the positive x-axis)
+     * origin - {<OpenLayers.Geometry.Point>} Center point for the rotation
+     */
+    rotate: function(angle, origin) {
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            this.components[i].rotate(angle, origin);
+        }
+    },
+
+    /**
+     * APIMethod: resize
+     * Resize a geometry relative to some origin.  Use this method to apply
+     *     a uniform scaling to a geometry.
+     *
+     * Parameters:
+     * scale - {Float} Factor by which to scale the geometry.  A scale of 2
+     *                 doubles the size of the geometry in each dimension
+     *                 (lines, for example, will be twice as long, and polygons
+     *                 will have four times the area).
+     * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
+     * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
+     */
+    resize: function(scale, origin, ratio) {
+        for(var i=0; i<this.components.length; ++i) {
+            this.components[i].resize(scale, origin, ratio);
+        }
+        return this;
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries (on the x-y plane).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and y1 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var details = edge && options && options.details;
+        var result, best, distance;
+        var min = Number.POSITIVE_INFINITY;
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            result = this.components[i].distanceTo(geometry, options);
+            distance = details ? result.distance : result;
+            if(distance < min) {
+                min = distance;
+                best = result;
+                if(min == 0) {
+                    break;
+                }
+            }
+        }
+        return best;
+    },
+
+    /** 
+     * APIMethod: equals
+     * Determine whether another geometry is equivalent to this one.  Geometries
+     *     are considered equivalent if all components have the same coordinates.
+     * 
+     * Parameters:
+     * geom - {<OpenLayers.Geometry>} The geometry to test. 
+     *
+     * Returns:
+     * {Boolean} The supplied geometry is equivalent to this geometry.
+     */
+    equals: function(geometry) {
+        var equivalent = true;
+        if(!geometry || !geometry.CLASS_NAME ||
+           (this.CLASS_NAME != geometry.CLASS_NAME)) {
+            equivalent = false;
+        } else if(!(OpenLayers.Util.isArray(geometry.components)) ||
+                  (geometry.components.length != this.components.length)) {
+            equivalent = false;
+        } else {
+            for(var i=0, len=this.components.length; i<len; ++i) {
+                if(!this.components[i].equals(geometry.components[i])) {
+                    equivalent = false;
+                    break;
+                }
+            }
+        }
+        return equivalent;
+    },
+
+    /**
+     * APIMethod: transform
+     * Reproject the components geometry from source to dest.
+     * 
+     * Parameters:
+     * source - {<OpenLayers.Projection>} 
+     * dest - {<OpenLayers.Projection>}
+     * 
+     * Returns:
+     * {<OpenLayers.Geometry>} 
+     */
+    transform: function(source, dest) {
+        if (source && dest) {
+            for (var i=0, len=this.components.length; i<len; i++) {  
+                var component = this.components[i];
+                component.transform(source, dest);
+            }
+            this.bounds = null;
+        }
+        return this;
+    },
+
+    /**
+     * APIMethod: intersects
+     * Determine if the input geometry intersects this one.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
+     *
+     * Returns:
+     * {Boolean} The input geometry intersects this one.
+     */
+    intersects: function(geometry) {
+        var intersect = false;
+        for(var i=0, len=this.components.length; i<len; ++ i) {
+            intersect = geometry.intersects(this.components[i]);
+            if(intersect) {
+                break;
+            }
+        }
+        return intersect;
+    },
+
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        var vertices = [];
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            Array.prototype.push.apply(
+                vertices, this.components[i].getVertices(nodes)
+            );
+        }
+        return vertices;
+    },
+
+
+    CLASS_NAME: "OpenLayers.Geometry.Collection"
+});
+/* ======================================================================
+    OpenLayers/Geometry/MultiPoint.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.MultiPoint
+ * MultiPoint is a collection of Points.  Create a new instance with the
+ * <OpenLayers.Geometry.MultiPoint> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Geometry.Collection>
+ *  - <OpenLayers.Geometry>
+ */
+OpenLayers.Geometry.MultiPoint = OpenLayers.Class(
+  OpenLayers.Geometry.Collection, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of
+     * components that the collection can include.  A null value means the
+     * component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.Point"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.MultiPoint
+     * Create a new MultiPoint Geometry
+     *
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry.Point>)} 
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.MultiPoint>}
+     */
+    initialize: function(components) {
+        OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
+                                                                  arguments);
+    },
+
+    /**
+     * APIMethod: addPoint
+     * Wrapper for <OpenLayers.Geometry.Collection.addComponent>
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>} Point to be added
+     * index - {Integer} Optional index
+     */
+    addPoint: function(point, index) {
+        this.addComponent(point, index);
+    },
+    
+    /**
+     * APIMethod: removePoint
+     * Wrapper for <OpenLayers.Geometry.Collection.removeComponent>
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>} Point to be removed
+     */
+    removePoint: function(point){
+        this.removeComponent(point);
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.MultiPoint"
+});
+/* ======================================================================
+    OpenLayers/Geometry/Curve.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.Curve
+ * A Curve is a MultiPoint, whose points are assumed to be connected. To 
+ * this end, we provide a "getLength()" function, which iterates through 
+ * the points, summing the distances between them. 
+ * 
+ * Inherits: 
+ *  - <OpenLayers.Geometry.MultiPoint>
+ */
+OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of 
+     *                 components that the collection can include.  A null 
+     *                 value means the component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.Point"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.Curve
+     * 
+     * Parameters:
+     * point - {Array(<OpenLayers.Geometry.Point>)}
+     */
+    initialize: function(points) {
+        OpenLayers.Geometry.MultiPoint.prototype.initialize.apply(this, 
+                                                                  arguments);
+    },
+    
+    /**
+     * APIMethod: getLength
+     * 
+     * Returns:
+     * {Float} The length of the curve
+     */
+    getLength: function() {
+        var length = 0.0;
+        if ( this.components && (this.components.length > 1)) {
+            for(var i=1, len=this.components.length; i<len; i++) {
+                length += this.components[i-1].distanceTo(this.components[i]);
+            }
+        }
+        return length;
+    },
+
+    /**
+     * APIMethod: getGeodesicLength
+     * Calculate the approximate length of the geometry were it projected onto
+     *     the earth.
+     *
+     * projection - {<OpenLayers.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Returns:
+     * {Float} The appoximate geodesic length of the geometry in meters.
+     */
+    getGeodesicLength: function(projection) {
+        var geom = this;  // so we can work with a clone if needed
+        if(projection) {
+            var gg = new OpenLayers.Projection("EPSG:4326");
+            if(!gg.equals(projection)) {
+                geom = this.clone().transform(projection, gg);
+            }
+        }
+        var length = 0.0;
+        if(geom.components && (geom.components.length > 1)) {
+            var p1, p2;
+            for(var i=1, len=geom.components.length; i<len; i++) {
+                p1 = geom.components[i-1];
+                p2 = geom.components[i];
+                // this returns km and requires lon/lat properties
+                length += OpenLayers.Util.distVincenty(
+                    {lon: p1.x, lat: p1.y}, {lon: p2.x, lat: p2.y}
+                );
+            }
+        }
+        // convert to m
+        return length * 1000;
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.Curve"
+});
+/* ======================================================================
+    OpenLayers/Geometry/LineString.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/Curve.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.LineString
+ * A LineString is a Curve which, once two points have been added to it, can 
+ * never be less than two points long.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Geometry.Curve>
+ */
+OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
+
+    /**
+     * Constructor: OpenLayers.Geometry.LineString
+     * Create a new LineString geometry
+     *
+     * Parameters:
+     * points - {Array(<OpenLayers.Geometry.Point>)} An array of points used to
+     *          generate the linestring
+     *
+     */
+    initialize: function(points) {
+        OpenLayers.Geometry.Curve.prototype.initialize.apply(this, arguments);        
+    },
+
+    /**
+     * APIMethod: removeComponent
+     * Only allows removal of a point if there are three or more points in 
+     * the linestring. (otherwise the result would be just a single point)
+     *
+     * Parameters: 
+     * point - {<OpenLayers.Geometry.Point>} The point to be removed
+     *
+     * Returns: 
+     * {Boolean} The component was removed.
+     */
+    removeComponent: function(point) {
+        var removed = this.components && (this.components.length > 2);
+        if (removed) {
+            OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, 
+                                                                  arguments);
+        }
+        return removed;
+    },
+    
+    /**
+     * APIMethod: intersects
+     * Test for instersection between two geometries.  This is a cheapo
+     *     implementation of the Bently-Ottmann algorigithm.  It doesn't
+     *     really keep track of a sweep line data structure.  It is closer
+     *     to the brute force method, except that segments are sorted and
+     *     potential intersections are only calculated when bounding boxes
+     *     intersect.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {Boolean} The input geometry intersects this geometry.
+     */
+    intersects: function(geometry) {
+        var intersect = false;
+        var type = geometry.CLASS_NAME;
+        if(type == "OpenLayers.Geometry.LineString" ||
+           type == "OpenLayers.Geometry.LinearRing" ||
+           type == "OpenLayers.Geometry.Point") {
+            var segs1 = this.getSortedSegments();
+            var segs2;
+            if(type == "OpenLayers.Geometry.Point") {
+                segs2 = [{
+                    x1: geometry.x, y1: geometry.y,
+                    x2: geometry.x, y2: geometry.y
+                }];
+            } else {
+                segs2 = geometry.getSortedSegments();
+            }
+            var seg1, seg1x1, seg1x2, seg1y1, seg1y2,
+                seg2, seg2y1, seg2y2;
+            // sweep right
+            outer: for(var i=0, len=segs1.length; i<len; ++i) {
+                seg1 = segs1[i];
+                seg1x1 = seg1.x1;
+                seg1x2 = seg1.x2;
+                seg1y1 = seg1.y1;
+                seg1y2 = seg1.y2;
+                inner: for(var j=0, jlen=segs2.length; j<jlen; ++j) {
+                    seg2 = segs2[j];
+                    if(seg2.x1 > seg1x2) {
+                        // seg1 still left of seg2
+                        break;
+                    }
+                    if(seg2.x2 < seg1x1) {
+                        // seg2 still left of seg1
+                        continue;
+                    }
+                    seg2y1 = seg2.y1;
+                    seg2y2 = seg2.y2;
+                    if(Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) {
+                        // seg2 above seg1
+                        continue;
+                    }
+                    if(Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) {
+                        // seg2 below seg1
+                        continue;
+                    }
+                    if(OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) {
+                        intersect = true;
+                        break outer;
+                    }
+                }
+            }
+        } else {
+            intersect = geometry.intersects(this);
+        }
+        return intersect;
+    },
+    
+    /**
+     * Method: getSortedSegments
+     *
+     * Returns:
+     * {Array} An array of segment objects.  Segment objects have properties
+     *     x1, y1, x2, and y2.  The start point is represented by x1 and y1.
+     *     The end point is represented by x2 and y2.  Start and end are
+     *     ordered so that x1 < x2.
+     */
+    getSortedSegments: function() {
+        var numSeg = this.components.length - 1;
+        var segments = new Array(numSeg), point1, point2;
+        for(var i=0; i<numSeg; ++i) {
+            point1 = this.components[i];
+            point2 = this.components[i + 1];
+            if(point1.x < point2.x) {
+                segments[i] = {
+                    x1: point1.x,
+                    y1: point1.y,
+                    x2: point2.x,
+                    y2: point2.y
+                };
+            } else {
+                segments[i] = {
+                    x1: point2.x,
+                    y1: point2.y,
+                    x2: point1.x,
+                    y2: point1.y
+                };
+            }
+        }
+        // more efficient to define this somewhere static
+        function byX1(seg1, seg2) {
+            return seg1.x1 - seg2.x1;
+        }
+        return segments.sort(byX1);
+    },
+    
+    /**
+     * Method: splitWithSegment
+     * Split this geometry with the given segment.
+     *
+     * Parameters:
+     * seg - {Object} An object with x1, y1, x2, and y2 properties referencing
+     *     segment endpoint coordinates.
+     * options - {Object} Properties of this object will be used to determine
+     *     how the split is conducted.
+     *
+     * Valid options:
+     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+     *     true.  If false, a vertex on the source segment must be within the
+     *     tolerance distance of the intersection to be considered a split.
+     * tolerance - {Number} If a non-null value is provided, intersections
+     *     within the tolerance distance of one of the source segment's
+     *     endpoints will be assumed to occur at the endpoint.
+     *
+     * Returns:
+     * {Object} An object with *lines* and *points* properties.  If the given
+     *     segment intersects this linestring, the lines array will reference
+     *     geometries that result from the split.  The points array will contain
+     *     all intersection points.  Intersection points are sorted along the
+     *     segment (in order from x1,y1 to x2,y2).
+     */
+    splitWithSegment: function(seg, options) {
+        var edge = !(options && options.edge === false);
+        var tolerance = options && options.tolerance;
+        var lines = [];
+        var verts = this.getVertices();
+        var points = [];
+        var intersections = [];
+        var split = false;
+        var vert1, vert2, point;
+        var node, vertex, target;
+        var interOptions = {point: true, tolerance: tolerance};
+        var result = null;
+        for(var i=0, stop=verts.length-2; i<=stop; ++i) {
+            vert1 = verts[i];
+            points.push(vert1.clone());
+            vert2 = verts[i+1];
+            target = {x1: vert1.x, y1: vert1.y, x2: vert2.x, y2: vert2.y};
+            point = OpenLayers.Geometry.segmentsIntersect(
+                seg, target, interOptions
+            );
+            if(point instanceof OpenLayers.Geometry.Point) {
+                if((point.x === seg.x1 && point.y === seg.y1) ||
+                   (point.x === seg.x2 && point.y === seg.y2) ||
+                   point.equals(vert1) || point.equals(vert2)) {
+                    vertex = true;
+                } else {
+                    vertex = false;
+                }
+                if(vertex || edge) {
+                    // push intersections different than the previous
+                    if(!point.equals(intersections[intersections.length-1])) {
+                        intersections.push(point.clone());
+                    }
+                    if(i === 0) {
+                        if(point.equals(vert1)) {
+                            continue;
+                        }
+                    }
+                    if(point.equals(vert2)) {
+                        continue;
+                    }
+                    split = true;
+                    if(!point.equals(vert1)) {
+                        points.push(point);
+                    }
+                    lines.push(new OpenLayers.Geometry.LineString(points));
+                    points = [point.clone()];
+                }
+            }
+        }
+        if(split) {
+            points.push(vert2.clone());
+            lines.push(new OpenLayers.Geometry.LineString(points));
+        }
+        if(intersections.length > 0) {
+            // sort intersections along segment
+            var xDir = seg.x1 < seg.x2 ? 1 : -1;
+            var yDir = seg.y1 < seg.y2 ? 1 : -1;
+            result = {
+                lines: lines,
+                points: intersections.sort(function(p1, p2) {
+                    return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);
+                })
+            };
+        }
+        return result;
+    },
+
+    /**
+     * Method: split
+     * Use this geometry (the source) to attempt to split a target geometry.
+     * 
+     * Parameters:
+     * target - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Properties of this object will be used to determine
+     *     how the split is conducted.
+     *
+     * Valid options:
+     * mutual - {Boolean} Split the source geometry in addition to the target
+     *     geometry.  Default is false.
+     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+     *     true.  If false, a vertex on the source must be within the tolerance
+     *     distance of the intersection to be considered a split.
+     * tolerance - {Number} If a non-null value is provided, intersections
+     *     within the tolerance distance of an existing vertex on the source
+     *     will be assumed to occur at the vertex.
+     * 
+     * Returns:
+     * {Array} A list of geometries (of this same type as the target) that
+     *     result from splitting the target with the source geometry.  The
+     *     source and target geometry will remain unmodified.  If no split
+     *     results, null will be returned.  If mutual is true and a split
+     *     results, return will be an array of two arrays - the first will be
+     *     all geometries that result from splitting the source geometry and
+     *     the second will be all geometries that result from splitting the
+     *     target geometry.
+     */
+    split: function(target, options) {
+        var results = null;
+        var mutual = options && options.mutual;
+        var sourceSplit, targetSplit, sourceParts, targetParts;
+        if(target instanceof OpenLayers.Geometry.LineString) {
+            var verts = this.getVertices();
+            var vert1, vert2, seg, splits, lines, point;
+            var points = [];
+            sourceParts = [];
+            for(var i=0, stop=verts.length-2; i<=stop; ++i) {
+                vert1 = verts[i];
+                vert2 = verts[i+1];
+                seg = {
+                    x1: vert1.x, y1: vert1.y,
+                    x2: vert2.x, y2: vert2.y
+                };
+                targetParts = targetParts || [target];
+                if(mutual) {
+                    points.push(vert1.clone());
+                }
+                for(var j=0; j<targetParts.length; ++j) {
+                    splits = targetParts[j].splitWithSegment(seg, options);
+                    if(splits) {
+                        // splice in new features
+                        lines = splits.lines;
+                        if(lines.length > 0) {
+                            lines.unshift(j, 1);
+                            Array.prototype.splice.apply(targetParts, lines);
+                            j += lines.length - 2;
+                        }
+                        if(mutual) {
+                            for(var k=0, len=splits.points.length; k<len; ++k) {
+                                point = splits.points[k];
+                                if(!point.equals(vert1)) {
+                                    points.push(point);
+                                    sourceParts.push(new OpenLayers.Geometry.LineString(points));
+                                    if(point.equals(vert2)) {
+                                        points = [];
+                                    } else {
+                                        points = [point.clone()];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if(mutual && sourceParts.length > 0 && points.length > 0) {
+                points.push(vert2.clone());
+                sourceParts.push(new OpenLayers.Geometry.LineString(points));
+            }
+        } else {
+            results = target.splitWith(this, options);
+        }
+        if(targetParts && targetParts.length > 1) {
+            targetSplit = true;
+        } else {
+            targetParts = [];
+        }
+        if(sourceParts && sourceParts.length > 1) {
+            sourceSplit = true;
+        } else {
+            sourceParts = [];
+        }
+        if(targetSplit || sourceSplit) {
+            if(mutual) {
+                results = [sourceParts, targetParts];
+            } else {
+                results = targetParts;
+            }
+        }
+        return results;
+    },
+
+    /**
+     * Method: splitWith
+     * Split this geometry (the target) with the given geometry (the source).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} A geometry used to split this
+     *     geometry (the source).
+     * options - {Object} Properties of this object will be used to determine
+     *     how the split is conducted.
+     *
+     * Valid options:
+     * mutual - {Boolean} Split the source geometry in addition to the target
+     *     geometry.  Default is false.
+     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+     *     true.  If false, a vertex on the source must be within the tolerance
+     *     distance of the intersection to be considered a split.
+     * tolerance - {Number} If a non-null value is provided, intersections
+     *     within the tolerance distance of an existing vertex on the source
+     *     will be assumed to occur at the vertex.
+     * 
+     * Returns:
+     * {Array} A list of geometries (of this same type as the target) that
+     *     result from splitting the target with the source geometry.  The
+     *     source and target geometry will remain unmodified.  If no split
+     *     results, null will be returned.  If mutual is true and a split
+     *     results, return will be an array of two arrays - the first will be
+     *     all geometries that result from splitting the source geometry and
+     *     the second will be all geometries that result from splitting the
+     *     target geometry.
+     */
+    splitWith: function(geometry, options) {
+        return geometry.split(this, options);
+
+    },
+
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        var vertices;
+        if(nodes === true) {
+            vertices = [
+                this.components[0],
+                this.components[this.components.length-1]
+            ];
+        } else if (nodes === false) {
+            vertices = this.components.slice(1, this.components.length-1);
+        } else {
+            vertices = this.components.slice();
+        }
+        return vertices;
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries (on the x-y plane).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var details = edge && options && options.details;
+        var result, best = {};
+        var min = Number.POSITIVE_INFINITY;
+        if(geometry instanceof OpenLayers.Geometry.Point) {
+            var segs = this.getSortedSegments();
+            var x = geometry.x;
+            var y = geometry.y;
+            var seg;
+            for(var i=0, len=segs.length; i<len; ++i) {
+                seg = segs[i];
+                result = OpenLayers.Geometry.distanceToSegment(geometry, seg);
+                if(result.distance < min) {
+                    min = result.distance;
+                    best = result;
+                    if(min === 0) {
+                        break;
+                    }
+                } else {
+                    // if distance increases and we cross y0 to the right of x0, no need to keep looking.
+                    if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) {
+                        break;
+                    }
+                }
+            }
+            if(details) {
+                best = {
+                    distance: best.distance,
+                    x0: best.x, y0: best.y,
+                    x1: x, y1: y
+                };
+            } else {
+                best = best.distance;
+            }
+        } else if(geometry instanceof OpenLayers.Geometry.LineString) { 
+            var segs0 = this.getSortedSegments();
+            var segs1 = geometry.getSortedSegments();
+            var seg0, seg1, intersection, x0, y0;
+            var len1 = segs1.length;
+            var interOptions = {point: true};
+            outer: for(var i=0, len=segs0.length; i<len; ++i) {
+                seg0 = segs0[i];
+                x0 = seg0.x1;
+                y0 = seg0.y1;
+                for(var j=0; j<len1; ++j) {
+                    seg1 = segs1[j];
+                    intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);
+                    if(intersection) {
+                        min = 0;
+                        best = {
+                            distance: 0,
+                            x0: intersection.x, y0: intersection.y,
+                            x1: intersection.x, y1: intersection.y
+                        };
+                        break outer;
+                    } else {
+                        result = OpenLayers.Geometry.distanceToSegment({x: x0, y: y0}, seg1);
+                        if(result.distance < min) {
+                            min = result.distance;
+                            best = {
+                                distance: min,
+                                x0: x0, y0: y0,
+                                x1: result.x, y1: result.y
+                            };
+                        }
+                    }
+                }
+            }
+            if(!details) {
+                best = best.distance;
+            }
+            if(min !== 0) {
+                // check the final vertex in this line's sorted segments
+                if(seg0) {
+                    result = geometry.distanceTo(
+                        new OpenLayers.Geometry.Point(seg0.x2, seg0.y2),
+                        options
+                    );
+                    var dist = details ? result.distance : result;
+                    if(dist < min) {
+                        if(details) {
+                            best = {
+                                distance: min,
+                                x0: result.x1, y0: result.y1,
+                                x1: result.x0, y1: result.y0
+                            };
+                        } else {
+                            best = dist;
+                        }
+                    }
+                }
+            }
+        } else {
+            best = geometry.distanceTo(this, options);
+            // swap since target comes from this line
+            if(details) {
+                best = {
+                    distance: best.distance,
+                    x0: best.x1, y0: best.y1,
+                    x1: best.x0, y1: best.y0
+                };
+            }
+        }
+        return best;
+    },
+    
+    /**
+     * APIMethod: simplify
+     * This function will return a simplified LineString.
+     * Simplification is based on the Douglas-Peucker algorithm.
+     *
+     *
+     * Parameters:
+     * tolerance - {number} threshhold for simplification in map units
+     *
+     * Returns:
+     * {OpenLayers.Geometry.LineString} the simplified LineString
+     */
+    simplify: function(tolerance){
+        if (this && this !== null) {
+            var points = this.getVertices();
+            if (points.length < 3) {
+                return this;
+            }
+    
+            var compareNumbers = function(a, b){
+                return (a-b);
+            };
+    
+            /**
+             * Private function doing the Douglas-Peucker reduction
+             */
+            var douglasPeuckerReduction = function(points, firstPoint, lastPoint, tolerance){
+                var maxDistance = 0;
+                var indexFarthest = 0;
+    
+                for (var index = firstPoint, distance; index < lastPoint; index++) {
+                    distance = perpendicularDistance(points[firstPoint], points[lastPoint], points[index]);
+                    if (distance > maxDistance) {
+                        maxDistance = distance;
+                        indexFarthest = index;
+                    }
+                }
+    
+                if (maxDistance > tolerance && indexFarthest != firstPoint) {
+                    //Add the largest point that exceeds the tolerance
+                    pointIndexsToKeep.push(indexFarthest);
+                    douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance);
+                    douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance);
+                }
+            };
+    
+            /**
+             * Private function calculating the perpendicular distance
+             * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower
+             */
+            var perpendicularDistance = function(point1, point2, point){
+                //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)|   *Area of triangle
+                //Base = v((x1-x2)²+(x1-x2)²)                               *Base of Triangle*
+                //Area = .5*Base*H                                          *Solve for height
+                //Height = Area/.5/Base
+    
+                var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y));
+                var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
+                var height = area / bottom * 2;
+    
+                return height;
+            };
+    
+            var firstPoint = 0;
+            var lastPoint = points.length - 1;
+            var pointIndexsToKeep = [];
+    
+            //Add the first and last index to the keepers
+            pointIndexsToKeep.push(firstPoint);
+            pointIndexsToKeep.push(lastPoint);
+    
+            //The first and the last point cannot be the same
+            while (points[firstPoint].equals(points[lastPoint])) {
+                lastPoint--;
+                //Addition: the first point not equal to first point in the LineString is kept as well
+                pointIndexsToKeep.push(lastPoint);
+            }
+    
+            douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance);
+            var returnPoints = [];
+            pointIndexsToKeep.sort(compareNumbers);
+            for (var index = 0; index < pointIndexsToKeep.length; index++) {
+                returnPoints.push(points[pointIndexsToKeep[index]]);
+            }
+            return new OpenLayers.Geometry.LineString(returnPoints);
+    
+        }
+        else {
+            return this;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.LineString"
+});
+/* ======================================================================
+    OpenLayers/Geometry/LinearRing.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/LineString.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.LinearRing
+ * 
+ * A Linear Ring is a special LineString which is closed. It closes itself 
+ * automatically on every addPoint/removePoint by adding a copy of the first
+ * point as the last point. 
+ * 
+ * Also, as it is the first in the line family to close itself, a getArea()
+ * function is defined to calculate the enclosed area of the linearRing
+ * 
+ * Inherits:
+ *  - <OpenLayers.Geometry.LineString>
+ */
+OpenLayers.Geometry.LinearRing = OpenLayers.Class(
+  OpenLayers.Geometry.LineString, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of 
+     *                 components that the collection can include.  A null 
+     *                 value means the component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.Point"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.LinearRing
+     * Linear rings are constructed with an array of points.  This array
+     *     can represent a closed or open ring.  If the ring is open (the last
+     *     point does not equal the first point), the constructor will close
+     *     the ring.  If the ring is already closed (the last point does equal
+     *     the first point), it will be left closed.
+     * 
+     * Parameters:
+     * points - {Array(<OpenLayers.Geometry.Point>)} points
+     */
+    initialize: function(points) {
+        OpenLayers.Geometry.LineString.prototype.initialize.apply(this, 
+                                                                  arguments);
+    },
+
+    /**
+     * APIMethod: addComponent
+     * Adds a point to geometry components.  If the point is to be added to
+     *     the end of the components array and it is the same as the last point
+     *     already in that array, the duplicate point is not added.  This has 
+     *     the effect of closing the ring if it is not already closed, and 
+     *     doing the right thing if it is already closed.  This behavior can 
+     *     be overridden by calling the method with a non-null index as the 
+     *     second argument.
+     *
+     * Parameter:
+     * point - {<OpenLayers.Geometry.Point>}
+     * index - {Integer} Index into the array to insert the component
+     * 
+     * Returns:
+     * {Boolean} Was the Point successfully added?
+     */
+    addComponent: function(point, index) {
+        var added = false;
+
+        //remove last point
+        var lastPoint = this.components.pop();
+
+        // given an index, add the point
+        // without an index only add non-duplicate points
+        if(index != null || !point.equals(lastPoint)) {
+            added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
+                                                                    arguments);
+        }
+
+        //append copy of first point
+        var firstPoint = this.components[0];
+        OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
+                                                                [firstPoint]);
+        
+        return added;
+    },
+    
+    /**
+     * APIMethod: removeComponent
+     * Removes a point from geometry components.
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     *
+     * Returns: 
+     * {Boolean} The component was removed.
+     */
+    removeComponent: function(point) {
+        var removed = this.components && (this.components.length > 3);
+        if (removed) {
+            //remove last point
+            this.components.pop();
+            
+            //remove our point
+            OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, 
+                                                                    arguments);
+            //append copy of first point
+            var firstPoint = this.components[0];
+            OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
+                                                                [firstPoint]);
+        }
+        return removed;
+    },
+    
+    /**
+     * APIMethod: move
+     * Moves a geometry by the given displacement along positive x and y axes.
+     *     This modifies the position of the geometry and clears the cached
+     *     bounds.
+     *
+     * Parameters:
+     * x - {Float} Distance to move geometry in positive x direction. 
+     * y - {Float} Distance to move geometry in positive y direction.
+     */
+    move: function(x, y) {
+        for(var i = 0, len=this.components.length; i<len - 1; i++) {
+            this.components[i].move(x, y);
+        }
+    },
+
+    /**
+     * APIMethod: rotate
+     * Rotate a geometry around some origin
+     *
+     * Parameters:
+     * angle - {Float} Rotation angle in degrees (measured counterclockwise
+     *                 from the positive x-axis)
+     * origin - {<OpenLayers.Geometry.Point>} Center point for the rotation
+     */
+    rotate: function(angle, origin) {
+        for(var i=0, len=this.components.length; i<len - 1; ++i) {
+            this.components[i].rotate(angle, origin);
+        }
+    },
+
+    /**
+     * APIMethod: resize
+     * Resize a geometry relative to some origin.  Use this method to apply
+     *     a uniform scaling to a geometry.
+     *
+     * Parameters:
+     * scale - {Float} Factor by which to scale the geometry.  A scale of 2
+     *                 doubles the size of the geometry in each dimension
+     *                 (lines, for example, will be twice as long, and polygons
+     *                 will have four times the area).
+     * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
+     * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
+     */
+    resize: function(scale, origin, ratio) {
+        for(var i=0, len=this.components.length; i<len - 1; ++i) {
+            this.components[i].resize(scale, origin, ratio);
+        }
+        return this;
+    },
+    
+    /**
+     * APIMethod: transform
+     * Reproject the components geometry from source to dest.
+     *
+     * Parameters:
+     * source - {<OpenLayers.Projection>}
+     * dest - {<OpenLayers.Projection>}
+     * 
+     * Returns:
+     * {<OpenLayers.Geometry>} 
+     */
+    transform: function(source, dest) {
+        if (source && dest) {
+            for (var i=0, len=this.components.length; i<len - 1; i++) {
+                var component = this.components[i];
+                component.transform(source, dest);
+            }
+            this.bounds = null;
+        }
+        return this;
+    },
+    
+    /**
+     * APIMethod: getCentroid
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Point>} The centroid of the collection
+     */
+    getCentroid: function() {
+        if (this.components && (this.components.length > 2)) {
+            var sumX = 0.0;
+            var sumY = 0.0;
+            for (var i = 0; i < this.components.length - 1; i++) {
+                var b = this.components[i];
+                var c = this.components[i+1];
+                sumX += (b.x + c.x) * (b.x * c.y - c.x * b.y);
+                sumY += (b.y + c.y) * (b.x * c.y - c.x * b.y);
+            }
+            var area = -1 * this.getArea();
+            var x = sumX / (6 * area);
+            var y = sumY / (6 * area);
+            return new OpenLayers.Geometry.Point(x, y);
+        } else {
+            return null;
+        }
+    },
+
+    /**
+     * APIMethod: getArea
+     * Note - The area is positive if the ring is oriented CW, otherwise
+     *         it will be negative.
+     * 
+     * Returns:
+     * {Float} The signed area for a ring.
+     */
+    getArea: function() {
+        var area = 0.0;
+        if ( this.components && (this.components.length > 2)) {
+            var sum = 0.0;
+            for (var i=0, len=this.components.length; i<len - 1; i++) {
+                var b = this.components[i];
+                var c = this.components[i+1];
+                sum += (b.x + c.x) * (c.y - b.y);
+            }
+            area = - sum / 2.0;
+        }
+        return area;
+    },
+    
+    /**
+     * APIMethod: getGeodesicArea
+     * Calculate the approximate area of the polygon were it projected onto
+     *     the earth.  Note that this area will be positive if ring is oriented
+     *     clockwise, otherwise it will be negative.
+     *
+     * Parameters:
+     * projection - {<OpenLayers.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Reference:
+     * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+     *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+     *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+     *
+     * Returns:
+     * {float} The approximate signed geodesic area of the polygon in square
+     *     meters.
+     */
+    getGeodesicArea: function(projection) {
+        var ring = this;  // so we can work with a clone if needed
+        if(projection) {
+            var gg = new OpenLayers.Projection("EPSG:4326");
+            if(!gg.equals(projection)) {
+                ring = this.clone().transform(projection, gg);
+            }
+        }
+        var area = 0.0;
+        var len = ring.components && ring.components.length;
+        if(len > 2) {
+            var p1, p2;
+            for(var i=0; i<len-1; i++) {
+                p1 = ring.components[i];
+                p2 = ring.components[i+1];
+                area += OpenLayers.Util.rad(p2.x - p1.x) *
+                        (2 + Math.sin(OpenLayers.Util.rad(p1.y)) +
+                        Math.sin(OpenLayers.Util.rad(p2.y)));
+            }
+            area = area * 6378137.0 * 6378137.0 / 2.0;
+        }
+        return area;
+    },
+    
+    /**
+     * Method: containsPoint
+     * Test if a point is inside a linear ring.  For the case where a point
+     *     is coincident with a linear ring edge, returns 1.  Otherwise,
+     *     returns boolean.
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     *
+     * Returns:
+     * {Boolean | Number} The point is inside the linear ring.  Returns 1 if
+     *     the point is coincident with an edge.  Returns boolean otherwise.
+     */
+    containsPoint: function(point) {
+        var approx = OpenLayers.Number.limitSigDigs;
+        var digs = 14;
+        var px = approx(point.x, digs);
+        var py = approx(point.y, digs);
+        function getX(y, x1, y1, x2, y2) {
+            return (((x1 - x2) * y) + ((x2 * y1) - (x1 * y2))) / (y1 - y2);
+        }
+        var numSeg = this.components.length - 1;
+        var start, end, x1, y1, x2, y2, cx, cy;
+        var crosses = 0;
+        for(var i=0; i<numSeg; ++i) {
+            start = this.components[i];
+            x1 = approx(start.x, digs);
+            y1 = approx(start.y, digs);
+            end = this.components[i + 1];
+            x2 = approx(end.x, digs);
+            y2 = approx(end.y, digs);
+            
+            /**
+             * The following conditions enforce five edge-crossing rules:
+             *    1. points coincident with edges are considered contained;
+             *    2. an upward edge includes its starting endpoint, and
+             *    excludes its final endpoint;
+             *    3. a downward edge excludes its starting endpoint, and
+             *    includes its final endpoint;
+             *    4. horizontal edges are excluded; and
+             *    5. the edge-ray intersection point must be strictly right
+             *    of the point P.
+             */
+            if(y1 == y2) {
+                // horizontal edge
+                if(py == y1) {
+                    // point on horizontal line
+                    if(x1 <= x2 && (px >= x1 && px <= x2) || // right or vert
+                       x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert
+                        // point on edge
+                        crosses = -1;
+                        break;
+                    }
+                }
+                // ignore other horizontal edges
+                continue;
+            }
+            cx = approx(getX(py, x1, y1, x2, y2), digs);
+            if(cx == px) {
+                // point on line
+                if(y1 < y2 && (py >= y1 && py <= y2) || // upward
+                   y1 > y2 && (py <= y1 && py >= y2)) { // downward
+                    // point on edge
+                    crosses = -1;
+                    break;
+                }
+            }
+            if(cx <= px) {
+                // no crossing to the right
+                continue;
+            }
+            if(x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {
+                // no crossing
+                continue;
+            }
+            if(y1 < y2 && (py >= y1 && py < y2) || // upward
+               y1 > y2 && (py < y1 && py >= y2)) { // downward
+                ++crosses;
+            }
+        }
+        var contained = (crosses == -1) ?
+            // on edge
+            1 :
+            // even (out) or odd (in)
+            !!(crosses & 1);
+
+        return contained;
+    },
+
+    /**
+     * APIMethod: intersects
+     * Determine if the input geometry intersects this one.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
+     *
+     * Returns:
+     * {Boolean} The input geometry intersects this one.
+     */
+    intersects: function(geometry) {
+        var intersect = false;
+        if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+            intersect = this.containsPoint(geometry);
+        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
+            intersect = geometry.intersects(this);
+        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+            intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply(
+                this, [geometry]
+            );
+        } else {
+            // check for component intersections
+            for(var i=0, len=geometry.components.length; i<len; ++ i) {
+                intersect = geometry.components[i].intersects(this);
+                if(intersect) {
+                    break;
+                }
+            }
+        }
+        return intersect;
+    },
+
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        return (nodes === true) ? [] : this.components.slice(0, this.components.length-1);
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.LinearRing"
+});
+/* ======================================================================
+    OpenLayers/Geometry/Polygon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Geometry/LinearRing.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.Polygon 
+ * Polygon is a collection of Geometry.LinearRings. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Geometry.Collection> 
+ *  - <OpenLayers.Geometry> 
+ */
+OpenLayers.Geometry.Polygon = OpenLayers.Class(
+  OpenLayers.Geometry.Collection, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of
+     * components that the collection can include.  A null value means the
+     * component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.LinearRing"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.Polygon
+     * Constructor for a Polygon geometry. 
+     * The first ring (this.component[0])is the outer bounds of the polygon and 
+     * all subsequent rings (this.component[1-n]) are internal holes.
+     *
+     *
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry.LinearRing>)} 
+     */
+    initialize: function(components) {
+        OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
+                                                                  arguments);
+    },
+    
+    /** 
+     * APIMethod: getArea
+     * Calculated by subtracting the areas of the internal holes from the 
+     *   area of the outer hole.
+     * 
+     * Returns:
+     * {float} The area of the geometry
+     */
+    getArea: function() {
+        var area = 0.0;
+        if ( this.components && (this.components.length > 0)) {
+            area += Math.abs(this.components[0].getArea());
+            for (var i=1, len=this.components.length; i<len; i++) {
+                area -= Math.abs(this.components[i].getArea());
+            }
+        }
+        return area;
+    },
+
+    /** 
+     * APIMethod: getGeodesicArea
+     * Calculate the approximate area of the polygon were it projected onto
+     *     the earth.
+     *
+     * Parameters:
+     * projection - {<OpenLayers.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Reference:
+     * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+     *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+     *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+     *
+     * Returns:
+     * {float} The approximate geodesic area of the polygon in square meters.
+     */
+    getGeodesicArea: function(projection) {
+        var area = 0.0;
+        if(this.components && (this.components.length > 0)) {
+            area += Math.abs(this.components[0].getGeodesicArea(projection));
+            for(var i=1, len=this.components.length; i<len; i++) {
+                area -= Math.abs(this.components[i].getGeodesicArea(projection));
+            }
+        }
+        return area;
+    },
+
+    /**
+     * Method: containsPoint
+     * Test if a point is inside a polygon.  Points on a polygon edge are
+     *     considered inside.
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     *
+     * Returns:
+     * {Boolean | Number} The point is inside the polygon.  Returns 1 if the
+     *     point is on an edge.  Returns boolean otherwise.
+     */
+    containsPoint: function(point) {
+        var numRings = this.components.length;
+        var contained = false;
+        if(numRings > 0) {
+            // check exterior ring - 1 means on edge, boolean otherwise
+            contained = this.components[0].containsPoint(point);
+            if(contained !== 1) {
+                if(contained && numRings > 1) {
+                    // check interior rings
+                    var hole;
+                    for(var i=1; i<numRings; ++i) {
+                        hole = this.components[i].containsPoint(point);
+                        if(hole) {
+                            if(hole === 1) {
+                                // on edge
+                                contained = 1;
+                            } else {
+                                // in hole
+                                contained = false;
+                            }                            
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return contained;
+    },
+
+    /**
+     * APIMethod: intersects
+     * Determine if the input geometry intersects this one.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
+     *
+     * Returns:
+     * {Boolean} The input geometry intersects this one.
+     */
+    intersects: function(geometry) {
+        var intersect = false;
+        var i, len;
+        if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+            intersect = this.containsPoint(geometry);
+        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
+                  geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+            // check if rings/linestrings intersect
+            for(i=0, len=this.components.length; i<len; ++i) {
+                intersect = geometry.intersects(this.components[i]);
+                if(intersect) {
+                    break;
+                }
+            }
+            if(!intersect) {
+                // check if this poly contains points of the ring/linestring
+                for(i=0, len=geometry.components.length; i<len; ++i) {
+                    intersect = this.containsPoint(geometry.components[i]);
+                    if(intersect) {
+                        break;
+                    }
+                }
+            }
+        } else {
+            for(i=0, len=geometry.components.length; i<len; ++ i) {
+                intersect = this.intersects(geometry.components[i]);
+                if(intersect) {
+                    break;
+                }
+            }
+        }
+        // check case where this poly is wholly contained by another
+        if(!intersect && geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
+            // exterior ring points will be contained in the other geometry
+            var ring = this.components[0];
+            for(i=0, len=ring.components.length; i<len; ++i) {
+                intersect = geometry.containsPoint(ring.components[i]);
+                if(intersect) {
+                    break;
+                }
+            }
+        }
+        return intersect;
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries (on the x-y plane).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and y1 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var result;
+        // this is the case where we might not be looking for distance to edge
+        if(!edge && this.intersects(geometry)) {
+            result = 0;
+        } else {
+            result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(
+                this, [geometry, options]
+            );
+        }
+        return result;
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.Polygon"
+});
+
+/**
+ * APIMethod: createRegularPolygon
+ * Create a regular polygon around a radius. Useful for creating circles 
+ * and the like.
+ *
+ * Parameters:
+ * origin - {<OpenLayers.Geometry.Point>} center of polygon.
+ * radius - {Float} distance to vertex, in map units.
+ * sides - {Integer} Number of sides. 20 approximates a circle.
+ * rotation - {Float} original angle of rotation, in degrees.
+ */
+OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {  
+    var angle = Math.PI * ((1/sides) - (1/2));
+    if(rotation) {
+        angle += (rotation / 180) * Math.PI;
+    }
+    var rotatedAngle, x, y;
+    var points = [];
+    for(var i=0; i<sides; ++i) {
+        rotatedAngle = angle + (i * 2 * Math.PI / sides);
+        x = origin.x + (radius * Math.cos(rotatedAngle));
+        y = origin.y + (radius * Math.sin(rotatedAngle));
+        points.push(new OpenLayers.Geometry.Point(x, y));
+    }
+    var ring = new OpenLayers.Geometry.LinearRing(points);
+    return new OpenLayers.Geometry.Polygon([ring]);
+};
+/* ======================================================================
+    OpenLayers/Events.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Namespace: OpenLayers.Event
+ * Utility functions for event handling.
+ */
+OpenLayers.Event = {
+
+    /** 
+     * Property: observers 
+     * {Object} A hashtable cache of the event observers. Keyed by
+     * element._eventCacheID 
+     */
+    observers: false,
+    
+    /** 
+     * Constant: KEY_BACKSPACE 
+     * {int} 
+     */
+    KEY_BACKSPACE: 8,
+
+    /** 
+     * Constant: KEY_TAB 
+     * {int} 
+     */
+    KEY_TAB: 9,
+
+    /** 
+     * Constant: KEY_RETURN 
+     * {int} 
+     */
+    KEY_RETURN: 13,
+
+    /** 
+     * Constant: KEY_ESC 
+     * {int} 
+     */
+    KEY_ESC: 27,
+
+    /** 
+     * Constant: KEY_LEFT 
+     * {int} 
+     */
+    KEY_LEFT: 37,
+
+    /** 
+     * Constant: KEY_UP 
+     * {int} 
+     */
+    KEY_UP: 38,
+
+    /** 
+     * Constant: KEY_RIGHT 
+     * {int} 
+     */
+    KEY_RIGHT: 39,
+
+    /** 
+     * Constant: KEY_DOWN 
+     * {int} 
+     */
+    KEY_DOWN: 40,
+
+    /** 
+     * Constant: KEY_DELETE 
+     * {int} 
+     */
+    KEY_DELETE: 46,
+
+
+    /**
+     * Method: element
+     * Cross browser event element detection.
+     * 
+     * Parameters:
+     * event - {Event} 
+     * 
+     * Returns:
+     * {DOMElement} The element that caused the event 
+     */
+    element: function(event) {
+        return event.target || event.srcElement;
+    },
+
+    /**
+     * Method: isSingleTouch
+     * Determine whether event was caused by a single touch
+     *
+     * Parameters:
+     * event - {Event}
+     *
+     * Returns:
+     * {Boolean}
+     */
+    isSingleTouch: function(event) {
+        return event.touches && event.touches.length == 1;
+    },
+
+    /**
+     * Method: isMultiTouch
+     * Determine whether event was caused by a multi touch
+     *
+     * Parameters:
+     * event - {Event}
+     *
+     * Returns:
+     * {Boolean}
+     */
+    isMultiTouch: function(event) {
+        return event.touches && event.touches.length > 1;
+    },
+
+    /**
+     * Method: isLeftClick
+     * Determine whether event was caused by a left click. 
+     *
+     * Parameters:
+     * event - {Event} 
+     * 
+     * Returns:
+     * {Boolean}
+     */
+    isLeftClick: function(event) {
+        return (((event.which) && (event.which == 1)) ||
+                ((event.button) && (event.button == 1)));
+    },
+
+    /**
+     * Method: isRightClick
+     * Determine whether event was caused by a right mouse click. 
+     *
+     * Parameters:
+     * event - {Event} 
+     * 
+     * Returns:
+     * {Boolean}
+     */
+     isRightClick: function(event) {
+        return (((event.which) && (event.which == 3)) ||
+                ((event.button) && (event.button == 2)));
+    },
+     
+    /**
+     * Method: stop
+     * Stops an event from propagating. 
+     *
+     * Parameters: 
+     * event - {Event} 
+     * allowDefault - {Boolean} If true, we stop the event chain but 
+     *                               still allow the default browser 
+     *                               behaviour (text selection, radio-button 
+     *                               clicking, etc)
+     *                               Default false
+     */
+    stop: function(event, allowDefault) {
+        
+        if (!allowDefault) { 
+            if (event.preventDefault) {
+                event.preventDefault();
+            } else {
+                event.returnValue = false;
+            }
+        }
+                
+        if (event.stopPropagation) {
+            event.stopPropagation();
+        } else {
+            event.cancelBubble = true;
+        }
+    },
+
+    /** 
+     * Method: findElement
+     * 
+     * Parameters:
+     * event - {Event} 
+     * tagName - {String} 
+     * 
+     * Returns:
+     * {DOMElement} The first node with the given tagName, starting from the
+     * node the event was triggered on and traversing the DOM upwards
+     */
+    findElement: function(event, tagName) {
+        var element = OpenLayers.Event.element(event);
+        while (element.parentNode && (!element.tagName ||
+              (element.tagName.toUpperCase() != tagName.toUpperCase()))){
+            element = element.parentNode;
+        }
+        return element;
+    },
+
+    /** 
+     * Method: observe
+     * 
+     * Parameters:
+     * elementParam - {DOMElement || String} 
+     * name - {String} 
+     * observer - {function} 
+     * useCapture - {Boolean} 
+     */
+    observe: function(elementParam, name, observer, useCapture) {
+        var element = OpenLayers.Util.getElement(elementParam);
+        useCapture = useCapture || false;
+
+        if (name == 'keypress' &&
+           (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+           || element.attachEvent)) {
+            name = 'keydown';
+        }
+
+        //if observers cache has not yet been created, create it
+        if (!this.observers) {
+            this.observers = {};
+        }
+
+        //if not already assigned, make a new unique cache ID
+        if (!element._eventCacheID) {
+            var idPrefix = "eventCacheID_";
+            if (element.id) {
+                idPrefix = element.id + "_" + idPrefix;
+            }
+            element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
+        }
+
+        var cacheID = element._eventCacheID;
+
+        //if there is not yet a hash entry for this element, add one
+        if (!this.observers[cacheID]) {
+            this.observers[cacheID] = [];
+        }
+
+        //add a new observer to this element's list
+        this.observers[cacheID].push({
+            'element': element,
+            'name': name,
+            'observer': observer,
+            'useCapture': useCapture
+        });
+
+        //add the actual browser event listener
+        if (element.addEventListener) {
+            element.addEventListener(name, observer, useCapture);
+        } else if (element.attachEvent) {
+            element.attachEvent('on' + name, observer);
+        }
+    },
+
+    /** 
+     * Method: stopObservingElement
+     * Given the id of an element to stop observing, cycle through the 
+     *   element's cached observers, calling stopObserving on each one, 
+     *   skipping those entries which can no longer be removed.
+     * 
+     * parameters:
+     * elementParam - {DOMElement || String} 
+     */
+    stopObservingElement: function(elementParam) {
+        var element = OpenLayers.Util.getElement(elementParam);
+        var cacheID = element._eventCacheID;
+
+        this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
+    },
+
+    /**
+     * Method: _removeElementObservers
+     *
+     * Parameters:
+     * elementObservers - {Array(Object)} Array of (element, name, 
+     *                                         observer, usecapture) objects, 
+     *                                         taken directly from hashtable
+     */
+    _removeElementObservers: function(elementObservers) {
+        if (elementObservers) {
+            for(var i = elementObservers.length-1; i >= 0; i--) {
+                var entry = elementObservers[i];
+                var args = new Array(entry.element,
+                                     entry.name,
+                                     entry.observer,
+                                     entry.useCapture);
+                var removed = OpenLayers.Event.stopObserving.apply(this, args);
+            }
+        }
+    },
+
+    /**
+     * Method: stopObserving
+     * 
+     * Parameters:
+     * elementParam - {DOMElement || String} 
+     * name - {String} 
+     * observer - {function} 
+     * useCapture - {Boolean} 
+     *  
+     * Returns:
+     * {Boolean} Whether or not the event observer was removed
+     */
+    stopObserving: function(elementParam, name, observer, useCapture) {
+        useCapture = useCapture || false;
+    
+        var element = OpenLayers.Util.getElement(elementParam);
+        var cacheID = element._eventCacheID;
+
+        if (name == 'keypress') {
+            if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || 
+                 element.detachEvent) {
+              name = 'keydown';
+            }
+        }
+
+        // find element's entry in this.observers cache and remove it
+        var foundEntry = false;
+        var elementObservers = OpenLayers.Event.observers[cacheID];
+        if (elementObservers) {
+    
+            // find the specific event type in the element's list
+            var i=0;
+            while(!foundEntry && i < elementObservers.length) {
+                var cacheEntry = elementObservers[i];
+    
+                if ((cacheEntry.name == name) &&
+                    (cacheEntry.observer == observer) &&
+                    (cacheEntry.useCapture == useCapture)) {
+    
+                    elementObservers.splice(i, 1);
+                    if (elementObservers.length == 0) {
+                        delete OpenLayers.Event.observers[cacheID];
+                    }
+                    foundEntry = true;
+                    break; 
+                }
+                i++;           
+            }
+        }
+    
+        //actually remove the event listener from browser
+        if (foundEntry) {
+            if (element.removeEventListener) {
+                element.removeEventListener(name, observer, useCapture);
+            } else if (element && element.detachEvent) {
+                element.detachEvent('on' + name, observer);
+            }
+        }
+        return foundEntry;
+    },
+    
+    /** 
+     * Method: unloadCache
+     * Cycle through all the element entries in the events cache and call
+     *   stopObservingElement on each. 
+     */
+    unloadCache: function() {
+        // check for OpenLayers.Event before checking for observers, because
+        // OpenLayers.Event may be undefined in IE if no map instance was
+        // created
+        if (OpenLayers.Event && OpenLayers.Event.observers) {
+            for (var cacheID in OpenLayers.Event.observers) {
+                var elementObservers = OpenLayers.Event.observers[cacheID];
+                OpenLayers.Event._removeElementObservers.apply(this, 
+                                                           [elementObservers]);
+            }
+            OpenLayers.Event.observers = false;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Event"
+};
+
+/* prevent memory leaks in IE */
+OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
+
+// FIXME: Remove this in 3.0. In 3.0, Event.stop will no longer be provided
+// by OpenLayers.
+if (window.Event) {
+    OpenLayers.Util.applyDefaults(window.Event, OpenLayers.Event);
+} else {
+    var Event = OpenLayers.Event;
+}
+
+/**
+ * Class: OpenLayers.Events
+ */
+OpenLayers.Events = OpenLayers.Class({
+
+    /** 
+     * Constant: BROWSER_EVENTS
+     * {Array(String)} supported events 
+     */
+    BROWSER_EVENTS: [
+        "mouseover", "mouseout",
+        "mousedown", "mouseup", "mousemove", 
+        "click", "dblclick", "rightclick", "dblrightclick",
+        "resize", "focus", "blur",
+        "touchstart", "touchmove", "touchend"
+    ],
+
+    /** 
+     * Property: listeners 
+     * {Object} Hashtable of Array(Function): events listener functions  
+     */
+    listeners: null,
+
+    /** 
+     * Property: object 
+     * {Object}  the code object issuing application events 
+     */
+    object: null,
+
+    /** 
+     * Property: element 
+     * {DOMElement}  the DOM element receiving browser events 
+     */
+    element: null,
+
+    /** 
+     * Property: eventTypes 
+     * {Array(String)}  list of support application events 
+     */
+    eventTypes: null,
+
+    /** 
+     * Property: eventHandler 
+     * {Function}  bound event handler attached to elements 
+     */
+    eventHandler: null,
+
+    /** 
+     * APIProperty: fallThrough 
+     * {Boolean} 
+     */
+    fallThrough: null,
+
+    /** 
+     * APIProperty: includeXY
+     * {Boolean} Should the .xy property automatically be created for browser
+     *    mouse events? In general, this should be false. If it is true, then
+     *    mouse events will automatically generate a '.xy' property on the 
+     *    event object that is passed. (Prior to OpenLayers 2.7, this was true
+     *    by default.) Otherwise, you can call the getMousePosition on the
+     *    relevant events handler on the object available via the 'evt.object'
+     *    property of the evt object. So, for most events, you can call:
+     *    function named(evt) { 
+     *        this.xy = this.object.events.getMousePosition(evt) 
+     *    } 
+     *
+     *    This option typically defaults to false for performance reasons:
+     *    when creating an events object whose primary purpose is to manage
+     *    relatively positioned mouse events within a div, it may make
+     *    sense to set it to true.
+     *
+     *    This option is also used to control whether the events object caches
+     *    offsets. If this is false, it will not: the reason for this is that
+     *    it is only expected to be called many times if the includeXY property
+     *    is set to true. If you set this to true, you are expected to clear 
+     *    the offset cache manually (using this.clearMouseCache()) if:
+     *        the border of the element changes
+     *        the location of the element in the page changes
+    */
+    includeXY: false,      
+
+    /**
+     * Method: clearMouseListener
+     * A version of <clearMouseCache> that is bound to this instance so that
+     *     it can be used with <OpenLayers.Event.observe> and
+     *     <OpenLayers.Event.stopObserving>.
+     */
+    clearMouseListener: null,
+
+    /**
+     * Constructor: OpenLayers.Events
+     * Construct an OpenLayers.Events object.
+     *
+     * Parameters:
+     * object - {Object} The js object to which this Events object  is being added
+     * element - {DOMElement} A dom element to respond to browser events
+     * eventTypes - {Array(String)} Array of custom application events 
+     * fallThrough - {Boolean} Allow events to fall through after these have
+     *                         been handled?
+     * options - {Object} Options for the events object.
+     */
+    initialize: function (object, element, eventTypes, fallThrough, options) {
+        OpenLayers.Util.extend(this, options);
+        this.object     = object;
+        this.fallThrough = fallThrough;
+        this.listeners  = {};
+
+        // keep a bound copy of handleBrowserEvent() so that we can
+        // pass the same function to both Event.observe() and .stopObserving()
+        this.eventHandler = OpenLayers.Function.bindAsEventListener(
+            this.handleBrowserEvent, this
+        );
+        
+        // to be used with observe and stopObserving
+        this.clearMouseListener = OpenLayers.Function.bind(
+            this.clearMouseCache, this
+        );
+
+        // if eventTypes is specified, create a listeners list for each 
+        // custom application event.
+        this.eventTypes = [];
+        if (eventTypes != null) {
+            for (var i=0, len=eventTypes.length; i<len; i++) {
+                this.addEventType(eventTypes[i]);
+            }
+        }
+        
+        // if a dom element is specified, add a listeners list 
+        // for browser events on the element and register them
+        if (element != null) {
+            this.attachToElement(element);
+        }
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function () {
+        if (this.element) {
+            OpenLayers.Event.stopObservingElement(this.element);
+            if(this.element.hasScrollEvent) {
+                OpenLayers.Event.stopObserving(
+                    window, "scroll", this.clearMouseListener
+                );
+            }
+        }
+        this.element = null;
+
+        this.listeners = null;
+        this.object = null;
+        this.eventTypes = null;
+        this.fallThrough = null;
+        this.eventHandler = null;
+    },
+
+    /**
+     * APIMethod: addEventType
+     * Add a new event type to this events object.
+     * If the event type has already been added, do nothing.
+     * 
+     * Parameters:
+     * eventName - {String}
+     */
+    addEventType: function(eventName) {
+        if (!this.listeners[eventName]) {
+            this.eventTypes.push(eventName);
+            this.listeners[eventName] = [];
+        }
+    },
+
+    /**
+     * Method: attachToElement
+     *
+     * Parameters:
+     * element - {HTMLDOMElement} a DOM element to attach browser events to
+     */
+    attachToElement: function (element) {
+        if(this.element) {
+            OpenLayers.Event.stopObservingElement(this.element);
+        }
+        this.element = element;
+        for (var i=0, len=this.BROWSER_EVENTS.length; i<len; i++) {
+            var eventType = this.BROWSER_EVENTS[i];
+
+            // every browser event has a corresponding application event 
+            // (whether it's listened for or not).
+            this.addEventType(eventType);
+            
+            // use Prototype to register the event cross-browser
+            OpenLayers.Event.observe(element, eventType, this.eventHandler);
+        }
+        // disable dragstart in IE so that mousedown/move/up works normally
+        OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
+    },
+    
+    /**
+     * APIMethod: on
+     * Convenience method for registering listeners with a common scope.
+     *     Internally, this method calls <register> as shown in the examples
+     *     below.
+     *
+     * Example use:
+     * (code)
+     * // register a single listener for the "loadstart" event
+     * events.on({"loadstart": loadStartListener});
+     *
+     * // this is equivalent to the following
+     * events.register("loadstart", undefined, loadStartListener);
+     *
+     * // register multiple listeners to be called with the same `this` object
+     * events.on({
+     *     "loadstart": loadStartListener,
+     *     "loadend": loadEndListener,
+     *     scope: object
+     * });
+     *
+     * // this is equivalent to the following
+     * events.register("loadstart", object, loadStartListener);
+     * events.register("loadend", object, loadEndListener);
+     * (end)
+     *
+     * Parameters:
+     *  object - {Object}     
+     */
+    on: function(object) {
+        for(var type in object) {
+            if(type != "scope") {
+                this.register(type, object.scope, object[type]);
+            }
+        }
+    },
+
+    /**
+     * APIMethod: register
+     * Register an event on the events object.
+     *
+     * When the event is triggered, the 'func' function will be called, in the
+     * context of 'obj'. Imagine we were to register an event, specifying an 
+     * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the 
+     * context in the callback function will be our Bounds object. This means
+     * that within our callback function, we can access the properties and 
+     * methods of the Bounds object through the "this" variable. So our 
+     * callback could execute something like: 
+     * :    leftStr = "Left: " + this.left;
+     *   
+     *                   or
+     *  
+     * :    centerStr = "Center: " + this.getCenterLonLat();
+     *
+     * Parameters:
+     * type - {String} Name of the event to register
+     * obj - {Object} The object to bind the context to for the callback#.
+     *                     If no object is specified, default is the Events's 
+     *                     'object' property.
+     * func - {Function} The callback function. If no callback is 
+     *                        specified, this function does nothing.
+     * 
+     * 
+     */
+    register: function (type, obj, func) {
+
+        if ( (func != null) && 
+             (OpenLayers.Util.indexOf(this.eventTypes, type) != -1) ) {
+
+            if (obj == null)  {
+                obj = this.object;
+            }
+            var listeners = this.listeners[type];
+            listeners.push( {obj: obj, func: func} );
+        }
+    },
+
+    /**
+     * APIMethod: registerPriority
+     * Same as register() but adds the new listener to the *front* of the
+     *     events queue instead of to the end.
+     *    
+     *     TODO: get rid of this in 3.0 - Decide whether listeners should be 
+     *     called in the order they were registered or in reverse order.
+     *
+     *
+     * Parameters:
+     * type - {String} Name of the event to register
+     * obj - {Object} The object to bind the context to for the callback#.
+     *                If no object is specified, default is the Events's 
+     *                'object' property.
+     * func - {Function} The callback function. If no callback is 
+     *                   specified, this function does nothing.
+     */
+    registerPriority: function (type, obj, func) {
+
+        if (func != null) {
+            if (obj == null)  {
+                obj = this.object;
+            }
+            var listeners = this.listeners[type];
+            if (listeners != null) {
+                listeners.unshift( {obj: obj, func: func} );
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: un
+     * Convenience method for unregistering listeners with a common scope.
+     *     Internally, this method calls <unregister> as shown in the examples
+     *     below.
+     *
+     * Example use:
+     * (code)
+     * // unregister a single listener for the "loadstart" event
+     * events.un({"loadstart": loadStartListener});
+     *
+     * // this is equivalent to the following
+     * events.unregister("loadstart", undefined, loadStartListener);
+     *
+     * // unregister multiple listeners with the same `this` object
+     * events.un({
+     *     "loadstart": loadStartListener,
+     *     "loadend": loadEndListener,
+     *     scope: object
+     * });
+     *
+     * // this is equivalent to the following
+     * events.unregister("loadstart", object, loadStartListener);
+     * events.unregister("loadend", object, loadEndListener);
+     * (end)
+     */
+    un: function(object) {
+        for(var type in object) {
+            if(type != "scope") {
+                this.unregister(type, object.scope, object[type]);
+            }
+        }
+    },
+
+    /**
+     * APIMethod: unregister
+     *
+     * Parameters:
+     * type - {String} 
+     * obj - {Object} If none specified, defaults to this.object
+     * func - {Function} 
+     */
+    unregister: function (type, obj, func) {
+        if (obj == null)  {
+            obj = this.object;
+        }
+        var listeners = this.listeners[type];
+        if (listeners != null) {
+            for (var i=0, len=listeners.length; i<len; i++) {
+                if (listeners[i].obj == obj && listeners[i].func == func) {
+                    listeners.splice(i, 1);
+                    break;
+                }
+            }
+        }
+    },
+
+    /** 
+     * Method: remove
+     * Remove all listeners for a given event type. If type is not registered,
+     *     does nothing.
+     *
+     * Parameters:
+     * type - {String} 
+     */
+    remove: function(type) {
+        if (this.listeners[type] != null) {
+            this.listeners[type] = [];
+        }
+    },
+
+    /**
+     * APIMethod: triggerEvent
+     * Trigger a specified registered event.  
+     * 
+     * Parameters:
+     * type - {String} 
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} The last listener return.  If a listener returns false, the
+     *     chain of listeners will stop getting called.
+     */
+    triggerEvent: function (type, evt) {
+        var listeners = this.listeners[type];
+
+        // fast path
+        if(!listeners || listeners.length == 0) {
+            return undefined;
+        }
+
+        // prep evt object with object & div references
+        if (evt == null) {
+            evt = {};
+        }
+        evt.object = this.object;
+        evt.element = this.element;
+        if(!evt.type) {
+            evt.type = type;
+        }
+    
+        // execute all callbacks registered for specified type
+        // get a clone of the listeners array to
+        // allow for splicing during callbacks
+        listeners = listeners.slice();
+        var continueChain;
+        for (var i=0, len=listeners.length; i<len; i++) {
+            var callback = listeners[i];
+            // bind the context to callback.obj
+            continueChain = callback.func.apply(callback.obj, [evt]);
+
+            if ((continueChain != undefined) && (continueChain == false)) {
+                // if callback returns false, execute no more callbacks.
+                break;
+            }
+        }
+        // don't fall through to other DOM elements
+        if (!this.fallThrough) {           
+            OpenLayers.Event.stop(evt, true);
+        }
+        return continueChain;
+    },
+
+    /**
+     * Method: handleBrowserEvent
+     * Basically just a wrapper to the triggerEvent() function, but takes 
+     *     care to set a property 'xy' on the event with the current mouse 
+     *     position.
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    handleBrowserEvent: function (evt) {
+        var type = evt.type, listeners = this.listeners[type];
+        if(!listeners || listeners.length == 0) {
+            // noone's listening, bail out
+            return;
+        }
+        // add clientX & clientY to all events - corresponds to average x, y
+        var touches = evt.touches;
+        if (touches && touches[0]) {
+            var x = 0;
+            var y = 0;
+            var num = touches.length;
+            var touch;
+            for (var i=0; i<num; ++i) {
+                touch = touches[i];
+                x += touch.clientX;
+                y += touch.clientY;
+            }
+            evt.clientX = x / num;
+            evt.clientY = y / num;
+        }
+        if (this.includeXY) {
+            evt.xy = this.getMousePosition(evt);
+        } 
+        this.triggerEvent(type, evt);
+    },
+
+    /**
+     * APIMethod: clearMouseCache
+     * Clear cached data about the mouse position. This should be called any 
+     *     time the element that events are registered on changes position 
+     *     within the page.
+     */
+    clearMouseCache: function() { 
+        this.element.scrolls = null;
+        this.element.lefttop = null;
+        // OpenLayers.Util.pagePosition needs to use
+        // element.getBoundingClientRect to correctly calculate the offsets
+        // for the iPhone, but once the page is scrolled, getBoundingClientRect
+        // returns incorrect offsets. So our best bet is to not invalidate the
+        // offsets once we have them, and hope that the page was not scrolled
+        // when we did the initial calculation.
+        var body = document.body;
+        if (body && !((body.scrollTop != 0 || body.scrollLeft != 0) &&
+                                    navigator.userAgent.match(/iPhone/i))) {
+            this.element.offsets = null;
+        }
+    },      
+
+    /**
+     * Method: getMousePosition
+     * 
+     * Parameters:
+     * evt - {Event} 
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} The current xy coordinate of the mouse, adjusted
+     *                      for offsets
+     */
+    getMousePosition: function (evt) {
+        if (!this.includeXY) {
+            this.clearMouseCache();
+        } else if (!this.element.hasScrollEvent) {
+            OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
+            this.element.hasScrollEvent = true;
+        }
+        
+        if (!this.element.scrolls) {
+            var viewportElement = OpenLayers.Util.getViewportElement();
+            this.element.scrolls = [
+                viewportElement.scrollLeft,
+                viewportElement.scrollTop
+            ];
+        }
+
+        if (!this.element.lefttop) {
+            this.element.lefttop = [
+                (document.documentElement.clientLeft || 0),
+                (document.documentElement.clientTop  || 0)
+            ];
+        }
+        
+        if (!this.element.offsets) {
+            this.element.offsets = OpenLayers.Util.pagePosition(this.element);
+        }
+
+        return new OpenLayers.Pixel(
+            (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
+                         - this.element.lefttop[0], 
+            (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
+                         - this.element.lefttop[1]
+        ); 
+    },
+
+    CLASS_NAME: "OpenLayers.Events"
+});
+/* ======================================================================
+    OpenLayers/Request.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Events.js
+ */
+
+/**
+ * Namespace: OpenLayers.Request
+ * The OpenLayers.Request namespace contains convenience methods for working
+ *     with XMLHttpRequests.  These methods work with a cross-browser
+ *     W3C compliant <OpenLayers.Request.XMLHttpRequest> class.
+ */
+OpenLayers.Request = {
+    
+    /**
+     * Constant: DEFAULT_CONFIG
+     * {Object} Default configuration for all requests.
+     */
+    DEFAULT_CONFIG: {
+        method: "GET",
+        url: window.location.href,
+        async: true,
+        user: undefined,
+        password: undefined,
+        params: null,
+        proxy: OpenLayers.ProxyHost,
+        headers: {},
+        data: null,
+        callback: function() {},
+        success: null,
+        failure: null,
+        scope: null
+    },
+    
+    /**
+     * Constant: URL_SPLIT_REGEX
+     */
+    URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,
+    
+    /**
+     * APIProperty: events
+     * {<OpenLayers.Events>} An events object that handles all 
+     *     events on the {<OpenLayers.Request>} object.
+     *
+     * All event listeners will receive an event object with three properties:
+     * request - {<OpenLayers.Request.XMLHttpRequest>} The request object.
+     * config - {Object} The config object sent to the specific request method.
+     * requestUrl - {String} The request url.
+     * 
+     * Supported event types:
+     * complete - Triggered when we have a response from the request, if a
+     *     listener returns false, no further response processing will take
+     *     place.
+     * success - Triggered when the HTTP response has a success code (200-299).
+     * failure - Triggered when the HTTP response does not have a success code.
+     */
+    events: new OpenLayers.Events(this, null, ["complete", "success", "failure"]),
+    
+    /**
+     * APIMethod: issue
+     * Create a new XMLHttpRequest object, open it, set any headers, bind
+     *     a callback to done state, and send any data.  It is recommended that
+     *     you use one <GET>, <POST>, <PUT>, <DELETE>, <OPTIONS>, or <HEAD>.
+     *     This method is only documented to provide detail on the configuration
+     *     options available to all request methods.
+     *
+     * Parameters:
+     * config - {Object} Object containing properties for configuring the
+     *     request.  Allowed configuration properties are described below.
+     *     This object is modified and should not be reused.
+     *
+     * Allowed config properties:
+     * method - {String} One of GET, POST, PUT, DELETE, HEAD, or
+     *     OPTIONS.  Default is GET.
+     * url - {String} URL for the request.
+     * async - {Boolean} Open an asynchronous request.  Default is true.
+     * user - {String} User for relevant authentication scheme.  Set
+     *     to null to clear current user.
+     * password - {String} Password for relevant authentication scheme.
+     *     Set to null to clear current password.
+     * proxy - {String} Optional proxy.  Defaults to
+     *     <OpenLayers.ProxyHost>.
+     * params - {Object} Any key:value pairs to be appended to the
+     *     url as a query string.  Assumes url doesn't already include a query
+     *     string or hash.  Typically, this is only appropriate for <GET>
+     *     requests where the query string will be appended to the url.
+     *     Parameter values that are arrays will be
+     *     concatenated with a comma (note that this goes against form-encoding)
+     *     as is done with <OpenLayers.Util.getParameterString>.
+     * headers - {Object} Object with header:value pairs to be set on
+     *     the request.
+     * data - {String | Document} Optional data to send with the request.
+     *     Typically, this is only used with <POST> and <PUT> requests.
+     *     Make sure to provide the appropriate "Content-Type" header for your
+     *     data.  For <POST> and <PUT> requests, the content type defaults to
+     *     "application-xml".  If your data is a different content type, or
+     *     if you are using a different HTTP method, set the "Content-Type"
+     *     header to match your data type.
+     * callback - {Function} Function to call when request is done.
+     *     To determine if the request failed, check request.status (200
+     *     indicates success).
+     * success - {Function} Optional function to call if request status is in
+     *     the 200s.  This will be called in addition to callback above and
+     *     would typically only be used as an alternative.
+     * failure - {Function} Optional function to call if request status is not
+     *     in the 200s.  This will be called in addition to callback above and
+     *     would typically only be used as an alternative.
+     * scope - {Object} If callback is a public method on some object,
+     *     set the scope to that object.
+     *
+     * Returns:
+     * {XMLHttpRequest} Request object.  To abort the request before a response
+     *     is received, call abort() on the request object.
+     */
+    issue: function(config) {        
+        // apply default config - proxy host may have changed
+        var defaultConfig = OpenLayers.Util.extend(
+            this.DEFAULT_CONFIG,
+            {proxy: OpenLayers.ProxyHost}
+        );
+        config = OpenLayers.Util.applyDefaults(config, defaultConfig);
+
+        // create request, open, and set headers
+        var request = new OpenLayers.Request.XMLHttpRequest();
+        var url = OpenLayers.Util.urlAppend(config.url, 
+            OpenLayers.Util.getParameterString(config.params || {}));
+        var sameOrigin = !(url.indexOf("http") == 0);
+        var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX);
+        if (urlParts) {
+            var location = window.location;
+            sameOrigin =
+                urlParts[1] == location.protocol &&
+                urlParts[3] == location.hostname;
+            var uPort = urlParts[4], lPort = location.port;
+            if (uPort != 80 && uPort != "" || lPort != "80" && lPort != "") {
+                sameOrigin = sameOrigin && uPort == lPort;
+            }
+        }
+        if (!sameOrigin) {
+            if (config.proxy) {
+                if (typeof config.proxy == "function") {
+                    url = config.proxy(url);
+                } else {
+                    url = config.proxy + encodeURIComponent(url);
+                }
+            } else {
+                OpenLayers.Console.warn(
+                    OpenLayers.i18n("proxyNeeded"), {url: url});
+            }
+        }
+        request.open(
+            config.method, url, config.async, config.user, config.password
+        );
+        for(var header in config.headers) {
+            request.setRequestHeader(header, config.headers[header]);
+        }
+
+        var events = this.events;
+
+        // we want to execute runCallbacks with "this" as the
+        // execution scope
+        var self = this;
+        
+        request.onreadystatechange = function() {
+            if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
+                var proceed = events.triggerEvent(
+                    "complete",
+                    {request: request, config: config, requestUrl: url}
+                );
+                if(proceed !== false) {
+                    self.runCallbacks(
+                        {request: request, config: config, requestUrl: url}
+                    );
+                }
+            }
+        };
+        
+        // send request (optionally with data) and return
+        // call in a timeout for asynchronous requests so the return is
+        // available before readyState == 4 for cached docs
+        if(config.async === false) {
+            request.send(config.data);
+        } else {
+            window.setTimeout(function(){
+                if (request.readyState !== 0) { // W3C: 0-UNSENT
+                    request.send(config.data);
+                }
+            }, 0);
+        }
+        return request;
+    },
+    
+    /**
+     * Method: runCallbacks
+     * Calls the complete, success and failure callbacks. Application
+     *    can listen to the "complete" event, have the listener 
+     *    display a confirm window and always return false, and
+     *    execute OpenLayers.Request.runCallbacks if the user
+     *    hits "yes" in the confirm window.
+     *
+     * Parameters:
+     * options - {Object} Hash containing request, config and requestUrl keys
+     */
+    runCallbacks: function(options) {
+        var request = options.request;
+        var config = options.config;
+        
+        // bind callbacks to readyState 4 (done)
+        var complete = (config.scope) ?
+            OpenLayers.Function.bind(config.callback, config.scope) :
+            config.callback;
+        
+        // optional success callback
+        var success;
+        if(config.success) {
+            success = (config.scope) ?
+                OpenLayers.Function.bind(config.success, config.scope) :
+                config.success;
+        }
+
+        // optional failure callback
+        var failure;
+        if(config.failure) {
+            failure = (config.scope) ?
+                OpenLayers.Function.bind(config.failure, config.scope) :
+                config.failure;
+        }
+
+        if (OpenLayers.Util.createUrlObject(config.url).protocol == "file:" &&
+                                                        request.responseText) {
+            request.status = 200;
+        }
+        complete(request);
+
+        if (!request.status || (request.status >= 200 && request.status < 300)) {
+            this.events.triggerEvent("success", options);
+            if(success) {
+                success(request);
+            }
+        }
+        if(request.status && (request.status < 200 || request.status >= 300)) {                    
+            this.events.triggerEvent("failure", options);
+            if(failure) {
+                failure(request);
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: GET
+     * Send an HTTP GET request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to GET.
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.
+     *     This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    GET: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "GET"});
+        return OpenLayers.Request.issue(config);
+    },
+    
+    /**
+     * APIMethod: POST
+     * Send a POST request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to POST and "Content-Type" header set to "application/xml".
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.  The
+     *     default "Content-Type" header will be set to "application-xml" if
+     *     none is provided.  This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    POST: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "POST"});
+        // set content type to application/xml if it isn't already set
+        config.headers = config.headers ? config.headers : {};
+        if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
+            config.headers["Content-Type"] = "application/xml";
+        }
+        return OpenLayers.Request.issue(config);
+    },
+    
+    /**
+     * APIMethod: PUT
+     * Send an HTTP PUT request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to PUT and "Content-Type" header set to "application/xml".
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.  The
+     *     default "Content-Type" header will be set to "application-xml" if
+     *     none is provided.  This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    PUT: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "PUT"});
+        // set content type to application/xml if it isn't already set
+        config.headers = config.headers ? config.headers : {};
+        if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
+            config.headers["Content-Type"] = "application/xml";
+        }
+        return OpenLayers.Request.issue(config);
+    },
+    
+    /**
+     * APIMethod: DELETE
+     * Send an HTTP DELETE request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to DELETE.
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.
+     *     This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    DELETE: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "DELETE"});
+        return OpenLayers.Request.issue(config);
+    },
+  
+    /**
+     * APIMethod: HEAD
+     * Send an HTTP HEAD request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to HEAD.
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.
+     *     This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    HEAD: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "HEAD"});
+        return OpenLayers.Request.issue(config);
+    },
+    
+    /**
+     * APIMethod: OPTIONS
+     * Send an HTTP OPTIONS request.  Additional configuration properties are
+     *     documented in the <issue> method, with the method property set
+     *     to OPTIONS.
+     *
+     * Parameters:
+     * config - {Object} Object with properties for configuring the request.
+     *     See the <issue> method for documentation of allowed properties.
+     *     This object is modified and should not be reused.
+     * 
+     * Returns:
+     * {XMLHttpRequest} Request object.
+     */
+    OPTIONS: function(config) {
+        config = OpenLayers.Util.extend(config, {method: "OPTIONS"});
+        return OpenLayers.Request.issue(config);
+    }
+
+};
+/* ======================================================================
+    OpenLayers/Request/XMLHttpRequest.js
+   ====================================================================== */
+
+// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @requires OpenLayers/Request.js
+ */
+
+(function () {
+
+    // Save reference to earlier defined object implementation (if any)
+    var oXMLHttpRequest    = window.XMLHttpRequest;
+
+    // Define on browser type
+    var bGecko    = !!window.controllers,
+        bIE        = window.document.all && !window.opera,
+        bIE7    = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
+
+    // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()"
+    function fXMLHttpRequest() {
+        this._object    = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
+        this._listeners    = [];
+    };
+
+    // Constructor
+    function cXMLHttpRequest() {
+        return new fXMLHttpRequest;
+    };
+    cXMLHttpRequest.prototype    = fXMLHttpRequest.prototype;
+
+    // BUGFIX: Firefox with Firebug installed would break pages if not executed
+    if (bGecko && oXMLHttpRequest.wrapped)
+        cXMLHttpRequest.wrapped    = oXMLHttpRequest.wrapped;
+
+    // Constants
+    cXMLHttpRequest.UNSENT                = 0;
+    cXMLHttpRequest.OPENED                = 1;
+    cXMLHttpRequest.HEADERS_RECEIVED    = 2;
+    cXMLHttpRequest.LOADING                = 3;
+    cXMLHttpRequest.DONE                = 4;
+
+    // Public Properties
+    cXMLHttpRequest.prototype.readyState    = cXMLHttpRequest.UNSENT;
+    cXMLHttpRequest.prototype.responseText    = '';
+    cXMLHttpRequest.prototype.responseXML    = null;
+    cXMLHttpRequest.prototype.status        = 0;
+    cXMLHttpRequest.prototype.statusText    = '';
+
+    // Priority proposal
+    cXMLHttpRequest.prototype.priority        = "NORMAL";
+
+    // Instance-level Events Handlers
+    cXMLHttpRequest.prototype.onreadystatechange    = null;
+
+    // Class-level Events Handlers
+    cXMLHttpRequest.onreadystatechange    = null;
+    cXMLHttpRequest.onopen                = null;
+    cXMLHttpRequest.onsend                = null;
+    cXMLHttpRequest.onabort                = null;
+
+    // Public Methods
+    cXMLHttpRequest.prototype.open    = function(sMethod, sUrl, bAsync, sUser, sPassword) {
+        // Delete headers, required when object is reused
+        delete this._headers;
+
+        // When bAsync parameter value is omitted, use true as default
+        if (arguments.length < 3)
+            bAsync    = true;
+
+        // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
+        this._async        = bAsync;
+
+        // Set the onreadystatechange handler
+        var oRequest    = this,
+            nState        = this.readyState,
+            fOnUnload;
+
+        // BUGFIX: IE - memory leak on page unload (inter-page leak)
+        if (bIE && bAsync) {
+            fOnUnload = function() {
+                if (nState != cXMLHttpRequest.DONE) {
+                    fCleanTransport(oRequest);
+                    // Safe to abort here since onreadystatechange handler removed
+                    oRequest.abort();
+                }
+            };
+            window.attachEvent("onunload", fOnUnload);
+        }
+
+        // Add method sniffer
+        if (cXMLHttpRequest.onopen)
+            cXMLHttpRequest.onopen.apply(this, arguments);
+
+        if (arguments.length > 4)
+            this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+        else
+        if (arguments.length > 3)
+            this._object.open(sMethod, sUrl, bAsync, sUser);
+        else
+            this._object.open(sMethod, sUrl, bAsync);
+
+        this.readyState    = cXMLHttpRequest.OPENED;
+        fReadyStateChange(this);
+
+        this._object.onreadystatechange    = function() {
+            if (bGecko && !bAsync)
+                return;
+
+            // Synchronize state
+            oRequest.readyState        = oRequest._object.readyState;
+
+            //
+            fSynchronizeValues(oRequest);
+
+            // BUGFIX: Firefox fires unnecessary DONE when aborting
+            if (oRequest._aborted) {
+                // Reset readyState to UNSENT
+                oRequest.readyState    = cXMLHttpRequest.UNSENT;
+
+                // Return now
+                return;
+            }
+
+            if (oRequest.readyState == cXMLHttpRequest.DONE) {
+                // Free up queue
+                delete oRequest._data;
+/*                if (bAsync)
+                    fQueue_remove(oRequest);*/
+                //
+                fCleanTransport(oRequest);
+// Uncomment this block if you need a fix for IE cache
+/*
+                // BUGFIX: IE - cache issue
+                if (!oRequest._object.getResponseHeader("Date")) {
+                    // Save object to cache
+                    oRequest._cached    = oRequest._object;
+
+                    // Instantiate a new transport object
+                    cXMLHttpRequest.call(oRequest);
+
+                    // Re-send request
+                    if (sUser) {
+                         if (sPassword)
+                            oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+                        else
+                            oRequest._object.open(sMethod, sUrl, bAsync, sUser);
+                    }
+                    else
+                        oRequest._object.open(sMethod, sUrl, bAsync);
+                    oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
+                    // Copy headers set
+                    if (oRequest._headers)
+                        for (var sHeader in oRequest._headers)
+                            if (typeof oRequest._headers[sHeader] == "string")    // Some frameworks prototype objects with functions
+                                oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
+
+                    oRequest._object.onreadystatechange    = function() {
+                        // Synchronize state
+                        oRequest.readyState        = oRequest._object.readyState;
+
+                        if (oRequest._aborted) {
+                            //
+                            oRequest.readyState    = cXMLHttpRequest.UNSENT;
+
+                            // Return
+                            return;
+                        }
+
+                        if (oRequest.readyState == cXMLHttpRequest.DONE) {
+                            // Clean Object
+                            fCleanTransport(oRequest);
+
+                            // get cached request
+                            if (oRequest.status == 304)
+                                oRequest._object    = oRequest._cached;
+
+                            //
+                            delete oRequest._cached;
+
+                            //
+                            fSynchronizeValues(oRequest);
+
+                            //
+                            fReadyStateChange(oRequest);
+
+                            // BUGFIX: IE - memory leak in interrupted
+                            if (bIE && bAsync)
+                                window.detachEvent("onunload", fOnUnload);
+                        }
+                    };
+                    oRequest._object.send(null);
+
+                    // Return now - wait until re-sent request is finished
+                    return;
+                };
+*/
+                // BUGFIX: IE - memory leak in interrupted
+                if (bIE && bAsync)
+                    window.detachEvent("onunload", fOnUnload);
+            }
+
+            // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
+            if (nState != oRequest.readyState)
+                fReadyStateChange(oRequest);
+
+            nState    = oRequest.readyState;
+        }
+    };
+    function fXMLHttpRequest_send(oRequest) {
+        oRequest._object.send(oRequest._data);
+
+        // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
+        if (bGecko && !oRequest._async) {
+            oRequest.readyState    = cXMLHttpRequest.OPENED;
+
+            // Synchronize state
+            fSynchronizeValues(oRequest);
+
+            // Simulate missing states
+            while (oRequest.readyState < cXMLHttpRequest.DONE) {
+                oRequest.readyState++;
+                fReadyStateChange(oRequest);
+                // Check if we are aborted
+                if (oRequest._aborted)
+                    return;
+            }
+        }
+    };
+    cXMLHttpRequest.prototype.send    = function(vData) {
+        // Add method sniffer
+        if (cXMLHttpRequest.onsend)
+            cXMLHttpRequest.onsend.apply(this, arguments);
+
+        if (!arguments.length)
+            vData    = null;
+
+        // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
+        // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
+        // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
+        if (vData && vData.nodeType) {
+            vData    = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
+            if (!oRequest._headers["Content-Type"])
+                oRequest._object.setRequestHeader("Content-Type", "application/xml");
+        }
+
+        this._data    = vData;
+/*
+        // Add to queue
+        if (this._async)
+            fQueue_add(this);
+        else*/
+            fXMLHttpRequest_send(this);
+    };
+    cXMLHttpRequest.prototype.abort    = function() {
+        // Add method sniffer
+        if (cXMLHttpRequest.onabort)
+            cXMLHttpRequest.onabort.apply(this, arguments);
+
+        // BUGFIX: Gecko - unnecessary DONE when aborting
+        if (this.readyState > cXMLHttpRequest.UNSENT)
+            this._aborted    = true;
+
+        this._object.abort();
+
+        // BUGFIX: IE - memory leak
+        fCleanTransport(this);
+
+        this.readyState    = cXMLHttpRequest.UNSENT;
+
+        delete this._data;
+/*        if (this._async)
+            fQueue_remove(this);*/
+    };
+    cXMLHttpRequest.prototype.getAllResponseHeaders    = function() {
+        return this._object.getAllResponseHeaders();
+    };
+    cXMLHttpRequest.prototype.getResponseHeader    = function(sName) {
+        return this._object.getResponseHeader(sName);
+    };
+    cXMLHttpRequest.prototype.setRequestHeader    = function(sName, sValue) {
+        // BUGFIX: IE - cache issue
+        if (!this._headers)
+            this._headers    = {};
+        this._headers[sName]    = sValue;
+
+        return this._object.setRequestHeader(sName, sValue);
+    };
+
+    // EventTarget interface implementation
+    cXMLHttpRequest.prototype.addEventListener    = function(sName, fHandler, bUseCapture) {
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
+                return;
+        // Add listener
+        this._listeners.push([sName, fHandler, bUseCapture]);
+    };
+
+    cXMLHttpRequest.prototype.removeEventListener    = function(sName, fHandler, bUseCapture) {
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
+                break;
+        // Remove listener
+        if (oListener)
+            this._listeners.splice(nIndex, 1);
+    };
+
+    cXMLHttpRequest.prototype.dispatchEvent    = function(oEvent) {
+        var oEventPseudo    = {
+            'type':            oEvent.type,
+            'target':        this,
+            'currentTarget':this,
+            'eventPhase':    2,
+            'bubbles':        oEvent.bubbles,
+            'cancelable':    oEvent.cancelable,
+            'timeStamp':    oEvent.timeStamp,
+            'stopPropagation':    function() {},    // There is no flow
+            'preventDefault':    function() {},    // There is no default action
+            'initEvent':        function() {}    // Original event object should be initialized
+        };
+
+        // Execute onreadystatechange
+        if (oEventPseudo.type == "readystatechange" && this.onreadystatechange)
+            (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
+
+        // Execute listeners
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == oEventPseudo.type && !oListener[2])
+                (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
+    };
+
+    //
+    cXMLHttpRequest.prototype.toString    = function() {
+        return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
+    };
+
+    cXMLHttpRequest.toString    = function() {
+        return '[' + "XMLHttpRequest" + ']';
+    };
+
+    // Helper function
+    function fReadyStateChange(oRequest) {
+        // Sniffing code
+        if (cXMLHttpRequest.onreadystatechange)
+            cXMLHttpRequest.onreadystatechange.apply(oRequest);
+
+        // Fake event
+        oRequest.dispatchEvent({
+            'type':            "readystatechange",
+            'bubbles':        false,
+            'cancelable':    false,
+            'timeStamp':    new Date + 0
+        });
+    };
+
+    function fGetDocument(oRequest) {
+        var oDocument    = oRequest.responseXML,
+            sResponse    = oRequest.responseText;
+        // Try parsing responseText
+        if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
+            oDocument    = new window.ActiveXObject("Microsoft.XMLDOM");
+            oDocument.async                = false;
+            oDocument.validateOnParse    = false;
+            oDocument.loadXML(sResponse);
+        }
+        // Check if there is no error in document
+        if (oDocument)
+            if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
+                return null;
+        return oDocument;
+    };
+
+    function fSynchronizeValues(oRequest) {
+        try {    oRequest.responseText    = oRequest._object.responseText;    } catch (e) {}
+        try {    oRequest.responseXML    = fGetDocument(oRequest._object);    } catch (e) {}
+        try {    oRequest.status            = oRequest._object.status;            } catch (e) {}
+        try {    oRequest.statusText        = oRequest._object.statusText;        } catch (e) {}
+    };
+
+    function fCleanTransport(oRequest) {
+        // BUGFIX: IE - memory leak (on-page leak)
+        oRequest._object.onreadystatechange    = new window.Function;
+    };
+/*
+    // Queue manager
+    var oQueuePending    = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
+        aQueueRunning    = [];
+    function fQueue_add(oRequest) {
+        oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
+        //
+        setTimeout(fQueue_process);
+    };
+
+    function fQueue_remove(oRequest) {
+        for (var nIndex = 0, bFound    = false; nIndex < aQueueRunning.length; nIndex++)
+            if (bFound)
+                aQueueRunning[nIndex - 1]    = aQueueRunning[nIndex];
+            else
+            if (aQueueRunning[nIndex] == oRequest)
+                bFound    = true;
+        if (bFound)
+            aQueueRunning.length--;
+        //
+        setTimeout(fQueue_process);
+    };
+
+    function fQueue_process() {
+        if (aQueueRunning.length < 6) {
+            for (var sPriority in oQueuePending) {
+                if (oQueuePending[sPriority].length) {
+                    var oRequest    = oQueuePending[sPriority][0];
+                    oQueuePending[sPriority]    = oQueuePending[sPriority].slice(1);
+                    //
+                    aQueueRunning.push(oRequest);
+                    // Send request
+                    fXMLHttpRequest_send(oRequest);
+                    break;
+                }
+            }
+        }
+    };
+*/
+    // Internet Explorer 5.0 (missing apply)
+    if (!window.Function.prototype.apply) {
+        window.Function.prototype.apply    = function(oRequest, oArguments) {
+            if (!oArguments)
+                oArguments    = [];
+            oRequest.__func    = this;
+            oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
+            delete oRequest.__func;
+        };
+    };
+
+    // Register new object with window
+    /**
+     * Class: OpenLayers.Request.XMLHttpRequest
+     * Standard-compliant (W3C) cross-browser implementation of the
+     *     XMLHttpRequest object.  From
+     *     http://code.google.com/p/xmlhttprequest/.
+     */
+    OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;
+})();
+/* ======================================================================
+    OpenLayers/Projection.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Class: OpenLayers.Projection
+ * Class for coordinate transforms between coordinate systems.
+ *     Depends on the proj4js library. If proj4js is not available, 
+ *     then this is just an empty stub.
+ */
+OpenLayers.Projection = OpenLayers.Class({
+
+    /**
+     * Property: proj
+     * {Object} Proj4js.Proj instance.
+     */
+    proj: null,
+    
+    /**
+     * Property: projCode
+     * {String}
+     */
+    projCode: null,
+    
+    /**
+     * Property: titleRegEx
+     * {RegExp} regular expression to strip the title from a proj4js definition
+     */
+    titleRegEx: /\+title=[^\+]*/,
+
+    /**
+     * Constructor: OpenLayers.Projection
+     * This class offers several methods for interacting with a wrapped 
+     *     pro4js projection object. 
+     *
+     * Parameters:
+     * projCode - {String} A string identifying the Well Known Identifier for
+     *    the projection.
+     * options - {Object} An optional object to set additional properties
+     *     on the layer.
+     *
+     * Returns:
+     * {<OpenLayers.Projection>} A projection object.
+     */
+    initialize: function(projCode, options) {
+        OpenLayers.Util.extend(this, options);
+        this.projCode = projCode;
+        if (window.Proj4js) {
+            this.proj = new Proj4js.Proj(projCode);
+        }
+    },
+    
+    /**
+     * APIMethod: getCode
+     * Get the string SRS code.
+     *
+     * Returns:
+     * {String} The SRS code.
+     */
+    getCode: function() {
+        return this.proj ? this.proj.srsCode : this.projCode;
+    },
+   
+    /**
+     * APIMethod: getUnits
+     * Get the units string for the projection -- returns null if 
+     *     proj4js is not available.
+     *
+     * Returns:
+     * {String} The units abbreviation.
+     */
+    getUnits: function() {
+        return this.proj ? this.proj.units : null;
+    },
+
+    /**
+     * Method: toString
+     * Convert projection to string (getCode wrapper).
+     *
+     * Returns:
+     * {String} The projection code.
+     */
+    toString: function() {
+        return this.getCode();
+    },
+
+    /**
+     * Method: equals
+     * Test equality of two projection instances.  Determines equality based
+     *     soley on the projection code.
+     *
+     * Returns:
+     * {Boolean} The two projections are equivalent.
+     */
+    equals: function(projection) {
+        var p = projection, equals = false;
+        if (p) {
+            if (window.Proj4js && this.proj.defData && p.proj.defData) {
+                equals = this.proj.defData.replace(this.titleRegEx, "") ==
+                    p.proj.defData.replace(this.titleRegEx, "");
+            } else if (p.getCode) {
+                var source = this.getCode(), target = p.getCode();
+                equals = source == target ||
+                    !!OpenLayers.Projection.transforms[source] &&
+                    OpenLayers.Projection.transforms[source][target] ===
+                        OpenLayers.Projection.nullTransform;
+            }
+        }
+        return equals;   
+    },
+
+    /* Method: destroy
+     * Destroy projection object.
+     */
+    destroy: function() {
+        delete this.proj;
+        delete this.projCode;
+    },
+    
+    CLASS_NAME: "OpenLayers.Projection" 
+});     
+
+/**
+ * Property: transforms
+ * Transforms is an object, with from properties, each of which may
+ * have a to property. This allows you to define projections without 
+ * requiring support for proj4js to be included.
+ *
+ * This object has keys which correspond to a 'source' projection object.  The
+ * keys should be strings, corresponding to the projection.getCode() value.
+ * Each source projection object should have a set of destination projection
+ * keys included in the object. 
+ * 
+ * Each value in the destination object should be a transformation function,
+ * where the function is expected to be passed an object with a .x and a .y
+ * property.  The function should return the object, with the .x and .y
+ * transformed according to the transformation function.
+ *
+ * Note - Properties on this object should not be set directly.  To add a
+ *     transform method to this object, use the <addTransform> method.  For an
+ *     example of usage, see the OpenLayers.Layer.SphericalMercator file.
+ */
+OpenLayers.Projection.transforms = {};
+
+/**
+ * APIMethod: addTransform
+ * Set a custom transform method between two projections.  Use this method in
+ *     cases where the proj4js lib is not available or where custom projections
+ *     need to be handled.
+ *
+ * Parameters:
+ * from - {String} The code for the source projection
+ * to - {String} the code for the destination projection
+ * method - {Function} A function that takes a point as an argument and
+ *     transforms that point from the source to the destination projection
+ *     in place.  The original point should be modified.
+ */
+OpenLayers.Projection.addTransform = function(from, to, method) {
+    if(!OpenLayers.Projection.transforms[from]) {
+        OpenLayers.Projection.transforms[from] = {};
+    }
+    OpenLayers.Projection.transforms[from][to] = method;
+};
+
+/**
+ * APIMethod: transform
+ * Transform a point coordinate from one projection to another.  Note that
+ *     the input point is transformed in place.
+ * 
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point> | Object} An object with x and y
+ *     properties representing coordinates in those dimensions.
+ * source - {OpenLayers.Projection} Source map coordinate system
+ * dest - {OpenLayers.Projection} Destination map coordinate system
+ *
+ * Returns:
+ * point - {object} A transformed coordinate.  The original point is modified.
+ */
+OpenLayers.Projection.transform = function(point, source, dest) {
+    if (source.proj && dest.proj) {
+        point = Proj4js.transform(source.proj, dest.proj, point);
+    } else if (source && dest && 
+               OpenLayers.Projection.transforms[source.getCode()] && 
+               OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]) {
+        OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point); 
+    }
+    return point;
+};
+
+/**
+ * APIFunction: nullTransform
+ * A null transformation - useful for defining projection aliases when
+ * proj4js is not available:
+ *
+ * (code)
+ * OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857",
+ *     OpenLayers.Layer.SphericalMercator.projectForward);
+ * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:3857",
+ *     OpenLayers.Layer.SphericalMercator.projectInverse);
+ * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913",
+ *     OpenLayers.Projection.nullTransform);
+ * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857",
+ *     OpenLayers.Projection.nullTransform);
+ * (end)
+ */
+OpenLayers.Projection.nullTransform = function(point) {
+    return point;
+};
+/* ======================================================================
+    OpenLayers/Format/KML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Date.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Format.KML
+ * Read/Write KML. Create a new instance with the <OpenLayers.Format.KML>
+ *     constructor. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        kml: "http://www.opengis.net/kml/2.2",
+        gx: "http://www.google.com/kml/ext/2.2"
+    },
+
+    /**
+     * APIProperty: kmlns
+     * {String} KML Namespace to use. Defaults to 2.0 namespace.
+     */
+    kmlns: "http://earth.google.com/kml/2.0",
+    
+    /** 
+     * APIProperty: placemarksDesc
+     * {String} Name of the placemarks.  Default is "No description available".
+     */
+    placemarksDesc: "No description available",
+    
+    /** 
+     * APIProperty: foldersName
+     * {String} Name of the folders.  Default is "OpenLayers export".
+     *          If set to null, no name element will be created.
+     */
+    foldersName: "OpenLayers export",
+    
+    /** 
+     * APIProperty: foldersDesc
+     * {String} Description of the folders. Default is "Exported on [date]."
+     *          If set to null, no description element will be created.
+     */
+    foldersDesc: "Exported on " + new Date(),
+    
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from KML.  Default is true.
+     *           Extracting styleUrls requires this to be set to true
+     */
+    extractAttributes: true,
+    
+    /**
+     * Property: extractStyles
+     * {Boolean} Extract styles from KML.  Default is false.
+     *           Extracting styleUrls also requires extractAttributes to be
+     *           set to true
+     */
+    extractStyles: false,
+    
+    /**
+     * APIProperty: extractTracks
+     * {Boolean} Extract gx:Track elements from Placemark elements.  Default
+     *     is false.  If true, features will be generated for all points in
+     *     all gx:Track elements.  Features will have a when (Date) attribute
+     *     based on when elements in the track.  If tracks include angle
+     *     elements, features will have heading, tilt, and roll attributes.
+     *     If track point coordinates have three values, features will have
+     *     an altitude attribute with the third coordinate value.
+     */
+    extractTracks: false,
+    
+    /**
+     * APIProperty: trackAttributes
+     * {Array} If <extractTracks> is true, points within gx:Track elements will 
+     *     be parsed as features with when, heading, tilt, and roll attributes.
+     *     Any additional attribute names can be provided in <trackAttributes>.
+     */
+    trackAttributes: null,
+    
+    /**
+     * Property: internalns
+     * {String} KML Namespace to use -- defaults to the namespace of the
+     *     Placemark node being parsed, but falls back to kmlns. 
+     */
+    internalns: null,
+
+    /**
+     * Property: features
+     * {Array} Array of features
+     *     
+     */
+    features: null,
+
+    /**
+     * Property: styles
+     * {Object} Storage of style objects
+     *     
+     */
+    styles: null,
+    
+    /**
+     * Property: styleBaseUrl
+     * {String}
+     */
+    styleBaseUrl: "",
+
+    /**
+     * Property: fetched
+     * {Object} Storage of KML URLs that have been fetched before
+     *     in order to prevent reloading them.
+     */
+    fetched: null,
+
+    /**
+     * APIProperty: maxDepth
+     * {Integer} Maximum depth for recursive loading external KML URLs 
+     *           Defaults to 0: do no external fetching
+     */
+    maxDepth: 0,
+
+    /**
+     * Constructor: OpenLayers.Format.KML
+     * Create a new parser for KML.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        // compile regular expressions once instead of every time they are used
+        this.regExes = {
+            trimSpace: (/^\s*|\s*$/g),
+            removeSpace: (/\s*/g),
+            splitSpace: (/\s+/),
+            trimComma: (/\s*,\s*/g),
+            kmlColor: (/(\w{2})(\w{2})(\w{2})(\w{2})/),
+            kmlIconPalette: (/root:\/\/icons\/palette-(\d+)(\.\w+)/),
+            straightBracket: (/\$\[(.*?)\]/g)
+        };
+        // KML coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read data from a string, and return a list of features. 
+     * 
+     * Parameters: 
+     * data    - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} List of features.
+     */
+    read: function(data) {
+        this.features = [];
+        this.styles   = {};
+        this.fetched  = {};
+
+        // Set default options 
+        var options = {
+            depth: 0,
+            styleBaseUrl: this.styleBaseUrl
+        };
+
+        return this.parseData(data, options);
+    },
+
+    /**
+     * Method: parseData
+     * Read data from a string, and return a list of features. 
+     * 
+     * Parameters: 
+     * data    - {String} or {DOMElement} data to read/parse.
+     * options - {Object} Hash of options
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} List of features.
+     */
+    parseData: function(data, options) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+
+        // Loop throught the following node types in this order and
+        // process the nodes found 
+        var types = ["Link", "NetworkLink", "Style", "StyleMap", "Placemark"];
+        for(var i=0, len=types.length; i<len; ++i) {
+            var type = types[i];
+
+            var nodes = this.getElementsByTagNameNS(data, "*", type);
+
+            // skip to next type if no nodes are found
+            if(nodes.length == 0) { 
+                continue;
+            }
+
+            switch (type.toLowerCase()) {
+
+                // Fetch external links 
+                case "link":
+                case "networklink":
+                    this.parseLinks(nodes, options);
+                    break;
+
+                // parse style information
+                case "style":
+                    if (this.extractStyles) {
+                        this.parseStyles(nodes, options);
+                    }
+                    break;
+                case "stylemap":
+                    if (this.extractStyles) {
+                        this.parseStyleMaps(nodes, options);
+                    }
+                    break;
+
+                // parse features
+                case "placemark":
+                    this.parseFeatures(nodes, options);
+                    break;
+            }
+        }
+        
+        return this.features;
+    },
+
+    /**
+     * Method: parseLinks
+     * Finds URLs of linked KML documents and fetches them
+     * 
+     * Parameters: 
+     * nodes   - {Array} of {DOMElement} data to read/parse.
+     * options - {Object} Hash of options
+     * 
+     */
+    parseLinks: function(nodes, options) {
+        
+        // Fetch external links <NetworkLink> and <Link>
+        // Don't do anything if we have reached our maximum depth for recursion
+        if (options.depth >= this.maxDepth) {
+            return false;
+        }
+
+        // increase depth
+        var newOptions = OpenLayers.Util.extend({}, options);
+        newOptions.depth++;
+
+        for(var i=0, len=nodes.length; i<len; i++) {
+            var href = this.parseProperty(nodes[i], "*", "href");
+            if(href && !this.fetched[href]) {
+                this.fetched[href] = true; // prevent reloading the same urls
+                var data = this.fetchLink(href);
+                if (data) {
+                    this.parseData(data, newOptions);
+                }
+            } 
+        }
+
+    },
+
+    /**
+     * Method: fetchLink
+     * Fetches a URL and returns the result
+     * 
+     * Parameters: 
+     * href  - {String} url to be fetched
+     * 
+     */
+    fetchLink: function(href) {
+        var request = OpenLayers.Request.GET({url: href, async: false});
+        if (request) {
+            return request.responseText;
+        }
+    },
+
+    /**
+     * Method: parseStyles
+     * Looks for <Style> nodes in the data and parses them
+     * Also parses <StyleMap> nodes, but only uses the 'normal' key
+     * 
+     * Parameters: 
+     * nodes    - {Array} of {DOMElement} data to read/parse.
+     * options  - {Object} Hash of options
+     * 
+     */
+    parseStyles: function(nodes, options) {
+        for(var i=0, len=nodes.length; i<len; i++) {
+            var style = this.parseStyle(nodes[i]);
+            if(style) {
+                var styleName = (options.styleBaseUrl || "") + "#" + style.id;
+                
+                this.styles[styleName] = style;
+            }
+        }
+    },
+
+    /**
+     * Method: parseKmlColor
+     * Parses a kml color (in 'aabbggrr' format) and returns the corresponding 
+     * color and opacity or null if the color is invalid.
+     *
+     * Parameters: 
+     * kmlColor - {String} a kml formated color
+     *
+     * Returns:
+     * {Object}
+     */
+    parseKmlColor: function(kmlColor) {
+        var color = null;
+        if (kmlColor) {
+            var matches = kmlColor.match(this.regExes.kmlColor);
+            if (matches) {
+                color = {
+                    color: '#' + matches[4] + matches[3] + matches[2],
+                    opacity: parseInt(matches[1], 16) / 255
+                };
+            }
+        }
+        return color;
+    },
+
+    /**
+     * Method: parseStyle
+     * Parses the children of a <Style> node and builds the style hash
+     * accordingly
+     * 
+     * Parameters: 
+     * node - {DOMElement} <Style> node
+     * 
+     */
+    parseStyle: function(node) {
+        var style = {};
+        
+        var types = ["LineStyle", "PolyStyle", "IconStyle", "BalloonStyle", 
+                     "LabelStyle"];
+        var type, styleTypeNode, nodeList, geometry, parser;
+        for(var i=0, len=types.length; i<len; ++i) {
+            type = types[i];
+            styleTypeNode = this.getElementsByTagNameNS(node, "*", type)[0];
+            if(!styleTypeNode) { 
+                continue;
+            }
+
+            // only deal with first geometry of this type
+            switch (type.toLowerCase()) {
+                case "linestyle":
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
+                    if (color) {
+                        style["strokeColor"] = color.color;
+                        style["strokeOpacity"] = color.opacity;
+                    }
+                    
+                    var width = this.parseProperty(styleTypeNode, "*", "width");
+                    if (width) {
+                        style["strokeWidth"] = width;
+                    }
+                    break;
+
+                case "polystyle":
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
+                    if (color) {
+                        style["fillOpacity"] = color.opacity;
+                        style["fillColor"] = color.color;
+                    }
+                    // Check if fill is disabled
+                    var fill = this.parseProperty(styleTypeNode, "*", "fill");
+                    if (fill == "0") {
+                        style["fillColor"] = "none";
+                    }
+                    // Check if outline is disabled
+                    var outline = this.parseProperty(styleTypeNode, "*", "outline");
+                    if (outline == "0") {
+                        style["strokeWidth"] = "0";
+                    }
+                   
+                    break;
+
+                case "iconstyle":
+                    // set scale
+                    var scale = parseFloat(this.parseProperty(styleTypeNode, 
+                                                          "*", "scale") || 1);
+  
+                    // set default width and height of icon
+                    var width = 32 * scale;
+                    var height = 32 * scale;
+
+                    var iconNode = this.getElementsByTagNameNS(styleTypeNode, 
+                                               "*", 
+                                               "Icon")[0];
+                    if (iconNode) {
+                        var href = this.parseProperty(iconNode, "*", "href");
+                        if (href) {                                                   
+
+                            var w = this.parseProperty(iconNode, "*", "w");
+                            var h = this.parseProperty(iconNode, "*", "h");
+
+                            // Settings for Google specific icons that are 64x64
+                            // We set the width and height to 64 and halve the
+                            // scale to prevent icons from being too big
+                            var google = "http://maps.google.com/mapfiles/kml";
+                            if (OpenLayers.String.startsWith(
+                                                 href, google) && !w && !h) {
+                                w = 64;
+                                h = 64;
+                                scale = scale / 2;
+                            }
+                                
+                            // if only dimension is defined, make sure the
+                            // other one has the same value
+                            w = w || h;
+                            h = h || w;
+
+                            if (w) {
+                                width = parseInt(w) * scale;
+                            }
+
+                            if (h) {
+                                height = parseInt(h) * scale;
+                            }
+
+                            // support for internal icons 
+                            //    (/root://icons/palette-x.png)
+                            // x and y tell the position on the palette:
+                            // - in pixels
+                            // - starting from the left bottom
+                            // We translate that to a position in the list 
+                            // and request the appropriate icon from the 
+                            // google maps website
+                            var matches = href.match(this.regExes.kmlIconPalette);
+                            if (matches)  {
+                                var palette = matches[1];
+                                var file_extension = matches[2];
+
+                                var x = this.parseProperty(iconNode, "*", "x");
+                                var y = this.parseProperty(iconNode, "*", "y");
+
+                                var posX = x ? x/32 : 0;
+                                var posY = y ? (7 - y/32) : 7;
+
+                                var pos = posY * 8 + posX;
+                                href = "http://maps.google.com/mapfiles/kml/pal" 
+                                     + palette + "/icon" + pos + file_extension;
+                            }
+
+                            style["graphicOpacity"] = 1; // fully opaque
+                            style["externalGraphic"] = href;
+                        }
+
+                    }
+
+
+                    // hotSpots define the offset for an Icon
+                    var hotSpotNode = this.getElementsByTagNameNS(styleTypeNode, 
+                                               "*", 
+                                               "hotSpot")[0];
+                    if (hotSpotNode) {
+                        var x = parseFloat(hotSpotNode.getAttribute("x"));
+                        var y = parseFloat(hotSpotNode.getAttribute("y"));
+
+                        var xUnits = hotSpotNode.getAttribute("xunits");
+                        if (xUnits == "pixels") {
+                            style["graphicXOffset"] = -x * scale;
+                        }
+                        else if (xUnits == "insetPixels") {
+                            style["graphicXOffset"] = -width + (x * scale);
+                        }
+                        else if (xUnits == "fraction") {
+                            style["graphicXOffset"] = -width * x;
+                        }
+
+                        var yUnits = hotSpotNode.getAttribute("yunits");
+                        if (yUnits == "pixels") {
+                            style["graphicYOffset"] = -height + (y * scale) + 1;
+                        }
+                        else if (yUnits == "insetPixels") {
+                            style["graphicYOffset"] = -(y * scale) + 1;
+                        }
+                        else if (yUnits == "fraction") {
+                            style["graphicYOffset"] =  -height * (1 - y) + 1;
+                        }
+                    }
+
+                    style["graphicWidth"] = width;
+                    style["graphicHeight"] = height;
+                    break;
+
+                case "balloonstyle":
+                    var balloonStyle = OpenLayers.Util.getXmlNodeValue(
+                                            styleTypeNode);
+                    if (balloonStyle) {
+                        style["balloonStyle"] = balloonStyle.replace(
+                                       this.regExes.straightBracket, "${$1}");
+                    }
+                    break;
+                case "labelstyle":
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
+                    if (color) {
+                        style["fontColor"] = color.color;
+                        style["fontOpacity"] = color.opacity;
+                    }
+                    break;
+
+                default:
+            }
+        }
+
+        // Some polygons have no line color, so we use the fillColor for that
+        if (!style["strokeColor"] && style["fillColor"]) {
+            style["strokeColor"] = style["fillColor"];
+        }
+
+        var id = node.getAttribute("id");
+        if (id && style) {
+            style.id = id;
+        }
+
+        return style;
+    },
+
+    /**
+     * Method: parseStyleMaps
+     * Looks for <Style> nodes in the data and parses them
+     * Also parses <StyleMap> nodes, but only uses the 'normal' key
+     * 
+     * Parameters: 
+     * nodes    - {Array} of {DOMElement} data to read/parse.
+     * options  - {Object} Hash of options
+     * 
+     */
+    parseStyleMaps: function(nodes, options) {
+        // Only the default or "normal" part of the StyleMap is processed now
+        // To do the select or "highlight" bit, we'd need to change lots more
+
+        for(var i=0, len=nodes.length; i<len; i++) {
+            var node = nodes[i];
+            var pairs = this.getElementsByTagNameNS(node, "*", 
+                            "Pair");
+
+            var id = node.getAttribute("id");
+            for (var j=0, jlen=pairs.length; j<jlen; j++) {
+                var pair = pairs[j];
+                // Use the shortcut in the SLD format to quickly retrieve the 
+                // value of a node. Maybe it's good to have a method in 
+                // Format.XML to do this
+                var key = this.parseProperty(pair, "*", "key");
+                var styleUrl = this.parseProperty(pair, "*", "styleUrl");
+
+                if (styleUrl && key == "normal") {
+                    this.styles[(options.styleBaseUrl || "") + "#" + id] =
+                        this.styles[(options.styleBaseUrl || "") + styleUrl];
+                }
+
+                if (styleUrl && key == "highlight") {
+                    // TODO: implement the "select" part
+                }
+
+            }
+        }
+
+    },
+
+
+    /**
+     * Method: parseFeatures
+     * Loop through all Placemark nodes and parse them.
+     * Will create a list of features
+     * 
+     * Parameters: 
+     * nodes    - {Array} of {DOMElement} data to read/parse.
+     * options  - {Object} Hash of options
+     * 
+     */
+    parseFeatures: function(nodes, options) {
+        var features = [];
+        for(var i=0, len=nodes.length; i<len; i++) {
+            var featureNode = nodes[i];
+            var feature = this.parseFeature.apply(this,[featureNode]) ;
+            if(feature) {
+
+                // Create reference to styleUrl 
+                if (this.extractStyles && feature.attributes &&
+                    feature.attributes.styleUrl) {
+                    feature.style = this.getStyle(feature.attributes.styleUrl, options);
+                }
+
+                if (this.extractStyles) {
+                    // Make sure that <Style> nodes within a placemark are 
+                    // processed as well
+                    var inlineStyleNode = this.getElementsByTagNameNS(featureNode,
+                                                        "*",
+                                                        "Style")[0];
+                    if (inlineStyleNode) {
+                        var inlineStyle= this.parseStyle(inlineStyleNode);
+                        if (inlineStyle) {
+                            feature.style = OpenLayers.Util.extend(
+                                feature.style, inlineStyle
+                            );
+                        }
+                    }
+                }
+
+                // check if gx:Track elements should be parsed
+                if (this.extractTracks) {
+                    var tracks = this.getElementsByTagNameNS(
+                        featureNode, this.namespaces.gx, "Track"
+                    );
+                    if (tracks && tracks.length > 0) {
+                        var track = tracks[0];
+                        var container = {
+                            features: [],
+                            feature: feature
+                        };
+                        this.readNode(track, container);
+                        if (container.features.length > 0) {
+                            features.push.apply(features, container.features);
+                        }
+                    }
+                } else {
+                    // add feature to list of features
+                    features.push(feature);                    
+                }
+            } else {
+                throw "Bad Placemark: " + i;
+            }
+        }
+
+        // add new features to existing feature list
+        this.features = this.features.concat(features);
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "kml": {
+            "when": function(node, container) {
+                container.whens.push(OpenLayers.Date.parse(
+                    this.getChildValue(node)
+                ));
+            },
+            "_trackPointAttribute": function(node, container) {
+                var name = node.nodeName.split(":").pop();
+                container.attributes[name].push(this.getChildValue(node));
+            }
+        },
+        "gx": {
+            "Track": function(node, container) {
+                var obj = {
+                    whens: [],
+                    points: [],
+                    angles: []
+                };
+                if (this.trackAttributes) {
+                    var name;
+                    obj.attributes = {};
+                    for (var i=0, ii=this.trackAttributes.length; i<ii; ++i) {
+                        name = this.trackAttributes[i];
+                        obj.attributes[name] = [];
+                        if (!(name in this.readers.kml)) {
+                            this.readers.kml[name] = this.readers.kml._trackPointAttribute;
+                        }
+                    }
+                }
+                this.readChildNodes(node, obj);
+                if (obj.whens.length !== obj.points.length) {
+                    throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:coord (" + obj.points.length + ") elements.");
+                }
+                var hasAngles = obj.angles.length > 0;
+                if (hasAngles && obj.whens.length !== obj.angles.length) {
+                    throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:angles (" + obj.angles.length + ") elements.");
+                }
+                var feature, point, angles;
+                for (var i=0, ii=obj.whens.length; i<ii; ++i) {
+                    feature = container.feature.clone();
+                    feature.fid = container.feature.fid || container.feature.id;
+                    point = obj.points[i];
+                    feature.geometry = point;
+                    if ("z" in point) {
+                        feature.attributes.altitude = point.z;
+                    }
+                    if (this.internalProjection && this.externalProjection) {
+                        feature.geometry.transform(
+                            this.externalProjection, this.internalProjection
+                        ); 
+                    }
+                    if (this.trackAttributes) {
+                        for (var j=0, jj=this.trackAttributes.length; j<jj; ++j) {
+                            feature.attributes[name] = obj.attributes[this.trackAttributes[j]][i];
+                        }
+                    }
+                    feature.attributes.when = obj.whens[i];
+                    feature.attributes.trackId = container.feature.id;
+                    if (hasAngles) {
+                        angles = obj.angles[i];
+                        feature.attributes.heading = parseFloat(angles[0]);
+                        feature.attributes.tilt = parseFloat(angles[1]);
+                        feature.attributes.roll = parseFloat(angles[2]);
+                    }
+                    container.features.push(feature);
+                }
+            },
+            "coord": function(node, container) {
+                var str = this.getChildValue(node);
+                var coords = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+                var point = new OpenLayers.Geometry.Point(coords[0], coords[1]);
+                if (coords.length > 2) {
+                    point.z = parseFloat(coords[2]);
+                }
+                container.points.push(point);
+            },
+            "angles": function(node, container) {
+                var str = this.getChildValue(node);
+                var parts = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+                container.angles.push(parts);
+            }
+        }
+    },
+    
+    /**
+     * Method: parseFeature
+     * This function is the core of the KML parsing code in OpenLayers.
+     *     It creates the geometries that are then attached to the returned
+     *     feature, and calls parseAttributes() to get attribute data out.
+     *
+     * Parameters:
+     * node - {DOMElement}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A vector feature.
+     */
+    parseFeature: function(node) {
+        // only accept one geometry per feature - look for highest "order"
+        var order = ["MultiGeometry", "Polygon", "LineString", "Point"];
+        var type, nodeList, geometry, parser;
+        for(var i=0, len=order.length; i<len; ++i) {
+            type = order[i];
+            this.internalns = node.namespaceURI ? 
+                    node.namespaceURI : this.kmlns;
+            nodeList = this.getElementsByTagNameNS(node, 
+                                                   this.internalns, type);
+            if(nodeList.length > 0) {
+                // only deal with first geometry of this type
+                var parser = this.parseGeometry[type.toLowerCase()];
+                if(parser) {
+                    geometry = parser.apply(this, [nodeList[0]]);
+                    if (this.internalProjection && this.externalProjection) {
+                        geometry.transform(this.externalProjection, 
+                                           this.internalProjection); 
+                    }                       
+                } else {
+                    OpenLayers.Console.error(OpenLayers.i18n(
+                                "unsupportedGeometryType", {'geomType':type}));
+                }
+                // stop looking for different geometry types
+                break;
+            }
+        }
+
+        // construct feature (optionally with attributes)
+        var attributes;
+        if(this.extractAttributes) {
+            attributes = this.parseAttributes(node);
+        }
+        var feature = new OpenLayers.Feature.Vector(geometry, attributes);
+
+        var fid = node.getAttribute("id") || node.getAttribute("name");
+        if(fid != null) {
+            feature.fid = fid;
+        }
+
+        return feature;
+    },        
+    
+    /**
+     * Method: getStyle
+     * Retrieves a style from a style hash using styleUrl as the key
+     * If the styleUrl doesn't exist yet, we try to fetch it 
+     * Internet
+     * 
+     * Parameters: 
+     * styleUrl  - {String} URL of style
+     * options   - {Object} Hash of options 
+     *
+     * Returns:
+     * {Object}  - (reference to) Style hash
+     */
+    getStyle: function(styleUrl, options) {
+
+        var styleBaseUrl = OpenLayers.Util.removeTail(styleUrl);
+
+        var newOptions = OpenLayers.Util.extend({}, options);
+        newOptions.depth++;
+        newOptions.styleBaseUrl = styleBaseUrl;
+
+        // Fetch remote Style URLs (if not fetched before) 
+        if (!this.styles[styleUrl] 
+                && !OpenLayers.String.startsWith(styleUrl, "#") 
+                && newOptions.depth <= this.maxDepth
+                && !this.fetched[styleBaseUrl] ) {
+
+            var data = this.fetchLink(styleBaseUrl);
+            if (data) {
+                this.parseData(data, newOptions);
+            }
+
+        }
+
+        // return requested style
+        var style = OpenLayers.Util.extend({}, this.styles[styleUrl]);
+        return style;
+    },
+    
+    /**
+     * Property: parseGeometry
+     * Properties of this object are the functions that parse geometries based
+     *     on their type.
+     */
+    parseGeometry: {
+        
+        /**
+         * Method: parseGeometry.point
+         * Given a KML node representing a point geometry, create an OpenLayers
+         *     point geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A KML Point node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.Point>} A point geometry.
+         */
+        point: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+                                                       "coordinates");
+            var coords = [];
+            if(nodeList.length > 0) {
+                var coordString = nodeList[0].firstChild.nodeValue;
+                coordString = coordString.replace(this.regExes.removeSpace, "");
+                coords = coordString.split(",");
+            }
+
+            var point = null;
+            if(coords.length > 1) {
+                // preserve third dimension
+                if(coords.length == 2) {
+                    coords[2] = null;
+                }
+                point = new OpenLayers.Geometry.Point(coords[0], coords[1],
+                                                      coords[2]);
+            } else {
+                throw "Bad coordinate string: " + coordString;
+            }
+            return point;
+        },
+        
+        /**
+         * Method: parseGeometry.linestring
+         * Given a KML node representing a linestring geometry, create an
+         *     OpenLayers linestring geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A KML LineString node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.LineString>} A linestring geometry.
+         */
+        linestring: function(node, ring) {
+            var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+                                                       "coordinates");
+            var line = null;
+            if(nodeList.length > 0) {
+                var coordString = this.getChildValue(nodeList[0]);
+
+                coordString = coordString.replace(this.regExes.trimSpace,
+                                                  "");
+                coordString = coordString.replace(this.regExes.trimComma,
+                                                  ",");
+                var pointList = coordString.split(this.regExes.splitSpace);
+                var numPoints = pointList.length;
+                var points = new Array(numPoints);
+                var coords, numCoords;
+                for(var i=0; i<numPoints; ++i) {
+                    coords = pointList[i].split(",");
+                    numCoords = coords.length;
+                    if(numCoords > 1) {
+                        if(coords.length == 2) {
+                            coords[2] = null;
+                        }
+                        points[i] = new OpenLayers.Geometry.Point(coords[0],
+                                                                  coords[1],
+                                                                  coords[2]);
+                    } else {
+                        throw "Bad LineString point coordinates: " +
+                              pointList[i];
+                    }
+                }
+                if(numPoints) {
+                    if(ring) {
+                        line = new OpenLayers.Geometry.LinearRing(points);
+                    } else {
+                        line = new OpenLayers.Geometry.LineString(points);
+                    }
+                } else {
+                    throw "Bad LineString coordinates: " + coordString;
+                }
+            }
+
+            return line;
+        },
+        
+        /**
+         * Method: parseGeometry.polygon
+         * Given a KML node representing a polygon geometry, create an
+         *     OpenLayers polygon geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A KML Polygon node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+         */
+        polygon: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+                                                       "LinearRing");
+            var numRings = nodeList.length;
+            var components = new Array(numRings);
+            if(numRings > 0) {
+                // this assumes exterior ring first, inner rings after
+                var ring;
+                for(var i=0, len=nodeList.length; i<len; ++i) {
+                    ring = this.parseGeometry.linestring.apply(this,
+                                                        [nodeList[i], true]);
+                    if(ring) {
+                        components[i] = ring;
+                    } else {
+                        throw "Bad LinearRing geometry: " + i;
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.Polygon(components);
+        },
+        
+        /**
+         * Method: parseGeometry.multigeometry
+         * Given a KML node representing a multigeometry, create an
+         *     OpenLayers geometry collection.
+         *
+         * Parameters:
+         * node - {DOMElement} A KML MultiGeometry node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.Collection>} A geometry collection.
+         */
+        multigeometry: function(node) {
+            var child, parser;
+            var parts = [];
+            var children = node.childNodes;
+            for(var i=0, len=children.length; i<len; ++i ) {
+                child = children[i];
+                if(child.nodeType == 1) {
+                    var type = (child.prefix) ?
+                            child.nodeName.split(":")[1] :
+                            child.nodeName;
+                    var parser = this.parseGeometry[type.toLowerCase()];
+                    if(parser) {
+                        parts.push(parser.apply(this, [child]));
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.Collection(parts);
+        }
+        
+    },
+
+    /**
+     * Method: parseAttributes
+     *
+     * Parameters:
+     * node - {DOMElement}
+     *
+     * Returns:
+     * {Object} An attributes object.
+     */
+    parseAttributes: function(node) {
+        var attributes = {};
+       
+        // Extended Data is parsed first.
+        var edNodes = node.getElementsByTagName("ExtendedData");
+        if (edNodes.length) {
+            attributes = this.parseExtendedData(edNodes[0]);
+        }
+        
+        // assume attribute nodes are type 1 children with a type 3 or 4 child
+        var child, grandchildren, grandchild;
+        var children = node.childNodes;
+
+        for(var i=0, len=children.length; i<len; ++i) {
+            child = children[i];
+            if(child.nodeType == 1) {
+                grandchildren = child.childNodes;
+                if(grandchildren.length >= 1 && grandchildren.length <= 3) {
+                    var grandchild;
+                    switch (grandchildren.length) {
+                        case 1:
+                            grandchild = grandchildren[0];
+                            break;
+                        case 2:
+                            var c1 = grandchildren[0];
+                            var c2 = grandchildren[1];
+                            grandchild = (c1.nodeType == 3 || c1.nodeType == 4) ?
+                                c1 : c2;
+                            break;
+                        case 3:
+                        default:
+                            grandchild = grandchildren[1];
+                            break;
+                    }
+                    if(grandchild.nodeType == 3 || grandchild.nodeType == 4) {
+                        var name = (child.prefix) ?
+                                child.nodeName.split(":")[1] :
+                                child.nodeName;
+                        var value = OpenLayers.Util.getXmlNodeValue(grandchild);
+                        if (value) {
+                            value = value.replace(this.regExes.trimSpace, "");
+                            attributes[name] = value;
+                        }
+                    }
+                } 
+            }
+        }
+        return attributes;
+    },
+
+    /**
+     * Method: parseExtendedData
+     * Parse ExtendedData from KML. Limited support for schemas/datatypes.
+     *     See http://code.google.com/apis/kml/documentation/kmlreference.html#extendeddata
+     *     for more information on extendeddata.
+     */
+    parseExtendedData: function(node) {
+        var attributes = {};
+        var i, len, data, key;
+        var dataNodes = node.getElementsByTagName("Data");
+        for (i = 0, len = dataNodes.length; i < len; i++) {
+            data = dataNodes[i];
+            key = data.getAttribute("name");
+            var ed = {};
+            var valueNode = data.getElementsByTagName("value");
+            if (valueNode.length) {
+                ed['value'] = this.getChildValue(valueNode[0]);
+            }    
+            var nameNode = data.getElementsByTagName("displayName");
+            if (nameNode.length) {
+                ed['displayName'] = this.getChildValue(nameNode[0]);
+            }
+            attributes[key] = ed;
+        }
+        var simpleDataNodes = node.getElementsByTagName("SimpleData");
+        for (i = 0, len = simpleDataNodes.length; i < len; i++) {
+            var ed = {};
+            data = simpleDataNodes[i];
+            key = data.getAttribute("name");
+            ed['value'] = this.getChildValue(data);
+            ed['displayName'] = key;
+            attributes[key] = ed;
+        }
+        
+        return attributes;    
+    },
+    
+    /**
+     * Method: parseProperty
+     * Convenience method to find a node and return its value
+     *
+     * Parameters:
+     * xmlNode    - {<DOMElement>}
+     * namespace  - {String} namespace of the node to find
+     * tagName    - {String} name of the property to parse
+     * 
+     * Returns:
+     * {String} The value for the requested property (defaults to null)
+     */    
+    parseProperty: function(xmlNode, namespace, tagName) {
+        var value;
+        var nodeList = this.getElementsByTagNameNS(xmlNode, namespace, tagName);
+        try {
+            value = OpenLayers.Util.getXmlNodeValue(nodeList[0]);
+        } catch(e) {
+            value = null;
+        }
+     
+        return value;
+    },                                                              
+
+    /**
+     * APIMethod: write
+     * Accept Feature Collection, and return a string. 
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} An array of features.
+     *
+     * Returns:
+     * {String} A KML string.
+     */
+    write: function(features) {
+        if(!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        var kml = this.createElementNS(this.kmlns, "kml");
+        var folder = this.createFolderXML();
+        for(var i=0, len=features.length; i<len; ++i) {
+            folder.appendChild(this.createPlacemarkXML(features[i]));
+        }
+        kml.appendChild(folder);
+        return OpenLayers.Format.XML.prototype.write.apply(this, [kml]);
+    },
+
+    /**
+     * Method: createFolderXML
+     * Creates and returns a KML folder node
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    createFolderXML: function() {
+        // Folder
+        var folder = this.createElementNS(this.kmlns, "Folder");
+
+        // Folder name
+        if (this.foldersName) {
+            var folderName = this.createElementNS(this.kmlns, "name");
+            var folderNameText = this.createTextNode(this.foldersName); 
+            folderName.appendChild(folderNameText);
+            folder.appendChild(folderName);
+        }
+
+        // Folder description
+        if (this.foldersDesc) {
+            var folderDesc = this.createElementNS(this.kmlns, "description");        
+            var folderDescText = this.createTextNode(this.foldersDesc); 
+            folderDesc.appendChild(folderDescText);
+            folder.appendChild(folderDesc);
+        }
+
+        return folder;
+    },
+
+    /**
+     * Method: createPlacemarkXML
+     * Creates and returns a KML placemark node representing the given feature. 
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    createPlacemarkXML: function(feature) {        
+        // Placemark name
+        var placemarkName = this.createElementNS(this.kmlns, "name");
+        var name = feature.style && feature.style.label ? feature.style.label :
+                   feature.attributes.name || feature.id;
+        placemarkName.appendChild(this.createTextNode(name));
+
+        // Placemark description
+        var placemarkDesc = this.createElementNS(this.kmlns, "description");
+        var desc = feature.attributes.description || this.placemarksDesc;
+        placemarkDesc.appendChild(this.createTextNode(desc));
+        
+        // Placemark
+        var placemarkNode = this.createElementNS(this.kmlns, "Placemark");
+        if(feature.fid != null) {
+            placemarkNode.setAttribute("id", feature.fid);
+        }
+        placemarkNode.appendChild(placemarkName);
+        placemarkNode.appendChild(placemarkDesc);
+
+        // Geometry node (Point, LineString, etc. nodes)
+        var geometryNode = this.buildGeometryNode(feature.geometry);
+        placemarkNode.appendChild(geometryNode);        
+        
+        // TBD - deal with remaining (non name/description) attributes.
+        return placemarkNode;
+    },    
+
+    /**
+     * Method: buildGeometryNode
+     * Builds and returns a KML geometry node with the given geometry.
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    buildGeometryNode: function(geometry) {
+        var className = geometry.CLASS_NAME;
+        var type = className.substring(className.lastIndexOf(".") + 1);
+        var builder = this.buildGeometry[type.toLowerCase()];
+        var node = null;
+        if(builder) {
+            node = builder.apply(this, [geometry]);
+        }
+        return node;
+    },
+
+    /**
+     * Property: buildGeometry
+     * Object containing methods to do the actual geometry node building
+     *     based on geometry type.
+     */
+    buildGeometry: {
+        // TBD: Anybody care about namespace aliases here (these nodes have
+        //    no prefixes)?
+
+        /**
+         * Method: buildGeometry.point
+         * Given an OpenLayers point geometry, create a KML point.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Point>} A point geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML point node.
+         */
+        point: function(geometry) {
+            var kml = this.createElementNS(this.kmlns, "Point");
+            kml.appendChild(this.buildCoordinatesNode(geometry));
+            return kml;
+        },
+        
+        /**
+         * Method: buildGeometry.multipoint
+         * Given an OpenLayers multipoint geometry, create a KML
+         *     GeometryCollection.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Point>} A multipoint geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML GeometryCollection node.
+         */
+        multipoint: function(geometry) {
+            return this.buildGeometry.collection.apply(this, [geometry]);
+        },
+
+        /**
+         * Method: buildGeometry.linestring
+         * Given an OpenLayers linestring geometry, create a KML linestring.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.LineString>} A linestring geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML linestring node.
+         */
+        linestring: function(geometry) {
+            var kml = this.createElementNS(this.kmlns, "LineString");
+            kml.appendChild(this.buildCoordinatesNode(geometry));
+            return kml;
+        },
+        
+        /**
+         * Method: buildGeometry.multilinestring
+         * Given an OpenLayers multilinestring geometry, create a KML
+         *     GeometryCollection.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Point>} A multilinestring geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML GeometryCollection node.
+         */
+        multilinestring: function(geometry) {
+            return this.buildGeometry.collection.apply(this, [geometry]);
+        },
+
+        /**
+         * Method: buildGeometry.linearring
+         * Given an OpenLayers linearring geometry, create a KML linearring.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.LinearRing>} A linearring geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML linearring node.
+         */
+        linearring: function(geometry) {
+            var kml = this.createElementNS(this.kmlns, "LinearRing");
+            kml.appendChild(this.buildCoordinatesNode(geometry));
+            return kml;
+        },
+        
+        /**
+         * Method: buildGeometry.polygon
+         * Given an OpenLayers polygon geometry, create a KML polygon.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML polygon node.
+         */
+        polygon: function(geometry) {
+            var kml = this.createElementNS(this.kmlns, "Polygon");
+            var rings = geometry.components;
+            var ringMember, ringGeom, type;
+            for(var i=0, len=rings.length; i<len; ++i) {
+                type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+                ringMember = this.createElementNS(this.kmlns, type);
+                ringGeom = this.buildGeometry.linearring.apply(this,
+                                                               [rings[i]]);
+                ringMember.appendChild(ringGeom);
+                kml.appendChild(ringMember);
+            }
+            return kml;
+        },
+        
+        /**
+         * Method: buildGeometry.multipolygon
+         * Given an OpenLayers multipolygon geometry, create a KML
+         *     GeometryCollection.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Point>} A multipolygon geometry.
+         *
+         * Returns:
+         * {DOMElement} A KML GeometryCollection node.
+         */
+        multipolygon: function(geometry) {
+            return this.buildGeometry.collection.apply(this, [geometry]);
+        },
+
+        /**
+         * Method: buildGeometry.collection
+         * Given an OpenLayers geometry collection, create a KML MultiGeometry.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Collection>} A geometry collection.
+         *
+         * Returns:
+         * {DOMElement} A KML MultiGeometry node.
+         */
+        collection: function(geometry) {
+            var kml = this.createElementNS(this.kmlns, "MultiGeometry");
+            var child;
+            for(var i=0, len=geometry.components.length; i<len; ++i) {
+                child = this.buildGeometryNode.apply(this,
+                                                     [geometry.components[i]]);
+                if(child) {
+                    kml.appendChild(child);
+                }
+            }
+            return kml;
+        }
+    },
+
+    /**
+     * Method: buildCoordinatesNode
+     * Builds and returns the KML coordinates node with the given geometry
+     * <coordinates>...</coordinates>
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Return:
+     * {DOMElement}
+     */     
+    buildCoordinatesNode: function(geometry) {
+        var coordinatesNode = this.createElementNS(this.kmlns, "coordinates");
+        
+        var path;
+        var points = geometry.components;
+        if(points) {
+            // LineString or LinearRing
+            var point;
+            var numPoints = points.length;
+            var parts = new Array(numPoints);
+            for(var i=0; i<numPoints; ++i) {
+                point = points[i];
+                parts[i] = this.buildCoordinates(point);
+            }
+            path = parts.join(" ");
+        } else {
+            // Point
+            path = this.buildCoordinates(geometry);
+        }
+        
+        var txtNode = this.createTextNode(path);
+        coordinatesNode.appendChild(txtNode);
+        
+        return coordinatesNode;
+    },    
+    
+    /**
+     * Method: buildCoordinates
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     *
+     * Returns
+     * {String} a coordinate pair
+     */
+    buildCoordinates: function(point) {
+        if (this.internalProjection && this.externalProjection) {
+            point = point.clone();
+            point.transform(this.internalProjection, 
+                               this.externalProjection);
+        }
+        return point.x + "," + point.y;                     
+    },
+
+    CLASS_NAME: "OpenLayers.Format.KML" 
+});
+/* ======================================================================
+    OpenLayers/Geometry/MultiLineString.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Geometry/LineString.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.MultiLineString
+ * A MultiLineString is a geometry with multiple <OpenLayers.Geometry.LineString>
+ * components.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Geometry.Collection>
+ *  - <OpenLayers.Geometry> 
+ */
+OpenLayers.Geometry.MultiLineString = OpenLayers.Class(
+  OpenLayers.Geometry.Collection, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of
+     * components that the collection can include.  A null value means the
+     * component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.LineString"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.MultiLineString
+     * Constructor for a MultiLineString Geometry.
+     *
+     * Parameters: 
+     * components - {Array(<OpenLayers.Geometry.LineString>)} 
+     *
+     */
+    initialize: function(components) {
+        OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
+                                                                  arguments);        
+    },
+    
+    /**
+     * Method: split
+     * Use this geometry (the source) to attempt to split a target geometry.
+     * 
+     * Parameters:
+     * target - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Properties of this object will be used to determine
+     *     how the split is conducted.
+     *
+     * Valid options:
+     * mutual - {Boolean} Split the source geometry in addition to the target
+     *     geometry.  Default is false.
+     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+     *     true.  If false, a vertex on the source must be within the tolerance
+     *     distance of the intersection to be considered a split.
+     * tolerance - {Number} If a non-null value is provided, intersections
+     *     within the tolerance distance of an existing vertex on the source
+     *     will be assumed to occur at the vertex.
+     * 
+     * Returns:
+     * {Array} A list of geometries (of this same type as the target) that
+     *     result from splitting the target with the source geometry.  The
+     *     source and target geometry will remain unmodified.  If no split
+     *     results, null will be returned.  If mutual is true and a split
+     *     results, return will be an array of two arrays - the first will be
+     *     all geometries that result from splitting the source geometry and
+     *     the second will be all geometries that result from splitting the
+     *     target geometry.
+     */
+    split: function(geometry, options) {
+        var results = null;
+        var mutual = options && options.mutual;
+        var splits, sourceLine, sourceLines, sourceSplit, targetSplit;
+        var sourceParts = [];
+        var targetParts = [geometry];
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            sourceLine = this.components[i];
+            sourceSplit = false;
+            for(var j=0; j < targetParts.length; ++j) { 
+                splits = sourceLine.split(targetParts[j], options);
+                if(splits) {
+                    if(mutual) {
+                        sourceLines = splits[0];
+                        for(var k=0, klen=sourceLines.length; k<klen; ++k) {
+                            if(k===0 && sourceParts.length) {
+                                sourceParts[sourceParts.length-1].addComponent(
+                                    sourceLines[k]
+                                );
+                            } else {
+                                sourceParts.push(
+                                    new OpenLayers.Geometry.MultiLineString([
+                                        sourceLines[k]
+                                    ])
+                                );
+                            }
+                        }
+                        sourceSplit = true;
+                        splits = splits[1];
+                    }
+                    if(splits.length) {
+                        // splice in new target parts
+                        splits.unshift(j, 1);
+                        Array.prototype.splice.apply(targetParts, splits);
+                        break;
+                    }
+                }
+            }
+            if(!sourceSplit) {
+                // source line was not hit
+                if(sourceParts.length) {
+                    // add line to existing multi
+                    sourceParts[sourceParts.length-1].addComponent(
+                        sourceLine.clone()
+                    );
+                } else {
+                    // create a fresh multi
+                    sourceParts = [
+                        new OpenLayers.Geometry.MultiLineString(
+                            sourceLine.clone()
+                        )
+                    ];
+                }
+            }
+        }
+        if(sourceParts && sourceParts.length > 1) {
+            sourceSplit = true;
+        } else {
+            sourceParts = [];
+        }
+        if(targetParts && targetParts.length > 1) {
+            targetSplit = true;
+        } else {
+            targetParts = [];
+        }
+        if(sourceSplit || targetSplit) {
+            if(mutual) {
+                results = [sourceParts, targetParts];
+            } else {
+                results = targetParts;
+            }
+        }
+        return results;
+    },
+    
+    /**
+     * Method: splitWith
+     * Split this geometry (the target) with the given geometry (the source).
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} A geometry used to split this
+     *     geometry (the source).
+     * options - {Object} Properties of this object will be used to determine
+     *     how the split is conducted.
+     *
+     * Valid options:
+     * mutual - {Boolean} Split the source geometry in addition to the target
+     *     geometry.  Default is false.
+     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+     *     true.  If false, a vertex on the source must be within the tolerance
+     *     distance of the intersection to be considered a split.
+     * tolerance - {Number} If a non-null value is provided, intersections
+     *     within the tolerance distance of an existing vertex on the source
+     *     will be assumed to occur at the vertex.
+     * 
+     * Returns:
+     * {Array} A list of geometries (of this same type as the target) that
+     *     result from splitting the target with the source geometry.  The
+     *     source and target geometry will remain unmodified.  If no split
+     *     results, null will be returned.  If mutual is true and a split
+     *     results, return will be an array of two arrays - the first will be
+     *     all geometries that result from splitting the source geometry and
+     *     the second will be all geometries that result from splitting the
+     *     target geometry.
+     */
+    splitWith: function(geometry, options) {
+        var results = null;
+        var mutual = options && options.mutual;
+        var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;
+        if(geometry instanceof OpenLayers.Geometry.LineString) {
+            targetParts = [];
+            sourceParts = [geometry];
+            for(var i=0, len=this.components.length; i<len; ++i) {
+                targetSplit = false;
+                targetLine = this.components[i];
+                for(var j=0; j<sourceParts.length; ++j) {
+                    splits = sourceParts[j].split(targetLine, options);
+                    if(splits) {
+                        if(mutual) {
+                            sourceLines = splits[0];
+                            if(sourceLines.length) {
+                                // splice in new source parts
+                                sourceLines.unshift(j, 1);
+                                Array.prototype.splice.apply(sourceParts, sourceLines);
+                                j += sourceLines.length - 2;
+                            }
+                            splits = splits[1];
+                            if(splits.length === 0) {
+                                splits = [targetLine.clone()];
+                            }
+                        }
+                        for(var k=0, klen=splits.length; k<klen; ++k) {
+                            if(k===0 && targetParts.length) {
+                                targetParts[targetParts.length-1].addComponent(
+                                    splits[k]
+                                );
+                            } else {
+                                targetParts.push(
+                                    new OpenLayers.Geometry.MultiLineString([
+                                        splits[k]
+                                    ])
+                                );
+                            }
+                        }
+                        targetSplit = true;                    
+                    }
+                }
+                if(!targetSplit) {
+                    // target component was not hit
+                    if(targetParts.length) {
+                        // add it to any existing multi-line
+                        targetParts[targetParts.length-1].addComponent(
+                            targetLine.clone()
+                        );
+                    } else {
+                        // or start with a fresh multi-line
+                        targetParts = [
+                            new OpenLayers.Geometry.MultiLineString([
+                                targetLine.clone()
+                            ])
+                        ];
+                    }
+                    
+                }
+            }
+        } else {
+            results = geometry.split(this);
+        }
+        if(sourceParts && sourceParts.length > 1) {
+            sourceSplit = true;
+        } else {
+            sourceParts = [];
+        }
+        if(targetParts && targetParts.length > 1) {
+            targetSplit = true;
+        } else {
+            targetParts = [];
+        }
+        if(sourceSplit || targetSplit) {
+            if(mutual) {
+                results = [sourceParts, targetParts];
+            } else {
+                results = targetParts;
+            }
+        }
+        return results;
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.MultiLineString"
+});
+/* ======================================================================
+    OpenLayers/Geometry/MultiPolygon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.MultiPolygon
+ * MultiPolygon is a geometry with multiple <OpenLayers.Geometry.Polygon>
+ * components.  Create a new instance with the <OpenLayers.Geometry.MultiPolygon>
+ * constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Geometry.Collection>
+ */
+OpenLayers.Geometry.MultiPolygon = OpenLayers.Class(
+  OpenLayers.Geometry.Collection, {
+
+    /**
+     * Property: componentTypes
+     * {Array(String)} An array of class names representing the types of
+     * components that the collection can include.  A null value means the
+     * component types are not restricted.
+     */
+    componentTypes: ["OpenLayers.Geometry.Polygon"],
+
+    /**
+     * Constructor: OpenLayers.Geometry.MultiPolygon
+     * Create a new MultiPolygon geometry
+     *
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry.Polygon>)} An array of polygons
+     *              used to generate the MultiPolygon
+     *
+     */
+    initialize: function(components) {
+        OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
+                                                                  arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.MultiPolygon"
+});
+/* ======================================================================
+    OpenLayers/Format/GML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML
+ * Read/Wite GML. Create a new instance with the <OpenLayers.Format.GML>
+ *     constructor.  Supports the GML simple features profile.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.GML = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /*
+     * APIProperty: featureNS
+     * {String} Namespace used for feature attributes.  Default is
+     *     "http://mapserver.gis.umn.edu/mapserver".
+     */
+    featureNS: "http://mapserver.gis.umn.edu/mapserver",
+    
+    /**
+     * APIProperty: featurePrefix
+     * {String} Namespace alias (or prefix) for feature nodes.  Default is
+     *     "feature".
+     */
+    featurePrefix: "feature",
+    
+    /*
+     * APIProperty: featureName
+     * {String} Element name for features. Default is "featureMember".
+     */
+    featureName: "featureMember", 
+    
+    /*
+     * APIProperty: layerName
+     * {String} Name of data layer. Default is "features".
+     */
+    layerName: "features",
+    
+    /**
+     * APIProperty: geometryName
+     * {String} Name of geometry element.  Defaults to "geometry".
+     */
+    geometryName: "geometry",
+    
+    /** 
+     * APIProperty: collectionName
+     * {String} Name of featureCollection element.
+     */
+    collectionName: "FeatureCollection",
+    
+    /**
+     * APIProperty: gmlns
+     * {String} GML Namespace.
+     */
+    gmlns: "http://www.opengis.net/gml",
+
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from GML.
+     */
+    extractAttributes: true,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */ 
+    xy: true,
+    
+    /**
+     * Constructor: OpenLayers.Format.GML
+     * Create a new parser for GML.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        // compile regular expressions once instead of every time they are used
+        this.regExes = {
+            trimSpace: (/^\s*|\s*$/g),
+            removeSpace: (/\s*/g),
+            splitSpace: (/\s+/),
+            trimComma: (/\s*,\s*/g)
+        };
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read data from a string, and return a list of features. 
+     * 
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var featureNodes = this.getElementsByTagNameNS(data.documentElement,
+                                                       this.gmlns,
+                                                       this.featureName);
+        var features = [];
+        for(var i=0; i<featureNodes.length; i++) {
+            var feature = this.parseFeature(featureNodes[i]);
+            if(feature) {
+                features.push(feature);
+            }
+        }
+        return features;
+    },
+    
+    /**
+     * Method: parseFeature
+     * This function is the core of the GML parsing code in OpenLayers.
+     *    It creates the geometries that are then attached to the returned
+     *    feature, and calls parseAttributes() to get attribute data out.
+     *    
+     * Parameters:
+     * node - {DOMElement} A GML feature node. 
+     */
+    parseFeature: function(node) {
+        // only accept one geometry per feature - look for highest "order"
+        var order = ["MultiPolygon", "Polygon",
+                     "MultiLineString", "LineString",
+                     "MultiPoint", "Point", "Envelope"];
+        // FIXME: In case we parse a feature with no geometry, but boundedBy an Envelope,
+        // this code creates a geometry derived from the Envelope. This is not correct.
+        var type, nodeList, geometry, parser;
+        for(var i=0; i<order.length; ++i) {
+            type = order[i];
+            nodeList = this.getElementsByTagNameNS(node, this.gmlns, type);
+            if(nodeList.length > 0) {
+                // only deal with first geometry of this type
+                parser = this.parseGeometry[type.toLowerCase()];
+                if(parser) {
+                    geometry = parser.apply(this, [nodeList[0]]);
+                    if (this.internalProjection && this.externalProjection) {
+                        geometry.transform(this.externalProjection, 
+                                           this.internalProjection); 
+                    }                       
+                } else {
+                    OpenLayers.Console.error(OpenLayers.i18n(
+                                "unsupportedGeometryType", {'geomType':type}));
+                }
+                // stop looking for different geometry types
+                break;
+            }
+        }
+
+        var bounds;
+        var boxNodes = this.getElementsByTagNameNS(node, this.gmlns, "Box");
+        for(i=0; i<boxNodes.length; ++i) {
+            var boxNode = boxNodes[i];
+            var box = this.parseGeometry["box"].apply(this, [boxNode]);
+            var parentNode = boxNode.parentNode;
+            var parentName = parentNode.localName ||
+                             parentNode.nodeName.split(":").pop();
+            if(parentName === "boundedBy") {
+                bounds = box;
+            } else {
+                geometry = box.toGeometry();
+            }
+        }
+        
+        // construct feature (optionally with attributes)
+        var attributes;
+        if(this.extractAttributes) {
+            attributes = this.parseAttributes(node);
+        }
+        var feature = new OpenLayers.Feature.Vector(geometry, attributes);
+        feature.bounds = bounds;
+        
+        feature.gml = {
+            featureType: node.firstChild.nodeName.split(":")[1],
+            featureNS: node.firstChild.namespaceURI,
+            featureNSPrefix: node.firstChild.prefix
+        };
+                
+        // assign fid - this can come from a "fid" or "id" attribute
+        var childNode = node.firstChild;
+        var fid;
+        while(childNode) {
+            if(childNode.nodeType == 1) {
+                fid = childNode.getAttribute("fid") ||
+                      childNode.getAttribute("id");
+                if(fid) {
+                    break;
+                }
+            }
+            childNode = childNode.nextSibling;
+        }
+        feature.fid = fid;
+        return feature;
+    },
+    
+    /**
+     * Property: parseGeometry
+     * Properties of this object are the functions that parse geometries based
+     *     on their type.
+     */
+    parseGeometry: {
+        
+        /**
+         * Method: parseGeometry.point
+         * Given a GML node representing a point geometry, create an OpenLayers
+         *     point geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.Point>} A point geometry.
+         */
+        point: function(node) {
+            /**
+             * Three coordinate variations to consider:
+             * 1) <gml:pos>x y z</gml:pos>
+             * 2) <gml:coordinates>x, y, z</gml:coordinates>
+             * 3) <gml:coord><gml:X>x</gml:X><gml:Y>y</gml:Y></gml:coord>
+             */
+            var nodeList, coordString;
+            var coords = [];
+
+            // look for <gml:pos>
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns, "pos");
+            if(nodeList.length > 0) {
+                coordString = nodeList[0].firstChild.nodeValue;
+                coordString = coordString.replace(this.regExes.trimSpace, "");
+                coords = coordString.split(this.regExes.splitSpace);
+            }
+
+            // look for <gml:coordinates>
+            if(coords.length == 0) {
+                nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "coordinates");
+                if(nodeList.length > 0) {
+                    coordString = nodeList[0].firstChild.nodeValue;
+                    coordString = coordString.replace(this.regExes.removeSpace,
+                                                      "");
+                    coords = coordString.split(",");
+                }
+            }
+
+            // look for <gml:coord>
+            if(coords.length == 0) {
+                nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "coord");
+                if(nodeList.length > 0) {
+                    var xList = this.getElementsByTagNameNS(nodeList[0],
+                                                            this.gmlns, "X");
+                    var yList = this.getElementsByTagNameNS(nodeList[0],
+                                                            this.gmlns, "Y");
+                    if(xList.length > 0 && yList.length > 0) {
+                        coords = [xList[0].firstChild.nodeValue,
+                                  yList[0].firstChild.nodeValue];
+                    }
+                }
+            }
+                
+            // preserve third dimension
+            if(coords.length == 2) {
+                coords[2] = null;
+            }
+            
+            if (this.xy) {
+                return new OpenLayers.Geometry.Point(coords[0], coords[1],
+                                                 coords[2]);
+            }
+            else{
+                return new OpenLayers.Geometry.Point(coords[1], coords[0],
+                                                 coords[2]);
+            }
+        },
+        
+        /**
+         * Method: parseGeometry.multipoint
+         * Given a GML node representing a multipoint geometry, create an
+         *     OpenLayers multipoint geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.MultiPoint>} A multipoint geometry.
+         */
+        multipoint: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "Point");
+            var components = [];
+            if(nodeList.length > 0) {
+                var point;
+                for(var i=0; i<nodeList.length; ++i) {
+                    point = this.parseGeometry.point.apply(this, [nodeList[i]]);
+                    if(point) {
+                        components.push(point);
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.MultiPoint(components);
+        },
+        
+        /**
+         * Method: parseGeometry.linestring
+         * Given a GML node representing a linestring geometry, create an
+         *     OpenLayers linestring geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.LineString>} A linestring geometry.
+         */
+        linestring: function(node, ring) {
+            /**
+             * Two coordinate variations to consider:
+             * 1) <gml:posList dimension="d">x0 y0 z0 x1 y1 z1</gml:posList>
+             * 2) <gml:coordinates>x0, y0, z0 x1, y1, z1</gml:coordinates>
+             */
+            var nodeList, coordString;
+            var coords = [];
+            var points = [];
+
+            // look for <gml:posList>
+            nodeList = this.getElementsByTagNameNS(node, this.gmlns, "posList");
+            if(nodeList.length > 0) {
+                coordString = this.getChildValue(nodeList[0]);
+                coordString = coordString.replace(this.regExes.trimSpace, "");
+                coords = coordString.split(this.regExes.splitSpace);
+                var dim = parseInt(nodeList[0].getAttribute("dimension"));
+                var j, x, y, z;
+                for(var i=0; i<coords.length/dim; ++i) {
+                    j = i * dim;
+                    x = coords[j];
+                    y = coords[j+1];
+                    z = (dim == 2) ? null : coords[j+2];
+                    if (this.xy) {
+                        points.push(new OpenLayers.Geometry.Point(x, y, z));
+                    } else {
+                        points.push(new OpenLayers.Geometry.Point(y, x, z));
+                    }
+                }
+            }
+
+            // look for <gml:coordinates>
+            if(coords.length == 0) {
+                nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "coordinates");
+                if(nodeList.length > 0) {
+                    coordString = this.getChildValue(nodeList[0]);
+                    coordString = coordString.replace(this.regExes.trimSpace,
+                                                      "");
+                    coordString = coordString.replace(this.regExes.trimComma,
+                                                      ",");
+                    var pointList = coordString.split(this.regExes.splitSpace);
+                    for(var i=0; i<pointList.length; ++i) {
+                        coords = pointList[i].split(",");
+                        if(coords.length == 2) {
+                            coords[2] = null;
+                        }
+                        if (this.xy) {
+                            points.push(new OpenLayers.Geometry.Point(coords[0],
+                                                                  coords[1],
+                                                                  coords[2]));
+                        } else {
+                            points.push(new OpenLayers.Geometry.Point(coords[1],
+                                                                  coords[0],
+                                                                  coords[2]));
+                        }
+                    }
+                }
+            }
+
+            var line = null;
+            if(points.length != 0) {
+                if(ring) {
+                    line = new OpenLayers.Geometry.LinearRing(points);
+                } else {
+                    line = new OpenLayers.Geometry.LineString(points);
+                }
+            }
+            return line;
+        },
+        
+        /**
+         * Method: parseGeometry.multilinestring
+         * Given a GML node representing a multilinestring geometry, create an
+         *     OpenLayers multilinestring geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.MultiLineString>} A multilinestring geometry.
+         */
+        multilinestring: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "LineString");
+            var components = [];
+            if(nodeList.length > 0) {
+                var line;
+                for(var i=0; i<nodeList.length; ++i) {
+                    line = this.parseGeometry.linestring.apply(this,
+                                                               [nodeList[i]]);
+                    if(line) {
+                        components.push(line);
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.MultiLineString(components);
+        },
+        
+        /**
+         * Method: parseGeometry.polygon
+         * Given a GML node representing a polygon geometry, create an
+         *     OpenLayers polygon geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+         */
+        polygon: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "LinearRing");
+            var components = [];
+            if(nodeList.length > 0) {
+                // this assumes exterior ring first, inner rings after
+                var ring;
+                for(var i=0; i<nodeList.length; ++i) {
+                    ring = this.parseGeometry.linestring.apply(this,
+                                                        [nodeList[i], true]);
+                    if(ring) {
+                        components.push(ring);
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.Polygon(components);
+        },
+        
+        /**
+         * Method: parseGeometry.multipolygon
+         * Given a GML node representing a multipolygon geometry, create an
+         *     OpenLayers multipolygon geometry.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry.MultiPolygon>} A multipolygon geometry.
+         */
+        multipolygon: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                       "Polygon");
+            var components = [];
+            if(nodeList.length > 0) {
+                var polygon;
+                for(var i=0; i<nodeList.length; ++i) {
+                    polygon = this.parseGeometry.polygon.apply(this,
+                                                               [nodeList[i]]);
+                    if(polygon) {
+                        components.push(polygon);
+                    }
+                }
+            }
+            return new OpenLayers.Geometry.MultiPolygon(components);
+        },
+        
+        envelope: function(node) {
+            var components = [];
+            var coordString;
+            var envelope;
+            
+            var lpoint = this.getElementsByTagNameNS(node, this.gmlns, "lowerCorner");
+            if (lpoint.length > 0) {
+                var coords = [];
+                
+                if(lpoint.length > 0) {
+                    coordString = lpoint[0].firstChild.nodeValue;
+                    coordString = coordString.replace(this.regExes.trimSpace, "");
+                    coords = coordString.split(this.regExes.splitSpace);
+                }
+                
+                if(coords.length == 2) {
+                    coords[2] = null;
+                }
+                if (this.xy) {
+                    var lowerPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]);
+                } else {
+                    var lowerPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]);
+                }
+            }
+            
+            var upoint = this.getElementsByTagNameNS(node, this.gmlns, "upperCorner");
+            if (upoint.length > 0) {
+                var coords = [];
+                
+                if(upoint.length > 0) {
+                    coordString = upoint[0].firstChild.nodeValue;
+                    coordString = coordString.replace(this.regExes.trimSpace, "");
+                    coords = coordString.split(this.regExes.splitSpace);
+                }
+                
+                if(coords.length == 2) {
+                    coords[2] = null;
+                }
+                if (this.xy) {
+                    var upperPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]);
+                } else {
+                    var upperPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]);
+                }
+            }
+            
+            if (lowerPoint && upperPoint) {
+                components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y));
+                components.push(new OpenLayers.Geometry.Point(upperPoint.x, lowerPoint.y));
+                components.push(new OpenLayers.Geometry.Point(upperPoint.x, upperPoint.y));
+                components.push(new OpenLayers.Geometry.Point(lowerPoint.x, upperPoint.y));
+                components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y));
+                
+                var ring = new OpenLayers.Geometry.LinearRing(components);
+                envelope = new OpenLayers.Geometry.Polygon([ring]);
+            }
+            return envelope; 
+        },
+
+        /**
+         * Method: parseGeometry.box
+         * Given a GML node representing a box geometry, create an
+         *     OpenLayers.Bounds.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Bounds>} A bounds representing the box.
+         */
+        box: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                   "coordinates");
+            var coordString;
+            var coords, beginPoint = null, endPoint = null;
+            if (nodeList.length > 0) {
+                coordString = nodeList[0].firstChild.nodeValue;
+                coords = coordString.split(" ");
+                if (coords.length == 2) {
+                    beginPoint = coords[0].split(",");
+                    endPoint = coords[1].split(",");
+                }
+            }
+            if (beginPoint !== null && endPoint !== null) {
+                return new OpenLayers.Bounds(parseFloat(beginPoint[0]),
+                    parseFloat(beginPoint[1]),
+                    parseFloat(endPoint[0]),
+                    parseFloat(endPoint[1]) );
+            }
+        }
+        
+    },
+    
+    /**
+     * Method: parseAttributes
+     *
+     * Parameters:
+     * node - {DOMElement}
+     *
+     * Returns:
+     * {Object} An attributes object.
+     */
+    parseAttributes: function(node) {
+        var attributes = {};
+        // assume attributes are children of the first type 1 child
+        var childNode = node.firstChild;
+        var children, i, child, grandchildren, grandchild, name, value;
+        while(childNode) {
+            if(childNode.nodeType == 1) {
+                // attributes are type 1 children with one type 3 child
+                children = childNode.childNodes;
+                for(i=0; i<children.length; ++i) {
+                    child = children[i];
+                    if(child.nodeType == 1) {
+                        grandchildren = child.childNodes;
+                        if(grandchildren.length == 1) {
+                            grandchild = grandchildren[0];
+                            if(grandchild.nodeType == 3 ||
+                               grandchild.nodeType == 4) {
+                                name = (child.prefix) ?
+                                        child.nodeName.split(":")[1] :
+                                        child.nodeName;
+                                value = grandchild.nodeValue.replace(
+                                                this.regExes.trimSpace, "");
+                                attributes[name] = value;
+                            }
+                        } else {
+                            // If child has no childNodes (grandchildren),
+                            // set an attribute with null value.
+                            // e.g. <prefix:fieldname/> becomes
+                            // {fieldname: null}
+                            attributes[child.nodeName.split(":").pop()] = null;
+                        }
+                    }
+                }
+                break;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return attributes;
+    },
+    
+    /**
+     * APIMethod: write
+     * Generate a GML document string given a list of features. 
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} List of features to
+     *     serialize into a string.
+     *
+     * Returns:
+     * {String} A string representing the GML document.
+     */
+    write: function(features) {
+        if(!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        var gml = this.createElementNS("http://www.opengis.net/wfs",
+                                       "wfs:" + this.collectionName);
+        for(var i=0; i<features.length; i++) {
+            gml.appendChild(this.createFeatureXML(features[i]));
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [gml]);
+    },
+
+    /** 
+     * Method: createFeatureXML
+     * Accept an OpenLayers.Feature.Vector, and build a GML node for it.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature to be built as GML.
+     *
+     * Returns:
+     * {DOMElement} A node reprensting the feature in GML.
+     */
+    createFeatureXML: function(feature) {
+        var geometry = feature.geometry;
+        var geometryNode = this.buildGeometryNode(geometry);
+        var geomContainer = this.createElementNS(this.featureNS,
+                                                 this.featurePrefix + ":" +
+                                                 this.geometryName);
+        geomContainer.appendChild(geometryNode);
+        var featureNode = this.createElementNS(this.gmlns,
+                                               "gml:" + this.featureName);
+        var featureContainer = this.createElementNS(this.featureNS,
+                                                    this.featurePrefix + ":" +
+                                                    this.layerName);
+        var fid = feature.fid || feature.id;
+        featureContainer.setAttribute("fid", fid);
+        featureContainer.appendChild(geomContainer);
+        for(var attr in feature.attributes) {
+            var attrText = this.createTextNode(feature.attributes[attr]); 
+            var nodename = attr.substring(attr.lastIndexOf(":") + 1);
+            var attrContainer = this.createElementNS(this.featureNS,
+                                                     this.featurePrefix + ":" +
+                                                     nodename);
+            attrContainer.appendChild(attrText);
+            featureContainer.appendChild(attrContainer);
+        }    
+        featureNode.appendChild(featureContainer);
+        return featureNode;
+    },
+    
+    /**
+     * APIMethod: buildGeometryNode
+     */
+    buildGeometryNode: function(geometry) {
+        if (this.externalProjection && this.internalProjection) {
+            geometry = geometry.clone();
+            geometry.transform(this.internalProjection, 
+                               this.externalProjection);
+        }    
+        var className = geometry.CLASS_NAME;
+        var type = className.substring(className.lastIndexOf(".") + 1);
+        var builder = this.buildGeometry[type.toLowerCase()];
+        return builder.apply(this, [geometry]);
+    },
+
+    /**
+     * Property: buildGeometry
+     * Object containing methods to do the actual geometry node building
+     *     based on geometry type.
+     */
+    buildGeometry: {
+        // TBD retrieve the srs from layer
+        // srsName is non-standard, so not including it until it's right.
+        // gml.setAttribute("srsName",
+        //                  "http://www.opengis.net/gml/srs/epsg.xml#4326");
+
+        /**
+         * Method: buildGeometry.point
+         * Given an OpenLayers point geometry, create a GML point.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Point>} A point geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML point node.
+         */
+        point: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:Point");
+            gml.appendChild(this.buildCoordinatesNode(geometry));
+            return gml;
+        },
+        
+        /**
+         * Method: buildGeometry.multipoint
+         * Given an OpenLayers multipoint geometry, create a GML multipoint.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.MultiPoint>} A multipoint geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML multipoint node.
+         */
+        multipoint: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:MultiPoint");
+            var points = geometry.components;
+            var pointMember, pointGeom;
+            for(var i=0; i<points.length; i++) { 
+                pointMember = this.createElementNS(this.gmlns,
+                                                   "gml:pointMember");
+                pointGeom = this.buildGeometry.point.apply(this,
+                                                               [points[i]]);
+                pointMember.appendChild(pointGeom);
+                gml.appendChild(pointMember);
+            }
+            return gml;            
+        },
+        
+        /**
+         * Method: buildGeometry.linestring
+         * Given an OpenLayers linestring geometry, create a GML linestring.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.LineString>} A linestring geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML linestring node.
+         */
+        linestring: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:LineString");
+            gml.appendChild(this.buildCoordinatesNode(geometry));
+            return gml;
+        },
+        
+        /**
+         * Method: buildGeometry.multilinestring
+         * Given an OpenLayers multilinestring geometry, create a GML
+         *     multilinestring.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.MultiLineString>} A multilinestring
+         *     geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML multilinestring node.
+         */
+        multilinestring: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:MultiLineString");
+            var lines = geometry.components;
+            var lineMember, lineGeom;
+            for(var i=0; i<lines.length; ++i) {
+                lineMember = this.createElementNS(this.gmlns,
+                                                  "gml:lineStringMember");
+                lineGeom = this.buildGeometry.linestring.apply(this,
+                                                                   [lines[i]]);
+                lineMember.appendChild(lineGeom);
+                gml.appendChild(lineMember);
+            }
+            return gml;
+        },
+        
+        /**
+         * Method: buildGeometry.linearring
+         * Given an OpenLayers linearring geometry, create a GML linearring.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.LinearRing>} A linearring geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML linearring node.
+         */
+        linearring: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:LinearRing");
+            gml.appendChild(this.buildCoordinatesNode(geometry));
+            return gml;
+        },
+        
+        /**
+         * Method: buildGeometry.polygon
+         * Given an OpenLayers polygon geometry, create a GML polygon.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML polygon node.
+         */
+        polygon: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:Polygon");
+            var rings = geometry.components;
+            var ringMember, ringGeom, type;
+            for(var i=0; i<rings.length; ++i) {
+                type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+                ringMember = this.createElementNS(this.gmlns,
+                                                  "gml:" + type);
+                ringGeom = this.buildGeometry.linearring.apply(this,
+                                                                   [rings[i]]);
+                ringMember.appendChild(ringGeom);
+                gml.appendChild(ringMember);
+            }
+            return gml;
+        },
+        
+        /**
+         * Method: buildGeometry.multipolygon
+         * Given an OpenLayers multipolygon geometry, create a GML multipolygon.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry.MultiPolygon>} A multipolygon
+         *     geometry.
+         *
+         * Returns:
+         * {DOMElement} A GML multipolygon node.
+         */
+        multipolygon: function(geometry) {
+            var gml = this.createElementNS(this.gmlns, "gml:MultiPolygon");
+            var polys = geometry.components;
+            var polyMember, polyGeom;
+            for(var i=0; i<polys.length; ++i) {
+                polyMember = this.createElementNS(this.gmlns,
+                                                  "gml:polygonMember");
+                polyGeom = this.buildGeometry.polygon.apply(this,
+                                                                [polys[i]]);
+                polyMember.appendChild(polyGeom);
+                gml.appendChild(polyMember);
+            }
+            return gml;
+
+        },
+ 
+        /**
+         * Method: buildGeometry.bounds
+         * Given an OpenLayers bounds, create a GML box.
+         *
+         * Parameters:
+         * bounds - {<OpenLayers.Geometry.Bounds>} A bounds object.
+         *
+         * Returns:
+         * {DOMElement} A GML box node.
+         */
+        bounds: function(bounds) {
+            var gml = this.createElementNS(this.gmlns, "gml:Box");
+            gml.appendChild(this.buildCoordinatesNode(bounds));
+            return gml;
+        }
+    },
+
+    /**
+     * Method: buildCoordinates
+     * builds the coordinates XmlNode
+     * (code)
+     * <gml:coordinates decimal="." cs="," ts=" ">...</gml:coordinates>
+     * (end)
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>} 
+     *
+     * Returns:
+     * {XmlNode} created xmlNode
+     */
+    buildCoordinatesNode: function(geometry) {
+        var coordinatesNode = this.createElementNS(this.gmlns,
+                                                   "gml:coordinates");
+        coordinatesNode.setAttribute("decimal", ".");
+        coordinatesNode.setAttribute("cs", ",");
+        coordinatesNode.setAttribute("ts", " ");
+
+        var parts = [];
+
+        if(geometry instanceof OpenLayers.Bounds){
+            parts.push(geometry.left + "," + geometry.bottom);
+            parts.push(geometry.right + "," + geometry.top);
+        } else {
+            var points = (geometry.components) ? geometry.components : [geometry];
+            for(var i=0; i<points.length; i++) {
+                parts.push(points[i].x + "," + points[i].y);                
+            }            
+        }
+
+        var txtNode = this.createTextNode(parts.join(" "));
+        coordinatesNode.appendChild(txtNode);
+        
+        return coordinatesNode;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.GML" 
+});
+/* ======================================================================
+    OpenLayers/Format/GML/Base.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML.js
+ */
+
+/**
+ * Though required in the full build, if the GML format is excluded, we set
+ * the namespace here.
+ */
+if(!OpenLayers.Format.GML) {
+    OpenLayers.Format.GML = {};
+}
+
+/**
+ * Class: OpenLayers.Format.GML.Base
+ * Superclass for GML parsers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        gml: "http://www.opengis.net/gml",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance",
+        wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection
+    },
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "gml",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: null,
+    
+    /**
+     * APIProperty: featureType
+     * {Array(String) or String} The local (without prefix) feature typeName(s).
+     */
+    featureType: null,
+    
+    /**
+     * APIProperty: featureNS
+     * {String} The feature namespace.  Must be set in the options at
+     *     construction.
+     */
+    featureNS: null,
+
+    /**
+     * APIProperty: geometry
+     * {String} Name of geometry element.  Defaults to "geometry". If null, it
+     * will be set on <read> when the first geometry is parsed.
+     */
+    geometryName: "geometry",
+
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from GML.  Default is true.
+     */
+    extractAttributes: true,
+    
+    /**
+     * APIProperty: srsName
+     * {String} URI for spatial reference system.  This is optional for
+     *     single part geometries and mandatory for collections and multis.
+     *     If set, the srsName attribute will be written for all geometries.
+     *     Default is null.
+     */
+    srsName: null,
+
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */ 
+    xy: true,
+
+    /**
+     * Property: geometryTypes
+     * {Object} Maps OpenLayers geometry class names to GML element names.
+     *     Use <setGeometryTypes> before accessing this property.
+     */
+    geometryTypes: null,
+
+    /**
+     * Property: singleFeatureType
+     * {Boolean} True if there is only 1 featureType, and not an array
+     *     of featuretypes.
+     */
+    singleFeatureType: null,
+    
+    /**
+     * Property: autoConfig
+     * {Boolean} Indicates if the format was configured without a <featureNS>,
+     * but auto-configured <featureNS> and <featureType> during read.
+     * Subclasses making use of <featureType> auto-configuration should make
+     * the first call to the <readNode> method (usually in the read method)
+     * with true as 3rd argument, so the auto-configured featureType can be
+     * reset and the format can be reused for subsequent reads with data from
+     * different featureTypes. Set to false after read if you want to keep the
+     * auto-configured values.
+     */
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g),
+        featureMember: (/^(.*:)?featureMembers?$/)
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.GML.Base
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.GML.v2> or <OpenLayers.Format.GML.v3> constructor
+     *     instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     *
+     * Valid options properties:
+     * featureType - {Array(String) or String} Local (without prefix) feature 
+     *     typeName(s) (required for write).
+     * featureNS - {String} Feature namespace (required for write).
+     * geometryName - {String} Geometry element name (required for write).
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.setGeometryTypes();
+        if(options && options.featureNS) {
+            this.setNamespace("feature", options.featureNS);
+        }
+        this.singleFeatureType = !options || (typeof options.featureType === "string");
+    },
+    
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement} A gml:featureMember element, a gml:featureMembers
+     *     element, or an element containing either of the above at any level.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var features = [];
+        this.readNode(data, {features: features}, true);
+        if(features.length == 0) {
+            // look for gml:featureMember elements
+            var elements = this.getElementsByTagNameNS(
+                data, this.namespaces.gml, "featureMember"
+            );
+            if(elements.length) {
+                for(var i=0, len=elements.length; i<len; ++i) {
+                    this.readNode(elements[i], {features: features}, true);
+                }
+            } else {
+                // look for gml:featureMembers elements (this is v3, but does no harm here)
+                var elements = this.getElementsByTagNameNS(
+                    data, this.namespaces.gml, "featureMembers"
+                );
+                if(elements.length) {
+                    // there can be only one
+                    this.readNode(elements[0], {features: features}, true);
+                }
+            }
+        }
+        return features;
+    },
+    
+    /**
+     * Method: readNode
+     * Shorthand for applying one of the named readers given the node
+     *     namespace and local name.  Readers take two args (node, obj) and
+     *     generally extend or modify the second.
+     *
+     * Parameters:
+     * node - {DOMElement} The node to be read (required).
+     * obj - {Object} The object to be modified (optional).
+     * first - {Boolean} Should be set to true for the first node read. This
+     *     is usually the readNode call in the read method. Without this being
+     *     set, auto-configured properties will stick on subsequent reads.
+     *
+     * Returns:
+     * {Object} The input object, modified (or a new one if none was provided).
+     */
+    readNode: function(node, obj, first) {
+        // on subsequent calls of format.read(), we want to reset auto-
+        // configured properties and auto-configure again.
+        if (first === true && this.autoConfig === true) {
+            this.featureType = null;
+            delete this.namespaceAlias[this.featureNS];
+            delete this.namespaces["feature"];
+            this.featureNS = null;
+        }
+        // featureType auto-configuration
+        if (!this.featureNS && (!(node.prefix in this.namespaces) &&
+                node.parentNode.namespaceURI == this.namespaces["gml"] &&
+                this.regExes.featureMember.test(node.parentNode.nodeName))) {
+            this.featureType = node.nodeName.split(":").pop();
+            this.setNamespace("feature", node.namespaceURI);
+            this.featureNS = node.namespaceURI;
+            this.autoConfig = true;
+        }
+        return OpenLayers.Format.XML.prototype.readNode.apply(this, [node, obj]);
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "gml": {
+            "featureMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "featureMembers": function(node, obj) {
+                this.readChildNodes(node, obj);                
+            },
+            "name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "boundedBy": function(node, obj) {
+                var container = {};
+                this.readChildNodes(node, container);
+                if(container.components && container.components.length > 0) {
+                    obj.bounds = container.components[0];
+                }
+            },
+            "Point": function(node, container) {
+                var obj = {points: []};
+                this.readChildNodes(node, obj);
+                if(!container.components) {
+                    container.components = [];
+                }
+                container.components.push(obj.points[0]);
+            },
+            "coordinates": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, ""
+                );
+                str = str.replace(this.regExes.trimComma, ",");
+                var pointList = str.split(this.regExes.splitSpace);
+                var coords;
+                var numPoints = pointList.length;
+                var points = new Array(numPoints);
+                for(var i=0; i<numPoints; ++i) {
+                    coords = pointList[i].split(",");
+                    if (this.xy) {
+                        points[i] = new OpenLayers.Geometry.Point(
+                            coords[0], coords[1], coords[2]
+                        );
+                    } else {
+                        points[i] = new OpenLayers.Geometry.Point(
+                            coords[1], coords[0], coords[2]
+                        );
+                    }
+                }
+                obj.points = points;
+            },
+            "coord": function(node, obj) {
+                var coord = {};
+                this.readChildNodes(node, coord);
+                if(!obj.points) {
+                    obj.points = [];
+                }
+                obj.points.push(new OpenLayers.Geometry.Point(
+                    coord.x, coord.y, coord.z
+                ));
+            },
+            "X": function(node, coord) {
+                coord.x = this.getChildValue(node);
+            },
+            "Y": function(node, coord) {
+                coord.y = this.getChildValue(node);
+            },
+            "Z": function(node, coord) {
+                coord.z = this.getChildValue(node);
+            },
+            "MultiPoint": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                container.components = [
+                    new OpenLayers.Geometry.MultiPoint(obj.components)
+                ];
+            },
+            "pointMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "LineString": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                if(!container.components) {
+                    container.components = [];
+                }
+                container.components.push(
+                    new OpenLayers.Geometry.LineString(obj.points)
+                );
+            },
+            "MultiLineString": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                container.components = [
+                    new OpenLayers.Geometry.MultiLineString(obj.components)
+                ];
+            },
+            "lineStringMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Polygon": function(node, container) {
+                var obj = {outer: null, inner: []};
+                this.readChildNodes(node, obj);
+                obj.inner.unshift(obj.outer);
+                if(!container.components) {
+                    container.components = [];
+                }
+                container.components.push(
+                    new OpenLayers.Geometry.Polygon(obj.inner)
+                );
+            },
+            "LinearRing": function(node, obj) {
+                var container = {};
+                this.readChildNodes(node, container);
+                obj.components = [new OpenLayers.Geometry.LinearRing(
+                    container.points
+                )];
+            },
+            "MultiPolygon": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                container.components = [
+                    new OpenLayers.Geometry.MultiPolygon(obj.components)
+                ];
+            },
+            "polygonMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "GeometryCollection": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                container.components = [
+                    new OpenLayers.Geometry.Collection(obj.components)
+                ];
+            },
+            "geometryMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            }
+        },
+        "feature": {
+            "*": function(node, obj) {
+                // The node can either be named like the featureType, or it
+                // can be a child of the feature:featureType.  Children can be
+                // geometry or attributes.
+                var name;
+                var local = node.localName || node.nodeName.split(":").pop();
+                // Since an attribute can have the same name as the feature type
+                // we only want to read the node as a feature if the parent
+                // node can have feature nodes as children.  In this case, the
+                // obj.features property is set.
+                if (obj.features) {
+                    if (!this.singleFeatureType &&
+                        (OpenLayers.Util.indexOf(this.featureType, local) !== -1)) {
+                        name = "_typeName";
+                    } else if(local === this.featureType) {
+                        name = "_typeName";
+                    }
+                } else {
+                    // Assume attribute elements have one child node and that the child
+                    // is a text node.  Otherwise assume it is a geometry node.
+                    if(node.childNodes.length == 0 ||
+                       (node.childNodes.length == 1 && node.firstChild.nodeType == 3)) {
+                        if(this.extractAttributes) {
+                            name = "_attribute";
+                        }
+                    } else {
+                        name = "_geometry";
+                    }
+                }
+                if(name) {
+                    this.readers.feature[name].apply(this, [node, obj]);
+                }
+            },
+            "_typeName": function(node, obj) {
+                var container = {components: [], attributes: {}};
+                this.readChildNodes(node, container);
+                // look for common gml namespaced elements
+                if(container.name) {
+                    container.attributes.name = container.name;
+                }
+                var feature = new OpenLayers.Feature.Vector(
+                    container.components[0], container.attributes
+                );
+                if (!this.singleFeatureType) {
+                    feature.type = node.nodeName.split(":").pop();
+                    feature.namespace = node.namespaceURI;
+                }
+                var fid = node.getAttribute("fid") ||
+                    this.getAttributeNS(node, this.namespaces["gml"], "id");
+                if(fid) {
+                    feature.fid = fid;
+                }
+                if(this.internalProjection && this.externalProjection &&
+                   feature.geometry) {
+                    feature.geometry.transform(
+                        this.externalProjection, this.internalProjection
+                    );
+                }
+                if(container.bounds) {
+                    feature.bounds = container.bounds;
+                }
+                obj.features.push(feature);
+            },
+            "_geometry": function(node, obj) {
+                if (!this.geometryName) {
+                    this.geometryName = node.nodeName.split(":").pop();
+                }
+                this.readChildNodes(node, obj);
+            },
+            "_attribute": function(node, obj) {
+                var local = node.localName || node.nodeName.split(":").pop();
+                var value = this.getChildValue(node);
+                obj.attributes[local] = value;
+            }
+        },
+        "wfs": {
+            "FeatureCollection": function(node, obj) {
+                this.readChildNodes(node, obj);
+            }
+        }
+    },
+    
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+     *     An array of features or a single feature.
+     *
+     * Returns:
+     * {String} Given an array of features, a doc with a gml:featureMembers
+     *     element will be returned.  Given a single feature, a doc with a
+     *     gml:featureMember element will be returned.
+     */
+    write: function(features) {
+        var name;
+        if(OpenLayers.Util.isArray(features)) {
+            name = "featureMembers";
+        } else {
+            name = "featureMember";
+        }
+        var root = this.writeNode("gml:" + name, features);
+        this.setAttributeNS(
+            root, this.namespaces["xsi"],
+            "xsi:schemaLocation", this.schemaLocation
+        );
+
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "gml": {
+            "featureMember": function(feature) {
+                var node = this.createElementNSPlus("gml:featureMember");
+                this.writeNode("feature:_typeName", feature, node);
+                return node;
+            },
+            "MultiPoint": function(geometry) {
+                var node = this.createElementNSPlus("gml:MultiPoint");
+                var components = geometry.components || [geometry];
+                for(var i=0, ii=components.length; i<ii; ++i) {
+                    this.writeNode("pointMember", components[i], node);
+                }
+                return node;
+            },
+            "pointMember": function(geometry) {
+                var node = this.createElementNSPlus("gml:pointMember");
+                this.writeNode("Point", geometry, node);
+                return node;
+            },
+            "MultiLineString": function(geometry) {
+                var node = this.createElementNSPlus("gml:MultiLineString");
+                var components = geometry.components || [geometry];
+                for(var i=0, ii=components.length; i<ii; ++i) {
+                    this.writeNode("lineStringMember", components[i], node);
+                }
+                return node;
+            },
+            "lineStringMember": function(geometry) {
+                var node = this.createElementNSPlus("gml:lineStringMember");
+                this.writeNode("LineString", geometry, node);
+                return node;
+            },
+            "MultiPolygon": function(geometry) {
+                var node = this.createElementNSPlus("gml:MultiPolygon");
+                var components = geometry.components || [geometry];
+                for(var i=0, ii=components.length; i<ii; ++i) {
+                    this.writeNode(
+                        "polygonMember", components[i], node
+                    );
+                }
+                return node;
+            },
+            "polygonMember": function(geometry) {
+                var node = this.createElementNSPlus("gml:polygonMember");
+                this.writeNode("Polygon", geometry, node);
+                return node;
+            },
+            "GeometryCollection": function(geometry) {
+                var node = this.createElementNSPlus("gml:GeometryCollection");
+                for(var i=0, len=geometry.components.length; i<len; ++i) {
+                    this.writeNode("geometryMember", geometry.components[i], node);
+                }
+                return node;
+            },
+            "geometryMember": function(geometry) {
+                var node = this.createElementNSPlus("gml:geometryMember");
+                var child = this.writeNode("feature:_geometry", geometry);
+                node.appendChild(child.firstChild);
+                return node;
+            }
+        },
+        "feature": {
+            "_typeName": function(feature) {
+                var node = this.createElementNSPlus("feature:" + this.featureType, {
+                    attributes: {fid: feature.fid}
+                });
+                if(feature.geometry) {
+                    this.writeNode("feature:_geometry", feature.geometry, node);
+                }
+                for(var name in feature.attributes) {
+                    var value = feature.attributes[name];
+                    if(value != null) {
+                        this.writeNode(
+                            "feature:_attribute",
+                            {name: name, value: value}, node
+                        );
+                    }
+                }
+                return node;
+            },
+            "_geometry": function(geometry) {
+                if(this.externalProjection && this.internalProjection) {
+                    geometry = geometry.clone().transform(
+                        this.internalProjection, this.externalProjection
+                    );
+                }    
+                var node = this.createElementNSPlus(
+                    "feature:" + this.geometryName
+                );
+                var type = this.geometryTypes[geometry.CLASS_NAME];
+                var child = this.writeNode("gml:" + type, geometry, node);
+                if(this.srsName) {
+                    child.setAttribute("srsName", this.srsName);
+                }
+                return node;
+            },
+            "_attribute": function(obj) {
+                return this.createElementNSPlus("feature:" + obj.name, {
+                    value: obj.value
+                });
+            }
+        },
+        "wfs": {
+            "FeatureCollection": function(features) {
+                /**
+                 * This is only here because GML2 only describes abstract
+                 * feature collections.  Typically, you would not be using
+                 * the GML format to write wfs elements.  This just provides
+                 * some way to write out lists of features.  GML3 defines the
+                 * featureMembers element, so that is used by default instead.
+                 */
+                var node = this.createElementNSPlus("wfs:FeatureCollection");
+                for(var i=0, len=features.length; i<len; ++i) {
+                    this.writeNode("gml:featureMember", features[i], node);
+                }
+                return node;
+            }
+        }
+    },
+    
+    /**
+     * Function: setGeometryTypes
+     * Sets the <geometryTypes> mapping.
+     */
+    setGeometryTypes: function() {
+        this.geometryTypes = {
+            "OpenLayers.Geometry.Point": "Point",
+            "OpenLayers.Geometry.MultiPoint": "MultiPoint",
+            "OpenLayers.Geometry.LineString": "LineString",
+            "OpenLayers.Geometry.MultiLineString": "MultiLineString",
+            "OpenLayers.Geometry.Polygon": "Polygon",
+            "OpenLayers.Geometry.MultiPolygon": "MultiPolygon",
+            "OpenLayers.Geometry.Collection": "GeometryCollection"
+        };
+    },
+
+    CLASS_NAME: "OpenLayers.Format.GML.Base" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/GML/v2.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/Base.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML.v2
+ * Parses GML version 2.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.GML.Base>
+ */
+OpenLayers.Format.GML.v2 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
+    
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.GML.v2
+     * Create a parser for GML v2.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (required).
+     * geometryName - {String} Geometry element name.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "outerBoundaryIs": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                container.outer = obj.components[0];
+            },
+            "innerBoundaryIs": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                container.inner.push(obj.components[0]);
+            },
+            "Box": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                if(!container.components) {
+                    container.components = [];
+                }
+                var min = obj.points[0];
+                var max = obj.points[1];
+                container.components.push(
+                    new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
+                );
+            }
+        }, OpenLayers.Format.GML.Base.prototype.readers["gml"]),
+        "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
+        "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
+    },
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+     *     An array of features or a single feature.
+     *
+     * Returns:
+     * {String} Given an array of features, a doc with a gml:featureMembers
+     *     element will be returned.  Given a single feature, a doc with a
+     *     gml:featureMember element will be returned.
+     */
+    write: function(features) {
+        var name;
+        if(OpenLayers.Util.isArray(features)) {
+            // GML2 only has abstract feature collections
+            // wfs provides a feature collection from a well-known schema
+            name = "wfs:FeatureCollection";
+        } else {
+            name = "gml:featureMember";
+        }
+        var root = this.writeNode(name, features);
+        this.setAttributeNS(
+            root, this.namespaces["xsi"],
+            "xsi:schemaLocation", this.schemaLocation
+        );
+
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "Point": function(geometry) {
+                var node = this.createElementNSPlus("gml:Point");
+                this.writeNode("coordinates", [geometry], node);
+                return node;
+            },
+            "coordinates": function(points) {
+                var numPoints = points.length;
+                var parts = new Array(numPoints);
+                var point;
+                for(var i=0; i<numPoints; ++i) {
+                    point = points[i];
+                    if(this.xy) {
+                        parts[i] = point.x + "," + point.y;
+                    } else {
+                        parts[i] = point.y + "," + point.x;
+                    }
+                    if(point.z != undefined) { // allow null or undefined
+                        parts[i] += "," + point.z;
+                    }
+                }
+                return this.createElementNSPlus("gml:coordinates", {
+                    attributes: {
+                        decimal: ".", cs: ",", ts: " "
+                    },
+                    value: (numPoints == 1) ? parts[0] : parts.join(" ")
+                });
+            },
+            "LineString": function(geometry) {
+                var node = this.createElementNSPlus("gml:LineString");
+                this.writeNode("coordinates", geometry.components, node);
+                return node;
+            },
+            "Polygon": function(geometry) {
+                var node = this.createElementNSPlus("gml:Polygon");
+                this.writeNode("outerBoundaryIs", geometry.components[0], node);
+                for(var i=1; i<geometry.components.length; ++i) {
+                    this.writeNode(
+                        "innerBoundaryIs", geometry.components[i], node
+                    );
+                }
+                return node;
+            },
+            "outerBoundaryIs": function(ring) {
+                var node = this.createElementNSPlus("gml:outerBoundaryIs");
+                this.writeNode("LinearRing", ring, node);
+                return node;
+            },
+            "innerBoundaryIs": function(ring) {
+                var node = this.createElementNSPlus("gml:innerBoundaryIs");
+                this.writeNode("LinearRing", ring, node);
+                return node;
+            },
+            "LinearRing": function(ring) {
+                var node = this.createElementNSPlus("gml:LinearRing");
+                this.writeNode("coordinates", ring.components, node);
+                return node;
+            },
+            "Box": function(bounds) {
+                var node = this.createElementNSPlus("gml:Box");
+                this.writeNode("coordinates", [
+                    {x: bounds.left, y: bounds.bottom},
+                    {x: bounds.right, y: bounds.top}
+                ], node);
+                // srsName attribute is optional for gml:Box
+                if(this.srsName) {
+                    node.setAttribute("srsName", this.srsName);
+                }
+                return node;
+            }
+        }, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
+        "feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
+        "wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.GML.v2" 
+
+});
+/* ======================================================================
+    OpenLayers/Style.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Style
+ * This class represents a UserStyle obtained
+ *     from a SLD, containing styling rules.
+ */
+OpenLayers.Style = OpenLayers.Class({
+
+    /**
+     * Property: id
+     * {String} A unique id for this session.
+     */
+    id: null,
+    
+    /**
+     * APIProperty: name
+     * {String}
+     */
+    name: null,
+    
+    /**
+     * Property: title
+     * {String} Title of this style (set if included in SLD)
+     */
+    title: null,
+    
+    /**
+     * Property: description
+     * {String} Description of this style (set if abstract is included in SLD)
+     */
+    description: null,
+
+    /**
+     * APIProperty: layerName
+     * {<String>} name of the layer that this style belongs to, usually
+     * according to the NamedLayer attribute of an SLD document.
+     */
+    layerName: null,
+    
+    /**
+     * APIProperty: isDefault
+     * {Boolean}
+     */
+    isDefault: false,
+     
+    /** 
+     * Property: rules 
+     * {Array(<OpenLayers.Rule>)}
+     */
+    rules: null,
+    
+    /**
+     * Property: context
+     * {Object} An optional object with properties that symbolizers' property
+     * values should be evaluated against. If no context is specified,
+     * feature.attributes will be used
+     */
+    context: null,
+
+    /**
+     * Property: defaultStyle
+     * {Object} hash of style properties to use as default for merging
+     * rule-based style symbolizers onto. If no rules are defined,
+     * createSymbolizer will return this style. If <defaultsPerSymbolizer> is set to
+     * true, the defaultStyle will only be taken into account if there are
+     * rules defined.
+     */
+    defaultStyle: null,
+    
+    /**
+     * Property: defaultsPerSymbolizer
+     * {Boolean} If set to true, the <defaultStyle> will extend the symbolizer
+     * of every rule. Properties of the <defaultStyle> will also be used to set
+     * missing symbolizer properties if the symbolizer has stroke, fill or
+     * graphic set to true. Default is false.
+     */
+    defaultsPerSymbolizer: false,
+    
+    /**
+     * Property: propertyStyles
+     * {Hash of Boolean} cache of style properties that need to be parsed for
+     * propertyNames. Property names are keys, values won't be used.
+     */
+    propertyStyles: null,
+    
+
+    /** 
+     * Constructor: OpenLayers.Style
+     * Creates a UserStyle.
+     *
+     * Parameters:
+     * style        - {Object} Optional hash of style properties that will be
+     *                used as default style for this style object. This style
+     *                applies if no rules are specified. Symbolizers defined in
+     *                rules will extend this default style.
+     * options - {Object} An optional object with properties to set on the
+     *     style.
+     *
+     * Valid options:
+     * rules - {Array(<OpenLayers.Rule>)} List of rules to be added to the
+     *     style.
+     * 
+     * Return:
+     * {<OpenLayers.Style>}
+     */
+    initialize: function(style, options) {
+
+        OpenLayers.Util.extend(this, options);
+        this.rules = [];
+        if(options && options.rules) {
+            this.addRules(options.rules);
+        }
+
+        // use the default style from OpenLayers.Feature.Vector if no style
+        // was given in the constructor
+        this.setDefaultStyle(style ||
+                             OpenLayers.Feature.Vector.style["default"]);
+
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        for (var i=0, len=this.rules.length; i<len; i++) {
+            this.rules[i].destroy();
+            this.rules[i] = null;
+        }
+        this.rules = null;
+        this.defaultStyle = null;
+    },
+    
+    /**
+     * Method: createSymbolizer
+     * creates a style by applying all feature-dependent rules to the base
+     * style.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature>} feature to evaluate rules for
+     * 
+     * Returns:
+     * {Object} symbolizer hash
+     */
+    createSymbolizer: function(feature) {
+        var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(
+            OpenLayers.Util.extend({}, this.defaultStyle), feature);
+        
+        var rules = this.rules;
+
+        var rule, context;
+        var elseRules = [];
+        var appliedRules = false;
+        for(var i=0, len=rules.length; i<len; i++) {
+            rule = rules[i];
+            // does the rule apply?
+            var applies = rule.evaluate(feature);
+            
+            if(applies) {
+                if(rule instanceof OpenLayers.Rule && rule.elseFilter) {
+                    elseRules.push(rule);
+                } else {
+                    appliedRules = true;
+                    this.applySymbolizer(rule, style, feature);
+                }
+            }
+        }
+        
+        // if no other rules apply, apply the rules with else filters
+        if(appliedRules == false && elseRules.length > 0) {
+            appliedRules = true;
+            for(var i=0, len=elseRules.length; i<len; i++) {
+                this.applySymbolizer(elseRules[i], style, feature);
+            }
+        }
+
+        // don't display if there were rules but none applied
+        if(rules.length > 0 && appliedRules == false) {
+            style.display = "none";
+        }
+        
+        if (style.label && typeof style.label !== "string") {
+            style.label = String(style.label);
+        }
+        
+        return style;
+    },
+    
+    /**
+     * Method: applySymbolizer
+     *
+     * Parameters:
+     * rule - {OpenLayers.Rule}
+     * style - {Object}
+     * feature - {<OpenLayer.Feature.Vector>}
+     *
+     * Returns:
+     * {Object} A style with new symbolizer applied.
+     */
+    applySymbolizer: function(rule, style, feature) {
+        var symbolizerPrefix = feature.geometry ?
+                this.getSymbolizerPrefix(feature.geometry) :
+                OpenLayers.Style.SYMBOLIZER_PREFIXES[0];
+
+        var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;
+        
+        if(this.defaultsPerSymbolizer === true) {
+            var defaults = this.defaultStyle;
+            OpenLayers.Util.applyDefaults(symbolizer, {
+                pointRadius: defaults.pointRadius
+            });
+            if(symbolizer.stroke === true || symbolizer.graphic === true) {
+                OpenLayers.Util.applyDefaults(symbolizer, {
+                    strokeWidth: defaults.strokeWidth,
+                    strokeColor: defaults.strokeColor,
+                    strokeOpacity: defaults.strokeOpacity,
+                    strokeDashstyle: defaults.strokeDashstyle,
+                    strokeLinecap: defaults.strokeLinecap
+                });
+            }
+            if(symbolizer.fill === true || symbolizer.graphic === true) {
+                OpenLayers.Util.applyDefaults(symbolizer, {
+                    fillColor: defaults.fillColor,
+                    fillOpacity: defaults.fillOpacity
+                });
+            }
+            if(symbolizer.graphic === true) {
+                OpenLayers.Util.applyDefaults(symbolizer, {
+                    pointRadius: this.defaultStyle.pointRadius,
+                    externalGraphic: this.defaultStyle.externalGraphic,
+                    graphicName: this.defaultStyle.graphicName,
+                    graphicOpacity: this.defaultStyle.graphicOpacity,
+                    graphicWidth: this.defaultStyle.graphicWidth,
+                    graphicHeight: this.defaultStyle.graphicHeight,
+                    graphicXOffset: this.defaultStyle.graphicXOffset,
+                    graphicYOffset: this.defaultStyle.graphicYOffset
+                });
+            }
+        }
+
+        // merge the style with the current style
+        return this.createLiterals(
+                OpenLayers.Util.extend(style, symbolizer), feature);
+    },
+    
+    /**
+     * Method: createLiterals
+     * creates literals for all style properties that have an entry in
+     * <this.propertyStyles>.
+     * 
+     * Parameters:
+     * style   - {Object} style to create literals for. Will be modified
+     *           inline.
+     * feature - {Object}
+     * 
+     * Returns:
+     * {Object} the modified style
+     */
+    createLiterals: function(style, feature) {
+        var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);
+        OpenLayers.Util.extend(context, this.context);
+        
+        for (var i in this.propertyStyles) {
+            style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i);
+        }
+        return style;
+    },
+    
+    /**
+     * Method: findPropertyStyles
+     * Looks into all rules for this style and the defaultStyle to collect
+     * all the style hash property names containing ${...} strings that have
+     * to be replaced using the createLiteral method before returning them.
+     * 
+     * Returns:
+     * {Object} hash of property names that need createLiteral parsing. The
+     * name of the property is the key, and the value is true;
+     */
+    findPropertyStyles: function() {
+        var propertyStyles = {};
+
+        // check the default style
+        var style = this.defaultStyle;
+        this.addPropertyStyles(propertyStyles, style);
+
+        // walk through all rules to check for properties in their symbolizer
+        var rules = this.rules;
+        var symbolizer, value;
+        for (var i=0, len=rules.length; i<len; i++) {
+            symbolizer = rules[i].symbolizer;
+            for (var key in symbolizer) {
+                value = symbolizer[key];
+                if (typeof value == "object") {
+                    // symbolizer key is "Point", "Line" or "Polygon"
+                    this.addPropertyStyles(propertyStyles, value);
+                } else {
+                    // symbolizer is a hash of style properties
+                    this.addPropertyStyles(propertyStyles, symbolizer);
+                    break;
+                }
+            }
+        }
+        return propertyStyles;
+    },
+    
+    /**
+     * Method: addPropertyStyles
+     * 
+     * Parameters:
+     * propertyStyles - {Object} hash to add new property styles to. Will be
+     *                  modified inline
+     * symbolizer     - {Object} search this symbolizer for property styles
+     * 
+     * Returns:
+     * {Object} propertyStyles hash
+     */
+    addPropertyStyles: function(propertyStyles, symbolizer) {
+        var property;
+        for (var key in symbolizer) {
+            property = symbolizer[key];
+            if (typeof property == "string" &&
+                    property.match(/\$\{\w+\}/)) {
+                propertyStyles[key] = true;
+            }
+        }
+        return propertyStyles;
+    },
+    
+    /**
+     * APIMethod: addRules
+     * Adds rules to this style.
+     * 
+     * Parameters:
+     * rules - {Array(<OpenLayers.Rule>)}
+     */
+    addRules: function(rules) {
+        Array.prototype.push.apply(this.rules, rules);
+        this.propertyStyles = this.findPropertyStyles();
+    },
+    
+    /**
+     * APIMethod: setDefaultStyle
+     * Sets the default style for this style object.
+     * 
+     * Parameters:
+     * style - {Object} Hash of style properties
+     */
+    setDefaultStyle: function(style) {
+        this.defaultStyle = style; 
+        this.propertyStyles = this.findPropertyStyles();
+    },
+        
+    /**
+     * Method: getSymbolizerPrefix
+     * Returns the correct symbolizer prefix according to the
+     * geometry type of the passed geometry
+     * 
+     * Parameters:
+     * geometry {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {String} key of the according symbolizer
+     */
+    getSymbolizerPrefix: function(geometry) {
+        var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;
+        for (var i=0, len=prefixes.length; i<len; i++) {
+            if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {
+                return prefixes[i];
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this style.
+     * 
+     * Returns:
+     * {<OpenLayers.Style>} Clone of this style.
+     */
+    clone: function() {
+        var options = OpenLayers.Util.extend({}, this);
+        // clone rules
+        if(this.rules) {
+            options.rules = [];
+            for(var i=0, len=this.rules.length; i<len; ++i) {
+                options.rules.push(this.rules[i].clone());
+            }
+        }
+        // clone context
+        options.context = this.context && OpenLayers.Util.extend({}, this.context);
+        //clone default style
+        var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle);
+        return new OpenLayers.Style(defaultStyle, options);
+    },
+    
+    CLASS_NAME: "OpenLayers.Style"
+});
+
+
+/**
+ * Function: createLiteral
+ * converts a style value holding a combination of PropertyName and Literal
+ * into a Literal, taking the property values from the passed features.
+ * 
+ * Parameters:
+ * value - {String} value to parse. If this string contains a construct like
+ *         "foo ${bar}", then "foo " will be taken as literal, and "${bar}"
+ *         will be replaced by the value of the "bar" attribute of the passed
+ *         feature.
+ * context - {Object} context to take attribute values from
+ * feature - {<OpenLayers.Feature.Vector>} optional feature to pass to
+ *           <OpenLayers.String.format> for evaluating functions in the
+ *           context.
+ * property - {String} optional, name of the property for which the literal is
+ *            being created for evaluating functions in the context.
+ * 
+ * Returns:
+ * {String} the parsed value. In the example of the value parameter above, the
+ * result would be "foo valueOfBar", assuming that the passed feature has an
+ * attribute named "bar" with the value "valueOfBar".
+ */
+OpenLayers.Style.createLiteral = function(value, context, feature, property) {
+    if (typeof value == "string" && value.indexOf("${") != -1) {
+        value = OpenLayers.String.format(value, context, [feature, property]);
+        value = (isNaN(value) || !value) ? value : parseFloat(value);
+    }
+    return value;
+};
+    
+/**
+ * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES
+ * {Array} prefixes of the sld symbolizers. These are the
+ * same as the main geometry types
+ */
+OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text',
+    'Raster'];
+/* ======================================================================
+    OpenLayers/Symbolizer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer
+ * Base class representing a symbolizer used for feature rendering.
+ */
+OpenLayers.Symbolizer = OpenLayers.Class({
+    
+
+    /**
+     * APIProperty: zIndex
+     * {Number} The zIndex determines the rendering order for a symbolizer.
+     *     Symbolizers with larger zIndex values are rendered over symbolizers
+     *     with smaller zIndex values.  Default is 0.
+     */
+    zIndex: 0,
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer
+     * Instances of this class are not useful.  See one of the subclasses.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Util.extend(this, config);
+    },
+    
+    /** 
+     * APIMethod: clone
+     * Create a copy of this symbolizer.
+     *
+     * Returns a symbolizer of the same type with the same properties.
+     */
+    clone: function() {
+        var Type = eval(this.CLASS_NAME);
+        return new Type(OpenLayers.Util.extend({}, this));
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer"
+    
+});
+
+/* ======================================================================
+    OpenLayers/Symbolizer/Point.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Point
+ * A symbolizer used to render point features.
+ */
+OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: fillColor
+     * {String} RGB hex fill color (e.g. "#ff0000" for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: fillOpacity
+     * {Number} Fill opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: pointRadius
+     * {Number} Pixel point radius.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: externalGraphic
+     * {String} Url to an external graphic that will be used for rendering 
+     *     points.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicWidth
+     * {Number} Pixel width for sizing an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicHeight
+     * {Number} Pixel height for sizing an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicOpacity
+     * {Number} Opacity (0-1) for an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicXOffset
+     * {Number} Pixel offset along the positive x axis for displacing an 
+     *     external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicYOffset
+     * {Number} Pixel offset along the positive y axis for displacing an 
+     *     external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: rotation
+     * {Number} The rotation of a graphic in the clockwise direction about its 
+     *     center point (or any point off center as specified by 
+     *     <graphicXOffset> and <graphicYOffset>).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicName
+     * {String} Named graphic to use when rendering points.  Supported values 
+     *     include "circle", "square", "star", "x", "cross", and "triangle".
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer.Point
+     * Create a symbolizer for rendering points.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new point symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Point"
+    
+});
+
+/* ======================================================================
+    OpenLayers/Symbolizer/Line.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Line
+ * A symbolizer used to render line features.
+ */
+OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, {
+
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).  
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Line
+     * Create a symbolizer for rendering lines.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new line symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Line"
+    
+});
+
+/* ======================================================================
+    OpenLayers/Symbolizer/Polygon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Polygon
+ * A symbolizer used to render line features.
+ */
+OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: fillColor
+     * {String} RGB hex fill color (e.g. "#ff0000" for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: fillOpacity
+     * {Number} Fill opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Polygon
+     * Create a symbolizer for rendering polygons.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new polygon symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Polygon"
+    
+});
+
+/* ======================================================================
+    OpenLayers/Symbolizer/Text.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Text
+ * A symbolizer used to render text labels for features.
+ */
+OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /** 
+     * APIProperty: label
+     * {String} The text for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /** 
+     * APIProperty: fontFamily
+     * {String} The font family for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /** 
+     * APIProperty: fontSize
+     * {String} The font size for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /** 
+     * APIProperty: fontWeight
+     * {String} The font weight for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: fontStyle
+     * {String} The font style for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Text
+     * Create a symbolizer for rendering text labels.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new text symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Text"
+    
+});
+
+/* ======================================================================
+    OpenLayers/Symbolizer/Raster.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Raster
+ * A symbolizer used to render raster images.
+ */
+OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer.Raster
+     * Create a symbolizer for rendering rasters.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new raster symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Raster"
+    
+});
+/* ======================================================================
+    OpenLayers/Rule.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Symbolizer/Point.js
+ * @requires OpenLayers/Symbolizer/Line.js
+ * @requires OpenLayers/Symbolizer/Polygon.js
+ * @requires OpenLayers/Symbolizer/Text.js
+ * @requires OpenLayers/Symbolizer/Raster.js
+ */
+
+/**
+ * Class: OpenLayers.Rule
+ * This class represents an SLD Rule, as being used for rule-based SLD styling.
+ */
+OpenLayers.Rule = OpenLayers.Class({
+    
+    /**
+     * Property: id
+     * {String} A unique id for this session.
+     */
+    id: null,
+    
+    /**
+     * APIProperty: name
+     * {String} name of this rule
+     */
+    name: null,
+    
+    /**
+     * Property: title
+     * {String} Title of this rule (set if included in SLD)
+     */
+    title: null,
+    
+    /**
+     * Property: description
+     * {String} Description of this rule (set if abstract is included in SLD)
+     */
+    description: null,
+
+    /**
+     * Property: context
+     * {Object} An optional object with properties that the rule should be
+     * evaluated against. If no context is specified, feature.attributes will
+     * be used.
+     */
+    context: null,
+    
+    /**
+     * Property: filter
+     * {<OpenLayers.Filter>} Optional filter for the rule.
+     */
+    filter: null,
+
+    /**
+     * Property: elseFilter
+     * {Boolean} Determines whether this rule is only to be applied only if
+     * no other rules match (ElseFilter according to the SLD specification). 
+     * Default is false.  For instances of OpenLayers.Rule, if elseFilter is
+     * false, the rule will always apply.  For subclasses, the else property is 
+     * ignored.
+     */
+    elseFilter: false,
+    
+    /**
+     * Property: symbolizer
+     * {Object} Symbolizer or hash of symbolizers for this rule. If hash of
+     * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The
+     * latter if useful if it is required to style e.g. vertices of a line
+     * with a point symbolizer. Note, however, that this is not implemented
+     * yet in OpenLayers, but it is the way how symbolizers are defined in
+     * SLD.
+     */
+    symbolizer: null,
+    
+    /**
+     * Property: symbolizers
+     * {Array} Collection of symbolizers associated with this rule.  If 
+     *     provided at construction, the symbolizers array has precedence
+     *     over the deprecated symbolizer property.  Note that multiple 
+     *     symbolizers are not currently supported by the vector renderers.
+     *     Rules with multiple symbolizers are currently only useful for
+     *     maintaining elements in an SLD document.
+     */
+    symbolizers: null,
+    
+    /**
+     * APIProperty: minScaleDenominator
+     * {Number} or {String} minimum scale at which to draw the feature.
+     * In the case of a String, this can be a combination of text and
+     * propertyNames in the form "literal ${propertyName}"
+     */
+    minScaleDenominator: null,
+
+    /**
+     * APIProperty: maxScaleDenominator
+     * {Number} or {String} maximum scale at which to draw the feature.
+     * In the case of a String, this can be a combination of text and
+     * propertyNames in the form "literal ${propertyName}"
+     */
+    maxScaleDenominator: null,
+    
+    /** 
+     * Constructor: OpenLayers.Rule
+     * Creates a Rule.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>}
+     */
+    initialize: function(options) {
+        this.symbolizer = {};
+        OpenLayers.Util.extend(this, options);
+        if (this.symbolizers) {
+            delete this.symbolizer;
+        }
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        for (var i in this.symbolizer) {
+            this.symbolizer[i] = null;
+        }
+        this.symbolizer = null;
+        delete this.symbolizers;
+    },
+    
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature>} feature to apply the rule to.
+     * 
+     * Returns:
+     * {Boolean} true if the rule applies, false if it does not.
+     * This rule is the default rule and always returns true.
+     */
+    evaluate: function(feature) {
+        var context = this.getContext(feature);
+        var applies = true;
+
+        if (this.minScaleDenominator || this.maxScaleDenominator) {
+            var scale = feature.layer.map.getScale();
+        }
+        
+        // check if within minScale/maxScale bounds
+        if (this.minScaleDenominator) {
+            applies = scale >= OpenLayers.Style.createLiteral(
+                    this.minScaleDenominator, context);
+        }
+        if (applies && this.maxScaleDenominator) {
+            applies = scale < OpenLayers.Style.createLiteral(
+                    this.maxScaleDenominator, context);
+        }
+        
+        // check if optional filter applies
+        if(applies && this.filter) {
+            // feature id filters get the feature, others get the context
+            if(this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") {
+                applies = this.filter.evaluate(feature);
+            } else {
+                applies = this.filter.evaluate(context);
+            }
+        }
+
+        return applies;
+    },
+    
+    /**
+     * Method: getContext
+     * Gets the context for evaluating this rule
+     * 
+     * Paramters:
+     * feature - {<OpenLayers.Feature>} feature to take the context from if
+     *           none is specified.
+     */
+    getContext: function(feature) {
+        var context = this.context;
+        if (!context) {
+            context = feature.attributes || feature.data;
+        }
+        if (typeof this.context == "function") {
+            context = this.context(feature);
+        }
+        return context;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this rule.
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>} Clone of this rule.
+     */
+    clone: function() {
+        var options = OpenLayers.Util.extend({}, this);
+        if (this.symbolizers) {
+            // clone symbolizers
+            var len = this.symbolizers.length;
+            options.symbolizers = new Array(len);
+            for (var i=0; i<len; ++i) {
+                options.symbolizers[i] = this.symbolizers[i].clone();
+            }
+        } else {
+            // clone symbolizer
+            options.symbolizer = {};
+            var value, type;
+            for(var key in this.symbolizer) {
+                value = this.symbolizer[key];
+                type = typeof value;
+                if(type === "object") {
+                    options.symbolizer[key] = OpenLayers.Util.extend({}, value);
+                } else if(type === "string") {
+                    options.symbolizer[key] = value;
+                }
+            }
+        }
+        // clone filter
+        options.filter = this.filter && this.filter.clone();
+        // clone context
+        options.context = this.context && OpenLayers.Util.extend({}, this.context);
+        return new OpenLayers.Rule(options);
+    },
+        
+    CLASS_NAME: "OpenLayers.Rule"
+});
+/* ======================================================================
+    OpenLayers/Format/OGCExceptionReport.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OGCExceptionReport
+ * Class to read exception reports for various OGC services and versions.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OGCExceptionReport = OpenLayers.Class(OpenLayers.Format.XML, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ogc: "http://www.opengis.net/ogc"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "ogc",
+
+    /**
+     * Constructor: OpenLayers.Format.OGCExceptionReport
+     * Create a new parser for OGC exception reports.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read OGC exception report data from a string, and return an object with
+     * information about the exceptions.
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the exceptions that occurred.
+     */
+    read: function(data) {
+        var result;
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var exceptionInfo = {exceptionReport: null}; 
+        if (root) {
+            this.readChildNodes(data, exceptionInfo);
+            if (exceptionInfo.exceptionReport === null) {
+                // fall-back to OWSCommon since this is a common output format for exceptions
+                // we cannot easily use the ows readers directly since they differ for 1.0 and 1.1
+                exceptionInfo = new OpenLayers.Format.OWSCommon().read(data);
+            }
+        }
+        return exceptionInfo;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ogc": {
+            "ServiceExceptionReport": function(node, obj) {
+                obj.exceptionReport = {exceptions: []};
+                this.readChildNodes(node, obj.exceptionReport);
+            },
+            "ServiceException": function(node, exceptionReport) {
+                var exception = {
+                    code: node.getAttribute("code"),
+                    locator: node.getAttribute("locator"),
+                    text: this.getChildValue(node)
+                };
+                exceptionReport.exceptions.push(exception);
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OGCExceptionReport"
+    
+});
+/* ======================================================================
+    OpenLayers/Format/XML/VersionedOGC.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XML.VersionedOGC
+ * Base class for versioned formats, i.e. a format which supports multiple
+ * versions.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.XML.VersionedOGC = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.
+     */
+    defaultVersion: null,
+    
+    /**
+     * APIProperty: version
+     * {String} Specify a version string if one is known.
+     */
+    version: null,
+
+    /**
+     * APIProperty: profile
+     * {String} If provided, use a custom profile.
+     */
+    profile: null,
+
+    /**
+     * APIProperty: errorProperty
+     * {String} Which property of the returned object to check for in order to
+     * determine whether or not parsing has failed. In the case that the
+     * errorProperty is undefined on the returned object, the document will be
+     * run through an OGCExceptionReport parser.
+     */
+    errorProperty: null,
+
+    /**
+     * Property: name
+     * {String} The name of this parser, this is the part of the CLASS_NAME
+     * except for "OpenLayers.Format."
+     */
+    name: null,
+
+    /**
+     * APIProperty: stringifyOutput
+     * {Boolean} If true, write will return a string otherwise a DOMElement.
+     * Default is false.
+     */
+    stringifyOutput: false,
+
+    /**
+     * Property: parser
+     * {Object} Instance of the versioned parser.  Cached for multiple read and
+     *     write calls of the same version.
+     */
+    parser: null,
+
+    /**
+     * Constructor: OpenLayers.Format.XML.VersionedOGC.
+     * Constructor.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on
+     *     the object.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        var className = this.CLASS_NAME;
+        this.name = className.substring(className.lastIndexOf(".")+1);
+    },
+
+    /**
+     * Method: getVersion
+     * Returns the version to use. Subclasses can override this function
+     * if a different version detection is needed.
+     *
+     * Parameters:
+     * root - {DOMElement}
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} The version to use.
+     */
+    getVersion: function(root, options) {
+        var version;
+        // read
+        if (root) {
+            version = this.version;
+            if(!version) {
+                version = root.getAttribute("version");
+                if(!version) {
+                    version = this.defaultVersion;
+                }
+            }
+        } else { // write
+            version = (options && options.version) || 
+                this.version || this.defaultVersion;
+        }
+        return version;
+    },
+
+    /**
+     * Method: getParser
+     * Get an instance of the cached parser if available, otherwise create one.
+     *
+     * Parameters:
+     * version - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Format>}
+     */
+    getParser: function(version) {
+        version = version || this.defaultVersion;
+        var profile = this.profile ? "_" + this.profile : "";
+        if(!this.parser || this.parser.VERSION != version) {
+            var format = OpenLayers.Format[this.name][
+                "v" + version.replace(/\./g, "_") + profile
+            ];
+            if(!format) {
+                throw "Can't find a " + this.name + " parser for version " +
+                      version + profile;
+            }
+            this.parser = new format(this.options);
+        }
+        return this.parser;
+    },
+
+    /**
+     * APIMethod: write
+     * Write a document.
+     *
+     * Parameters:
+     * obj - {Object} An object representing the document.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} The document as a string
+     */
+    write: function(obj, options) {
+        var version = this.getVersion(null, options);
+        this.parser = this.getParser(version);
+        var root = this.parser.write(obj, options);
+        if (this.stringifyOutput === false) {
+            return root;
+        } else {
+            return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+        }
+    },
+
+    /**
+     * APIMethod: read
+     * Read a doc and return an object representing the document.
+     *
+     * Parameters:
+     * data - {String | DOMElement} Data to read.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the document.
+     */
+    read: function(data, options) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var version = this.getVersion(root);
+        this.parser = this.getParser(version);
+        var obj = this.parser.read(data, options);
+        if (this.errorProperty !== null && obj[this.errorProperty] === undefined) {
+            // an error must have happened, so parse it and report back
+            var format = new OpenLayers.Format.OGCExceptionReport();
+            obj.error = format.read(data);
+        }
+        obj.version = version;
+        return obj;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.XML.VersionedOGC"
+});
+/* ======================================================================
+    OpenLayers/Filter.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Style.js
+ */
+
+/**
+ * Class: OpenLayers.Filter
+ * This class represents an OGC Filter.
+ */
+OpenLayers.Filter = OpenLayers.Class({
+    
+    /** 
+     * Constructor: OpenLayers.Filter
+     * This class represents a generic filter.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter>}
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+    },
+
+    /** 
+     * APIMethod: destroy
+     * Remove reference to anything added.
+     */
+    destroy: function() {
+    },
+
+    /**
+     * APIMethod: evaluate
+     * Evaluates this filter in a specific context.  Instances or subclasses
+     * are supposed to override this method.
+     * 
+     * Parameters:
+     * context - {Object} Context to use in evaluating the filter.  If a vector
+     *     feature is provided, the feature.attributes will be used as context.
+     * 
+     * Returns:
+     * {Boolean} The filter applies.
+     */
+    evaluate: function(context) {
+        return true;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this filter. Should be implementted by subclasses.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter>} Clone of this filter.
+     */
+    clone: function() {
+        return null;
+    },
+    
+    CLASS_NAME: "OpenLayers.Filter"
+});
+/* ======================================================================
+    OpenLayers/Filter/FeatureId.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Filter.js
+ */
+
+/**
+ * Class: OpenLayers.Filter.FeatureId
+ * This class represents a ogc:FeatureId Filter, as being used for rule-based SLD
+ * styling
+ * 
+ * Inherits from
+ * - <OpenLayers.Filter>
+ */
+OpenLayers.Filter.FeatureId = OpenLayers.Class(OpenLayers.Filter, {
+
+    /** 
+     * APIProperty: fids
+     * {Array(String)} Feature Ids to evaluate this rule against. To be passed
+     * To be passed inside the params object.
+     */
+    fids: null,
+    
+    /** 
+     * Property: type
+     * {String} Type to identify this filter.
+     */
+    type: "FID",
+    
+    /** 
+     * Constructor: OpenLayers.Filter.FeatureId
+     * Creates an ogc:FeatureId rule.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.FeatureId>}
+     */
+    initialize: function(options) {
+        this.fids = [];
+        OpenLayers.Filter.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature>} feature to apply the rule to.
+     *           For vector features, the check is run against the fid,
+     *           for plain features against the id.
+     * 
+     * Returns:
+     * {Boolean} true if the rule applies, false if it does not
+     */
+    evaluate: function(feature) {
+        for (var i=0, len=this.fids.length; i<len; i++) {
+            var fid = feature.fid || feature.id;
+            if (fid == this.fids[i]) {
+                return true;
+            }
+        }
+        return false;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.FeatureId>} Clone of this filter.
+     */
+    clone: function() {
+        var filter = new OpenLayers.Filter.FeatureId();
+        OpenLayers.Util.extend(filter, this);
+        filter.fids = this.fids.slice();
+        return filter;
+    },
+    
+    CLASS_NAME: "OpenLayers.Filter.FeatureId"
+});
+/* ======================================================================
+    OpenLayers/Filter/Logical.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Filter.js
+ */
+
+/**
+ * Class: OpenLayers.Filter.Logical
+ * This class represents ogc:And, ogc:Or and ogc:Not rules.
+ * 
+ * Inherits from
+ * - <OpenLayers.Filter>
+ */
+OpenLayers.Filter.Logical = OpenLayers.Class(OpenLayers.Filter, {
+
+    /**
+     * APIProperty: filters
+     * {Array(<OpenLayers.Filter>)} Child filters for this filter.
+     */
+    filters: null, 
+     
+    /**
+     * APIProperty: type
+     * {String} type of logical operator. Available types are:
+     * - OpenLayers.Filter.Logical.AND = "&&";
+     * - OpenLayers.Filter.Logical.OR  = "||";
+     * - OpenLayers.Filter.Logical.NOT = "!";
+     */
+    type: null,
+
+    /** 
+     * Constructor: OpenLayers.Filter.Logical
+     * Creates a logical filter (And, Or, Not).
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *     filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Logical>}
+     */
+    initialize: function(options) {
+        this.filters = [];
+        OpenLayers.Filter.prototype.initialize.apply(this, [options]);
+    },
+    
+    /** 
+     * APIMethod: destroy
+     * Remove reference to child filters.
+     */
+    destroy: function() {
+        this.filters = null;
+        OpenLayers.Filter.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: evaluate
+     * Evaluates this filter in a specific context.
+     * 
+     * Parameters:
+     * context - {Object} Context to use in evaluating the filter.  A vector
+     *     feature may also be provided to evaluate feature attributes in 
+     *     comparison filters or geometries in spatial filters.
+     * 
+     * Returns:
+     * {Boolean} The filter applies.
+     */
+    evaluate: function(context) {
+        var i, len;
+        switch(this.type) {
+            case OpenLayers.Filter.Logical.AND:
+                for (i=0, len=this.filters.length; i<len; i++) {
+                    if (this.filters[i].evaluate(context) == false) {
+                        return false;
+                    }
+                }
+                return true;
+                
+            case OpenLayers.Filter.Logical.OR:
+                for (i=0, len=this.filters.length; i<len; i++) {
+                    if (this.filters[i].evaluate(context) == true) {
+                        return true;
+                    }
+                }
+                return false;
+            
+            case OpenLayers.Filter.Logical.NOT:
+                return (!this.filters[0].evaluate(context));
+        }
+        return undefined;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Logical>} Clone of this filter.
+     */
+    clone: function() {
+        var filters = [];        
+        for(var i=0, len=this.filters.length; i<len; ++i) {
+            filters.push(this.filters[i].clone());
+        }
+        return new OpenLayers.Filter.Logical({
+            type: this.type,
+            filters: filters
+        });
+    },
+    
+    CLASS_NAME: "OpenLayers.Filter.Logical"
+});
+
+
+OpenLayers.Filter.Logical.AND = "&&";
+OpenLayers.Filter.Logical.OR  = "||";
+OpenLayers.Filter.Logical.NOT = "!";
+/* ======================================================================
+    OpenLayers/Filter/Comparison.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Filter.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Filter.Comparison
+ * This class represents a comparison filter.
+ * 
+ * Inherits from
+ * - <OpenLayers.Filter>
+ */
+OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, {
+
+    /**
+     * APIProperty: type
+     * {String} type: type of the comparison. This is one of
+     * - OpenLayers.Filter.Comparison.EQUAL_TO                 = "==";
+     * - OpenLayers.Filter.Comparison.NOT_EQUAL_TO             = "!=";
+     * - OpenLayers.Filter.Comparison.LESS_THAN                = "<";
+     * - OpenLayers.Filter.Comparison.GREATER_THAN             = ">";
+     * - OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO    = "<=";
+     * - OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO = ">=";
+     * - OpenLayers.Filter.Comparison.BETWEEN                  = "..";
+     * - OpenLayers.Filter.Comparison.LIKE                     = "~"; 
+     */
+    type: null,
+    
+    /**
+     * APIProperty: property
+     * {String}
+     * name of the context property to compare
+     */
+    property: null,
+    
+    /**
+     * APIProperty: value
+     * {Number} or {String}
+     * comparison value for binary comparisons. In the case of a String, this
+     * can be a combination of text and propertyNames in the form
+     * "literal ${propertyName}"
+     */
+    value: null,
+    
+    /**
+     * Property: matchCase
+     * {Boolean} Force case sensitive searches for EQUAL_TO and NOT_EQUAL_TO
+     *     comparisons.  The Filter Encoding 1.1 specification added a matchCase
+     *     attribute to ogc:PropertyIsEqualTo and ogc:PropertyIsNotEqualTo
+     *     elements.  This property will be serialized with those elements only
+     *     if using the v1.1.0 filter format. However, when evaluating filters
+     *     here, the matchCase property will always be respected (for EQUAL_TO
+     *     and NOT_EQUAL_TO).  Default is true. 
+     */
+    matchCase: true,
+    
+    /**
+     * APIProperty: lowerBoundary
+     * {Number} or {String}
+     * lower boundary for between comparisons. In the case of a String, this
+     * can be a combination of text and propertyNames in the form
+     * "literal ${propertyName}"
+     */
+    lowerBoundary: null,
+    
+    /**
+     * APIProperty: upperBoundary
+     * {Number} or {String}
+     * upper boundary for between comparisons. In the case of a String, this
+     * can be a combination of text and propertyNames in the form
+     * "literal ${propertyName}"
+     */
+    upperBoundary: null,
+
+    /** 
+     * Constructor: OpenLayers.Filter.Comparison
+     * Creates a comparison rule.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Comparison>}
+     */
+    initialize: function(options) {
+        OpenLayers.Filter.prototype.initialize.apply(this, [options]);
+        // since matchCase on PropertyIsLike is not schema compliant, we only
+        // want to use this if explicitly asked for
+        if (this.type === OpenLayers.Filter.Comparison.LIKE 
+            && options.matchCase === undefined) {
+                this.matchCase = null;
+        }
+    },
+
+    /**
+     * APIMethod: evaluate
+     * Evaluates this filter in a specific context.
+     * 
+     * Parameters:
+     * context - {Object} Context to use in evaluating the filter.  If a vector
+     *     feature is provided, the feature.attributes will be used as context.
+     * 
+     * Returns:
+     * {Boolean} The filter applies.
+     */
+    evaluate: function(context) {
+        if (context instanceof OpenLayers.Feature.Vector) {
+            context = context.attributes;
+        }
+        var result = false;
+        var got = context[this.property];
+        var exp;
+        switch(this.type) {
+            case OpenLayers.Filter.Comparison.EQUAL_TO:
+                exp = this.value;
+                if(!this.matchCase &&
+                   typeof got == "string" && typeof exp == "string") {
+                    result = (got.toUpperCase() == exp.toUpperCase());
+                } else {
+                    result = (got == exp);
+                }
+                break;
+            case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:
+                exp = this.value;
+                if(!this.matchCase &&
+                   typeof got == "string" && typeof exp == "string") {
+                    result = (got.toUpperCase() != exp.toUpperCase());
+                } else {
+                    result = (got != exp);
+                }
+                break;
+            case OpenLayers.Filter.Comparison.LESS_THAN:
+                result = got < this.value;
+                break;
+            case OpenLayers.Filter.Comparison.GREATER_THAN:
+                result = got > this.value;
+                break;
+            case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:
+                result = got <= this.value;
+                break;
+            case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:
+                result = got >= this.value;
+                break;
+            case OpenLayers.Filter.Comparison.BETWEEN:
+                result = (got >= this.lowerBoundary) &&
+                    (got <= this.upperBoundary);
+                break;
+            case OpenLayers.Filter.Comparison.LIKE:
+                var regexp = new RegExp(this.value, "gi");
+                result = regexp.test(got);
+                break;
+        }
+        return result;
+    },
+    
+    /**
+     * APIMethod: value2regex
+     * Converts the value of this rule into a regular expression string,
+     * according to the wildcard characters specified. This method has to
+     * be called after instantiation of this class, if the value is not a
+     * regular expression already.
+     * 
+     * Parameters:
+     * wildCard   - {<Char>} wildcard character in the above value, default
+     *              is "*"
+     * singleChar - {<Char>) single-character wildcard in the above value
+     *              default is "."
+     * escape     - {<Char>) escape character in the above value, default is
+     *              "!"
+     * 
+     * Returns:
+     * {String} regular expression string
+     */
+    value2regex: function(wildCard, singleChar, escapeChar) {
+        if (wildCard == ".") {
+            var msg = "'.' is an unsupported wildCard character for "+
+                    "OpenLayers.Filter.Comparison";
+            OpenLayers.Console.error(msg);
+            return null;
+        }
+        
+
+        // set UMN MapServer defaults for unspecified parameters
+        wildCard = wildCard ? wildCard : "*";
+        singleChar = singleChar ? singleChar : ".";
+        escapeChar = escapeChar ? escapeChar : "!";
+        
+        this.value = this.value.replace(
+                new RegExp("\\"+escapeChar+"(.|$)", "g"), "\\$1");
+        this.value = this.value.replace(
+                new RegExp("\\"+singleChar, "g"), ".");
+        this.value = this.value.replace(
+                new RegExp("\\"+wildCard, "g"), ".*");
+        this.value = this.value.replace(
+                new RegExp("\\\\.\\*", "g"), "\\"+wildCard);
+        this.value = this.value.replace(
+                new RegExp("\\\\\\.", "g"), "\\"+singleChar);
+        
+        return this.value;
+    },
+    
+    /**
+     * Method: regex2value
+     * Convert the value of this rule from a regular expression string into an
+     *     ogc literal string using a wildCard of *, a singleChar of ., and an
+     *     escape of !.  Leaves the <value> property unmodified.
+     * 
+     * Returns:
+     * {String} A string value.
+     */
+    regex2value: function() {
+        
+        var value = this.value;
+        
+        // replace ! with !!
+        value = value.replace(/!/g, "!!");
+
+        // replace \. with !. (watching out for \\.)
+        value = value.replace(/(\\)?\\\./g, function($0, $1) {
+            return $1 ? $0 : "!.";
+        });
+        
+        // replace \* with #* (watching out for \\*)
+        value = value.replace(/(\\)?\\\*/g, function($0, $1) {
+            return $1 ? $0 : "!*";
+        });
+        
+        // replace \\ with \
+        value = value.replace(/\\\\/g, "\\");
+
+        // convert .* to * (the sequence #.* is not allowed)
+        value = value.replace(/\.\*/g, "*");
+        
+        return value;
+    },
+    
+    /**
+     * APIMethod: clone
+     * Clones this filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Comparison>} Clone of this filter.
+     */
+    clone: function() {
+        return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(), this);
+    },
+    
+    CLASS_NAME: "OpenLayers.Filter.Comparison"
+});
+
+
+OpenLayers.Filter.Comparison.EQUAL_TO                 = "==";
+OpenLayers.Filter.Comparison.NOT_EQUAL_TO             = "!=";
+OpenLayers.Filter.Comparison.LESS_THAN                = "<";
+OpenLayers.Filter.Comparison.GREATER_THAN             = ">";
+OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO    = "<=";
+OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO = ">=";
+OpenLayers.Filter.Comparison.BETWEEN                  = "..";
+OpenLayers.Filter.Comparison.LIKE                     = "~";
+/* ======================================================================
+    OpenLayers/Filter/Spatial.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Filter.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Filter.Spatial
+ * This class represents a spatial filter.
+ * Currently implemented: BBOX, DWithin and Intersects
+ * 
+ * Inherits from
+ * - <OpenLayers.Filter>
+ */
+OpenLayers.Filter.Spatial = OpenLayers.Class(OpenLayers.Filter, {
+
+    /**
+     * APIProperty: type
+     * {String} Type of spatial filter.
+     *
+     * The type should be one of:
+     * - OpenLayers.Filter.Spatial.BBOX
+     * - OpenLayers.Filter.Spatial.INTERSECTS
+     * - OpenLayers.Filter.Spatial.DWITHIN
+     * - OpenLayers.Filter.Spatial.WITHIN
+     * - OpenLayers.Filter.Spatial.CONTAINS
+     */
+    type: null,
+    
+    /**
+     * APIProperty: property
+     * {String} Name of the context property to compare.
+     */
+    property: null,
+    
+    /**
+     * APIProperty: value
+     * {<OpenLayers.Bounds> || <OpenLayers.Geometry>} The bounds or geometry
+     *     to be used by the filter.  Use bounds for BBOX filters and geometry
+     *     for INTERSECTS or DWITHIN filters.
+     */
+    value: null,
+
+    /**
+     * APIProperty: distance
+     * {Number} The distance to use in a DWithin spatial filter.
+     */
+    distance: null,
+
+    /**
+     * APIProperty: distanceUnits
+     * {String} The units to use for the distance, e.g. 'm'.
+     */
+    distanceUnits: null,
+    
+    /** 
+     * Constructor: OpenLayers.Filter.Spatial
+     * Creates a spatial filter.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *     filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Spatial>}
+     */
+    initialize: function(options) {
+        OpenLayers.Filter.prototype.initialize.apply(this, [options]);
+    },
+
+   /**
+    * Method: evaluate
+    * Evaluates this filter for a specific feature.
+    * 
+    * Parameters:
+    * feature - {<OpenLayers.Feature.Vector>} feature to apply the filter to.
+    * 
+    * Returns:
+    * {Boolean} The feature meets filter criteria.
+    */
+    evaluate: function(feature) {
+        var intersect = false;
+        switch(this.type) {
+            case OpenLayers.Filter.Spatial.BBOX:
+            case OpenLayers.Filter.Spatial.INTERSECTS:
+                if(feature.geometry) {
+                    var geom = this.value;
+                    if(this.value.CLASS_NAME == "OpenLayers.Bounds") {
+                        geom = this.value.toGeometry();
+                    }
+                    if(feature.geometry.intersects(geom)) {
+                        intersect = true;
+                    }
+                }
+                break;
+            default:
+                OpenLayers.Console.error(
+                    OpenLayers.i18n("filterEvaluateNotImplemented"));
+                break;
+        }
+        return intersect;
+    },
+
+    /**
+     * APIMethod: clone
+     * Clones this filter.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Spatial>} Clone of this filter.
+     */
+    clone: function() {
+        var options = OpenLayers.Util.applyDefaults({
+            value: this.value && this.value.clone && this.value.clone()
+        }, this);
+        return new OpenLayers.Filter.Spatial(options);
+    },
+    CLASS_NAME: "OpenLayers.Filter.Spatial"
+});
+
+OpenLayers.Filter.Spatial.BBOX = "BBOX";
+OpenLayers.Filter.Spatial.INTERSECTS = "INTERSECTS";
+OpenLayers.Filter.Spatial.DWITHIN = "DWITHIN";
+OpenLayers.Filter.Spatial.WITHIN = "WITHIN";
+OpenLayers.Filter.Spatial.CONTAINS = "CONTAINS";
+/* ======================================================================
+    OpenLayers/Format/SLD.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Filter/FeatureId.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD
+ * Read/Wite SLD. Create a new instance with the <OpenLayers.Format.SLD>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * APIProperty: stringifyOutput
+     * {Boolean} If true, write will return a string otherwise a DOMElement.
+     * Default is true.
+     */
+    stringifyOutput: true,
+    
+    /**
+     * APIProperty: namedLayersAsArray
+     * {Boolean} Generate a namedLayers array.  If false, the namedLayers
+     *     property value will be an object keyed by layer name. Default is
+     *     false.
+     */
+    namedLayersAsArray: false,
+    
+    /**
+     * APIMethod: write
+     * Write a SLD document given a list of styles.
+     *
+     * Parameters:
+     * sld - {Object} An object representing the SLD.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} An SLD document string.
+     */
+    
+    /**
+     * APIMethod: read
+     * Read and SLD doc and return an object representing the SLD.
+     *
+     * Parameters:
+     * data - {String | DOMElement} Data to read.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the SLD.
+     */
+
+    CLASS_NAME: "OpenLayers.Format.SLD" 
+});
+/* ======================================================================
+    OpenLayers/Format/Filter.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ * @requires OpenLayers/Filter/FeatureId.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Filter/Comparison.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter
+ * Read/Wite ogc:Filter. Create a new instance with the <OpenLayers.Format.Filter>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.Filter = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * APIMethod: write
+     * Write an ogc:Filter given a filter object.
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter>} An filter.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {Elment} An ogc:Filter element node.
+     */
+    
+    /**
+     * APIMethod: read
+     * Read and Filter doc and return an object representing the Filter.
+     *
+     * Parameters:
+     * data - {String | DOMElement} Data to read.
+     *
+     * Returns:
+     * {<OpenLayers.Filter>} A filter object.
+     */
+
+    CLASS_NAME: "OpenLayers.Format.Filter" 
+});
+/* ======================================================================
+    OpenLayers/Filter/Function.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Filter.js
+ */
+
+/**
+ * Class: OpenLayers.Filter.Function
+ * This class represents a filter function.
+ * We are using this class for creation of complex 
+ * filters that can contain filter functions as values.
+ * Nesting function as other functions parameter is supported.
+ * 
+ * Inherits from
+ * - <OpenLayers.Filter>
+ */
+OpenLayers.Filter.Function = OpenLayers.Class(OpenLayers.Filter, {
+
+    /**
+     * APIProperty: name
+     * {String} Name of the function.
+     */
+    name: null,
+    
+    /**
+     * APIProperty: params
+     * {Array(<OpenLayers.Filter.Function> || String || Number)} Function parameters
+     * For now support only other Functions, String or Number
+     */
+    params: null,  
+    
+    /** 
+     * Constructor: OpenLayers.Filter.Function
+     * Creates a filter function.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *     function.
+     * 
+     * Returns:
+     * {<OpenLayers.Filter.Function>}
+     */
+    initialize: function(options) {
+        OpenLayers.Filter.prototype.initialize.apply(this, [options]);
+    },
+
+    CLASS_NAME: "OpenLayers.Filter.Function"
+});
+
+/* ======================================================================
+    OpenLayers/Format/Filter/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+/**
+ * @requires OpenLayers/Format/Filter.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Filter/Function.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1
+ * Superclass for Filter version 1 parsers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ogc: "http://www.opengis.net/ogc",
+        gml: "http://www.opengis.net/gml",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "ogc",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.Filter.v1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.Filter> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement} A Filter document element.
+     *
+     * Returns:
+     * {<OpenLayers.Filter>} A filter object.
+     */
+    read: function(data) {
+        var obj = {};
+        this.readers.ogc["Filter"].apply(this, [data, obj]);
+        return obj.filter;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ogc": {
+            "Filter": function(node, parent) {
+                // Filters correspond to subclasses of OpenLayers.Filter.
+                // Since they contain information we don't persist, we
+                // create a temporary object and then pass on the filter
+                // (ogc:Filter) to the parent obj.
+                var obj = {
+                    fids: [],
+                    filters: []
+                };
+                this.readChildNodes(node, obj);
+                if(obj.fids.length > 0) {
+                    parent.filter = new OpenLayers.Filter.FeatureId({
+                        fids: obj.fids
+                    });
+                } else if(obj.filters.length > 0) {
+                    parent.filter = obj.filters[0];
+                }
+            },
+            "FeatureId": function(node, obj) {
+                var fid = node.getAttribute("fid");
+                if(fid) {
+                    obj.fids.push(fid);
+                }
+            },
+            "And": function(node, obj) {
+                var filter = new OpenLayers.Filter.Logical({
+                    type: OpenLayers.Filter.Logical.AND
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "Or": function(node, obj) {
+                var filter = new OpenLayers.Filter.Logical({
+                    type: OpenLayers.Filter.Logical.OR
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "Not": function(node, obj) {
+                var filter = new OpenLayers.Filter.Logical({
+                    type: OpenLayers.Filter.Logical.NOT
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsLessThan": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LESS_THAN
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsGreaterThan": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.GREATER_THAN
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsLessThanOrEqualTo": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsGreaterThanOrEqualTo": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsBetween": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.BETWEEN
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "Literal": function(node, obj) {
+                obj.value = OpenLayers.String.numericIf(
+                    this.getChildValue(node));
+            },
+            "PropertyName": function(node, filter) {
+                filter.property = this.getChildValue(node);
+            },
+            "LowerBoundary": function(node, filter) {
+                filter.lowerBoundary = OpenLayers.String.numericIf(
+                    this.readOgcExpression(node));
+            },
+            "UpperBoundary": function(node, filter) {
+                filter.upperBoundary = OpenLayers.String.numericIf(
+                    this.readOgcExpression(node));
+            },
+            "Intersects": function(node, obj) {
+                this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS);
+            },
+            "Within": function(node, obj) {
+                this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN);
+            },
+            "Contains": function(node, obj) {
+                this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS);
+            },
+            "DWithin": function(node, obj) {
+                this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN);
+            },
+            "Distance": function(node, obj) {
+                obj.distance = parseInt(this.getChildValue(node));
+                obj.distanceUnits = node.getAttribute("units");
+            },
+            "Function": function(node, obj) {
+                //TODO write decoder for it
+                return;
+            }
+        }
+    },
+    
+    /**
+     * Method: readSpatial
+     *
+     * Read a {<OpenLayers.Filter.Spatial>} filter.
+     * 
+     * Parameters:
+     * node - {DOMElement} A DOM element that contains an ogc:expression.
+     * obj - {Object} The target object.
+     * type - {String} One of the OpenLayers.Filter.Spatial.* constants.
+     *
+     * Returns:
+     * {<OpenLayers.Filter.Spatial>} The created filter.
+     */
+    readSpatial: function(node, obj, type) {
+        var filter = new OpenLayers.Filter.Spatial({
+            type: type
+        });
+        this.readChildNodes(node, filter);
+        filter.value = filter.components[0];
+        delete filter.components;
+        obj.filters.push(filter);
+    },
+
+    /**
+     * Method: readOgcExpression
+     * Limited support for OGC expressions.
+     *
+     * Parameters:
+     * node - {DOMElement} A DOM element that contains an ogc:expression.
+     *
+     * Returns:
+     * {String} A value to be used in a symbolizer.
+     */
+    readOgcExpression: function(node) {
+        var obj = {};
+        this.readChildNodes(node, obj);
+        var value = obj.value;
+        if(value === undefined) {
+            value = this.getChildValue(node);
+        }
+        return value;
+    },
+
+    /**
+     * Method: writeOgcExpression
+     * Limited support for writing OGC expressions. Currently it supports
+     * (<OpenLayers.Filter.Function> || String || Number)
+     *
+     * Parameters:
+     * value - (<OpenLayers.Filter.Function> || String || Number)
+     * node - {DOMElement} A parent DOM element 
+     *
+     * Returns:
+     * {DOMElement} Updated node element.
+     */
+    writeOgcExpression: function(value, node) {
+        if(value instanceof OpenLayers.Filter.Function){
+            var child = this.writeNode("Function", value, node);
+            node.appendChild(child);
+        } else {
+            this.writeNode("Literal", value, node);
+        }
+        return node;
+    },    
+    
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter>} A filter object.
+     *
+     * Returns:
+     * {DOMElement} An ogc:Filter element.
+     */
+    write: function(filter) {
+        return this.writers.ogc["Filter"].apply(this, [filter]);
+    },
+    
+    /**
+     * Method: writeFeatureIdNodes
+     * 
+     * Parameters:
+     * filter - {<OpenLayers.Filter.FeatureId}
+     * node - {DOMElement}
+     */
+    writeFeatureIdNodes: function(filter, node) {
+        for (var i=0, ii=filter.fids.length; i<ii; ++i) {
+            this.writeNode("FeatureId", filter.fids[i], node);
+        }
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ogc": {
+            "Filter": function(filter) {
+                var node = this.createElementNSPlus("ogc:Filter");
+                if (filter.type === "FID") {
+                    this.writeFeatureIdNodes(filter, node);
+                } else {
+                    this.writeNode(this.getFilterType(filter), filter, node);
+                }
+                return node;
+            },
+            "FeatureId": function(fid) {
+                return this.createElementNSPlus("ogc:FeatureId", {
+                    attributes: {fid: fid}
+                });
+            },
+            "And": function(filter) {
+                var node = this.createElementNSPlus("ogc:And");
+                var childFilter;
+                for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+                    childFilter = filter.filters[i];
+                    if (childFilter.type === "FID") {
+                        this.writeFeatureIdNodes(childFilter, node);
+                    } else {
+                    this.writeNode(
+                        this.getFilterType(childFilter), childFilter, node
+                    );
+                }
+                }
+                return node;
+            },
+            "Or": function(filter) {
+                var node = this.createElementNSPlus("ogc:Or");
+                var childFilter;
+                for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+                    childFilter = filter.filters[i];
+                    if (childFilter.type === "FID") {
+                        this.writeFeatureIdNodes(childFilter, node);
+                    } else {
+                    this.writeNode(
+                        this.getFilterType(childFilter), childFilter, node
+                    );
+                }
+                }
+                return node;
+            },
+            "Not": function(filter) {
+                var node = this.createElementNSPlus("ogc:Not");
+                var childFilter = filter.filters[0];
+                if (childFilter.type === "FID") {
+                    this.writeFeatureIdNodes(childFilter, node);
+                } else {
+                this.writeNode(
+                    this.getFilterType(childFilter), childFilter, node
+                );
+                }
+                return node;
+            },
+            "PropertyIsLessThan": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsLessThan");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsGreaterThan": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsGreaterThan");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsLessThanOrEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsGreaterThanOrEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsBetween": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsBetween");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                this.writeNode("LowerBoundary", filter, node);
+                this.writeNode("UpperBoundary", filter, node);
+                return node;
+            },
+            "PropertyName": function(filter) {
+                // no ogc:expression handling for now
+                return this.createElementNSPlus("ogc:PropertyName", {
+                    value: filter.property
+                });
+            },
+            "Literal": function(value) {
+                // no ogc:expression handling for now
+                return this.createElementNSPlus("ogc:Literal", {
+                    value: value
+                });
+            },
+            "LowerBoundary": function(filter) {
+                // handle Literals or Functions for now
+                var node = this.createElementNSPlus("ogc:LowerBoundary");
+                this.writeOgcExpression(filter.lowerBoundary, node);
+                return node;
+            },
+            "UpperBoundary": function(filter) {
+                // handle Literals or Functions for now
+                var node = this.createElementNSPlus("ogc:UpperBoundary");
+                this.writeNode("Literal", filter.upperBoundary, node);
+                return node;
+            },
+            "INTERSECTS": function(filter) {
+                return this.writeSpatial(filter, "Intersects");
+            },
+            "WITHIN": function(filter) {
+                return this.writeSpatial(filter, "Within");
+            },
+            "CONTAINS": function(filter) {
+                return this.writeSpatial(filter, "Contains");
+            },
+            "DWITHIN": function(filter) {
+                var node = this.writeSpatial(filter, "DWithin");
+                this.writeNode("Distance", filter, node);
+                return node;
+            },
+            "Distance": function(filter) {
+                return this.createElementNSPlus("ogc:Distance", {
+                    attributes: {
+                        units: filter.distanceUnits
+                    },
+                    value: filter.distance
+                });
+            },
+            "Function": function(filter) {
+                var node = this.createElementNSPlus("ogc:Function", {
+                    attributes: {
+                        name: filter.name
+                    }
+                });
+                var params = filter.params;
+                for(var i=0, len=params.length; i<len; i++){
+                    this.writeOgcExpression(params[i], node);
+                }
+                return node;
+            }
+        }
+    },
+
+    /**
+     * Method: getFilterType
+     */
+    getFilterType: function(filter) {
+        var filterType = this.filterMap[filter.type];
+        if(!filterType) {
+            throw "Filter writing not supported for rule type: " + filter.type;
+        }
+        return filterType;
+    },
+    
+    /**
+     * Property: filterMap
+     * {Object} Contains a member for each filter type.  Values are node names
+     *     for corresponding OGC Filter child elements.
+     */
+    filterMap: {
+        "&&": "And",
+        "||": "Or",
+        "!": "Not",
+        "==": "PropertyIsEqualTo",
+        "!=": "PropertyIsNotEqualTo",
+        "<": "PropertyIsLessThan",
+        ">": "PropertyIsGreaterThan",
+        "<=": "PropertyIsLessThanOrEqualTo",
+        ">=": "PropertyIsGreaterThanOrEqualTo",
+        "..": "PropertyIsBetween",
+        "~": "PropertyIsLike",
+        "BBOX": "BBOX",
+        "DWITHIN": "DWITHIN",
+        "WITHIN": "WITHIN",
+        "CONTAINS": "CONTAINS",
+        "INTERSECTS": "INTERSECTS",
+        "FID": "FeatureId"
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Filter.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/Filter/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/v2.js
+ * @requires OpenLayers/Format/Filter/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1_0_0
+ * Write ogc:Filter version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.GML.v2>
+ *  - <OpenLayers.Format.Filter.v1>
+ */
+OpenLayers.Format.Filter.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.GML.v2, OpenLayers.Format.Filter.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/ogc/filter/1.0.0/filter.xsd
+     */
+    schemaLocation: "http://www.opengis.net/ogc/filter/1.0.0/filter.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.Filter.v1_0_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.Filter> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.GML.v2.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ogc": OpenLayers.Util.applyDefaults({
+            "PropertyIsEqualTo": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsNotEqualTo": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsLike": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LIKE
+                });
+                this.readChildNodes(node, filter);
+                var wildCard = node.getAttribute("wildCard");
+                var singleChar = node.getAttribute("singleChar");
+                var esc = node.getAttribute("escape");
+                filter.value2regex(wildCard, singleChar, esc);
+                obj.filters.push(filter);
+            }
+        }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),
+        "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"],
+        "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"]        
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ogc": OpenLayers.Util.applyDefaults({
+            "PropertyIsEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsEqualTo");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsNotEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo");
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsLike": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsLike", {
+                    attributes: {
+                        wildCard: "*", singleChar: ".", escape: "!"
+                    }
+                });
+                // no ogc:expression handling for now
+                this.writeNode("PropertyName", filter, node);
+                // convert regex string to ogc string
+                this.writeNode("Literal", filter.regex2value(), node);
+                return node;
+            },
+            "BBOX": function(filter) {
+                var node = this.createElementNSPlus("ogc:BBOX");
+                // PropertyName is mandatory in 1.0.0, but e.g. GeoServer also
+                // accepts filters without it. When this is used with
+                // OpenLayers.Protocol.WFS, OpenLayers.Format.WFST will set a
+                // missing filter.property to the geometryName that is
+                // configured with the protocol, which defaults to "the_geom".
+                // So the only way to omit this mandatory property is to not
+                // set the property on the filter and to set the geometryName
+                // on the WFS protocol to null. The latter also happens when
+                // the protocol is configured without a geometryName and a
+                // featureNS.
+                filter.property && this.writeNode("PropertyName", filter, node);
+                var box = this.writeNode("gml:Box", filter.value, node);
+                if(filter.projection) {
+                    box.setAttribute("srsName", filter.projection);
+                }
+                return node;
+            }
+        }, OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),
+        "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"],
+        "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"]
+    },
+
+    /**
+     * Method: writeSpatial
+     *
+     * Read a {<OpenLayers.Filter.Spatial>} filter and converts it into XML.
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter.Spatial>} The filter.
+     * name - {String} Name of the generated XML element.
+     *
+     * Returns:
+     * {DOMElement} The created XML element.
+     */
+    writeSpatial: function(filter, name) {
+        var node = this.createElementNSPlus("ogc:"+name);
+        this.writeNode("PropertyName", filter, node);
+        if(filter.value instanceof OpenLayers.Filter.Function) {
+            this.writeNode("Function", filter.value, node);
+        } else {
+        var child;
+        if(filter.value instanceof OpenLayers.Geometry) {
+            child = this.writeNode("feature:_geometry", filter.value).firstChild;
+        } else {
+            child = this.writeNode("gml:Box", filter.value);
+        }
+        if(filter.projection) {
+            child.setAttribute("srsName", filter.projection);
+        }
+        node.appendChild(child);
+        }
+        return node;
+    },
+
+
+    CLASS_NAME: "OpenLayers.Format.Filter.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/SLD/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Format/SLD.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD.v1
+ * Superclass for SLD version 1 parsers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.Filter.v1_0_0>
+ */
+OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        sld: "http://www.opengis.net/sld",
+        ogc: "http://www.opengis.net/ogc",
+        gml: "http://www.opengis.net/gml",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "sld",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: null,
+    
+    /** 
+     * APIProperty: multipleSymbolizers
+     * {Boolean} Support multiple symbolizers per rule.  Default is false.  if
+     *     true, an OpenLayers.Style2 instance will be created to represent 
+     *     user styles instead of an OpenLayers.Style instace.  The 
+     *     OpenLayers.Style2 class allows collections of rules with multiple
+     *     symbolizers, but is not currently useful for client side rendering.
+     *     If multiple symbolizers is true, multiple FeatureTypeStyle elements
+     *     are preserved in reading/writing by setting symbolizer zIndex values.
+     *     In addition, the <defaultSymbolizer> property is ignored if 
+     *     multiple symbolizers are supported (defaults should be applied
+     *     when rendering).
+     */
+    multipleSymbolizers: false,
+
+    /**
+     * Property: featureTypeCounter
+     * {Number} Private counter for multiple feature type styles.
+     */
+    featureTypeCounter: null,
+
+    /**
+     * APIProperty: defaultSymbolizer.
+     * {Object} A symbolizer with the SLD defaults.
+     */
+    defaultSymbolizer: {
+        fillColor: "#808080",
+        fillOpacity: 1,
+        strokeColor: "#000000",
+        strokeOpacity: 1,
+        strokeWidth: 1,
+        strokeDashstyle: "solid",
+        pointRadius: 3,
+        graphicName: "square"
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.SLD.v1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.SLD> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement} An SLD document element.
+     * options - {Object} Options for the reader.
+     *
+     * Valid options:
+     * namedLayersAsArray - {Boolean}  Generate a namedLayers array.  If false,
+     *     the namedLayers property value will be an object keyed by layer name.
+     *     Default is false.
+     *
+     * Returns:
+     * {Object} An object representing the SLD.
+     */
+    read: function(data, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        var sld = {
+            namedLayers: options.namedLayersAsArray === true ? [] : {}
+        };
+        this.readChildNodes(data, sld);
+        return sld;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: OpenLayers.Util.applyDefaults({
+        "sld": {
+            "StyledLayerDescriptor": function(node, sld) {
+                sld.version = node.getAttribute("version");
+                this.readChildNodes(node, sld);
+            },
+            "Name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+            },
+            "Abstract": function(node, obj) {
+                obj.description = this.getChildValue(node);
+            },
+            "NamedLayer": function(node, sld) {
+                var layer = {
+                    userStyles: [],
+                    namedStyles: []
+                };
+                this.readChildNodes(node, layer);
+                // give each of the user styles this layer name
+                for(var i=0, len=layer.userStyles.length; i<len; ++i) {
+                    layer.userStyles[i].layerName = layer.name;
+                }
+                if(OpenLayers.Util.isArray(sld.namedLayers)) {
+                    sld.namedLayers.push(layer);                
+                } else {
+                    sld.namedLayers[layer.name] = layer;
+                }
+            },
+            "NamedStyle": function(node, layer) {
+                layer.namedStyles.push(
+                    this.getChildName(node.firstChild)
+                );
+            },
+            "UserStyle": function(node, layer) {
+                var obj = {defaultsPerSymbolizer: true, rules: []};
+                this.featureTypeCounter = -1;
+                this.readChildNodes(node, obj);
+                var style;
+                if (this.multipleSymbolizers) {
+                    delete obj.defaultsPerSymbolizer;
+                    style = new OpenLayers.Style2(obj);
+                } else {
+                    style = new OpenLayers.Style(this.defaultSymbolizer, obj);
+                }
+                layer.userStyles.push(style);
+            },
+            "IsDefault": function(node, style) {
+                if(this.getChildValue(node) == "1") {
+                    style.isDefault = true;
+                }
+            },
+            "FeatureTypeStyle": function(node, style) {
+                ++this.featureTypeCounter;
+                var obj = {
+                    rules: this.multipleSymbolizers ? style.rules : []
+                };
+                this.readChildNodes(node, obj);
+                if (!this.multipleSymbolizers) {
+                    style.rules = obj.rules;
+                }
+            },
+            "Rule": function(node, obj) {
+                var config;
+                if (this.multipleSymbolizers) {
+                    config = {symbolizers: []};
+                }
+                var rule = new OpenLayers.Rule(config);
+                this.readChildNodes(node, rule);
+                obj.rules.push(rule);
+            },
+            "ElseFilter": function(node, rule) {
+                rule.elseFilter = true;
+            },
+            "MinScaleDenominator": function(node, rule) {
+                rule.minScaleDenominator = parseFloat(this.getChildValue(node));
+            },
+            "MaxScaleDenominator": function(node, rule) {
+                rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
+            },
+            "TextSymbolizer": function(node, rule) {
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Text(config)
+                    );
+                } else {
+                    rule.symbolizer["Text"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Text"]
+                    );
+                }
+            },
+            "Label": function(node, symbolizer) {
+                // only supporting literal or property name
+                var obj = {};
+                this.readChildNodes(node, obj);
+                if(obj.property) {
+                    symbolizer.label = "${" + obj.property + "}";
+                } else {
+                    var value = this.readOgcExpression(node);
+                    if(value) {
+                        symbolizer.label = value;
+                    }
+                }
+            },
+            "Font": function(node, symbolizer) {
+                this.readChildNodes(node, symbolizer);
+            },
+            "Halo": function(node, symbolizer) {
+                // halo has a fill, so send fresh object
+                var obj = {};
+                this.readChildNodes(node, obj);
+                symbolizer.haloRadius = obj.haloRadius;
+                symbolizer.haloColor = obj.fillColor;
+                symbolizer.haloOpacity = obj.fillOpacity;
+            },
+            "Radius": function(node, symbolizer) {
+                var radius = this.readOgcExpression(node);
+                if(radius != null) {
+                    // radius is only used for halo
+                    symbolizer.haloRadius = radius;
+                }
+            },
+            "RasterSymbolizer": function(node, rule) {
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Raster(config)
+                    );
+                } else {
+                    rule.symbolizer["Raster"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Raster"]
+                    );
+                }
+            },
+            "Geometry": function(node, obj) {
+                obj.geometry = {};
+                this.readChildNodes(node, obj.geometry);
+            },
+            "ColorMap": function(node, symbolizer) {
+                symbolizer.colorMap = [];
+                this.readChildNodes(node, symbolizer.colorMap);
+            },
+            "ColorMapEntry": function(node, colorMap) {
+                var q = node.getAttribute("quantity");
+                var o = node.getAttribute("opacity");
+                colorMap.push({
+                    color: node.getAttribute("color"),
+                    quantity: q !== null ? parseFloat(q) : undefined,
+                    label: node.getAttribute("label") || undefined,
+                    opacity: o !== null ? parseFloat(o) : undefined
+                });
+            },
+            "LineSymbolizer": function(node, rule) {
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Line(config)
+                    );
+                } else {
+                    rule.symbolizer["Line"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Line"]
+                    );
+                }
+            },
+            "PolygonSymbolizer": function(node, rule) {
+                var config = {
+                    fill: false,
+                    stroke: false
+                };
+                if (!this.multipleSymbolizers) {
+                    config = rule.symbolizer["Polygon"] || config;
+                }
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Polygon(config)
+                    );
+                } else {
+                    rule.symbolizer["Polygon"] = config;
+                }
+            },
+            "PointSymbolizer": function(node, rule) {
+                var config = {
+                    fill: false,
+                    stroke: false,
+                    graphic: false
+                };
+                if (!this.multipleSymbolizers) {
+                    config = rule.symbolizer["Point"] || config;
+                }
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Point(config)
+                    );
+                } else {
+                    rule.symbolizer["Point"] = config;
+                }
+            },
+            "Stroke": function(node, symbolizer) {
+                symbolizer.stroke = true;
+                this.readChildNodes(node, symbolizer);
+            },
+            "Fill": function(node, symbolizer) {
+                symbolizer.fill = true;
+                this.readChildNodes(node, symbolizer);
+            },
+            "CssParameter": function(node, symbolizer) {
+                var cssProperty = node.getAttribute("name");
+                var symProperty = this.cssMap[cssProperty];
+                if(symProperty) {
+                    // Limited support for parsing of OGC expressions
+                    var value = this.readOgcExpression(node);
+                    // always string, could be an empty string
+                    if(value) {
+                        symbolizer[symProperty] = value;
+                    }
+                }
+            },
+            "Graphic": function(node, symbolizer) {
+                symbolizer.graphic = true;
+                var graphic = {};
+                // painter's order not respected here, clobber previous with next
+                this.readChildNodes(node, graphic);
+                // directly properties with names that match symbolizer properties
+                var properties = [
+                    "stroke", "strokeColor", "strokeWidth", "strokeOpacity",
+                    "strokeLinecap", "fill", "fillColor", "fillOpacity",
+                    "graphicName", "rotation", "graphicFormat"
+                ];
+                var prop, value;
+                for(var i=0, len=properties.length; i<len; ++i) {
+                    prop = properties[i];
+                    value = graphic[prop];
+                    if(value != undefined) {
+                        symbolizer[prop] = value;
+                    }
+                }
+                // set other generic properties with specific graphic property names
+                if(graphic.opacity != undefined) {
+                    symbolizer.graphicOpacity = graphic.opacity;
+                }
+                if(graphic.size != undefined) {
+                    symbolizer.pointRadius = graphic.size / 2;
+                }
+                if(graphic.href != undefined) {
+                    symbolizer.externalGraphic = graphic.href;
+                }
+                if(graphic.rotation != undefined) {
+                    symbolizer.rotation = graphic.rotation;
+                }
+            },
+            "ExternalGraphic": function(node, graphic) {
+                this.readChildNodes(node, graphic);
+            },
+            "Mark": function(node, graphic) {
+                this.readChildNodes(node, graphic);
+            },
+            "WellKnownName": function(node, graphic) {
+                graphic.graphicName = this.getChildValue(node);
+            },
+            "Opacity": function(node, obj) {
+                var opacity = this.readOgcExpression(node);
+                // always string, could be empty string
+                if(opacity) {
+                    obj.opacity = opacity;
+                }
+            },
+            "Size": function(node, obj) {
+                var size = this.readOgcExpression(node);
+                // always string, could be empty string
+                if(size) {
+                    obj.size = size;
+                }
+            },
+            "Rotation": function(node, obj) {
+                var rotation = this.readOgcExpression(node);
+                // always string, could be empty string
+                if(rotation) {
+                    obj.rotation = rotation;
+                }
+            },
+            "OnlineResource": function(node, obj) {
+                obj.href = this.getAttributeNS(
+                    node, this.namespaces.xlink, "href"
+                );
+            },
+            "Format": function(node, graphic) {
+                graphic.graphicFormat = this.getChildValue(node);
+            }
+        }
+    }, OpenLayers.Format.Filter.v1_0_0.prototype.readers),
+    
+    /**
+     * Property: cssMap
+     * {Object} Object mapping supported css property names to OpenLayers
+     *     symbolizer property names.
+     */
+    cssMap: {
+        "stroke": "strokeColor",
+        "stroke-opacity": "strokeOpacity",
+        "stroke-width": "strokeWidth",
+        "stroke-linecap": "strokeLinecap",
+        "stroke-dasharray": "strokeDashstyle",
+        "fill": "fillColor",
+        "fill-opacity": "fillOpacity",
+        "font-family": "fontFamily",
+        "font-size": "fontSize",
+        "font-weight": "fontWeight",
+        "font-style": "fontStyle"
+    },
+    
+    /**
+     * Method: getCssProperty
+     * Given a symbolizer property, get the corresponding CSS property
+     *     from the <cssMap>.
+     *
+     * Parameters:
+     * sym - {String} A symbolizer property name.
+     *
+     * Returns:
+     * {String} A CSS property name or null if none found.
+     */
+    getCssProperty: function(sym) {
+        var css = null;
+        for(var prop in this.cssMap) {
+            if(this.cssMap[prop] == sym) {
+                css = prop;
+                break;
+            }
+        }
+        return css;
+    },
+    
+    /**
+     * Method: getGraphicFormat
+     * Given a href for an external graphic, try to determine the mime-type.
+     *     This method doesn't try too hard, and will fall back to
+     *     <defautlGraphicFormat> if one of the known <graphicFormats> is not
+     *     the file extension of the provided href.
+     *
+     * Parameters:
+     * href - {String}
+     *
+     * Returns:
+     * {String} The graphic format.
+     */
+    getGraphicFormat: function(href) {
+        var format, regex;
+        for(var key in this.graphicFormats) {
+            if(this.graphicFormats[key].test(href)) {
+                format = key;
+                break;
+            }
+        }
+        return format || this.defautlGraphicFormat;
+    },
+    
+    /**
+     * Property: defaultGraphicFormat
+     * {String} If none other can be determined from <getGraphicFormat>, this
+     *     default will be returned.
+     */
+    defaultGraphicFormat: "image/png",
+    
+    /**
+     * Property: graphicFormats
+     * {Object} Mapping of image mime-types to regular extensions matching 
+     *     well-known file extensions.
+     */
+    graphicFormats: {
+        "image/jpeg": /\.jpe?g$/i,
+        "image/gif": /\.gif$/i,
+        "image/png": /\.png$/i
+    },
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * sld - {Object} An object representing the SLD.
+     *
+     * Returns:
+     * {DOMElement} The root of an SLD document.
+     */
+    write: function(sld) {
+        return this.writers.sld.StyledLayerDescriptor.apply(this, [sld]);
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: OpenLayers.Util.applyDefaults({
+        "sld": {
+            "StyledLayerDescriptor": function(sld) {
+                var root = this.createElementNSPlus(
+                    "sld:StyledLayerDescriptor",
+                    {attributes: {
+                        "version": this.VERSION,
+                        "xsi:schemaLocation": this.schemaLocation
+                    }}
+                );
+
+                // For ArcGIS Server it is necessary to define this
+                // at the root level (see ticket:2166).
+                root.setAttribute("xmlns:ogc", this.namespaces.ogc);
+                root.setAttribute("xmlns:gml", this.namespaces.gml);
+
+                // add in optional name
+                if(sld.name) {
+                    this.writeNode("Name", sld.name, root);
+                }
+                // add in optional title
+                if(sld.title) {
+                    this.writeNode("Title", sld.title, root);
+                }
+                // add in optional description
+                if(sld.description) {
+                    this.writeNode("Abstract", sld.description, root);
+                }
+                // add in named layers
+                // allow namedLayers to be an array
+                if(OpenLayers.Util.isArray(sld.namedLayers)) {
+                    for(var i=0, len=sld.namedLayers.length; i<len; ++i) {
+                        this.writeNode("NamedLayer", sld.namedLayers[i], root);
+                    }
+                } else {
+                    for(var name in sld.namedLayers) {
+                        this.writeNode("NamedLayer", sld.namedLayers[name], root);
+                    }
+                }
+                return root;
+            },
+            "Name": function(name) {
+                return this.createElementNSPlus("sld:Name", {value: name});
+            },
+            "Title": function(title) {
+                return this.createElementNSPlus("sld:Title", {value: title});
+            },
+            "Abstract": function(description) {
+                return this.createElementNSPlus(
+                    "sld:Abstract", {value: description}
+                );
+            },
+            "NamedLayer": function(layer) {
+                var node = this.createElementNSPlus("sld:NamedLayer");
+
+                // add in required name
+                this.writeNode("Name", layer.name, node);
+
+                // optional sld:LayerFeatureConstraints here
+
+                // add in named styles
+                if(layer.namedStyles) {
+                    for(var i=0, len=layer.namedStyles.length; i<len; ++i) {
+                        this.writeNode(
+                            "NamedStyle", layer.namedStyles[i], node
+                        );
+                    }
+                }
+                
+                // add in user styles
+                if(layer.userStyles) {
+                    for(var i=0, len=layer.userStyles.length; i<len; ++i) {
+                        this.writeNode(
+                            "UserStyle", layer.userStyles[i], node
+                        );
+                    }
+                }
+                
+                return node;
+            },
+            "NamedStyle": function(name) {
+                var node = this.createElementNSPlus("sld:NamedStyle");
+                this.writeNode("Name", name, node);
+                return node;
+            },
+            "UserStyle": function(style) {
+                var node = this.createElementNSPlus("sld:UserStyle");
+
+                // add in optional name
+                if(style.name) {
+                    this.writeNode("Name", style.name, node);
+                }
+                // add in optional title
+                if(style.title) {
+                    this.writeNode("Title", style.title, node);
+                }
+                // add in optional description
+                if(style.description) {
+                    this.writeNode("Abstract", style.description, node);
+                }
+                
+                // add isdefault
+                if(style.isDefault) {
+                    this.writeNode("IsDefault", style.isDefault, node);
+                }
+                
+                // add FeatureTypeStyles
+                if (this.multipleSymbolizers && style.rules) {
+                    // group style objects by symbolizer zIndex
+                    var rulesByZ = {
+                        0: []
+                    };
+                    var zValues = [0];
+                    var rule, ruleMap, symbolizer, zIndex, clone;
+                    for (var i=0, ii=style.rules.length; i<ii; ++i) {
+                        rule = style.rules[i];
+                        if (rule.symbolizers) {
+                            ruleMap = {};
+                            for (var j=0, jj=rule.symbolizers.length; j<jj; ++j) {
+                                symbolizer = rule.symbolizers[j];
+                                zIndex = symbolizer.zIndex;
+                                if (!(zIndex in ruleMap)) {
+                                    clone = rule.clone();
+                                    clone.symbolizers = [];
+                                    ruleMap[zIndex] = clone;
+                                }
+                                ruleMap[zIndex].symbolizers.push(symbolizer.clone());
+                            }
+                            for (zIndex in ruleMap) {
+                                if (!(zIndex in rulesByZ)) {
+                                    zValues.push(zIndex);
+                                    rulesByZ[zIndex] = [];
+                                }
+                                rulesByZ[zIndex].push(ruleMap[zIndex]);
+                            }
+                        } else {
+                            // no symbolizers in rule
+                            rulesByZ[0].push(rule.clone());
+                        }
+                    }
+                    // write one FeatureTypeStyle per zIndex
+                    zValues.sort();
+                    var rules;
+                    for (var i=0, ii=zValues.length; i<ii; ++i) {
+                        rules = rulesByZ[zValues[i]];
+                        if (rules.length > 0) {
+                            clone = style.clone();
+                            clone.rules = rulesByZ[zValues[i]];
+                            this.writeNode("FeatureTypeStyle", clone, node);
+                        }
+                    }                    
+                } else {
+                    this.writeNode("FeatureTypeStyle", style, node);
+                }
+                
+                return node;
+            },
+            "IsDefault": function(bool) {
+                return this.createElementNSPlus(
+                    "sld:IsDefault", {value: (bool) ? "1" : "0"}
+                );
+            },
+            "FeatureTypeStyle": function(style) {
+                var node = this.createElementNSPlus("sld:FeatureTypeStyle");
+                
+                // OpenLayers currently stores no Name, Title, Abstract,
+                // FeatureTypeName, or SemanticTypeIdentifier information
+                // related to FeatureTypeStyle
+                
+                // add in rules
+                for(var i=0, len=style.rules.length; i<len; ++i) {
+                    this.writeNode("Rule", style.rules[i], node);
+                }
+                
+                return node;
+            },
+            "Rule": function(rule) {
+                var node = this.createElementNSPlus("sld:Rule");
+
+                // add in optional name
+                if(rule.name) {
+                    this.writeNode("Name", rule.name, node);
+                }
+                // add in optional title
+                if(rule.title) {
+                    this.writeNode("Title", rule.title, node);
+                }
+                // add in optional description
+                if(rule.description) {
+                    this.writeNode("Abstract", rule.description, node);
+                }
+                
+                // add in LegendGraphic here
+                
+                // add in optional filters
+                if(rule.elseFilter) {
+                    this.writeNode("ElseFilter", null, node);
+                } else if(rule.filter) {
+                    this.writeNode("ogc:Filter", rule.filter, node);
+                }
+                
+                // add in scale limits
+                if(rule.minScaleDenominator != undefined) {
+                    this.writeNode(
+                        "MinScaleDenominator", rule.minScaleDenominator, node
+                    );
+                }
+                if(rule.maxScaleDenominator != undefined) {
+                    this.writeNode(
+                        "MaxScaleDenominator", rule.maxScaleDenominator, node
+                    );
+                }
+                
+                var type, symbolizer;
+                if (this.multipleSymbolizers && rule.symbolizers) {
+                    var symbolizer;
+                    for (var i=0, ii=rule.symbolizers.length; i<ii; ++i) {
+                        symbolizer = rule.symbolizers[i];
+                        type = symbolizer.CLASS_NAME.split(".").pop();
+                        this.writeNode(
+                            type + "Symbolizer", symbolizer, node
+                        );
+                    }
+                } else {
+                    // add in symbolizers (relies on geometry type keys)
+                    var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
+                    for(var i=0, len=types.length; i<len; ++i) {
+                        type = types[i];
+                        symbolizer = rule.symbolizer[type];
+                        if(symbolizer) {
+                            this.writeNode(
+                                type + "Symbolizer", symbolizer, node
+                            );
+                        }
+                    }
+                }
+                return node;
+
+            },
+            "ElseFilter": function() {
+                return this.createElementNSPlus("sld:ElseFilter");
+            },
+            "MinScaleDenominator": function(scale) {
+                return this.createElementNSPlus(
+                    "sld:MinScaleDenominator", {value: scale}
+                );
+            },
+            "MaxScaleDenominator": function(scale) {
+                return this.createElementNSPlus(
+                    "sld:MaxScaleDenominator", {value: scale}
+                );
+            },
+            "LineSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:LineSymbolizer");
+                this.writeNode("Stroke", symbolizer, node);
+                return node;
+            },
+            "Stroke": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Stroke");
+
+                // GraphicFill here
+                // GraphicStroke here
+
+                // add in CssParameters
+                if(symbolizer.strokeColor != undefined) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "strokeColor"},
+                        node
+                    );
+                }
+                if(symbolizer.strokeOpacity != undefined) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "strokeOpacity"},
+                        node
+                    );
+                }
+                if(symbolizer.strokeWidth != undefined) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "strokeWidth"},
+                        node
+                    );
+                }
+                if(symbolizer.strokeDashstyle != undefined && symbolizer.strokeDashstyle !== "solid") {
+                    // assumes valid stroke-dasharray value
+                    this.writeNode(
+                        "CssParameter", 
+                        {symbolizer: symbolizer, key: "strokeDashstyle"},
+                        node
+                    );
+                }
+                if(symbolizer.strokeLinecap != undefined) {
+                    this.writeNode(
+                        "CssParameter", 
+                        {symbolizer: symbolizer, key: "strokeLinecap"},
+                        node
+                    );
+                }
+                return node;
+            },
+            "CssParameter": function(obj) {
+                // not handling ogc:expressions for now
+                return this.createElementNSPlus("sld:CssParameter", {
+                    attributes: {name: this.getCssProperty(obj.key)},
+                    value: obj.symbolizer[obj.key]
+                });
+            },
+            "TextSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:TextSymbolizer");
+                // add in optional Label
+                if(symbolizer.label != null) {
+                    this.writeNode("Label", symbolizer.label, node);
+                }
+                // add in optional Font
+                if(symbolizer.fontFamily != null ||
+                   symbolizer.fontSize != null ||
+                   symbolizer.fontWeight != null ||
+                   symbolizer.fontStyle != null) {
+                    this.writeNode("Font", symbolizer, node);
+                }
+                // add in optional Halo
+                if(symbolizer.haloRadius != null ||
+                   symbolizer.haloColor != null ||
+                   symbolizer.haloOpacity != null) {
+                    this.writeNode("Halo", symbolizer, node);
+                }
+                // add in optional Fill
+                if(symbolizer.fillColor != null ||
+                   symbolizer.fillOpacity != null) {
+                    this.writeNode("Fill", symbolizer, node);
+                }
+                return node;
+            },
+            "Font": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Font");
+                // add in CssParameters
+                if(symbolizer.fontFamily) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fontFamily"},
+                        node
+                    );
+                }
+                if(symbolizer.fontSize) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fontSize"},
+                        node
+                    );
+                }
+                if(symbolizer.fontWeight) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fontWeight"},
+                        node
+                    );
+                }
+                if(symbolizer.fontStyle) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fontStyle"},
+                        node
+                    );
+                }
+                return node;
+            },
+            "Label": function(label) {
+                // only the simplest of ogc:expression handled
+                // {label: "some text and a ${propertyName}"}
+                var node = this.createElementNSPlus("sld:Label");
+                var tokens = label.split("${");
+                node.appendChild(this.createTextNode(tokens[0]));
+                var item, last;
+                for(var i=1, len=tokens.length; i<len; i++) {
+                    item = tokens[i];
+                    last = item.indexOf("}"); 
+                    if(last > 0) {
+                        this.writeNode(
+                            "ogc:PropertyName",
+                            {property: item.substring(0, last)},
+                            node
+                        );
+                        node.appendChild(
+                            this.createTextNode(item.substring(++last))
+                        );
+                    } else {
+                        // no ending }, so this is a literal ${
+                        node.appendChild(
+                            this.createTextNode("${" + item)
+                        );
+                    }
+                }
+                return node;
+            },
+            "Halo": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Halo");
+                if(symbolizer.haloRadius) {
+                    this.writeNode("Radius", symbolizer.haloRadius, node);
+                }
+                if(symbolizer.haloColor || symbolizer.haloOpacity) {
+                    this.writeNode("Fill", {
+                        fillColor: symbolizer.haloColor,
+                        fillOpacity: symbolizer.haloOpacity
+                    }, node);
+                }
+                return node;
+            },
+            "Radius": function(value) {
+                return this.createElementNSPlus("sld:Radius", {
+                    value: value
+                });
+            },
+            "RasterSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:RasterSymbolizer");
+                if (symbolizer.geometry) {
+                    this.writeNode("Geometry", symbolizer.geometry, node);
+                }
+                if (symbolizer.opacity) {
+                    this.writeNode("Opacity", symbolizer.opacity, node);
+                }
+                if (symbolizer.colorMap) {
+                    this.writeNode("ColorMap", symbolizer.colorMap, node);
+                }
+                return node;
+            },
+            "Geometry": function(geometry) {
+                var node = this.createElementNSPlus("sld:Geometry");
+                if (geometry.property) {
+                    this.writeNode("ogc:PropertyName", geometry, node);
+                }
+                return node;
+            },
+            "ColorMap": function(colorMap) {
+                var node = this.createElementNSPlus("sld:ColorMap");
+                for (var i=0, len=colorMap.length; i<len; ++i) {
+                    this.writeNode("ColorMapEntry", colorMap[i], node);
+                }
+                return node;
+            },
+            "ColorMapEntry": function(colorMapEntry) {
+                var node = this.createElementNSPlus("sld:ColorMapEntry");
+                var a = colorMapEntry;
+                node.setAttribute("color", a.color);
+                a.opacity !== undefined && node.setAttribute("opacity",
+                    parseFloat(a.opacity));
+                a.quantity !== undefined && node.setAttribute("quantity",
+                    parseFloat(a.quantity));
+                a.label !== undefined && node.setAttribute("label", a.label);
+                return node;
+            },
+            "PolygonSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:PolygonSymbolizer");
+                if(symbolizer.fill !== false) {
+                    this.writeNode("Fill", symbolizer, node);
+                }
+                if(symbolizer.stroke !== false) {
+                    this.writeNode("Stroke", symbolizer, node);
+                }
+                return node;
+            },
+            "Fill": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Fill");
+                
+                // GraphicFill here
+                
+                // add in CssParameters
+                if(symbolizer.fillColor) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fillColor"},
+                        node
+                    );
+                }
+                if(symbolizer.fillOpacity != null) {
+                    this.writeNode(
+                        "CssParameter",
+                        {symbolizer: symbolizer, key: "fillOpacity"},
+                        node
+                    );
+                }
+                return node;
+            },
+            "PointSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:PointSymbolizer");
+                this.writeNode("Graphic", symbolizer, node);
+                return node;
+            },
+            "Graphic": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Graphic");
+                if(symbolizer.externalGraphic != undefined) {
+                    this.writeNode("ExternalGraphic", symbolizer, node);
+                } else {
+                    this.writeNode("Mark", symbolizer, node);
+                }
+                
+                if(symbolizer.graphicOpacity != undefined) {
+                    this.writeNode("Opacity", symbolizer.graphicOpacity, node);
+                }
+                if(symbolizer.pointRadius != undefined) {
+                    this.writeNode("Size", symbolizer.pointRadius * 2, node);
+                }
+                if(symbolizer.rotation != undefined) {
+                    this.writeNode("Rotation", symbolizer.rotation, node);
+                }
+                return node;
+            },
+            "ExternalGraphic": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:ExternalGraphic");
+                this.writeNode(
+                    "OnlineResource", symbolizer.externalGraphic, node
+                );
+                var format = symbolizer.graphicFormat ||
+                             this.getGraphicFormat(symbolizer.externalGraphic);
+                this.writeNode("Format", format, node);
+                return node;
+            },
+            "Mark": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:Mark");
+                if(symbolizer.graphicName) {
+                    this.writeNode("WellKnownName", symbolizer.graphicName, node);
+                }
+                if (symbolizer.fill !== false) {
+                    this.writeNode("Fill", symbolizer, node);
+                }
+                if (symbolizer.stroke !== false) {
+                    this.writeNode("Stroke", symbolizer, node);
+                }
+                return node;
+            },
+            "WellKnownName": function(name) {
+                return this.createElementNSPlus("sld:WellKnownName", {
+                    value: name
+                });
+            },
+            "Opacity": function(value) {
+                return this.createElementNSPlus("sld:Opacity", {
+                    value: value
+                });
+            },
+            "Size": function(value) {
+                return this.createElementNSPlus("sld:Size", {
+                    value: value
+                });
+            },
+            "Rotation": function(value) {
+                return this.createElementNSPlus("sld:Rotation", {
+                    value: value
+                });
+            },
+            "OnlineResource": function(href) {
+                return this.createElementNSPlus("sld:OnlineResource", {
+                    attributes: {
+                        "xlink:type": "simple",
+                        "xlink:href": href
+                    }
+                });
+            },
+            "Format": function(format) {
+                return this.createElementNSPlus("sld:Format", {
+                    value: format
+                });
+            }
+        }
+    }, OpenLayers.Format.Filter.v1_0_0.prototype.writers),
+    
+    CLASS_NAME: "OpenLayers.Format.SLD.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/SLD/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/SLD/v1.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD.v1_0_0
+ * Write SLD version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.SLD.v1>
+ */
+OpenLayers.Format.SLD.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.SLD.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/sld
+     *   http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd
+     */
+    schemaLocation: "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.SLD.v1_0_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.SLD> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.SLD.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    CLASS_NAME: "OpenLayers.Format.SLD.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/Context.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Context
+ * Base class for both Format.WMC and Format.OWSContext
+ */
+OpenLayers.Format.Context = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+    /**
+     * Property: layerOptions
+     * {Object} Default options for layers created by the parser. These
+     *     options are overridden by the options which are read from the
+     *     capabilities document.
+     */
+    layerOptions: null,
+
+    /**
+     * Property: layerParams
+     * {Object} Default parameters for layers created by the parser. This
+     *     can be used e.g. to override DEFAULT_PARAMS for 
+     *     OpenLayers.Layer.WMS.
+     */
+    layerParams: null,
+
+    /**
+     * Constructor: OpenLayers.Format.Context
+     * Create a new parser for Context documents.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read Context data from a string, and return an object with map
+     *     properties and a list of layers.
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     * options - {Object} The options object must contain a map property.  If
+     *     the map property is a string, it must be the id of a dom element
+     *     where the new map will be placed.  If the map property is an
+     *     <OpenLayers.Map>, the layers from the context document will be added
+     *     to the map.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} A map based on the context.
+     */
+    read: function(data, options) {
+        var context = OpenLayers.Format.XML.VersionedOGC.prototype.read.apply(this, 
+            arguments);
+        var map;
+        if(options && options.map) {
+            this.context = context;
+            if(options.map instanceof OpenLayers.Map) {
+                map = this.mergeContextToMap(context, options.map);
+            } else {
+                var mapOptions = options.map;
+                if(OpenLayers.Util.isElement(mapOptions) ||
+                   typeof mapOptions == "string") {
+                    // we assume mapOptions references a div
+                    // element
+                    mapOptions = {div: mapOptions};
+                }
+                map = this.contextToMap(context, mapOptions);
+            }
+        } else {
+            // not documented as part of the API, provided as a non-API option
+            map = context;
+        }
+        return map;
+    },
+
+    /**
+     * Method: getLayerFromContext
+     * Create a WMS layer from a layerContext object.
+     *
+     * Parameters:
+     * layerContext - {Object} An object representing a WMS layer.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS>} A WMS layer.
+     */
+    getLayerFromContext: function(layerContext) {
+        var i, len;
+        // fill initial options object from layerContext
+        var options = {
+            queryable: layerContext.queryable, //keep queryable for api compatibility
+            visibility: layerContext.visibility,
+            maxExtent: layerContext.maxExtent,
+            metadata: OpenLayers.Util.applyDefaults(layerContext.metadata, 
+            {styles: layerContext.styles,
+             formats: layerContext.formats,
+             "abstract": layerContext["abstract"],
+             dataURL: layerContext.dataURL
+            }),
+            numZoomLevels: layerContext.numZoomLevels,
+            units: layerContext.units,
+            isBaseLayer: layerContext.isBaseLayer,
+            opacity: layerContext.opacity,
+            displayInLayerSwitcher: layerContext.displayInLayerSwitcher,
+            singleTile: layerContext.singleTile,
+            tileSize: (layerContext.tileSize) ? 
+                new OpenLayers.Size(
+                    layerContext.tileSize.width, 
+                    layerContext.tileSize.height
+                ) : undefined,
+            minScale: layerContext.minScale || layerContext.maxScaleDenominator,
+            maxScale: layerContext.maxScale || layerContext.minScaleDenominator,
+            srs: layerContext.srs,
+            dimensions: layerContext.dimensions,
+            metadataURL: layerContext.metadataURL
+        };
+        if (this.layerOptions) {
+            OpenLayers.Util.applyDefaults(options, this.layerOptions);
+        }
+
+        var params = {
+            layers: layerContext.name,
+            transparent: layerContext.transparent,
+            version: layerContext.version
+        };
+        if (layerContext.formats && layerContext.formats.length>0) {
+            // set default value for params if current attribute is not positionned
+            params.format = layerContext.formats[0].value;
+            for (i=0, len=layerContext.formats.length; i<len; i++) {
+                var format = layerContext.formats[i];
+                if (format.current == true) {
+                    params.format = format.value;
+                    break;
+                }
+            }
+        }
+        if (layerContext.styles && layerContext.styles.length>0) {
+            for (i=0, len=layerContext.styles.length; i<len; i++) {
+                var style = layerContext.styles[i];
+                if (style.current == true) {
+                    // three style types to consider
+                    // 1) linked SLD
+                    // 2) inline SLD
+                    // 3) named style
+                    if(style.href) {
+                        params.sld = style.href;
+                    } else if(style.body) {
+                        params.sld_body = style.body;
+                    } else {
+                        params.styles = style.name;
+                    }
+                    break;
+                }
+            }
+        }
+        if (this.layerParams) {
+            OpenLayers.Util.applyDefaults(params, this.layerParams);
+        }
+
+        var layer = null;
+        var service = layerContext.service;
+        if (service == OpenLayers.Format.Context.serviceTypes.WFS) {
+            options.strategies = [new OpenLayers.Strategy.BBOX()];
+            options.protocol = new OpenLayers.Protocol.WFS({
+                url: layerContext.url,
+                // since we do not know featureNS, let the protocol
+                // determine it automagically using featurePrefix
+                featurePrefix: layerContext.name.split(":")[0],
+                featureType: layerContext.name.split(":").pop()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (service == OpenLayers.Format.Context.serviceTypes.KML) {
+            // use a vector layer with an HTTP Protcol and a Fixed strategy
+            options.strategies = [new OpenLayers.Strategy.Fixed()];
+            options.protocol = new OpenLayers.Protocol.HTTP({
+                url: layerContext.url, 
+                format: new OpenLayers.Format.KML()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (service == OpenLayers.Format.Context.serviceTypes.GML) {
+            // use a vector layer with a HTTP Protocol and a Fixed strategy
+            options.strategies = [new OpenLayers.Strategy.Fixed()];
+            options.protocol = new OpenLayers.Protocol.HTTP({
+                url: layerContext.url, 
+                format: new OpenLayers.Format.GML()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (layerContext.features) {
+            // inline GML or KML features
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+            layer.addFeatures(layerContext.features);
+        } else if (layerContext.categoryLayer !== true) {
+            layer = new OpenLayers.Layer.WMS(
+                layerContext.title || layerContext.name,
+                layerContext.url,
+                params,
+                options
+            );
+        }
+        return layer;
+    },
+
+    /**
+     * Method: getLayersFromContext
+     * Create an array of layers from an array of layerContext objects.
+     *
+     * Parameters:
+     * layersContext - {Array(Object)} An array of objects representing layers.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Layer>)} An array of layers.
+     */
+    getLayersFromContext: function(layersContext) {
+        var layers = [];
+        for (var i=0, len=layersContext.length; i<len; i++) {
+            var layer = this.getLayerFromContext(layersContext[i]);
+            if (layer !== null) {
+                layers.push(layer);
+            }
+        }
+        return layers;
+    },
+
+    /**
+     * Method: contextToMap
+     * Create a map given a context object.
+     *
+     * Parameters:
+     * context - {Object} The context object.
+     * options - {Object} Default map options.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} A map based on the context object.
+     */
+    contextToMap: function(context, options) {
+        options = OpenLayers.Util.applyDefaults({
+            maxExtent:  context.maxExtent,
+            projection: context.projection,
+            units:      context.units
+        }, options);
+
+        if (options.maxExtent) {
+            options.maxResolution = 
+                options.maxExtent.getWidth() / OpenLayers.Map.TILE_WIDTH;
+        }
+
+        var metadata = {
+            contactInformation: context.contactInformation,
+            "abstract":         context["abstract"],
+            keywords:           context.keywords,
+            logo:               context.logo,
+            descriptionURL:     context.descriptionURL
+        }
+
+        options.metadata = metadata;
+
+        var map = new OpenLayers.Map(options);
+        map.addLayers(this.getLayersFromContext(context.layersContext));
+        map.setCenter(
+            context.bounds.getCenterLonLat(),
+            map.getZoomForExtent(context.bounds, true)
+        );
+        return map;
+    },
+
+    /**
+     * Method: mergeContextToMap
+     * Add layers from a context object to a map.
+     *
+     * Parameters:
+     * context - {Object} The context object.
+     * map - {<OpenLayers.Map>} The map.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} The same map with layers added.
+     */
+    mergeContextToMap: function(context, map) {
+        map.addLayers(this.getLayersFromContext(context.layersContext));
+        return map;
+    },
+
+    /**
+     * APIMethod: write
+     * Write a context document given a map.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Map> | Object} A map or context object.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} A context document string.
+     */
+    write: function(obj, options) {
+        obj = this.toContext(obj);
+        return OpenLayers.Format.XML.VersionedOGC.prototype.write.apply(this,
+            arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Context"
+});
+
+/**
+ * Constant: OpenLayers.Format.Context.serviceTypes
+ * Enumeration for service types
+ */
+OpenLayers.Format.Context.serviceTypes = {
+    "WMS": "urn:ogc:serviceType:WMS",
+    "WFS": "urn:ogc:serviceType:WFS",
+    "WCS": "urn:ogc:serviceType:WCS",
+    "GML": "urn:ogc:serviceType:GML",
+    "SLD": "urn:ogc:serviceType:SLD",
+    "FES": "urn:ogc:serviceType:FES",
+    "KML": "urn:ogc:serviceType:KML"
+};
+/* ======================================================================
+    OpenLayers/Format/OWSContext.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/Context.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext
+ * Read and write OWS Context documents. OWS Context documents are a 
+ * preliminary OGC (Open Geospatial Consortium) standard for storing the 
+ * state of a web mapping application. In a way it is the successor to
+ * Web Map Context (WMC), since it is more generic and more types of layers
+ * can be stored. Also, nesting of layers is supported since version 0.3.1.
+ * For more information see: http://www.ogcnetwork.net/context
+ */
+OpenLayers.Format.OWSContext = OpenLayers.Class(OpenLayers.Format.Context,{
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "0.3.1".
+     */
+    defaultVersion: "0.3.1",
+
+    /**
+     * Constructor: OpenLayers.Format.OWSContext
+     * Create a new parser for OWS Context documents.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    
+    /**
+     * Method: getVersion
+     * Returns the version to use. Subclasses can override this function
+     * if a different version detection is needed.
+     *
+     * Parameters:
+     * root - {DOMElement}
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} The version to use.
+     */
+    getVersion: function(root, options) {
+        var version = OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(
+            this, arguments);
+        // 0.3.1 is backwards compatible with 0.3.0
+        if (version === "0.3.0") {
+            version = this.defaultVersion;
+        }
+        return version;
+    },
+
+    /**
+     * Method: toContext
+     * Create a context object free from layer given a map or a
+     * context object.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Map> | Object} The map or context.
+     *
+     * Returns:
+     * {Object} A context object.
+     */
+    toContext: function(obj) {
+        var context = {};
+        if(obj.CLASS_NAME == "OpenLayers.Map") {
+            context.bounds = obj.getExtent();
+            context.maxExtent = obj.maxExtent;
+            context.projection = obj.projection;
+            context.size = obj.getSize();
+            context.layers = obj.layers;
+        }
+        return context;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OWSContext" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/OWSCommon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon
+ * Read OWSCommon. Create a new instance with the <OpenLayers.Format.OWSCommon>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.OWSCommon = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * Constructor: OpenLayers.Format.OWSCommon
+     * Create a new parser for OWSCommon.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * Method: getVersion
+     * Returns the version to use. Subclasses can override this function
+     * if a different version detection is needed.
+     *
+     * Parameters:
+     * root - {DOMElement}
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} The version to use.
+     */
+    getVersion: function(root, options) {
+        var version = this.version;
+        if(!version) {
+            // remember version does not correspond to the OWS version
+            // it corresponds to the WMS/WFS/WCS etc. request version
+            var uri = root.getAttribute("xmlns:ows");
+            // the above will fail if the namespace prefix is different than
+            // ows and if the namespace is declared on a different element
+            if (uri && uri.substring(uri.lastIndexOf("/")+1) === "1.1") {
+                version ="1.1.0";
+            } 
+            if(!version) {
+                version = this.defaultVersion;
+            }
+        }
+        return version;
+    },
+
+    /**
+     * APIMethod: read
+     * Read an OWSCommon document and return an object.
+     *
+     * Parameters:
+     * data - {String | DOMElement} Data to read.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the structure of the document.
+     */
+
+    CLASS_NAME: "OpenLayers.Format.OWSCommon" 
+});
+/* ======================================================================
+    OpenLayers/Format/OWSCommon/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1
+ * Common readers and writers for OWSCommon v1.X formats
+ */
+OpenLayers.Format.OWSCommon.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+   
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement} An OWSCommon document element.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the OWSCommon document.
+     */
+    read: function(data, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        var ows = {};
+        this.readChildNodes(data, ows);
+        return ows;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": {
+            "Exception": function(node, exceptionReport) {
+                var exception = {
+                    code: node.getAttribute('exceptionCode'),
+                    locator: node.getAttribute('locator'),
+                    texts: []
+                };
+                exceptionReport.exceptions.push(exception);
+                this.readChildNodes(node, exception);
+            },
+            "ExceptionText": function(node, exception) {
+                var text = this.getChildValue(node);
+                exception.texts.push(text);
+            },
+            "ServiceIdentification": function(node, obj) {
+                obj.serviceIdentification = {};
+                this.readChildNodes(node, obj.serviceIdentification);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+            },
+            "Abstract": function(node, serviceIdentification) {
+                serviceIdentification["abstract"] = this.getChildValue(node);
+            },
+            "Keywords": function(node, serviceIdentification) {
+                serviceIdentification.keywords = {};
+                this.readChildNodes(node, serviceIdentification.keywords);
+            },
+            "Keyword": function(node, keywords) {
+                keywords[this.getChildValue(node)] = true;
+            },
+            "ServiceType": function(node, serviceIdentification) {
+                serviceIdentification.serviceType = {
+                    codeSpace: node.getAttribute('codeSpace'), 
+                    value: this.getChildValue(node)};
+            },
+            "ServiceTypeVersion": function(node, serviceIdentification) {
+                serviceIdentification.serviceTypeVersion = this.getChildValue(node);
+            },
+            "Fees": function(node, serviceIdentification) {
+                serviceIdentification.fees = this.getChildValue(node);
+            },
+            "AccessConstraints": function(node, serviceIdentification) {
+                serviceIdentification.accessConstraints = 
+                    this.getChildValue(node);
+            },
+            "ServiceProvider": function(node, obj) {
+                obj.serviceProvider = {};
+                this.readChildNodes(node, obj.serviceProvider);
+            },
+            "ProviderName": function(node, serviceProvider) {
+                serviceProvider.providerName = this.getChildValue(node);
+            },
+            "ProviderSite": function(node, serviceProvider) {
+                serviceProvider.providerSite = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "ServiceContact": function(node, serviceProvider) {
+                serviceProvider.serviceContact = {};
+                this.readChildNodes(node, serviceProvider.serviceContact);
+            },
+            "IndividualName": function(node, serviceContact) {
+                serviceContact.individualName = this.getChildValue(node);
+            },
+            "PositionName": function(node, serviceContact) {
+                serviceContact.positionName = this.getChildValue(node);
+            },
+            "ContactInfo": function(node, serviceContact) {
+                serviceContact.contactInfo = {};
+                this.readChildNodes(node, serviceContact.contactInfo);
+            },
+            "Phone": function(node, contactInfo) {
+                contactInfo.phone = {};
+                this.readChildNodes(node, contactInfo.phone);
+            },
+            "Voice": function(node, phone) {
+                phone.voice = this.getChildValue(node);
+            },
+            "Address": function(node, contactInfo) {
+                contactInfo.address = {};
+                this.readChildNodes(node, contactInfo.address);
+            },
+            "DeliveryPoint": function(node, address) {
+                address.deliveryPoint = this.getChildValue(node);
+            },
+            "City": function(node, address) {
+                address.city = this.getChildValue(node);
+            },
+            "AdministrativeArea": function(node, address) {
+                address.administrativeArea = this.getChildValue(node);
+            },
+            "PostalCode": function(node, address) {
+                address.postalCode = this.getChildValue(node);
+            },
+            "Country": function(node, address) {
+                address.country = this.getChildValue(node);
+            },
+            "ElectronicMailAddress": function(node, address) {
+                address.electronicMailAddress = this.getChildValue(node);
+            },
+            "Role": function(node, serviceContact) {
+                serviceContact.role = this.getChildValue(node);
+            },
+            "OperationsMetadata": function(node, obj) {
+                obj.operationsMetadata = {};
+                this.readChildNodes(node, obj.operationsMetadata);
+            },
+            "Operation": function(node, operationsMetadata) {
+                var name = node.getAttribute("name");
+                operationsMetadata[name] = {};
+                this.readChildNodes(node, operationsMetadata[name]);
+            },
+            "DCP": function(node, operation) {
+                operation.dcp = {};
+                this.readChildNodes(node, operation.dcp);
+            },
+            "HTTP": function(node, dcp) {
+                dcp.http = {};
+                this.readChildNodes(node, dcp.http);
+            },
+            "Get": function(node, http) {
+                http.get = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "Post": function(node, http) {
+                http.post = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "Parameter": function(node, operation) {
+                if (!operation.parameters) {
+                    operation.parameters = {};
+                }
+                var name = node.getAttribute("name");
+                operation.parameters[name] = {};
+                this.readChildNodes(node, operation.parameters[name]);
+            },
+            "Value": function(node, allowedValues) {
+                allowedValues[this.getChildValue(node)] = true;
+            },
+            "OutputFormat": function(node, obj) {
+                obj.formats.push({value: this.getChildValue(node)});
+                this.readChildNodes(node, obj);
+            },
+            "WGS84BoundingBox": function(node, obj) {
+                var boundingBox = {};
+                boundingBox.crs = node.getAttribute("crs");
+                if (obj.BoundingBox) {
+                    obj.BoundingBox.push(boundingBox);
+                } else {
+                    obj.projection = boundingBox.crs;
+                    boundingBox = obj;
+               }
+               this.readChildNodes(node, boundingBox);
+            },
+            "BoundingBox": function(node, obj) {
+                // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox
+                // LowerCorner = "min_x min_y"
+                // UpperCorner = "max_x max_y"
+                // It should normally depend on the projection
+                this.readers['ows']['WGS84BoundingBox'].apply(this, [node, obj]);
+            },
+            "LowerCorner": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, "");
+                str = str.replace(this.regExes.trimComma, ",");
+                var pointList = str.split(this.regExes.splitSpace);
+                obj.left = pointList[0];
+                obj.bottom = pointList[1];
+            },
+            "UpperCorner": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, "");
+                str = str.replace(this.regExes.trimComma, ",");
+                var pointList = str.split(this.regExes.splitSpace);
+                obj.right = pointList[0];
+                obj.top = pointList[1];
+                obj.bounds = new OpenLayers.Bounds(obj.left, obj.bottom,
+                    obj.right, obj.top);
+                delete obj.left;
+                delete obj.bottom;
+                delete obj.right;
+                delete obj.top;
+            },
+            "Language": function(node, obj) {
+                obj.language = this.getChildValue(node);
+            }
+        }
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ows": {
+            "BoundingBox": function(options) {
+                var node = this.createElementNSPlus("ows:BoundingBox", {
+                    attributes: {
+                        crs: options.projection
+                    }
+                });
+                this.writeNode("ows:LowerCorner", options, node);
+                this.writeNode("ows:UpperCorner", options, node);
+                return node;
+            },
+            "LowerCorner": function(options) {
+                var node = this.createElementNSPlus("ows:LowerCorner", {
+                    value: options.bounds.left + " " + options.bounds.bottom });
+                return node;
+            },
+            "UpperCorner": function(options) {
+                var node = this.createElementNSPlus("ows:UpperCorner", {
+                    value: options.bounds.right + " " + options.bounds.top });
+                return node;
+            },
+            "Identifier": function(identifier) {
+                var node = this.createElementNSPlus("ows:Identifier", {
+                    value: identifier });
+                return node;
+            },
+            "Title": function(title) {
+                var node = this.createElementNSPlus("ows:Title", {
+                    value: title });
+                return node;
+            },
+            "Abstract": function(abstractValue) {
+                var node = this.createElementNSPlus("ows:Abstract", {
+                    value: abstractValue });
+                return node;
+            },
+            "OutputFormat": function(format) {
+                var node = this.createElementNSPlus("ows:OutputFormat", {
+                    value: format });
+                return node;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1"
+
+});
+/* ======================================================================
+    OpenLayers/Format/OWSCommon/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_0_0
+ * Parser for OWS Common version 1.0.0.
+ */
+OpenLayers.Format.OWSCommon.v1_0_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": OpenLayers.Util.applyDefaults({
+            "ExceptionReport": function(node, obj) {
+                obj.success = false;
+                obj.exceptionReport = {
+                    version: node.getAttribute('version'),
+                    language: node.getAttribute('language'),
+                    exceptions: []
+                };
+                this.readChildNodes(node, obj.exceptionReport);
+            } 
+        }, OpenLayers.Format.OWSCommon.v1.prototype.readers.ows)
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ows": OpenLayers.Format.OWSCommon.v1.prototype.writers.ows
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_0_0"
+
+});
+/* ======================================================================
+    OpenLayers/Format/OWSContext/v0_3_1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/KML.js
+ * @requires OpenLayers/Format/GML.js
+ * @requires OpenLayers/Format/GML/v2.js
+ * @requires OpenLayers/Format/SLD/v1_0_0.js
+ * @requires OpenLayers/Format/OWSContext.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext.v0_3_1
+ * Read and write OWSContext version 0.3.1.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OWSContext.v0_3_1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        owc: "http://www.opengis.net/ows-context",
+        gml: "http://www.opengis.net/gml",
+        kml: "http://www.opengis.net/kml/2.2",
+        ogc: "http://www.opengis.net/ogc",
+        ows: "http://www.opengis.net/ows",
+        sld: "http://www.opengis.net/sld",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 0.3.1
+     */
+    VERSION: "0.3.1", 
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",
+
+    /**
+     * Property: defaultPrefix
+     * {String} Default namespace prefix to use.
+     */
+    defaultPrefix: "owc",
+
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from GML.  Default is true.
+     */
+    extractAttributes: true,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */ 
+    xy: true, 
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Property: featureNS
+     * {String} The namespace uri to use for writing InlineGeometry
+     */
+    featureNS: "http://mapserver.gis.umn.edu/mapserver",
+
+    /**
+     * Property: featureType
+     * {String} The name to use as the feature type when writing out
+     *     InlineGeometry
+     */
+    featureType: 'vector',
+              
+    /**
+     * Property: geometryName
+     * {String} The name to use for the geometry attribute when writing out
+     *     InlineGeometry
+     */
+    geometryName: 'geometry',
+
+    /**
+     * Property: nestingLayerLookup
+     * {Object} Hashtable lookup for nesting layer nodes. Used while writing 
+     *     the OWS context document. It is necessary to keep track of the 
+     *     nestingPaths for which nesting layer nodes have already been 
+     *     created, so (nesting) layer nodes are added to those nodes.
+     *
+     * For example:
+     *
+     *     If there are three layers with nestingPaths:
+     *         layer1.metadata.nestingPath = "a/b/"
+     *         layer2.metadata.nestingPath = "a/b/"
+     *         layer2.metadata.nestingPath = "a/c"
+     *
+     *     then a nesting layer node "a" should be created once and added 
+     *     to the resource list, a nesting layer node "b" should be created 
+     *     once and added under "a", and a nesting layer node "c" should be 
+     *     created and added under "a". The lookup paths for these nodes 
+     *     will be "a", "a/b", and "a/c" respectively.
+     */
+    nestingLayerLookup: null,
+
+    /**
+     * Constructor: OpenLayers.Format.OWSContext.v0_3_1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.OWSContext> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);
+    },
+
+    /**
+     * Method: setNestingPath
+     * Set the nestingPath property of the layer depending on the position
+     *     of the layer in hierarchy of layers.
+     *
+     * Parameters:
+     * l - {Object} An object that may have a layersContext array property.
+     * 
+     */
+    setNestingPath : function(l){
+        if(l.layersContext){
+            for (var i = 0, len = l.layersContext.length; i < len; i++) {
+                var layerContext = l.layersContext[i];
+                var nPath = [];
+                var nTitle = l.title || "";
+                if(l.metadata && l.metadata.nestingPath){
+                    nPath = l.metadata.nestingPath.slice();
+                }
+                if (nTitle != "") {
+                    nPath.push(nTitle);
+                }
+                layerContext.metadata.nestingPath = nPath;
+                if(layerContext.layersContext){
+                    this.setNestingPath(layerContext);
+                }
+            }
+        }
+    },
+
+    /**
+     * Function: decomposeNestingPath
+     * Takes a nestingPath like "a/b/c" and decomposes it into subpaths:
+     * "a", "a/b", "a/b/c"
+     *
+     * Parameters:
+     * nPath  - {Array} the nesting path
+     *
+     * Returns:
+     * Array({String}) Array with subpaths, or empty array if there is nothing
+     *     to decompose
+     */
+    decomposeNestingPath: function(nPath){
+        var a = [];
+        if (OpenLayers.Util.isArray(nPath)) {
+            var path = nPath.slice();
+            while (path.length > 0) {
+                a.push(path.slice());
+                path.pop();
+            }
+            a.reverse();
+        }
+        return a;
+    },
+
+    /**
+     * APIMethod: read
+     * Read OWS context data from a string or DOMElement, and return a list 
+     *     of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} The context object with a flat layer list as a property named
+     *     layersContext.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var context = {};
+        this.readNode(data, context);
+        // since an OWSContext can be nested we need to go through this
+        // structure recursively      
+        this.setNestingPath({layersContext : context.layersContext});
+        // after nesting path has been set, create a flat list of layers
+        var layers = [];
+        this.processLayer(layers, context);
+        delete context.layersContext;
+        context.layersContext = layers;
+        return context;
+    },
+
+    /**
+     * Method: processLayer
+     * Recursive function to get back a flat list of layers from the hierarchic
+     *     layer structure.
+     *
+     * Parameters:
+     * layerArray - {Array({Object})} Array of layerContext objects
+     * layerContext - {Object} layerContext object
+     */
+    processLayer: function(layerArray, layer) {
+        if (layer.layersContext) {
+            for (var i=0, len = layer.layersContext.length; i<len; i++) {
+                var l = layer.layersContext[i];
+                layerArray.push(l);
+                if (l.layersContext) {
+                    this.processLayer(layerArray, l);
+                }
+            }
+        }
+    },
+
+    /**
+     * APIMethod: write
+     *
+     * Parameters:
+     * context - {Object} An object representing the map context.
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} An OWS Context document string.
+     */
+    write: function(context, options) {
+        var name = "OWSContext";
+        this.nestingLayerLookup = {}; //start with empty lookup
+        options = options || {};
+        OpenLayers.Util.applyDefaults(options, context);
+        var root = this.writeNode(name, options);
+        this.nestingLayerLookup = null; //clear lookup
+        this.setAttributeNS(
+            root, this.namespaces["xsi"],
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    }, 
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "kml": {
+            "Document": function(node, obj) {
+                obj.features = new OpenLayers.Format.KML(
+                    {kmlns: this.namespaces.kml, 
+                        extractStyles: true}).read(node);
+            }
+        },
+        "owc": { 
+            "OWSContext": function(node, obj) {
+                this.readChildNodes(node, obj);
+            }, 
+            "General": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "ResourceList": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Layer": function(node, obj) {
+                var layerContext = {
+                    metadata: {},
+                    visibility: (node.getAttribute("hidden") != "1"),
+                    queryable: (node.getAttribute("queryable") == "1"),
+                    opacity: ((node.getAttribute("opacity") != null) ? 
+                        parseFloat(node.getAttribute("opacity")) : null),
+                    name: node.getAttribute("name"),
+                    /* A category layer is a dummy layer meant for creating
+                       hierarchies. It is not a physical layer in the 
+                       OpenLayers sense. The assumption we make here is that
+                       category layers do not have a name attribute */
+                    categoryLayer: (node.getAttribute("name") == null),
+                    formats: [],
+                    styles: []
+                };
+                if (!obj.layersContext) {
+                    obj.layersContext = [];
+                }
+                obj.layersContext.push(layerContext);
+                this.readChildNodes(node, layerContext);
+            },
+            "InlineGeometry": function(node, obj) {
+                obj.features = [];
+                var elements = this.getElementsByTagNameNS(node, 
+                    this.namespaces.gml, "featureMember");
+                var el;
+                if (elements.length >= 1) {
+                    el = elements[0];
+                }
+                if (el && el.firstChild) {
+                    var featurenode = (el.firstChild.nextSibling) ? 
+                        el.firstChild.nextSibling : el.firstChild;
+                    this.setNamespace("feature", featurenode.namespaceURI);
+                    this.featureType = featurenode.localName || 
+                        featurenode.nodeName.split(":").pop();
+                    this.readChildNodes(node, obj);
+                }
+            },
+            "Server": function(node, obj) {
+                // when having multiple Server types, we prefer WMS
+                if ((!obj.service && !obj.version) || 
+                    (obj.service != 
+                        OpenLayers.Format.Context.serviceTypes.WMS)) {
+                            obj.service = node.getAttribute("service");
+                            obj.version = node.getAttribute("version");
+                            this.readChildNodes(node, obj);
+                }
+            },
+            "Name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+                this.readChildNodes(node, obj);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+                this.readChildNodes(node, obj);
+            },
+            "StyleList": function(node, obj) {
+                this.readChildNodes(node, obj.styles);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                obj.push(style);
+                this.readChildNodes(node, style);
+            },
+            "LegendURL": function(node, obj) {
+                var legend = {};
+                obj.legend = legend;
+                this.readChildNodes(node, legend);
+            },
+            "OnlineResource": function(node, obj) {
+                obj.url = this.getAttributeNS(node, this.namespaces.xlink, 
+                    "href");
+                this.readChildNodes(node, obj);
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,
+        "gml": OpenLayers.Format.GML.v2.prototype.readers.gml,
+        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,
+        "feature": OpenLayers.Format.GML.v2.prototype.readers.feature
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "owc": {
+            "OWSContext": function(options) {
+                var node = this.createElementNSPlus("OWSContext", {
+                    attributes: {
+                        version: this.VERSION,
+                        id: options.id || OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")
+                    } 
+                }); 
+                this.writeNode("General", options, node);
+                this.writeNode("ResourceList", options, node);
+                return node; 
+            },
+            "General": function(options) {
+                var node = this.createElementNSPlus("General");
+                this.writeNode("ows:BoundingBox", options, node);
+                this.writeNode("ows:Title", options.title || 'OpenLayers OWSContext', node);
+                return node;
+            },
+            "ResourceList": function(options) {
+                var node = this.createElementNSPlus("ResourceList");
+                for (var i=0, len=options.layers.length; i<len; i++) {
+                    var layer = options.layers[i];
+                    var decomposedPath = this.decomposeNestingPath(layer.metadata.nestingPath);
+                    this.writeNode("_Layer", {layer: layer, subPaths: decomposedPath}, node);
+                }
+                return node;
+            },
+            "Server": function(options) {
+                var node = this.createElementNSPlus("Server", {attributes: {
+                    version: options.version,
+                    service: options.service }
+                });
+                this.writeNode("OnlineResource", options, node);
+                return node;
+            },
+            "OnlineResource": function(options) {
+                var node = this.createElementNSPlus("OnlineResource", {attributes: {
+                    "xlink:href": options.url }
+                });
+                return node;
+            },
+            "InlineGeometry": function(layer) {
+                var node = this.createElementNSPlus("InlineGeometry");
+                this.writeNode("gml:boundedBy", layer.getDataExtent(), node);
+                for (var i=0, len=layer.features.length; i<len; i++) {
+                    this.writeNode("gml:featureMember", layer.features[i], node);
+                }
+                return node;
+            },
+            "StyleList": function(styles) {
+                var node = this.createElementNSPlus("StyleList");
+                for (var i=0, len=styles.length; i<len; i++) {
+                    this.writeNode("Style", styles[i], node);
+                }
+                return node;
+            },
+            "Style": function(style) {
+                var node = this.createElementNSPlus("Style");
+                this.writeNode("Name", style, node);
+                this.writeNode("Title", style, node);
+                if (style.legend) {
+                    this.writeNode("LegendURL", style, node);
+                }
+                return node;
+            },
+            "Name": function(obj) {
+                var node = this.createElementNSPlus("Name", {
+                    value: obj.name });
+                return node;
+            },
+            "Title": function(obj) {
+                var node = this.createElementNSPlus("Title", {
+                    value: obj.title });
+                return node;
+            },
+            "LegendURL": function(style) {
+                var node = this.createElementNSPlus("LegendURL");
+                this.writeNode("OnlineResource", style.legend, node);
+                return node;
+            },
+            "_WMS": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: layer.params.LAYERS,
+                    queryable: layer.queryable ? "1" : "0",
+                    hidden: layer.visibility ? "0" : "1",
+                    opacity: layer.opacity ? layer.opacity: null}
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("ows:OutputFormat", layer.params.FORMAT, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.WMS,
+                    version: layer.params.VERSION, url: layer.url}, node);
+                if (layer.metadata.styles && layer.metadata.styles.length > 0) {
+                    this.writeNode("StyleList", layer.metadata.styles, node);
+                }
+                return node;
+            },
+            "_Layer": function(options) {
+                var layer, subPaths, node, title;
+                layer = options.layer;
+                subPaths = options.subPaths;
+                node = null;
+                title = null;
+                // subPaths is an array of an array
+                // recursively calling _Layer writer eats up subPaths, until a 
+                // real writer is called and nodes are returned.
+                if(subPaths.length > 0){
+                    var path = subPaths[0].join("/");
+                    var index = path.lastIndexOf("/");
+                    node = this.nestingLayerLookup[path];
+                    title = (index > 0)?path.substring(index + 1, path.length):path;
+                    if(!node){
+                        // category layer
+                        node = this.createElementNSPlus("Layer");
+                        this.writeNode("ows:Title", title, node);
+                        this.nestingLayerLookup[path] = node;
+                    }
+                    options.subPaths.shift();//remove a path after each call
+                    this.writeNode("_Layer", options, node);
+                    return node;
+                } else {
+                    // write out the actual layer
+                    if (layer instanceof OpenLayers.Layer.WMS) {
+                        node = this.writeNode("_WMS", layer);
+                    } else if (layer instanceof OpenLayers.Layer.Vector) {
+                        if (layer.protocol instanceof OpenLayers.Protocol.WFS.v1) {
+                            node = this.writeNode("_WFS", layer);
+                        } else if (layer.protocol instanceof OpenLayers.Protocol.HTTP) {
+                            if (layer.protocol.format instanceof OpenLayers.Format.GML) {
+                                layer.protocol.format.version = "2.1.2";
+                                node = this.writeNode("_GML", layer);
+                            } else if (layer.protocol.format instanceof OpenLayers.Format.KML) {
+                                layer.protocol.format.version = "2.2";
+                                node = this.writeNode("_KML", layer);
+                            }
+                        } else {
+                            // write out as inline GML since we have no idea
+                            // about the original Format
+                            this.setNamespace("feature", this.featureNS);
+                            node = this.writeNode("_InlineGeometry", layer);
+                        }
+                    }
+                    if (layer.options.maxScale) {
+                        this.writeNode("sld:MinScaleDenominator", 
+                            layer.options.maxScale, node);
+                    }
+                    if (layer.options.minScale) {
+                        this.writeNode("sld:MaxScaleDenominator", 
+                            layer.options.minScale, node);
+                    }
+                    this.nestingLayerLookup[layer.name] = node;
+                    return node;
+                }
+            },
+            "_WFS": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: layer.protocol.featurePrefix + ":" + layer.protocol.featureType,
+                    hidden: layer.visibility ? "0" : "1" }
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.WFS, 
+                    version: layer.protocol.version, 
+                    url: layer.protocol.url}, node);
+                return node;
+            },
+            "_InlineGeometry": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: this.featureType,
+                    hidden: layer.visibility ? "0" : "1" }
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("InlineGeometry", layer, node);
+                return node;
+            },
+            "_GML": function(layer) {
+                var node = this.createElementNSPlus("Layer");
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.GML, 
+                    url: layer.protocol.url, version: 
+                    layer.protocol.format.version}, node);
+                return node;
+            },
+            "_KML": function(layer) {
+                var node = this.createElementNSPlus("Layer");
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.KML,
+                    version: layer.protocol.format.version, url: 
+                    layer.protocol.url}, node);
+                return node;
+            }
+        },
+        "gml": OpenLayers.Util.applyDefaults({
+            "boundedBy": function(bounds) {
+                var node = this.createElementNSPlus("gml:boundedBy");
+                this.writeNode("gml:Box", bounds, node);
+                return node;
+            }
+        }, OpenLayers.Format.GML.v2.prototype.writers.gml),
+        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,
+        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,
+        "feature": OpenLayers.Format.GML.v2.prototype.writers.feature
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OWSContext.v0_3_1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/CSWGetRecords.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetRecords
+ * Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetRecords format of the given version.
+ */
+OpenLayers.Format.CSWGetRecords = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Format.CSWGetRecords.DEFAULTS
+    );
+    var cls = OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported CSWGetRecords version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: DEFAULTS
+ * {Object} Default properties for the CSWGetRecords format.
+ */
+OpenLayers.Format.CSWGetRecords.DEFAULTS = {
+    "version": "2.0.2"
+};
+/* ======================================================================
+    OpenLayers/Control.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Control
+ * Controls affect the display or behavior of the map. They allow everything
+ * from panning and zooming to displaying a scale indicator. Controls by 
+ * default are added to the map they are contained within however it is
+ * possible to add a control to an external div by passing the div in the
+ * options parameter.
+ * 
+ * Example:
+ * The following example shows how to add many of the common controls
+ * to a map.
+ * 
+ * > var map = new OpenLayers.Map('map', { controls: [] });
+ * >
+ * > map.addControl(new OpenLayers.Control.PanZoomBar());
+ * > map.addControl(new OpenLayers.Control.MouseToolbar());
+ * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
+ * > map.addControl(new OpenLayers.Control.Permalink());
+ * > map.addControl(new OpenLayers.Control.Permalink('permalink'));
+ * > map.addControl(new OpenLayers.Control.MousePosition());
+ * > map.addControl(new OpenLayers.Control.OverviewMap());
+ * > map.addControl(new OpenLayers.Control.KeyboardDefaults());
+ *
+ * The next code fragment is a quick example of how to intercept 
+ * shift-mouse click to display the extent of the bounding box
+ * dragged out by the user.  Usually controls are not created
+ * in exactly this manner.  See the source for a more complete 
+ * example:
+ *
+ * > var control = new OpenLayers.Control();
+ * > OpenLayers.Util.extend(control, {
+ * >     draw: function () {
+ * >         // this Handler.Box will intercept the shift-mousedown
+ * >         // before Control.MouseDefault gets to see it
+ * >         this.box = new OpenLayers.Handler.Box( control, 
+ * >             {"done": this.notice},
+ * >             {keyMask: OpenLayers.Handler.MOD_SHIFT});
+ * >         this.box.activate();
+ * >     },
+ * >
+ * >     notice: function (bounds) {
+ * >         OpenLayers.Console.userError(bounds);
+ * >     }
+ * > }); 
+ * > map.addControl(control);
+ * 
+ */
+OpenLayers.Control = OpenLayers.Class({
+
+    /** 
+     * Property: id 
+     * {String} 
+     */
+    id: null,
+    
+    /** 
+     * Property: map 
+     * {<OpenLayers.Map>} this gets set in the addControl() function in
+     * OpenLayers.Map 
+     */
+    map: null,
+
+    /** 
+     * APIProperty: div 
+     * {DOMElement} The element that contains the control, if not present the 
+     *     control is placed inside the map.
+     */
+    div: null,
+
+    /** 
+     * APIProperty: type 
+     * {Number} Controls can have a 'type'. The type determines the type of
+     * interactions which are possible with them when they are placed in an
+     * <OpenLayers.Control.Panel>. 
+     */
+    type: null, 
+
+    /** 
+     * Property: allowSelection
+     * {Boolean} By deafault, controls do not allow selection, because
+     * it may interfere with map dragging. If this is true, OpenLayers
+     * will not prevent selection of the control.
+     * Default is false.
+     */
+    allowSelection: false,  
+
+    /** 
+     * Property: displayClass 
+     * {string}  This property is used for CSS related to the drawing of the
+     * Control. 
+     */
+    displayClass: "",
+    
+    /**
+    * APIProperty: title  
+    * {string}  This property is used for showing a tooltip over the  
+    * Control.  
+    */ 
+    title: "",
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     false.
+     */
+    autoActivate: false,
+
+    /** 
+     * APIProperty: active 
+     * {Boolean} The control is active (read-only).  Use <activate> and 
+     *     <deactivate> to change control state.
+     */
+    active: null,
+
+    /** 
+     * Property: handler 
+     * {<OpenLayers.Handler>} null
+     */
+    handler: null,
+
+    /**
+     * APIProperty: eventListeners
+     * {Object} If set as an option at construction, the eventListeners
+     *     object will be registered with <OpenLayers.Events.on>.  Object
+     *     structure must be a listeners object as shown in the example for
+     *     the events.on method.
+     */
+    eventListeners: null,
+
+    /** 
+     * APIProperty: events
+     * {<OpenLayers.Events>} Events instance for listeners and triggering
+     *     control specific events.
+     */
+    events: null,
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * All event objects have at least the following properties:
+     * object - {Object} A reference to control.events.object (a reference
+     *      to the control).
+     * element - {DOMElement} A reference to control.events.element (which
+     *      will be null unless documented otherwise).
+     *
+     * Supported map event types:
+     * activate - Triggered when activated.
+     * deactivate - Triggered when deactivated.
+     */
+    EVENT_TYPES: ["activate", "deactivate"],
+
+    /**
+     * Constructor: OpenLayers.Control
+     * Create an OpenLayers Control.  The options passed as a parameter
+     * directly extend the control.  For example passing the following:
+     * 
+     * > var control = new OpenLayers.Control({div: myDiv});
+     *
+     * Overrides the default div attribute value of null.
+     * 
+     * Parameters:
+     * options - {Object} 
+     */
+    initialize: function (options) {
+        // We do this before the extend so that instances can override
+        // className in options.
+        this.displayClass = 
+            this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
+        
+        OpenLayers.Util.extend(this, options);
+        
+        this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
+        if(this.eventListeners instanceof Object) {
+            this.events.on(this.eventListeners);
+        }
+        if (this.id == null) {
+            this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+        }
+    },
+
+    /**
+     * Method: destroy
+     * The destroy method is used to perform any clean up before the control
+     * is dereferenced.  Typically this is where event listeners are removed
+     * to prevent memory leaks.
+     */
+    destroy: function () {
+        if(this.events) {
+            if(this.eventListeners) {
+                this.events.un(this.eventListeners);
+            }
+            this.events.destroy();
+            this.events = null;
+        }
+        this.eventListeners = null;
+
+        // eliminate circular references
+        if (this.handler) {
+            this.handler.destroy();
+            this.handler = null;
+        }
+        if(this.handlers) {
+            for(var key in this.handlers) {
+                if(this.handlers.hasOwnProperty(key) &&
+                   typeof this.handlers[key].destroy == "function") {
+                    this.handlers[key].destroy();
+                }
+            }
+            this.handlers = null;
+        }
+        if (this.map) {
+            this.map.removeControl(this);
+            this.map = null;
+        }
+        this.div = null;
+    },
+
+    /** 
+     * Method: setMap
+     * Set the map property for the control. This is done through an accessor
+     * so that subclasses can override this and take special action once 
+     * they have their map variable set. 
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        this.map = map;
+        if (this.handler) {
+            this.handler.setMap(map);
+        }
+    },
+  
+    /**
+     * Method: draw
+     * The draw method is called when the control is ready to be displayed
+     * on the page.  If a div has not been created one is created.  Controls
+     * with a visual component will almost always want to override this method 
+     * to customize the look of control. 
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} The top-left pixel position of the control
+     *      or null.
+     *
+     * Returns:
+     * {DOMElement} A reference to the DIV DOMElement containing the control
+     */
+    draw: function (px) {
+        if (this.div == null) {
+            this.div = OpenLayers.Util.createDiv(this.id);
+            this.div.className = this.displayClass;
+            if (!this.allowSelection) {
+                this.div.className += " olControlNoSelect";
+                this.div.setAttribute("unselectable", "on", 0);
+                this.div.onselectstart = OpenLayers.Function.False; 
+            }    
+            if (this.title != "") {
+                this.div.title = this.title;
+            }
+        }
+        if (px != null) {
+            this.position = px.clone();
+        }
+        this.moveTo(this.position);
+        return this.div;
+    },
+
+    /**
+     * Method: moveTo
+     * Sets the left and top style attributes to the passed in pixel 
+     * coordinates.
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     */
+    moveTo: function (px) {
+        if ((px != null) && (this.div != null)) {
+            this.div.style.left = px.x + "px";
+            this.div.style.top = px.y + "px";
+        }
+    },
+
+    /**
+     * APIMethod: activate
+     * Explicitly activates a control and it's associated
+     * handler if one has been set.  Controls can be
+     * deactivated by calling the deactivate() method.
+     * 
+     * Returns:
+     * {Boolean}  True if the control was successfully activated or
+     *            false if the control was already active.
+     */
+    activate: function () {
+        if (this.active) {
+            return false;
+        }
+        if (this.handler) {
+            this.handler.activate();
+        }
+        this.active = true;
+        if(this.map) {
+            OpenLayers.Element.addClass(
+                this.map.viewPortDiv,
+                this.displayClass.replace(/ /g, "") + "Active"
+            );
+        }
+        this.events.triggerEvent("activate");
+        return true;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivates a control and it's associated handler if any.  The exact
+     * effect of this depends on the control itself.
+     * 
+     * Returns:
+     * {Boolean} True if the control was effectively deactivated or false
+     *           if the control was already inactive.
+     */
+    deactivate: function () {
+        if (this.active) {
+            if (this.handler) {
+                this.handler.deactivate();
+            }
+            this.active = false;
+            if(this.map) {
+                OpenLayers.Element.removeClass(
+                    this.map.viewPortDiv,
+                    this.displayClass.replace(/ /g, "") + "Active"
+                );
+            }
+            this.events.triggerEvent("deactivate");
+            return true;
+        }
+        return false;
+    },
+
+    CLASS_NAME: "OpenLayers.Control"
+});
+
+/**
+ * Constant: OpenLayers.Control.TYPE_BUTTON
+ */
+OpenLayers.Control.TYPE_BUTTON = 1;
+
+/**
+ * Constant: OpenLayers.Control.TYPE_TOGGLE
+ */
+OpenLayers.Control.TYPE_TOGGLE = 2;
+
+/**
+ * Constant: OpenLayers.Control.TYPE_TOOL
+ */
+OpenLayers.Control.TYPE_TOOL   = 3;
+/* ======================================================================
+    OpenLayers/Control/OverviewMap.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/** 
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/BaseTypes.js
+ * @requires OpenLayers/Events.js
+ */
+
+/**
+ * Class: OpenLayers.Control.OverviewMap
+ * The OverMap control creates a small overview map, useful to display the 
+ * extent of a zoomed map and your main map and provide additional 
+ * navigation options to the User.  By default the overview map is drawn in
+ * the lower right corner of the main map. Create a new overview map with the
+ * <OpenLayers.Control.OverviewMap> constructor.
+ *
+ * Inerits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: element
+     * {DOMElement} The DOM element that contains the overview map
+     */
+    element: null,
+    
+    /**
+     * APIProperty: ovmap
+     * {<OpenLayers.Map>} A reference to the overview map itself.
+     */
+    ovmap: null,
+
+    /**
+     * APIProperty: size
+     * {<OpenLayers.Size>} The overvew map size in pixels.  Note that this is
+     * the size of the map itself - the element that contains the map (default
+     * class name olControlOverviewMapElement) may have padding or other style
+     * attributes added via CSS.
+     */
+    size: new OpenLayers.Size(180, 90),
+
+    /**
+     * APIProperty: layers
+     * {Array(<OpenLayers.Layer>)} Ordered list of layers in the overview map.
+     * If none are sent at construction, the base layer for the main map is used.
+     */
+    layers: null,
+    
+    /**
+     * APIProperty: minRectSize
+     * {Integer} The minimum width or height (in pixels) of the extent
+     *     rectangle on the overview map.  When the extent rectangle reaches
+     *     this size, it will be replaced depending on the value of the
+     *     <minRectDisplayClass> property.  Default is 15 pixels.
+     */
+    minRectSize: 15,
+    
+    /**
+     * APIProperty: minRectDisplayClass
+     * {String} Replacement style class name for the extent rectangle when
+     *     <minRectSize> is reached.  This string will be suffixed on to the
+     *     displayClass.  Default is "RectReplacement".
+     *
+     * Example CSS declaration:
+     * (code)
+     * .olControlOverviewMapRectReplacement {
+     *     overflow: hidden;
+     *     cursor: move;
+     *     background-image: url("img/overview_replacement.gif");
+     *     background-repeat: no-repeat;
+     *     background-position: center;
+     * }
+     * (end)
+     */
+    minRectDisplayClass: "RectReplacement",
+
+    /**
+     * APIProperty: minRatio
+     * {Float} The ratio of the overview map resolution to the main map
+     *     resolution at which to zoom farther out on the overview map.
+     */
+    minRatio: 8,
+
+    /**
+     * APIProperty: maxRatio
+     * {Float} The ratio of the overview map resolution to the main map
+     *     resolution at which to zoom farther in on the overview map.
+     */
+    maxRatio: 32,
+    
+    /**
+     * APIProperty: mapOptions
+     * {Object} An object containing any non-default properties to be sent to
+     *     the overview map's map constructor.  These should include any
+     *     non-default options that the main map was constructed with.
+     */
+    mapOptions: null,
+
+    /**
+     * APIProperty: autoPan
+     * {Boolean} Always pan the overview map, so the extent marker remains in
+     *     the center.  Default is false.  If true, when you drag the extent
+     *     marker, the overview map will update itself so the marker returns
+     *     to the center.
+     */
+    autoPan: false,
+    
+    /**
+     * Property: handlers
+     * {Object}
+     */
+    handlers: null,
+
+    /**
+     * Property: resolutionFactor
+     * {Object}
+     */
+    resolutionFactor: 1,
+
+    /**
+     * APIProperty: maximized
+     * {Boolean} Start as maximized (visible). Defaults to false.
+     */
+    maximized: false,
+
+    /**
+     * Constructor: OpenLayers.Control.OverviewMap
+     * Create a new overview map
+     *
+     * Parameters:
+     * object - {Object} Properties of this object will be set on the overview
+     * map object.  Note, to set options on the map object contained in this
+     * control, set <mapOptions> as one of the options properties.
+     */
+    initialize: function(options) {
+        this.layers = [];
+        this.handlers = {};
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Deconstruct the control
+     */
+    destroy: function() {
+        if (!this.mapDiv) { // we've already been destroyed
+            return;
+        }
+        if (this.handlers.click) {
+            this.handlers.click.destroy();
+        }
+        if (this.handlers.drag) {
+            this.handlers.drag.destroy();
+        }
+
+        this.ovmap && this.ovmap.eventsDiv.removeChild(this.extentRectangle);
+        this.extentRectangle = null;
+
+        if (this.rectEvents) {
+            this.rectEvents.destroy();
+            this.rectEvents = null;
+        }
+
+        if (this.ovmap) {
+            this.ovmap.destroy();
+            this.ovmap = null;
+        }
+        
+        this.element.removeChild(this.mapDiv);
+        this.mapDiv = null;
+
+        this.div.removeChild(this.element);
+        this.element = null;
+
+        if (this.maximizeDiv) {
+            OpenLayers.Event.stopObservingElement(this.maximizeDiv);
+            this.div.removeChild(this.maximizeDiv);
+            this.maximizeDiv = null;
+        }
+        
+        if (this.minimizeDiv) {
+            OpenLayers.Event.stopObservingElement(this.minimizeDiv);
+            this.div.removeChild(this.minimizeDiv);
+            this.minimizeDiv = null;
+        }
+
+        this.map.events.un({
+            "moveend": this.update,
+            "changebaselayer": this.baseLayerDraw,
+            scope: this
+        });
+
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);    
+    },
+
+    /**
+     * Method: draw
+     * Render the control in the browser.
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        if(!(this.layers.length > 0)) {
+            if (this.map.baseLayer) {
+                var layer = this.map.baseLayer.clone();
+                this.layers = [layer];
+            } else {
+                this.map.events.register("changebaselayer", this, this.baseLayerDraw);
+                return this.div;
+            }
+        }
+
+        // create overview map DOM elements
+        this.element = document.createElement('div');
+        this.element.className = this.displayClass + 'Element';
+        this.element.style.display = 'none';
+
+        this.mapDiv = document.createElement('div');
+        this.mapDiv.style.width = this.size.w + 'px';
+        this.mapDiv.style.height = this.size.h + 'px';
+        this.mapDiv.style.position = 'relative';
+        this.mapDiv.style.overflow = 'hidden';
+        this.mapDiv.id = OpenLayers.Util.createUniqueID('overviewMap');
+        
+        this.extentRectangle = document.createElement('div');
+        this.extentRectangle.style.position = 'absolute';
+        this.extentRectangle.style.zIndex = 1000;  //HACK
+        this.extentRectangle.className = this.displayClass+'ExtentRectangle';
+
+        this.element.appendChild(this.mapDiv);  
+
+        this.div.appendChild(this.element);
+
+        // Optionally add min/max buttons if the control will go in the
+        // map viewport.
+        if(!this.outsideViewport) {
+            this.div.className += " " + this.displayClass + 'Container';
+            var imgLocation = OpenLayers.Util.getImagesLocation();
+            // maximize button div
+            var img = imgLocation + 'layer-switcher-maximize.png';
+            this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
+                                        this.displayClass + 'MaximizeButton', 
+                                        null, 
+                                        new OpenLayers.Size(18,18), 
+                                        img, 
+                                        'absolute');
+            this.maximizeDiv.style.display = 'none';
+            this.maximizeDiv.className = this.displayClass + 'MaximizeButton';
+            OpenLayers.Event.observe(this.maximizeDiv, 'click', 
+                OpenLayers.Function.bindAsEventListener(this.maximizeControl,
+                                                        this)
+            );
+            this.div.appendChild(this.maximizeDiv);
+    
+            // minimize button div
+            var img = imgLocation + 'layer-switcher-minimize.png';
+            this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
+                                        'OpenLayers_Control_minimizeDiv', 
+                                        null, 
+                                        new OpenLayers.Size(18,18), 
+                                        img, 
+                                        'absolute');
+            this.minimizeDiv.style.display = 'none';
+            this.minimizeDiv.className = this.displayClass + 'MinimizeButton';
+            OpenLayers.Event.observe(this.minimizeDiv, 'click', 
+                OpenLayers.Function.bindAsEventListener(this.minimizeControl,
+                                                        this)
+            );
+            this.div.appendChild(this.minimizeDiv);
+            
+            var eventsToStop = ['dblclick','mousedown'];
+            
+            for (var i=0, len=eventsToStop.length; i<len; i++) {
+
+                OpenLayers.Event.observe(this.maximizeDiv, 
+                                         eventsToStop[i], 
+                                         OpenLayers.Event.stop);
+
+                OpenLayers.Event.observe(this.minimizeDiv,
+                                         eventsToStop[i], 
+                                         OpenLayers.Event.stop);
+            }
+            
+            this.minimizeControl();
+        } else {
+            // show the overview map
+            this.element.style.display = '';
+        }
+        if(this.map.getExtent()) {
+            this.update();
+        }
+        
+        this.map.events.register('moveend', this, this.update);
+        
+        if (this.maximized) {
+            this.maximizeControl();
+        }
+        return this.div;
+    },
+    
+    /**
+     * Method: baseLayerDraw
+     * Draw the base layer - called if unable to complete in the initial draw
+     */
+    baseLayerDraw: function() {
+        this.draw();
+        this.map.events.unregister("changebaselayer", this, this.baseLayerDraw);
+    },
+
+    /**
+     * Method: rectDrag
+     * Handle extent rectangle drag
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} The pixel location of the drag.
+     */
+    rectDrag: function(px) {
+        var deltaX = this.handlers.drag.last.x - px.x;
+        var deltaY = this.handlers.drag.last.y - px.y;
+        if(deltaX != 0 || deltaY != 0) {
+            var rectTop = this.rectPxBounds.top;
+            var rectLeft = this.rectPxBounds.left;
+            var rectHeight = Math.abs(this.rectPxBounds.getHeight());
+            var rectWidth = this.rectPxBounds.getWidth();
+            // don't allow dragging off of parent element
+            var newTop = Math.max(0, (rectTop - deltaY));
+            newTop = Math.min(newTop,
+                              this.ovmap.size.h - this.hComp - rectHeight);
+            var newLeft = Math.max(0, (rectLeft - deltaX));
+            newLeft = Math.min(newLeft,
+                               this.ovmap.size.w - this.wComp - rectWidth);
+            this.setRectPxBounds(new OpenLayers.Bounds(newLeft,
+                                                       newTop + rectHeight,
+                                                       newLeft + rectWidth,
+                                                       newTop));
+        }
+    },
+    
+    /**
+     * Method: mapDivClick
+     * Handle browser events
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} evt
+     */
+    mapDivClick: function(evt) {
+        var pxCenter = this.rectPxBounds.getCenterPixel();
+        var deltaX = evt.xy.x - pxCenter.x;
+        var deltaY = evt.xy.y - pxCenter.y;
+        var top = this.rectPxBounds.top;
+        var left = this.rectPxBounds.left;
+        var height = Math.abs(this.rectPxBounds.getHeight());
+        var width = this.rectPxBounds.getWidth();
+        var newTop = Math.max(0, (top + deltaY));
+        newTop = Math.min(newTop, this.ovmap.size.h - height);
+        var newLeft = Math.max(0, (left + deltaX));
+        newLeft = Math.min(newLeft, this.ovmap.size.w - width);
+        this.setRectPxBounds(new OpenLayers.Bounds(newLeft,
+                                                   newTop + height,
+                                                   newLeft + width,
+                                                   newTop));
+        this.updateMapToRect();
+    },
+
+    /**
+     * Method: maximizeControl
+     * Unhide the control.  Called when the control is in the map viewport.
+     *
+     * Parameters:
+     * e - {<OpenLayers.Event>}
+     */
+    maximizeControl: function(e) {
+        this.element.style.display = '';
+        this.showToggle(false);
+        if (e != null) {
+            OpenLayers.Event.stop(e);                                            
+        }
+    },
+
+    /**
+     * Method: minimizeControl
+     * Hide all the contents of the control, shrink the size, 
+     * add the maximize icon
+     * 
+     * Parameters:
+     * e - {<OpenLayers.Event>}
+     */
+    minimizeControl: function(e) {
+        this.element.style.display = 'none';
+        this.showToggle(true);
+        if (e != null) {
+            OpenLayers.Event.stop(e);                                            
+        }
+    },
+
+    /**
+     * Method: showToggle
+     * Hide/Show the toggle depending on whether the control is minimized
+     *
+     * Parameters:
+     * minimize - {Boolean} 
+     */
+    showToggle: function(minimize) {
+        this.maximizeDiv.style.display = minimize ? '' : 'none';
+        this.minimizeDiv.style.display = minimize ? 'none' : '';
+    },
+
+    /**
+     * Method: update
+     * Update the overview map after layers move.
+     */
+    update: function() {
+        if(this.ovmap == null) {
+            this.createMap();
+        }
+        
+        if(this.autoPan || !this.isSuitableOverview()) {
+            this.updateOverview();
+        }
+        
+        // update extent rectangle
+        this.updateRectToMap();
+    },
+    
+    /**
+     * Method: isSuitableOverview
+     * Determines if the overview map is suitable given the extent and
+     * resolution of the main map.
+     */
+    isSuitableOverview: function() {
+        var mapExtent = this.map.getExtent();
+        var maxExtent = this.map.maxExtent;
+        var testExtent = new OpenLayers.Bounds(
+                                Math.max(mapExtent.left, maxExtent.left),
+                                Math.max(mapExtent.bottom, maxExtent.bottom),
+                                Math.min(mapExtent.right, maxExtent.right),
+                                Math.min(mapExtent.top, maxExtent.top));        
+
+        if (this.ovmap.getProjection() != this.map.getProjection()) {
+            testExtent = testExtent.transform(
+                this.map.getProjectionObject(),
+                this.ovmap.getProjectionObject() );
+        }
+
+        var resRatio = this.ovmap.getResolution() / this.map.getResolution();
+        return ((resRatio > this.minRatio) &&
+                (resRatio <= this.maxRatio) &&
+                (this.ovmap.getExtent().containsBounds(testExtent)));
+    },
+    
+    /**
+     * Method updateOverview
+     * Called by <update> if <isSuitableOverview> returns true
+     */
+    updateOverview: function() {
+        var mapRes = this.map.getResolution();
+        var targetRes = this.ovmap.getResolution();
+        var resRatio = targetRes / mapRes;
+        if(resRatio > this.maxRatio) {
+            // zoom in overview map
+            targetRes = this.minRatio * mapRes;            
+        } else if(resRatio <= this.minRatio) {
+            // zoom out overview map
+            targetRes = this.maxRatio * mapRes;
+        }
+        var center;
+        if (this.ovmap.getProjection() != this.map.getProjection()) {
+            center = this.map.center.clone();
+            center.transform(this.map.getProjectionObject(),
+                this.ovmap.getProjectionObject() );
+        } else {
+            center = this.map.center;
+        }
+        this.ovmap.setCenter(center, this.ovmap.getZoomForResolution(
+            targetRes * this.resolutionFactor));
+        this.updateRectToMap();
+    },
+    
+    /**
+     * Method: createMap
+     * Construct the map that this control contains
+     */
+    createMap: function() {
+        // create the overview map
+        var options = OpenLayers.Util.extend(
+                        {controls: [], maxResolution: 'auto', 
+                         fallThrough: false}, this.mapOptions);
+        this.ovmap = new OpenLayers.Map(this.mapDiv, options);
+        this.ovmap.eventsDiv.appendChild(this.extentRectangle);
+        
+        // prevent ovmap from being destroyed when the page unloads, because
+        // the OverviewMap control has to do this (and does it).
+        OpenLayers.Event.stopObserving(window, 'unload', this.ovmap.unloadDestroy);
+        
+        this.ovmap.addLayers(this.layers);
+        this.ovmap.zoomToMaxExtent();
+        // check extent rectangle border width
+        this.wComp = parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
+                                               'border-left-width')) +
+                     parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
+                                               'border-right-width'));
+        this.wComp = (this.wComp) ? this.wComp : 2;
+        this.hComp = parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
+                                               'border-top-width')) +
+                     parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
+                                               'border-bottom-width'));
+        this.hComp = (this.hComp) ? this.hComp : 2;
+
+        this.handlers.drag = new OpenLayers.Handler.Drag(
+            this, {move: this.rectDrag, done: this.updateMapToRect},
+            {map: this.ovmap}
+        );
+        this.handlers.click = new OpenLayers.Handler.Click(
+            this, {
+                "click": this.mapDivClick
+            },{
+                "single": true, "double": false,
+                "stopSingle": true, "stopDouble": true,
+                "pixelTolerance": 1,
+                map: this.ovmap
+            }
+        );
+        this.handlers.click.activate();
+        
+        this.rectEvents = new OpenLayers.Events(this, this.extentRectangle,
+                                                null, true);
+        this.rectEvents.register("mouseover", this, function(e) {
+            if(!this.handlers.drag.active && !this.map.dragging) {
+                this.handlers.drag.activate();
+            }
+        });
+        this.rectEvents.register("mouseout", this, function(e) {
+            if(!this.handlers.drag.dragging) {
+                this.handlers.drag.deactivate();
+            }
+        });
+
+        if (this.ovmap.getProjection() != this.map.getProjection()) {
+            var sourceUnits = this.map.getProjectionObject().getUnits() ||
+                this.map.units || this.map.baseLayer.units;
+            var targetUnits = this.ovmap.getProjectionObject().getUnits() ||
+                this.ovmap.units || this.ovmap.baseLayer.units;
+            this.resolutionFactor = sourceUnits && targetUnits ?
+                OpenLayers.INCHES_PER_UNIT[sourceUnits] /
+                OpenLayers.INCHES_PER_UNIT[targetUnits] : 1;
+        }
+    },
+        
+    /**
+     * Method: updateRectToMap
+     * Updates the extent rectangle position and size to match the map extent
+     */
+    updateRectToMap: function() {
+        // If the projections differ we need to reproject
+        var bounds;
+        if (this.ovmap.getProjection() != this.map.getProjection()) {
+            bounds = this.map.getExtent().transform(
+                this.map.getProjectionObject(), 
+                this.ovmap.getProjectionObject() );
+        } else {
+            bounds = this.map.getExtent();
+        }
+        var pxBounds = this.getRectBoundsFromMapBounds(bounds);
+        if (pxBounds) {
+            this.setRectPxBounds(pxBounds);
+        }
+    },
+    
+    /**
+     * Method: updateMapToRect
+     * Updates the map extent to match the extent rectangle position and size
+     */
+    updateMapToRect: function() {
+        var lonLatBounds = this.getMapBoundsFromRectBounds(this.rectPxBounds);
+        if (this.ovmap.getProjection() != this.map.getProjection()) {
+            lonLatBounds = lonLatBounds.transform(
+                this.ovmap.getProjectionObject(),
+                this.map.getProjectionObject() );
+        }
+        this.map.panTo(lonLatBounds.getCenterLonLat());
+    },
+
+    /**
+     * Method: setRectPxBounds
+     * Set extent rectangle pixel bounds.
+     *
+     * Parameters:
+     * pxBounds - {<OpenLayers.Bounds>}
+     */
+    setRectPxBounds: function(pxBounds) {
+        var top = Math.max(pxBounds.top, 0);
+        var left = Math.max(pxBounds.left, 0);
+        var bottom = Math.min(pxBounds.top + Math.abs(pxBounds.getHeight()),
+                              this.ovmap.size.h - this.hComp);
+        var right = Math.min(pxBounds.left + pxBounds.getWidth(),
+                             this.ovmap.size.w - this.wComp);
+        var width = Math.max(right - left, 0);
+        var height = Math.max(bottom - top, 0);
+        if(width < this.minRectSize || height < this.minRectSize) {
+            this.extentRectangle.className = this.displayClass +
+                                             this.minRectDisplayClass;
+            var rLeft = left + (width / 2) - (this.minRectSize / 2);
+            var rTop = top + (height / 2) - (this.minRectSize / 2);
+            this.extentRectangle.style.top = Math.round(rTop) + 'px';
+            this.extentRectangle.style.left = Math.round(rLeft) + 'px';
+            this.extentRectangle.style.height = this.minRectSize + 'px';
+            this.extentRectangle.style.width = this.minRectSize + 'px';
+        } else {
+            this.extentRectangle.className = this.displayClass +
+                                             'ExtentRectangle';
+            this.extentRectangle.style.top = Math.round(top) + 'px';
+            this.extentRectangle.style.left = Math.round(left) + 'px';
+            this.extentRectangle.style.height = Math.round(height) + 'px';
+            this.extentRectangle.style.width = Math.round(width) + 'px';
+        }
+        this.rectPxBounds = new OpenLayers.Bounds(
+            Math.round(left), Math.round(bottom),
+            Math.round(right), Math.round(top)
+        );
+    },
+
+    /**
+     * Method: getRectBoundsFromMapBounds
+     * Get the rect bounds from the map bounds.
+     *
+     * Parameters:
+     * lonLatBounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>}A bounds which is the passed-in map lon/lat extent
+     * translated into pixel bounds for the overview map
+     */
+    getRectBoundsFromMapBounds: function(lonLatBounds) {
+        var leftBottomLonLat = new OpenLayers.LonLat(lonLatBounds.left,
+                                                     lonLatBounds.bottom);
+        var rightTopLonLat = new OpenLayers.LonLat(lonLatBounds.right,
+                                                   lonLatBounds.top);
+        var leftBottomPx = this.getOverviewPxFromLonLat(leftBottomLonLat);
+        var rightTopPx = this.getOverviewPxFromLonLat(rightTopLonLat);
+        var bounds = null;
+        if (leftBottomPx && rightTopPx) {
+            bounds = new OpenLayers.Bounds(leftBottomPx.x, leftBottomPx.y,
+                                           rightTopPx.x, rightTopPx.y);
+        }
+        return bounds;
+    },
+
+    /**
+     * Method: getMapBoundsFromRectBounds
+     * Get the map bounds from the rect bounds.
+     *
+     * Parameters:
+     * pxBounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} Bounds which is the passed-in overview rect bounds
+     * translated into lon/lat bounds for the overview map
+     */
+    getMapBoundsFromRectBounds: function(pxBounds) {
+        var leftBottomPx = new OpenLayers.Pixel(pxBounds.left,
+                                                pxBounds.bottom);
+        var rightTopPx = new OpenLayers.Pixel(pxBounds.right,
+                                              pxBounds.top);
+        var leftBottomLonLat = this.getLonLatFromOverviewPx(leftBottomPx);
+        var rightTopLonLat = this.getLonLatFromOverviewPx(rightTopPx);
+        return new OpenLayers.Bounds(leftBottomLonLat.lon, leftBottomLonLat.lat,
+                                     rightTopLonLat.lon, rightTopLonLat.lat);
+    },
+
+    /**
+     * Method: getLonLatFromOverviewPx
+     * Get a map location from a pixel location
+     *
+     * Parameters:
+     * overviewMapPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} Location which is the passed-in overview map
+     * OpenLayers.Pixel, translated into lon/lat by the overview map
+     */
+    getLonLatFromOverviewPx: function(overviewMapPx) {
+        var size = this.ovmap.size;
+        var res  = this.ovmap.getResolution();
+        var center = this.ovmap.getExtent().getCenterLonLat();
+    
+        var delta_x = overviewMapPx.x - (size.w / 2);
+        var delta_y = overviewMapPx.y - (size.h / 2);
+        
+        return new OpenLayers.LonLat(center.lon + delta_x * res ,
+                                     center.lat - delta_y * res); 
+    },
+
+    /**
+     * Method: getOverviewPxFromLonLat
+     * Get a pixel location from a map location
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} Location which is the passed-in OpenLayers.LonLat, 
+     * translated into overview map pixels
+     */
+    getOverviewPxFromLonLat: function(lonlat) {
+        var res  = this.ovmap.getResolution();
+        var extent = this.ovmap.getExtent();
+        var px = null;
+        if (extent) {
+            px = new OpenLayers.Pixel(
+                        Math.round(1/res * (lonlat.lon - extent.left)),
+                        Math.round(1/res * (extent.top - lonlat.lat)));
+        } 
+        return px;
+    },
+
+    CLASS_NAME: 'OpenLayers.Control.OverviewMap'
+});
+/* ======================================================================
+    OpenLayers/Tween.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Namespace: OpenLayers.Tween
+ */
+OpenLayers.Tween = OpenLayers.Class({
+    
+    /**
+     * Constant: INTERVAL
+     * {int} Interval in milliseconds between 2 steps
+     */
+    INTERVAL: 10,
+    
+    /**
+     * APIProperty: easing
+     * {<OpenLayers.Easing>(Function)} Easing equation used for the animation
+     *     Defaultly set to OpenLayers.Easing.Expo.easeOut
+     */
+    easing: null,
+    
+    /**
+     * APIProperty: begin
+     * {Object} Values to start the animation with
+     */
+    begin: null,
+    
+    /**
+     * APIProperty: finish
+     * {Object} Values to finish the animation with
+     */
+    finish: null,
+    
+    /**
+     * APIProperty: duration
+     * {int} duration of the tween (number of steps)
+     */
+    duration: null,
+    
+    /**
+     * APIProperty: callbacks
+     * {Object} An object with start, eachStep and done properties whose values
+     *     are functions to be call during the animation. They are passed the
+     *     current computed value as argument.
+     */
+    callbacks: null,
+    
+    /**
+     * Property: time
+     * {int} Step counter
+     */
+    time: null,
+    
+    /**
+     * Property: interval
+     * {int} Interval id returned by window.setInterval
+     */
+    interval: null,
+    
+    /**
+     * Property: playing
+     * {Boolean} Tells if the easing is currently playing
+     */
+    playing: false,
+    
+    /** 
+     * Constructor: OpenLayers.Tween
+     * Creates a Tween.
+     *
+     * Parameters:
+     * easing - {<OpenLayers.Easing>(Function)} easing function method to use
+     */ 
+    initialize: function(easing) {
+        this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
+    },
+    
+    /**
+     * APIMethod: start
+     * Plays the Tween, and calls the callback method on each step
+     * 
+     * Parameters:
+     * begin - {Object} values to start the animation with
+     * finish - {Object} values to finish the animation with
+     * duration - {int} duration of the tween (number of steps)
+     * options - {Object} hash of options (for example callbacks (start, eachStep, done))
+     */
+    start: function(begin, finish, duration, options) {
+        this.playing = true;
+        this.begin = begin;
+        this.finish = finish;
+        this.duration = duration;
+        this.callbacks = options.callbacks;
+        this.time = 0;
+        if (this.interval) {
+            window.clearInterval(this.interval);
+            this.interval = null;
+        }
+        if (this.callbacks && this.callbacks.start) {
+            this.callbacks.start.call(this, this.begin);
+        }
+        this.interval = window.setInterval(
+            OpenLayers.Function.bind(this.play, this), this.INTERVAL);
+    },
+    
+    /**
+     * APIMethod: stop
+     * Stops the Tween, and calls the done callback
+     *     Doesn't do anything if animation is already finished
+     */
+    stop: function() {
+        if (!this.playing) {
+            return;
+        }
+        
+        if (this.callbacks && this.callbacks.done) {
+            this.callbacks.done.call(this, this.finish);
+        }
+        window.clearInterval(this.interval);
+        this.interval = null;
+        this.playing = false;
+    },
+    
+    /**
+     * Method: play
+     * Calls the appropriate easing method
+     */
+    play: function() {
+        var value = {};
+        for (var i in this.begin) {
+            var b = this.begin[i];
+            var f = this.finish[i];
+            if (b == null || f == null || isNaN(b) || isNaN(f)) {
+                OpenLayers.Console.error('invalid value for Tween');
+            }
+            
+            var c = f - b;
+            value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
+        }
+        this.time++;
+        
+        if (this.callbacks && this.callbacks.eachStep) {
+            this.callbacks.eachStep.call(this, value);
+        }
+        
+        if (this.time > this.duration) {
+            this.stop();
+        }
+    },
+    
+    /**
+     * Create empty functions for all easing methods.
+     */
+    CLASS_NAME: "OpenLayers.Tween"
+});
+
+/**
+ * Namespace: OpenLayers.Easing
+ * 
+ * Credits:
+ *      Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>
+ */
+OpenLayers.Easing = {
+    /**
+     * Create empty functions for all easing methods.
+     */
+    CLASS_NAME: "OpenLayers.Easing"
+};
+
+/**
+ * Namespace: OpenLayers.Easing.Linear
+ */
+OpenLayers.Easing.Linear = {
+    
+    /**
+     * Function: easeIn
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeIn: function(t, b, c, d) {
+        return c*t/d + b;
+    },
+    
+    /**
+     * Function: easeOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeOut: function(t, b, c, d) {
+        return c*t/d + b;
+    },
+    
+    /**
+     * Function: easeInOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeInOut: function(t, b, c, d) {
+        return c*t/d + b;
+    },
+
+    CLASS_NAME: "OpenLayers.Easing.Linear"
+};
+
+/**
+ * Namespace: OpenLayers.Easing.Expo
+ */
+OpenLayers.Easing.Expo = {
+    
+    /**
+     * Function: easeIn
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeIn: function(t, b, c, d) {
+        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+    },
+    
+    /**
+     * Function: easeOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeOut: function(t, b, c, d) {
+        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+    },
+    
+    /**
+     * Function: easeInOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeInOut: function(t, b, c, d) {
+        if (t==0) return b;
+        if (t==d) return b+c;
+        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+    },
+
+    CLASS_NAME: "OpenLayers.Easing.Expo"
+};
+
+/**
+ * Namespace: OpenLayers.Easing.Quad
+ */
+OpenLayers.Easing.Quad = {
+    
+    /**
+     * Function: easeIn
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeIn: function(t, b, c, d) {
+        return c*(t/=d)*t + b;
+    },
+    
+    /**
+     * Function: easeOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeOut: function(t, b, c, d) {
+        return -c *(t/=d)*(t-2) + b;
+    },
+    
+    /**
+     * Function: easeInOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeInOut: function(t, b, c, d) {
+        if ((t/=d/2) < 1) return c/2*t*t + b;
+        return -c/2 * ((--t)*(t-2) - 1) + b;
+    },
+
+    CLASS_NAME: "OpenLayers.Easing.Quad"
+};
+/* ======================================================================
+    OpenLayers/Map.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Events.js
+ * @requires OpenLayers/Tween.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Map
+ * Instances of OpenLayers.Map are interactive maps embedded in a web page.
+ * Create a new map with the <OpenLayers.Map> constructor.
+ * 
+ * On their own maps do not provide much functionality.  To extend a map
+ * it's necessary to add controls (<OpenLayers.Control>) and 
+ * layers (<OpenLayers.Layer>) to the map. 
+ */
+OpenLayers.Map = OpenLayers.Class({
+    
+    /**
+     * Constant: Z_INDEX_BASE
+     * {Object} Base z-indexes for different classes of thing 
+     */
+    Z_INDEX_BASE: {
+        BaseLayer: 100,
+        Overlay: 325,
+        Feature: 725,
+        Popup: 750,
+        Control: 1000
+    },
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * map.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * All event objects have at least the following properties:
+     *  - *object* {Object} A reference to map.events.object.
+     *  - *element* {DOMElement} A reference to map.events.element.
+     *
+     * Browser events have the following additional properties:
+     *  - *xy* {<OpenLayers.Pixel>} The pixel location of the event (relative
+     *      to the the map viewport).
+     *  - other properties that come with browser events
+     *
+     * Supported map event types:
+     *  - *preaddlayer* triggered before a layer has been added.  The event
+     *      object will include a *layer* property that references the layer  
+     *      to be added. When a listener returns "false" the adding will be 
+     *      aborted.
+     *  - *addlayer* triggered after a layer has been added.  The event object
+     *      will include a *layer* property that references the added layer.
+     *  - *preremovelayer* triggered before a layer has been removed. The event
+     *      object will include a *layer* property that references the layer  
+     *      to be removed. When a listener returns "false" the removal will be 
+     *      aborted.
+     *  - *removelayer* triggered after a layer has been removed.  The event
+     *      object will include a *layer* property that references the removed
+     *      layer.
+     *  - *changelayer* triggered after a layer name change, order change,
+     *      opacity change, params change, visibility change (due to resolution
+     *      thresholds) or attribution change (due to extent change). Listeners
+     *      will receive an event object with *layer* and *property* properties.
+     *      The *layer* property will be a reference to the changed layer. The
+     *      *property* property will be a key to the changed property (name,
+     *      order, opacity, params, visibility or attribution).
+     *  - *movestart* triggered after the start of a drag, pan, or zoom
+     *  - *move* triggered after each drag, pan, or zoom
+     *  - *moveend* triggered after a drag, pan, or zoom completes
+     *  - *zoomend* triggered after a zoom completes
+     *  - *mouseover* triggered after mouseover the map
+     *  - *mouseout* triggered after mouseout the map
+     *  - *mousemove* triggered after mousemove the map
+     *  - *changebaselayer* triggered after the base layer changes
+     */
+    EVENT_TYPES: [ 
+        "preaddlayer", "addlayer","preremovelayer", "removelayer", 
+        "changelayer", "movestart",
+        "move", "moveend", "zoomend", "popupopen", "popupclose",
+        "addmarker", "removemarker", "clearmarkers", "mouseover",
+        "mouseout", "mousemove", "dragstart", "drag", "dragend",
+        "changebaselayer"],
+
+    /**
+     * Property: id
+     * {String} Unique identifier for the map
+     */
+    id: null,
+    
+    /**
+     * Property: fractionalZoom
+     * {Boolean} For a base layer that supports it, allow the map resolution
+     *     to be set to a value between one of the values in the resolutions
+     *     array.  Default is false.
+     *
+     * When fractionalZoom is set to true, it is possible to zoom to
+     *     an arbitrary extent.  This requires a base layer from a source
+     *     that supports requests for arbitrary extents (i.e. not cached
+     *     tiles on a regular lattice).  This means that fractionalZoom
+     *     will not work with commercial layers (Google, Yahoo, VE), layers
+     *     using TileCache, or any other pre-cached data sources.
+     *
+     * If you are using fractionalZoom, then you should also use
+     *     <getResolutionForZoom> instead of layer.resolutions[zoom] as the
+     *     former works for non-integer zoom levels.
+     */
+    fractionalZoom: false,
+    
+    /**
+     * APIProperty: events
+     * {<OpenLayers.Events>} An events object that handles all 
+     *                       events on the map
+     */
+    events: null,
+    
+    /**
+     * APIProperty: allOverlays
+     * {Boolean} Allow the map to function with "overlays" only.  Defaults to
+     *     false.  If true, the lowest layer in the draw order will act as
+     *     the base layer.  In addition, if set to true, all layers will
+     *     have isBaseLayer set to false when they are added to the map.
+     *
+     * Note:
+     * If you set map.allOverlays to true, then you *cannot* use
+     *     map.setBaseLayer or layer.setIsBaseLayer.  With allOverlays true,
+     *     the lowest layer in the draw layer is the base layer.  So, to change
+     *     the base layer, use <setLayerIndex> or <raiseLayer> to set the layer
+     *     index to 0.
+     */
+    allOverlays: false,
+
+    /**
+     * APIProperty: div
+     * {DOMElement|String} The element that contains the map (or an id for
+     *     that element).  If the <OpenLayers.Map> constructor is called
+     *     with two arguments, this should be provided as the first argument.
+     *     Alternatively, the map constructor can be called with the options
+     *     object as the only argument.  In this case (one argument), a
+     *     div property may or may not be provided.  If the div property
+     *     is not provided, the map can be rendered to a container later
+     *     using the <render> method.
+     *     
+     * Note:
+     * If you are calling <render> after map construction, do not use
+     *     <maxResolution>  auto.  Instead, divide your <maxExtent> by your
+     *     maximum expected dimension.
+     */
+    div: null,
+    
+    /**
+     * Property: dragging
+     * {Boolean} The map is currently being dragged.
+     */
+    dragging: false,
+
+    /**
+     * Property: size
+     * {<OpenLayers.Size>} Size of the main div (this.div)
+     */
+    size: null,
+    
+    /**
+     * Property: viewPortDiv
+     * {HTMLDivElement} The element that represents the map viewport
+     */
+    viewPortDiv: null,
+
+    /**
+     * Property: layerContainerOrigin
+     * {<OpenLayers.LonLat>} The lonlat at which the later container was
+     *                       re-initialized (on-zoom)
+     */
+    layerContainerOrigin: null,
+
+    /**
+     * Property: layerContainerDiv
+     * {HTMLDivElement} The element that contains the layers.
+     */
+    layerContainerDiv: null,
+
+    /**
+     * APIProperty: layers
+     * {Array(<OpenLayers.Layer>)} Ordered list of layers in the map
+     */
+    layers: null,
+
+    /**
+     * Property: controls
+     * {Array(<OpenLayers.Control>)} List of controls associated with the map.
+     *
+     * If not provided in the map options at construction, the map will
+     *     be given the following controls by default:
+     *  - <OpenLayers.Control.Navigation>
+     *  - <OpenLayers.Control.PanZoom>
+     *  - <OpenLayers.Control.ArgParser>
+     *  - <OpenLayers.Control.Attribution>
+     */
+    controls: null,
+
+    /**
+     * Property: popups
+     * {Array(<OpenLayers.Popup>)} List of popups associated with the map
+     */
+    popups: null,
+
+    /**
+     * APIProperty: baseLayer
+     * {<OpenLayers.Layer>} The currently selected base layer.  This determines
+     * min/max zoom level, projection, etc.
+     */
+    baseLayer: null,
+    
+    /**
+     * Property: center
+     * {<OpenLayers.LonLat>} The current center of the map
+     */
+    center: null,
+
+    /**
+     * Property: resolution
+     * {Float} The resolution of the map.
+     */
+    resolution: null,
+
+    /**
+     * Property: zoom
+     * {Integer} The current zoom level of the map
+     */
+    zoom: 0,    
+
+    /**
+     * Property: panRatio
+     * {Float} The ratio of the current extent within
+     *         which panning will tween.
+     */
+    panRatio: 1.5,    
+
+    /**
+     * Property: viewRequestID
+     * {String} Used to store a unique identifier that changes when the map 
+     *          view changes. viewRequestID should be used when adding data 
+     *          asynchronously to the map: viewRequestID is incremented when 
+     *          you initiate your request (right now during changing of 
+     *          baselayers and changing of zooms). It is stored here in the 
+     *          map and also in the data that will be coming back 
+     *          asynchronously. Before displaying this data on request 
+     *          completion, we check that the viewRequestID of the data is 
+     *          still the same as that of the map. Fix for #480
+     */
+    viewRequestID: 0,
+
+  // Options
+
+    /**
+     * APIProperty: tileSize
+     * {<OpenLayers.Size>} Set in the map options to override the default tile
+     *                     size for this map.
+     */
+    tileSize: null,
+
+    /**
+     * APIProperty: projection
+     * {String} Set in the map options to override the default projection 
+     *          string this map - also set maxExtent, maxResolution, and 
+     *          units if appropriate.  Default is "EPSG:4326".
+     */
+    projection: "EPSG:4326",    
+        
+    /**
+     * APIProperty: units
+     * {String} The map units.  Defaults to 'degrees'.  Possible values are
+     *          'degrees' (or 'dd'), 'm', 'ft', 'km', 'mi', 'inches'.
+     */
+    units: 'degrees',
+
+    /**
+     * APIProperty: resolutions
+     * {Array(Float)} A list of map resolutions (map units per pixel) in 
+     *     descending order.  If this is not set in the layer constructor, it 
+     *     will be set based on other resolution related properties 
+     *     (maxExtent, maxResolution, maxScale, etc.).
+     */
+    resolutions: null,
+
+    /**
+     * APIProperty: maxResolution
+     * {Float} Default max is 360 deg / 256 px, which corresponds to
+     *          zoom level 0 on gmaps.  Specify a different value in the map 
+     *          options if you are not using a geographic projection and 
+     *          displaying the whole world.
+     */
+    maxResolution: 1.40625,
+
+    /**
+     * APIProperty: minResolution
+     * {Float}
+     */
+    minResolution: null,
+
+    /**
+     * APIProperty: maxScale
+     * {Float}
+     */
+    maxScale: null,
+
+    /**
+     * APIProperty: minScale
+     * {Float}
+     */
+    minScale: null,
+
+    /**
+     * APIProperty: maxExtent
+     * {<OpenLayers.Bounds>} The maximum extent for the map.  Defaults to the
+     *                       whole world in decimal degrees 
+     *                       (-180, -90, 180, 90).  Specify a different
+     *                        extent in the map options if you are not using a 
+     *                        geographic projection and displaying the whole 
+     *                        world.
+     */
+    maxExtent: null,
+    
+    /**
+     * APIProperty: minExtent
+     * {<OpenLayers.Bounds>}
+     */
+    minExtent: null,
+    
+    /**
+     * APIProperty: restrictedExtent
+     * {<OpenLayers.Bounds>} Limit map navigation to this extent where possible.
+     *     If a non-null restrictedExtent is set, panning will be restricted
+     *     to the given bounds.  In addition, zooming to a resolution that
+     *     displays more than the restricted extent will center the map
+     *     on the restricted extent.  If you wish to limit the zoom level
+     *     or resolution, use maxResolution.
+     */
+    restrictedExtent: null,
+
+    /**
+     * APIProperty: numZoomLevels
+     * {Integer} Number of zoom levels for the map.  Defaults to 16.  Set a
+     *           different value in the map options if needed.
+     */
+    numZoomLevels: 16,
+
+    /**
+     * APIProperty: theme
+     * {String} Relative path to a CSS file from which to load theme styles.
+     *          Specify null in the map options (e.g. {theme: null}) if you 
+     *          want to get cascading style declarations - by putting links to 
+     *          stylesheets or style declarations directly in your page.
+     */
+    theme: null,
+    
+    /** 
+     * APIProperty: displayProjection
+     * {<OpenLayers.Projection>} Requires proj4js support.Projection used by
+     *     several controls to display data to user. If this property is set,
+     *     it will be set on any control which has a null displayProjection
+     *     property at the time the control is added to the map. 
+     */
+    displayProjection: null,
+
+    /**
+     * APIProperty: fallThrough
+     * {Boolean} Should OpenLayers allow events on the map to fall through to
+     *           other elements on the page, or should it swallow them? (#457)
+     *           Default is to fall through.
+     */
+    fallThrough: true,
+    
+    /**
+     * Property: panTween
+     * {OpenLayers.Tween} Animated panning tween object, see panTo()
+     */
+    panTween: null,
+
+    /**
+     * APIProperty: eventListeners
+     * {Object} If set as an option at construction, the eventListeners
+     *     object will be registered with <OpenLayers.Events.on>.  Object
+     *     structure must be a listeners object as shown in the example for
+     *     the events.on method.
+     */
+    eventListeners: null,
+
+    /**
+     * APIProperty: panMethod
+     * {Function} The Easing function to be used for tweening.  Default is
+     * OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off
+     * animated panning.
+     */
+    panMethod: OpenLayers.Easing.Expo.easeOut,
+    
+    /**
+     * Property: panDuration
+     * {Integer} The number of steps to be passed to the
+     * OpenLayers.Tween.start() method when the map is
+     * panned.
+     * Default is 50.
+     */
+    panDuration: 50,
+    
+    /**
+     * Property: paddingForPopups
+     * {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent 
+     *     the popup from getting too close to the map border.
+     */
+    paddingForPopups : null,
+    
+    /**
+     * Property: minPx
+     * {<OpenLayers.Pixel>} Lower left of maxExtent in viewport pixel space.
+     *     Used to verify in moveByPx that the new location we're moving to
+     *     is valid. It is also used in the getLonLatFromViewPortPx function
+     *     of Layer.
+     */
+    minPx: null,
+    
+    /**
+     * Property: maxPx
+     * {<OpenLayers.Pixel>} Top right of maxExtent in viewport pixel space.
+     *     Used to verify in moveByPx that the new location we're moving to
+     *     is valid.
+     */
+    maxPx: null,
+    
+    /**
+     * Constructor: OpenLayers.Map
+     * Constructor for a new OpenLayers.Map instance.  There are two possible
+     *     ways to call the map constructor.  See the examples below.
+     *
+     * Parameters:
+     * div - {DOMElement|String}  The element or id of an element in your page
+     *     that will contain the map.  May be omitted if the <div> option is
+     *     provided or if you intend to call the <render> method later.
+     * options - {Object} Optional object with properties to tag onto the map.
+     *
+     * Examples:
+     * (code)
+     * // create a map with default options in an element with the id "map1"
+     * var map = new OpenLayers.Map("map1");
+     *
+     * // create a map with non-default options in an element with id "map2"
+     * var options = {
+     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
+     *     maxResolution: 156543,
+     *     units: 'm',
+     *     projection: "EPSG:41001"
+     * };
+     * var map = new OpenLayers.Map("map2", options);
+     *
+     * // map with non-default options - same as above but with a single argument
+     * var map = new OpenLayers.Map({
+     *     div: "map_id",
+     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
+     *     maxResolution: 156543,
+     *     units: 'm',
+     *     projection: "EPSG:41001"
+     * });
+     *
+     * // create a map without a reference to a container - call render later
+     * var map = new OpenLayers.Map({
+     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
+     *     maxResolution: 156543,
+     *     units: 'm',
+     *     projection: "EPSG:41001"
+     * });
+     * (end)
+     */    
+    initialize: function (div, options) {
+        
+        // If only one argument is provided, check if it is an object.
+        if(arguments.length === 1 && typeof div === "object") {
+            options = div;
+            div = options && options.div;
+        }
+
+        // Simple-type defaults are set in class definition. 
+        //  Now set complex-type defaults 
+        this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,
+                                            OpenLayers.Map.TILE_HEIGHT);
+        
+        this.maxExtent = new OpenLayers.Bounds(-180, -90, 180, 90);
+        
+        this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15);
+
+        this.theme = OpenLayers._getScriptLocation() + 
+                             'theme/default/style.css'; 
+
+        // now override default options 
+        OpenLayers.Util.extend(this, options);
+
+        // initialize layers array
+        this.layers = [];
+
+        this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_");
+
+        this.div = OpenLayers.Util.getElement(div);
+        if(!this.div) {
+            this.div = document.createElement("div");
+            this.div.style.height = "1px";
+            this.div.style.width = "1px";
+        }
+        
+        OpenLayers.Element.addClass(this.div, 'olMap');
+
+        // the viewPortDiv is the outermost div we modify
+        var id = this.id + "_OpenLayers_ViewPort";
+        this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,
+                                                     "relative", null,
+                                                     "hidden");
+        this.viewPortDiv.style.width = "100%";
+        this.viewPortDiv.style.height = "100%";
+        this.viewPortDiv.className = "olMapViewport";
+        this.div.appendChild(this.viewPortDiv);
+
+        // the eventsDiv is where we listen for all map events
+        var eventsDiv = document.createElement("div");
+        eventsDiv.id = this.id + "_events";
+        eventsDiv.style.position = "absolute";
+        eventsDiv.style.width = "100%";
+        eventsDiv.style.height = "100%";
+        eventsDiv.style.zIndex = this.Z_INDEX_BASE.Control - 1;
+        this.viewPortDiv.appendChild(eventsDiv);
+        this.eventsDiv = eventsDiv;
+        this.events = new OpenLayers.Events(
+            this, this.eventsDiv, this.EVENT_TYPES, this.fallThrough, 
+            {includeXY: true}
+        );
+
+        // the layerContainerDiv is the one that holds all the layers
+        id = this.id + "_OpenLayers_Container";
+        this.layerContainerDiv = OpenLayers.Util.createDiv(id);
+        this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
+        
+        this.eventsDiv.appendChild(this.layerContainerDiv);
+
+        this.updateSize();
+        if(this.eventListeners instanceof Object) {
+            this.events.on(this.eventListeners);
+        }
+ 
+        // update the map size and location before the map moves
+        this.events.register("movestart", this, this.updateSize);
+
+        // Because Mozilla does not support the "resize" event for elements 
+        // other than "window", we need to put a hack here. 
+        if (OpenLayers.String.contains(navigator.appName, "Microsoft")) {
+            // If IE, register the resize on the div
+            this.events.register("resize", this, this.updateSize);
+        } else {
+            // Else updateSize on catching the window's resize
+            //  Note that this is ok, as updateSize() does nothing if the 
+            //  map's size has not actually changed.
+            this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize, 
+                this);
+            OpenLayers.Event.observe(window, 'resize',
+                            this.updateSizeDestroy);
+        }
+        
+        // only append link stylesheet if the theme property is set
+        if(this.theme) {
+            // check existing links for equivalent url
+            var addNode = true;
+            var nodes = document.getElementsByTagName('link');
+            for(var i=0, len=nodes.length; i<len; ++i) {
+                if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,
+                                                   this.theme)) {
+                    addNode = false;
+                    break;
+                }
+            }
+            // only add a new node if one with an equivalent url hasn't already
+            // been added
+            if(addNode) {
+                var cssNode = document.createElement('link');
+                cssNode.setAttribute('rel', 'stylesheet');
+                cssNode.setAttribute('type', 'text/css');
+                cssNode.setAttribute('href', this.theme);
+                document.getElementsByTagName('head')[0].appendChild(cssNode);
+            }
+        }
+        
+        if (this.controls == null) {
+            if (OpenLayers.Control != null) { // running full or lite?
+                this.controls = [ new OpenLayers.Control.Navigation(),
+                                  new OpenLayers.Control.PanZoom(),
+                                  new OpenLayers.Control.ArgParser(),
+                                  new OpenLayers.Control.Attribution()
+                                ];
+            } else {
+                this.controls = [];
+            }
+        }
+
+        for(var i=0, len=this.controls.length; i<len; i++) {
+            this.addControlToMap(this.controls[i]);
+        }
+
+        this.popups = [];
+
+        this.unloadDestroy = OpenLayers.Function.bind(this.destroy, this);
+        
+
+        // always call map.destroy()
+        OpenLayers.Event.observe(window, 'unload', this.unloadDestroy);
+        
+        // add any initial layers
+        if (options && options.layers) {
+            /** 
+             * If you have set options.center, the map center property will be
+             * set at this point.  However, since setCenter has not been caleld,
+             * addLayers gets confused.  So we delete the map center in this 
+             * case.  Because the check below uses options.center, it will
+             * be properly set below.
+             */
+            delete this.center;
+            this.addLayers(options.layers);        
+            // set center (and optionally zoom)
+            if (options.center) {
+                // zoom can be undefined here
+                this.setCenter(options.center, options.zoom);
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: render
+     * Render the map to a specified container.
+     * 
+     * Parameters:
+     * div - {String|DOMElement} The container that the map should be rendered
+     *     to. If different than the current container, the map viewport
+     *     will be moved from the current to the new container.
+     */
+    render: function(div) {
+        this.div = OpenLayers.Util.getElement(div);
+        OpenLayers.Element.addClass(this.div, 'olMap');
+        this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
+        this.div.appendChild(this.viewPortDiv);
+        this.updateSize();
+    },
+
+    /**
+     * Method: unloadDestroy
+     * Function that is called to destroy the map on page unload. stored here
+     *     so that if map is manually destroyed, we can unregister this.
+     */
+    unloadDestroy: null,
+    
+    /**
+     * Method: updateSizeDestroy
+     * When the map is destroyed, we need to stop listening to updateSize
+     *    events: this method stores the function we need to unregister in 
+     *    non-IE browsers.
+     */
+    updateSizeDestroy: null,
+
+    /**
+     * APIMethod: destroy
+     * Destroy this map.
+     *    Note that if you are using an application which removes a container
+     *    of the map from the DOM, you need to ensure that you destroy the
+     *    map *before* this happens; otherwise, the page unload handler
+     *    will fail because the DOM elements that map.destroy() wants
+     *    to clean up will be gone. (See 
+     *    http://trac.osgeo.org/openlayers/ticket/2277 for more information).
+     *    This will apply to GeoExt and also to other applications which
+     *    modify the DOM of the container of the OpenLayers Map.
+     */
+    destroy:function() {
+        // if unloadDestroy is null, we've already been destroyed
+        if (!this.unloadDestroy) {
+            return false;
+        }
+        
+        // make sure panning doesn't continue after destruction
+        if(this.panTween) {
+            this.panTween.stop();
+            this.panTween = null;
+        }
+
+        // map has been destroyed. dont do it again!
+        OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
+        this.unloadDestroy = null;
+
+        if (this.updateSizeDestroy) {
+            OpenLayers.Event.stopObserving(window, 'resize', 
+                                           this.updateSizeDestroy);
+        } else {
+            this.events.unregister("resize", this, this.updateSize);
+        }    
+        
+        this.paddingForPopups = null;    
+
+        if (this.controls != null) {
+            for (var i = this.controls.length - 1; i>=0; --i) {
+                this.controls[i].destroy();
+            } 
+            this.controls = null;
+        }
+        if (this.layers != null) {
+            for (var i = this.layers.length - 1; i>=0; --i) {
+                //pass 'false' to destroy so that map wont try to set a new 
+                // baselayer after each baselayer is removed
+                this.layers[i].destroy(false);
+            } 
+            this.layers = null;
+        }
+        if (this.viewPortDiv) {
+            this.div.removeChild(this.viewPortDiv);
+        }
+        this.viewPortDiv = null;
+
+        if(this.eventListeners) {
+            this.events.un(this.eventListeners);
+            this.eventListeners = null;
+        }
+        this.events.destroy();
+        this.events = null;
+
+    },
+
+    /**
+     * APIMethod: setOptions
+     * Change the map options
+     *
+     * Parameters:
+     * options - {Object} Hashtable of options to tag to the map
+     */
+    setOptions: function(options) {
+        var updatePxExtent = this.minPx &&
+            options.restrictedExtent != this.restrictedExtent;
+        OpenLayers.Util.extend(this, options);
+        // force recalculation of minPx and maxPx
+        updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, {
+            forceZoomChange: true
+        });
+    },
+
+    /**
+     * APIMethod: getTileSize
+     * Get the tile size for the map
+     *
+     * Returns:
+     * {<OpenLayers.Size>}
+     */
+     getTileSize: function() {
+         return this.tileSize;
+     },
+
+
+    /**
+     * APIMethod: getBy
+     * Get a list of objects given a property and a match item.
+     *
+     * Parameters:
+     * array - {String} A property on the map whose value is an array.
+     * property - {String} A property on each item of the given array.
+     * match - {String | Object} A string to match.  Can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     match.test(map[array][i][property]) evaluates to true, the item will
+     *     be included in the array returned.  If no items are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array} An array of items where the given property matches the given
+     *     criteria.
+     */
+    getBy: function(array, property, match) {
+        var test = (typeof match.test == "function");
+        var found = OpenLayers.Array.filter(this[array], function(item) {
+            return item[property] == match || (test && match.test(item[property]));
+        });
+        return found;
+    },
+
+    /**
+     * APIMethod: getLayersBy
+     * Get a list of layers with properties matching the given criteria.
+     *
+     * Parameter:
+     * property - {String} A layer property to be matched.
+     * match - {String | Object} A string to match.  Can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     match.test(layer[property]) evaluates to true, the layer will be
+     *     included in the array returned.  If no layers are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Layer>)} A list of layers matching the given criteria.
+     *     An empty array is returned if no matches are found.
+     */
+    getLayersBy: function(property, match) {
+        return this.getBy("layers", property, match);
+    },
+
+    /**
+     * APIMethod: getLayersByName
+     * Get a list of layers with names matching the given name.
+     *
+     * Parameter:
+     * match - {String | Object} A layer name.  The name can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     name.test(layer.name) evaluates to true, the layer will be included
+     *     in the list of layers returned.  If no layers are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Layer>)} A list of layers matching the given name.
+     *     An empty array is returned if no matches are found.
+     */
+    getLayersByName: function(match) {
+        return this.getLayersBy("name", match);
+    },
+
+    /**
+     * APIMethod: getLayersByClass
+     * Get a list of layers of a given class (CLASS_NAME).
+     *
+     * Parameter:
+     * match - {String | Object} A layer class name.  The match can also be a
+     *     regular expression literal or object.  In addition, it can be any
+     *     object with a method named test.  For reqular expressions or other,
+     *     if type.test(layer.CLASS_NAME) evaluates to true, the layer will
+     *     be included in the list of layers returned.  If no layers are
+     *     found, an empty array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Layer>)} A list of layers matching the given class.
+     *     An empty array is returned if no matches are found.
+     */
+    getLayersByClass: function(match) {
+        return this.getLayersBy("CLASS_NAME", match);
+    },
+
+    /**
+     * APIMethod: getControlsBy
+     * Get a list of controls with properties matching the given criteria.
+     *
+     * Parameter:
+     * property - {String} A control property to be matched.
+     * match - {String | Object} A string to match.  Can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     match.test(layer[property]) evaluates to true, the layer will be
+     *     included in the array returned.  If no layers are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Control>)} A list of controls matching the given
+     *     criteria.  An empty array is returned if no matches are found.
+     */
+    getControlsBy: function(property, match) {
+        return this.getBy("controls", property, match);
+    },
+
+    /**
+     * APIMethod: getControlsByClass
+     * Get a list of controls of a given class (CLASS_NAME).
+     *
+     * Parameter:
+     * match - {String | Object} A control class name.  The match can also be a
+     *     regular expression literal or object.  In addition, it can be any
+     *     object with a method named test.  For reqular expressions or other,
+     *     if type.test(control.CLASS_NAME) evaluates to true, the control will
+     *     be included in the list of controls returned.  If no controls are
+     *     found, an empty array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Control>)} A list of controls matching the given class.
+     *     An empty array is returned if no matches are found.
+     */
+    getControlsByClass: function(match) {
+        return this.getControlsBy("CLASS_NAME", match);
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                  Layer Functions                     */
+  /*                                                      */
+  /*     The following functions deal with adding and     */
+  /*        removing Layers to and from the Map           */
+  /*                                                      */
+  /********************************************************/         
+
+    /**
+     * APIMethod: getLayer
+     * Get a layer based on its id
+     *
+     * Parameter:
+     * id - {String} A layer id
+     *
+     * Returns:
+     * {<OpenLayers.Layer>} The Layer with the corresponding id from the map's 
+     *                      layer collection, or null if not found.
+     */
+    getLayer: function(id) {
+        var foundLayer = null;
+        for (var i=0, len=this.layers.length; i<len; i++) {
+            var layer = this.layers[i];
+            if (layer.id == id) {
+                foundLayer = layer;
+                break;
+            }
+        }
+        return foundLayer;
+    },
+
+    /**
+    * Method: setLayerZIndex
+    * 
+    * Parameters:
+    * layer - {<OpenLayers.Layer>} 
+    * zIdx - {int} 
+    */    
+    setLayerZIndex: function (layer, zIdx) {
+        layer.setZIndex(
+            this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay']
+            + zIdx * 5 );
+    },
+
+    /**
+     * Method: resetLayersZIndex
+     * Reset each layer's z-index based on layer's array index
+     */
+    resetLayersZIndex: function() {
+        for (var i=0, len=this.layers.length; i<len; i++) {
+            var layer = this.layers[i];
+            this.setLayerZIndex(layer, i);
+        }
+    },
+
+    /**
+    * APIMethod: addLayer
+    *
+    * Parameters:
+    * layer - {<OpenLayers.Layer>} 
+    */    
+    addLayer: function (layer) {
+        for(var i=0, len=this.layers.length; i <len; i++) {
+            if (this.layers[i] == layer) {
+                var msg = OpenLayers.i18n('layerAlreadyAdded', 
+                                                      {'layerName':layer.name});
+                OpenLayers.Console.warn(msg);
+                return false;
+            }
+        }
+        if (this.events.triggerEvent("preaddlayer", {layer: layer}) === false) {
+            return;
+        }
+        if(this.allOverlays) {
+            layer.isBaseLayer = false;
+        }
+
+        
+        layer.div.className = "olLayerDiv";
+        layer.div.style.overflow = "";
+        this.setLayerZIndex(layer, this.layers.length);
+
+        if (layer.isFixed) {
+            this.viewPortDiv.appendChild(layer.div);
+        } else {
+            this.layerContainerDiv.appendChild(layer.div);
+        }
+        this.layers.push(layer);
+        layer.setMap(this);
+
+        if (layer.isBaseLayer || (this.allOverlays && !this.baseLayer))  {
+            if (this.baseLayer == null) {
+                // set the first baselaye we add as the baselayer
+                this.setBaseLayer(layer);
+            } else {
+                layer.setVisibility(false);
+            }
+        } else {
+            layer.redraw();
+        }
+
+        this.events.triggerEvent("addlayer", {layer: layer});
+        layer.events.triggerEvent("added", {map: this, layer: layer});
+        layer.afterAdd();
+    },
+
+    /**
+    * APIMethod: addLayers 
+    *
+    * Parameters:
+    * layers - {Array(<OpenLayers.Layer>)} 
+    */    
+    addLayers: function (layers) {
+        for (var i=0, len=layers.length; i<len; i++) {
+            this.addLayer(layers[i]);
+        }
+    },
+
+    /** 
+     * APIMethod: removeLayer
+     * Removes a layer from the map by removing its visual element (the 
+     *   layer.div property), then removing it from the map's internal list 
+     *   of layers, setting the layer's map property to null. 
+     * 
+     *   a "removelayer" event is triggered.
+     * 
+     *   very worthy of mention is that simply removing a layer from a map
+     *   will not cause the removal of any popups which may have been created
+     *   by the layer. this is due to the fact that it was decided at some
+     *   point that popups would not belong to layers. thus there is no way 
+     *   for us to know here to which layer the popup belongs.
+     *    
+     *     A simple solution to this is simply to call destroy() on the layer.
+     *     the default OpenLayers.Layer class's destroy() function
+     *     automatically takes care to remove itself from whatever map it has
+     *     been attached to. 
+     * 
+     *     The correct solution is for the layer itself to register an 
+     *     event-handler on "removelayer" and when it is called, if it 
+     *     recognizes itself as the layer being removed, then it cycles through
+     *     its own personal list of popups, removing them from the map.
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} 
+     * setNewBaseLayer - {Boolean} Default is true
+     */
+    removeLayer: function(layer, setNewBaseLayer) {
+        if (this.events.triggerEvent("preremovelayer", {layer: layer}) === false) {
+            return;
+        }
+        if (setNewBaseLayer == null) {
+            setNewBaseLayer = true;
+        }
+
+        if (layer.isFixed) {
+            this.viewPortDiv.removeChild(layer.div);
+        } else {
+            this.layerContainerDiv.removeChild(layer.div);
+        }
+        OpenLayers.Util.removeItem(this.layers, layer);
+        layer.removeMap(this);
+        layer.map = null;
+
+        // if we removed the base layer, need to set a new one
+        if(this.baseLayer == layer) {
+            this.baseLayer = null;
+            if(setNewBaseLayer) {
+                for(var i=0, len=this.layers.length; i<len; i++) {
+                    var iLayer = this.layers[i];
+                    if (iLayer.isBaseLayer || this.allOverlays) {
+                        this.setBaseLayer(iLayer);
+                        break;
+                    }
+                }
+            }
+        }
+
+        this.resetLayersZIndex();
+
+        this.events.triggerEvent("removelayer", {layer: layer});
+        layer.events.triggerEvent("removed", {map: this, layer: layer});
+    },
+
+    /**
+     * APIMethod: getNumLayers
+     * 
+     * Returns:
+     * {Int} The number of layers attached to the map.
+     */
+    getNumLayers: function () {
+        return this.layers.length;
+    },
+
+    /** 
+     * APIMethod: getLayerIndex
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer>}
+     *
+     * Returns:
+     * {Integer} The current (zero-based) index of the given layer in the map's
+     *           layer stack. Returns -1 if the layer isn't on the map.
+     */
+    getLayerIndex: function (layer) {
+        return OpenLayers.Util.indexOf(this.layers, layer);
+    },
+    
+    /** 
+     * APIMethod: setLayerIndex
+     * Move the given layer to the specified (zero-based) index in the layer
+     *     list, changing its z-index in the map display. Use
+     *     map.getLayerIndex() to find out the current index of a layer. Note
+     *     that this cannot (or at least should not) be effectively used to
+     *     raise base layers above overlays.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} 
+     * idx - {int} 
+     */
+    setLayerIndex: function (layer, idx) {
+        var base = this.getLayerIndex(layer);
+        if (idx < 0) {
+            idx = 0;
+        } else if (idx > this.layers.length) {
+            idx = this.layers.length;
+        }
+        if (base != idx) {
+            this.layers.splice(base, 1);
+            this.layers.splice(idx, 0, layer);
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                this.setLayerZIndex(this.layers[i], i);
+            }
+            this.events.triggerEvent("changelayer", {
+                layer: layer, property: "order"
+            });
+            if(this.allOverlays) {
+                if(idx === 0) {
+                    this.setBaseLayer(layer);
+                } else if(this.baseLayer !== this.layers[0]) {
+                    this.setBaseLayer(this.layers[0]);
+                }
+            }
+        }
+    },
+
+    /** 
+     * APIMethod: raiseLayer
+     * Change the index of the given layer by delta. If delta is positive, 
+     *     the layer is moved up the map's layer stack; if delta is negative,
+     *     the layer is moved down.  Again, note that this cannot (or at least
+     *     should not) be effectively used to raise base layers above overlays.
+     *
+     * Paremeters:
+     * layer - {<OpenLayers.Layer>} 
+     * delta - {int} 
+     */
+    raiseLayer: function (layer, delta) {
+        var idx = this.getLayerIndex(layer) + delta;
+        this.setLayerIndex(layer, idx);
+    },
+    
+    /** 
+     * APIMethod: setBaseLayer
+     * Allows user to specify one of the currently-loaded layers as the Map's
+     *     new base layer.
+     * 
+     * Parameters:
+     * newBaseLayer - {<OpenLayers.Layer>}
+     */
+    setBaseLayer: function(newBaseLayer) {
+        
+        if (newBaseLayer != this.baseLayer) {
+          
+            // ensure newBaseLayer is already loaded
+            if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
+
+                // preserve center and scale when changing base layers
+                var center = this.getCachedCenter();
+                var newResolution = OpenLayers.Util.getResolutionFromScale(
+                    this.getScale(), newBaseLayer.units
+                );
+
+                // make the old base layer invisible 
+                if (this.baseLayer != null && !this.allOverlays) {
+                    this.baseLayer.setVisibility(false);
+                }
+
+                // set new baselayer
+                this.baseLayer = newBaseLayer;
+                
+                // Increment viewRequestID since the baseLayer is 
+                // changing. This is used by tiles to check if they should 
+                // draw themselves.
+                this.viewRequestID++;
+                if(!this.allOverlays || this.baseLayer.visibility) {
+                    this.baseLayer.setVisibility(true);
+                }
+
+                // recenter the map
+                if (center != null) {
+                    // new zoom level derived from old scale
+                    var newZoom = this.getZoomForResolution(
+                        newResolution || this.resolution, true
+                    );
+                    // zoom and force zoom change
+                    this.setCenter(center, newZoom, false, true);
+                }
+
+                this.events.triggerEvent("changebaselayer", {
+                    layer: this.baseLayer
+                });
+            }        
+        }
+    },
+
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Control Functions                    */
+  /*                                                      */
+  /*     The following functions deal with adding and     */
+  /*        removing Controls to and from the Map         */
+  /*                                                      */
+  /********************************************************/         
+
+    /**
+     * APIMethod: addControl
+     * Add the passed over control to the map. Optionally 
+     *     position the control at the given pixel.
+     * 
+     * Parameters:
+     * control - {<OpenLayers.Control>}
+     * px - {<OpenLayers.Pixel>}
+     */    
+    addControl: function (control, px) {
+        this.controls.push(control);
+        this.addControlToMap(control, px);
+    },
+    
+    /**
+     * APIMethod: addControls
+     * Add all of the passed over controls to the map. 
+     *     You can pass over an optional second array
+     *     with pixel-objects to position the controls.
+     *     The indices of the two arrays should match and
+     *     you can add null as pixel for those controls 
+     *     you want to be autopositioned.   
+     *     
+     * Parameters:
+     * controls - {Array(<OpenLayers.Control>)}
+     * pixels - {Array(<OpenLayers.Pixel>)}
+     */    
+    addControls: function (controls, pixels) {
+        var pxs = (arguments.length === 1) ? [] : pixels;
+        for (var i=0, len=controls.length; i<len; i++) {
+            var ctrl = controls[i];
+            var px = (pxs[i]) ? pxs[i] : null;
+            this.addControl( ctrl, px );
+        }
+    },
+
+    /**
+     * Method: addControlToMap
+     * 
+     * Parameters:
+     * 
+     * control - {<OpenLayers.Control>}
+     * px - {<OpenLayers.Pixel>}
+     */    
+    addControlToMap: function (control, px) {
+        // If a control doesn't have a div at this point, it belongs in the
+        // viewport.
+        control.outsideViewport = (control.div != null);
+        
+        // If the map has a displayProjection, and the control doesn't, set 
+        // the display projection.
+        if (this.displayProjection && !control.displayProjection) {
+            control.displayProjection = this.displayProjection;
+        }    
+        
+        control.setMap(this);
+        var div = control.draw(px);
+        if (div) {
+            if(!control.outsideViewport) {
+                div.style.zIndex = this.Z_INDEX_BASE['Control'] +
+                                    this.controls.length;
+                this.viewPortDiv.appendChild( div );
+            }
+        }
+        if(control.autoActivate) {
+            control.activate();
+        }
+    },
+    
+    /**
+     * APIMethod: getControl
+     * 
+     * Parameters:
+     * id - {String} ID of the control to return.
+     * 
+     * Returns:
+     * {<OpenLayers.Control>} The control from the map's list of controls 
+     *                        which has a matching 'id'. If none found, 
+     *                        returns null.
+     */    
+    getControl: function (id) {
+        var returnControl = null;
+        for(var i=0, len=this.controls.length; i<len; i++) {
+            var control = this.controls[i];
+            if (control.id == id) {
+                returnControl = control;
+                break;
+            }
+        }
+        return returnControl;
+    },
+    
+    /** 
+     * APIMethod: removeControl
+     * Remove a control from the map. Removes the control both from the map 
+     *     object's internal array of controls, as well as from the map's 
+     *     viewPort (assuming the control was not added outsideViewport)
+     * 
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control to remove.
+     */    
+    removeControl: function (control) {
+        //make sure control is non-null and actually part of our map
+        if ( (control) && (control == this.getControl(control.id)) ) {
+            if (control.div && (control.div.parentNode == this.viewPortDiv)) {
+                this.viewPortDiv.removeChild(control.div);
+            }
+            OpenLayers.Util.removeItem(this.controls, control);
+        }
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                  Popup Functions                     */
+  /*                                                      */
+  /*     The following functions deal with adding and     */
+  /*        removing Popups to and from the Map           */
+  /*                                                      */
+  /********************************************************/         
+
+    /** 
+     * APIMethod: addPopup
+     * 
+     * Parameters:
+     * popup - {<OpenLayers.Popup>}
+     * exclusive - {Boolean} If true, closes all other popups first
+     */
+    addPopup: function(popup, exclusive) {
+
+        if (exclusive) {
+            //remove all other popups from screen
+            for (var i = this.popups.length - 1; i >= 0; --i) {
+                this.removePopup(this.popups[i]);
+            }
+        }
+
+        popup.map = this;
+        this.popups.push(popup);
+        var popupDiv = popup.draw();
+        if (popupDiv) {
+            popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] +
+                                    this.popups.length;
+            this.layerContainerDiv.appendChild(popupDiv);
+        }
+    },
+    
+    /** 
+    * APIMethod: removePopup
+    * 
+    * Parameters:
+    * popup - {<OpenLayers.Popup>}
+    */
+    removePopup: function(popup) {
+        OpenLayers.Util.removeItem(this.popups, popup);
+        if (popup.div) {
+            try { this.layerContainerDiv.removeChild(popup.div); }
+            catch (e) { } // Popups sometimes apparently get disconnected
+                      // from the layerContainerDiv, and cause complaints.
+        }
+        popup.map = null;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*              Container Div Functions                 */
+  /*                                                      */
+  /*   The following functions deal with the access to    */
+  /*    and maintenance of the size of the container div  */
+  /*                                                      */
+  /********************************************************/     
+
+    /**
+     * APIMethod: getSize
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} An <OpenLayers.Size> object that represents the 
+     *                     size, in pixels, of the div into which OpenLayers 
+     *                     has been loaded. 
+     *                     Note - A clone() of this locally cached variable is
+     *                     returned, so as not to allow users to modify it.
+     */
+    getSize: function () {
+        var size = null;
+        if (this.size != null) {
+            size = this.size.clone();
+        }
+        return size;
+    },
+
+    /**
+     * APIMethod: updateSize
+     * This function should be called by any external code which dynamically
+     *     changes the size of the map div (because mozilla wont let us catch 
+     *     the "onresize" for an element)
+     */
+    updateSize: function() {
+        // the div might have moved on the page, also
+        var newSize = this.getCurrentSize();
+        if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) {
+            this.events.clearMouseCache();
+            var oldSize = this.getSize();
+            if (oldSize == null) {
+                this.size = oldSize = newSize;
+            }
+            if (!newSize.equals(oldSize)) {
+                
+                // store the new size
+                this.size = newSize;
+    
+                //notify layers of mapresize
+                for(var i=0, len=this.layers.length; i<len; i++) {
+                    this.layers[i].onMapResize();                
+                }
+    
+                var center = this.getCachedCenter();
+    
+                if (this.baseLayer != null && center != null) {
+                    var zoom = this.getZoom();
+                    this.zoom = null;
+                    this.setCenter(center, zoom);
+                }
+    
+            }
+        }
+    },
+    
+    /**
+     * Method: getCurrentSize
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} A new <OpenLayers.Size> object with the dimensions 
+     *                     of the map div
+     */
+    getCurrentSize: function() {
+
+        var size = new OpenLayers.Size(this.div.clientWidth, 
+                                       this.div.clientHeight);
+
+        if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
+            size.w = this.div.offsetWidth;
+            size.h = this.div.offsetHeight;
+        }
+        if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
+            size.w = parseInt(this.div.style.width);
+            size.h = parseInt(this.div.style.height);
+        }
+        return size;
+    },
+
+    /** 
+     * Method: calculateBounds
+     * 
+     * Parameters:
+     * center - {<OpenLayers.LonLat>} Default is this.getCenter()
+     * resolution - {float} Default is this.getResolution() 
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A bounds based on resolution, center, and 
+     *                       current mapsize.
+     */
+    calculateBounds: function(center, resolution) {
+
+        var extent = null;
+        
+        if (center == null) {
+            center = this.getCachedCenter();
+        }                
+        if (resolution == null) {
+            resolution = this.getResolution();
+        }
+    
+        if ((center != null) && (resolution != null)) {
+
+            var size = this.getSize();
+            var w_deg = size.w * resolution;
+            var h_deg = size.h * resolution;
+        
+            extent = new OpenLayers.Bounds(center.lon - w_deg / 2,
+                                           center.lat - h_deg / 2,
+                                           center.lon + w_deg / 2,
+                                           center.lat + h_deg / 2);
+        
+        }
+
+        return extent;
+    },
+
+
+  /********************************************************/
+  /*                                                      */
+  /*            Zoom, Center, Pan Functions               */
+  /*                                                      */
+  /*    The following functions handle the validation,    */
+  /*   getting and setting of the Zoom Level and Center   */
+  /*       as well as the panning of the Map              */
+  /*                                                      */
+  /********************************************************/
+    /**
+     * APIMethod: getCenter
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>}
+     */
+    getCenter: function () {
+        var center = null;
+        var cachedCenter = this.getCachedCenter();
+        if (cachedCenter) {
+            center = cachedCenter.clone();
+        }
+        return center;
+    },
+
+    /**
+     * Method: getCachedCenter
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>}
+     */
+    getCachedCenter: function() {
+        if (!this.center && this.size) {
+            this.center = this.getLonLatFromViewPortPx(
+                new OpenLayers.Pixel(this.size.w / 2, this.size.h / 2)
+            );
+        }
+        return this.center;
+    },
+
+    /**
+     * APIMethod: getZoom
+     * 
+     * Returns:
+     * {Integer}
+     */
+    getZoom: function () {
+        return this.zoom;
+    },
+    
+    /** 
+     * APIMethod: pan
+     * Allows user to pan by a value of screen pixels
+     * 
+     * Parameters:
+     * dx - {Integer}
+     * dy - {Integer}
+     * options - {Object} Options to configure panning:
+     *  - *animate* {Boolean} Use panTo instead of setCenter. Default is true.
+     *  - *dragging* {Boolean} Call setCenter with dragging true.  Default is
+     *    false.
+     */
+    pan: function(dx, dy, options) {
+        options = OpenLayers.Util.applyDefaults(options, {
+            animate: true,
+            dragging: false
+        });
+        if (options.dragging) {
+            if (dx != 0 || dy != 0) {
+                this.moveByPx(dx, dy);
+            }
+        } else {
+            // getCenter
+            var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter());
+
+            // adjust
+            var newCenterPx = centerPx.add(dx, dy);
+
+            if (this.dragging || !newCenterPx.equals(centerPx)) {
+                var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);
+                if (options.animate) {
+                    this.panTo(newCenterLonLat);
+                } else {
+                    this.moveTo(newCenterLonLat);
+                    this.dragging = false;
+                    this.events.triggerEvent("moveend");
+                }    
+            }
+        }        
+
+   },
+   
+   /** 
+     * APIMethod: panTo
+     * Allows user to pan to a new lonlat
+     * If the new lonlat is in the current extent the map will slide smoothly
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     */
+    panTo: function(lonlat) {
+        if (this.panMethod && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
+            if (!this.panTween) {
+                this.panTween = new OpenLayers.Tween(this.panMethod);
+            }
+            var center = this.getCachedCenter();
+
+            // center will not change, don't do nothing
+            if (lonlat.equals(center)) {
+                return;
+            }
+
+            var from = this.getPixelFromLonLat(center);
+            var to = this.getPixelFromLonLat(lonlat);
+            var vector = { x: to.x - from.x, y: to.y - from.y };
+            var last = { x: 0, y: 0 };
+
+            this.panTween.start( { x: 0, y: 0 }, vector, this.panDuration, {
+                callbacks: {
+                    eachStep: OpenLayers.Function.bind(function(px) {
+                        var x = px.x - last.x,
+                            y = px.y - last.y;
+                        this.moveByPx(x, y);
+                        last.x = Math.round(px.x);
+                        last.y = Math.round(px.y);
+                    }, this),
+                    done: OpenLayers.Function.bind(function(px) {
+                        this.moveTo(lonlat);
+                        this.dragging = false;
+                        this.events.triggerEvent("moveend");
+                    }, this)
+                }
+            });
+        } else {
+            this.setCenter(lonlat);
+        }
+    },
+
+    /**
+     * APIMethod: setCenter
+     * Set the map center (and optionally, the zoom level).
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>} The new center location.
+     * zoom - {Integer} Optional zoom level.
+     * dragging - {Boolean} Specifies whether or not to trigger 
+     *                      movestart/end events
+     * forceZoomChange - {Boolean} Specifies whether or not to trigger zoom 
+     *                             change events (needed on baseLayer change)
+     *
+     * TBD: reconsider forceZoomChange in 3.0
+     */
+    setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
+        this.panTween && this.panTween.stop();             
+        this.moveTo(lonlat, zoom, {
+            'dragging': dragging,
+            'forceZoomChange': forceZoomChange
+        });
+    },
+    
+    /** 
+     * Method: moveByPx
+     * Drag the map by pixels.
+     *
+     * Parameters:
+     * dx - {Number}
+     * dy - {Number}
+     */
+    moveByPx: function(dx, dy) {
+        var hw = this.size.w / 2;
+        var hh = this.size.h / 2;
+        var x = hw + dx;
+        var y = hh + dy;
+        var wrapDateLine = this.baseLayer.wrapDateLine;
+        var xRestriction = 0;
+        var yRestriction = 0;
+        if (this.restrictedExtent) {
+            xRestriction = hw;
+            yRestriction = hh;
+            // wrapping the date line makes no sense for restricted extents
+            wrapDateLine = false;
+        }
+        dx = wrapDateLine ||
+                    x <= this.maxPx.x - xRestriction &&
+                    x >= this.minPx.x + xRestriction ? Math.round(dx) : 0;
+        dy = y <= this.maxPx.y - yRestriction &&
+                    y >= this.minPx.y + yRestriction ? Math.round(dy) : 0;
+        var minX = this.minPx.x, maxX = this.maxPx.x;
+        if (dx || dy) {
+            if (!this.dragging) {
+                this.dragging = true;
+                this.events.triggerEvent("movestart");
+            }
+            this.center = null;
+            if (dx) {
+                this.layerContainerDiv.style.left =
+                    parseInt(this.layerContainerDiv.style.left) - dx + "px";
+                this.minPx.x -= dx;
+                this.maxPx.x -= dx;
+                if (wrapDateLine) {
+                    if (this.maxPx.x > maxX) {
+                        this.maxPx.x -= (maxX - minX);
+                    }
+                    if (this.minPx.x < minX) {
+                        this.minPx.x += (maxX - minX);
+                    }
+                }
+            }
+            if (dy) {
+                this.layerContainerDiv.style.top =
+                    parseInt(this.layerContainerDiv.style.top) - dy + "px";
+                this.minPx.y -= dy;
+                this.maxPx.y -= dy;
+            }
+            var layer, i, len;
+            for (i=0, len=this.layers.length; i<len; ++i) {
+                layer = this.layers[i];
+                if (layer.visibility &&
+                    (layer === this.baseLayer || layer.inRange)) {
+                    layer.moveByPx(dx, dy);
+                    layer.events.triggerEvent("move");
+                }
+            }
+            this.events.triggerEvent("move");
+        }
+    },
+
+    /**
+     * Method: moveTo
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     * zoom - {Integer}
+     * options - {Object}
+     */
+    moveTo: function(lonlat, zoom, options) {
+        if (!options) { 
+            options = {};
+        }
+        if (zoom != null) {
+            zoom = parseFloat(zoom);
+            if (!this.fractionalZoom) {
+                zoom = Math.round(zoom);
+            }
+        }
+        // dragging is false by default
+        var dragging = options.dragging || this.dragging;
+        // forceZoomChange is false by default
+        var forceZoomChange = options.forceZoomChange;
+
+        if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) {
+            lonlat = this.maxExtent.getCenterLonLat();
+            this.center = lonlat.clone();
+        }
+
+        if(this.restrictedExtent != null) {
+            // In 3.0, decide if we want to change interpretation of maxExtent.
+            if(lonlat == null) { 
+                lonlat = this.center; 
+            }
+            if(zoom == null) { 
+                zoom = this.getZoom(); 
+            }
+            var resolution = this.getResolutionForZoom(zoom);
+            var extent = this.calculateBounds(lonlat, resolution); 
+            if(!this.restrictedExtent.containsBounds(extent)) {
+                var maxCenter = this.restrictedExtent.getCenterLonLat(); 
+                if(extent.getWidth() > this.restrictedExtent.getWidth()) { 
+                    lonlat = new OpenLayers.LonLat(maxCenter.lon, lonlat.lat); 
+                } else if(extent.left < this.restrictedExtent.left) {
+                    lonlat = lonlat.add(this.restrictedExtent.left -
+                                        extent.left, 0); 
+                } else if(extent.right > this.restrictedExtent.right) { 
+                    lonlat = lonlat.add(this.restrictedExtent.right -
+                                        extent.right, 0); 
+                } 
+                if(extent.getHeight() > this.restrictedExtent.getHeight()) { 
+                    lonlat = new OpenLayers.LonLat(lonlat.lon, maxCenter.lat); 
+                } else if(extent.bottom < this.restrictedExtent.bottom) { 
+                    lonlat = lonlat.add(0, this.restrictedExtent.bottom -
+                                        extent.bottom); 
+                } 
+                else if(extent.top > this.restrictedExtent.top) { 
+                    lonlat = lonlat.add(0, this.restrictedExtent.top -
+                                        extent.top); 
+                } 
+            }
+        }
+        
+        var zoomChanged = forceZoomChange || (
+                            (this.isValidZoomLevel(zoom)) && 
+                            (zoom != this.getZoom()) );
+
+        var centerChanged = (this.isValidLonLat(lonlat)) && 
+                            (!lonlat.equals(this.center));
+
+        // if neither center nor zoom will change, no need to do anything
+        if (zoomChanged || centerChanged || dragging) {
+            dragging || this.events.triggerEvent("movestart");
+
+            if (centerChanged) {
+                if (!zoomChanged && this.center) { 
+                    // if zoom hasnt changed, just slide layerContainer
+                    //  (must be done before setting this.center to new value)
+                    this.centerLayerContainer(lonlat);
+                }
+                this.center = lonlat.clone();
+            }
+
+            var res = zoomChanged ?
+                this.getResolutionForZoom(zoom) : this.getResolution();
+            // (re)set the layerContainerDiv's location
+            if (zoomChanged || this.layerContainerOrigin == null) {
+                this.layerContainerOrigin = this.getCachedCenter();
+                this.layerContainerDiv.style.left = "0px";
+                this.layerContainerDiv.style.top  = "0px";
+                var maxExtent = this.getMaxExtent({restricted: true});
+                var maxExtentCenter = maxExtent.getCenterLonLat();
+                var lonDelta = this.center.lon - maxExtentCenter.lon;
+                var latDelta = maxExtentCenter.lat - this.center.lat;
+                var extentWidth = Math.round(maxExtent.getWidth() / res);
+                var extentHeight = Math.round(maxExtent.getHeight() / res);
+                var left = (this.size.w - extentWidth) / 2 - lonDelta / res;
+                var top = (this.size.h - extentHeight) / 2 - latDelta / res;
+                this.minPx = new OpenLayers.Pixel(left, top);
+                this.maxPx = new OpenLayers.Pixel(left + extentWidth, top + extentHeight);
+            }
+
+            if (zoomChanged) {
+                this.zoom = zoom;
+                this.resolution = res;
+                // zoom level has changed, increment viewRequestID.
+                this.viewRequestID++;
+            }    
+            
+            var bounds = this.getExtent();
+            
+            //send the move call to the baselayer and all the overlays    
+
+            if(this.baseLayer.visibility) {
+                this.baseLayer.moveTo(bounds, zoomChanged, options.dragging);
+                options.dragging || this.baseLayer.events.triggerEvent(
+                    "moveend", {zoomChanged: zoomChanged}
+                );
+            }
+            
+            bounds = this.baseLayer.getExtent();
+            
+            for (var i=this.layers.length-1; i>=0; --i) {
+                var layer = this.layers[i];
+                if (layer !== this.baseLayer && !layer.isBaseLayer) {
+                    var inRange = layer.calculateInRange();
+                    if (layer.inRange != inRange) {
+                        // the inRange property has changed. If the layer is
+                        // no longer in range, we turn it off right away. If
+                        // the layer is no longer out of range, the moveTo
+                        // call below will turn on the layer.
+                        layer.inRange = inRange;
+                        if (!inRange) {
+                            layer.display(false);
+                        }
+                        this.events.triggerEvent("changelayer", {
+                            layer: layer, property: "visibility"
+                        });
+                    }
+                    if (inRange && layer.visibility) {
+                        layer.moveTo(bounds, zoomChanged, options.dragging);
+                        options.dragging || layer.events.triggerEvent(
+                            "moveend", {zoomChanged: zoomChanged}
+                        );
+                    }
+                }                
+            }
+            
+            this.events.triggerEvent("move");
+            dragging || this.events.triggerEvent("moveend");
+
+            if (zoomChanged) {
+                //redraw popups
+                for (var i=0, len=this.popups.length; i<len; i++) {
+                    this.popups[i].updatePosition();
+                }
+                this.events.triggerEvent("zoomend");
+            }
+        }
+    },
+
+    /** 
+     * Method: centerLayerContainer
+     * This function takes care to recenter the layerContainerDiv.
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     */
+    centerLayerContainer: function (lonlat) {
+        var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin);
+        var newPx = this.getViewPortPxFromLonLat(lonlat);
+
+        if ((originPx != null) && (newPx != null)) {
+            var oldLeft = parseInt(this.layerContainerDiv.style.left);
+            var oldTop = parseInt(this.layerContainerDiv.style.top);
+            var newLeft = Math.round(originPx.x - newPx.x);
+            var newTop = Math.round(originPx.y - newPx.y);
+            this.layerContainerDiv.style.left = newLeft + "px";
+            this.layerContainerDiv.style.top  = newTop + "px";
+            var dx = oldLeft - newLeft;
+            var dy = oldTop - newTop;
+            this.minPx.x -= dx;
+            this.maxPx.x -= dx;
+            this.minPx.y -= dy;
+            this.maxPx.y -= dy;
+        }        
+    },
+
+    /**
+     * Method: isValidZoomLevel
+     * 
+     * Parameters:
+     * zoomLevel - {Integer}
+     * 
+     * Returns:
+     * {Boolean} Whether or not the zoom level passed in is non-null and 
+     *           within the min/max range of zoom levels.
+     */
+    isValidZoomLevel: function(zoomLevel) {
+        return ( (zoomLevel != null) &&
+                 (zoomLevel >= 0) && 
+                 (zoomLevel < this.getNumZoomLevels()) );
+    },
+    
+    /**
+     * Method: isValidLonLat
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {Boolean} Whether or not the lonlat passed in is non-null and within
+     *           the maxExtent bounds
+     */
+    isValidLonLat: function(lonlat) {
+        var valid = false;
+        if (lonlat != null) {
+            var maxExtent = this.getMaxExtent();
+            valid = maxExtent.containsLonLat(lonlat);        
+        }
+        return valid;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Layer Options                        */
+  /*                                                      */
+  /*    Accessor functions to Layer Options parameters    */
+  /*                                                      */
+  /********************************************************/
+    
+    /**
+     * APIMethod: getProjection
+     * This method returns a string representing the projection. In 
+     *     the case of projection support, this will be the srsCode which
+     *     is loaded -- otherwise it will simply be the string value that
+     *     was passed to the projection at startup.
+     *
+     * FIXME: In 3.0, we will remove getProjectionObject, and instead
+     *     return a Projection object from this function. 
+     * 
+     * Returns:
+     * {String} The Projection string from the base layer or null. 
+     */
+    getProjection: function() {
+        var projection = this.getProjectionObject();
+        return projection ? projection.getCode() : null;
+    },
+    
+    /**
+     * APIMethod: getProjectionObject
+     * Returns the projection obect from the baselayer.
+     *
+     * Returns:
+     * {<OpenLayers.Projection>} The Projection of the base layer.
+     */
+    getProjectionObject: function() {
+        var projection = null;
+        if (this.baseLayer != null) {
+            projection = this.baseLayer.projection;
+        }
+        return projection;
+    },
+    
+    /**
+     * APIMethod: getMaxResolution
+     * 
+     * Returns:
+     * {String} The Map's Maximum Resolution
+     */
+    getMaxResolution: function() {
+        var maxResolution = null;
+        if (this.baseLayer != null) {
+            maxResolution = this.baseLayer.maxResolution;
+        }
+        return maxResolution;
+    },
+        
+    /**
+     * APIMethod: getMaxExtent
+     *
+     * Parameters:
+     * options - {Object} 
+     * 
+     * Allowed Options:
+     * restricted - {Boolean} If true, returns restricted extent (if it is 
+     *     available.)
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} The maxExtent property as set on the current 
+     *     baselayer, unless the 'restricted' option is set, in which case
+     *     the 'restrictedExtent' option from the map is returned (if it
+     *     is set).
+     */
+    getMaxExtent: function (options) {
+        var maxExtent = null;
+        if(options && options.restricted && this.restrictedExtent){
+            maxExtent = this.restrictedExtent;
+        } else if (this.baseLayer != null) {
+            maxExtent = this.baseLayer.maxExtent;
+        }        
+        return maxExtent;
+    },
+    
+    /**
+     * APIMethod: getNumZoomLevels
+     * 
+     * Returns:
+     * {Integer} The total number of zoom levels that can be displayed by the 
+     *           current baseLayer.
+     */
+    getNumZoomLevels: function() {
+        var numZoomLevels = null;
+        if (this.baseLayer != null) {
+            numZoomLevels = this.baseLayer.numZoomLevels;
+        }
+        return numZoomLevels;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /*    The following functions, all publicly exposed     */
+  /*       in the API?, are all merely wrappers to the    */
+  /*       the same calls on whatever layer is set as     */
+  /*                the current base layer                */
+  /*                                                      */
+  /********************************************************/
+
+    /**
+     * APIMethod: getExtent
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
+     *                       bounds of the current viewPort. 
+     *                       If no baselayer is set, returns null.
+     */
+    getExtent: function () {
+        var extent = null;
+        if (this.baseLayer != null) {
+            extent = this.baseLayer.getExtent();
+        }
+        return extent;
+    },
+
+    /**
+     * APIMethod: getResolution
+     * 
+     * Returns:
+     * {Float} The current resolution of the map. 
+     *         If no baselayer is set, returns null.
+     */
+    getResolution: function () {
+        var resolution = null;
+        if (this.baseLayer != null) {
+            resolution = this.baseLayer.getResolution();
+        } else if(this.allOverlays === true && this.layers.length > 0) {
+            // while adding the 1st layer to the map in allOverlays mode,
+            // this.baseLayer is not set yet when we need the resolution
+            // for calculateInRange.
+            resolution = this.layers[0].getResolution();
+        }
+        return resolution;
+    },
+
+    /**
+     * APIMethod: getUnits
+     * 
+     * Returns:
+     * {Float} The current units of the map. 
+     *         If no baselayer is set, returns null.
+     */
+    getUnits: function () {
+        var units = null;
+        if (this.baseLayer != null) {
+            units = this.baseLayer.units;
+        }
+        return units;
+    },
+
+     /**
+      * APIMethod: getScale
+      * 
+      * Returns:
+      * {Float} The current scale denominator of the map. 
+      *         If no baselayer is set, returns null.
+      */
+    getScale: function () {
+        var scale = null;
+        if (this.baseLayer != null) {
+            var res = this.getResolution();
+            var units = this.baseLayer.units;
+            scale = OpenLayers.Util.getScaleFromResolution(res, units);
+        }
+        return scale;
+    },
+
+
+    /**
+     * APIMethod: getZoomForExtent
+     * 
+     * Parameters: 
+     * bounds - {<OpenLayers.Bounds>}
+     * closest - {Boolean} Find the zoom level that most closely fits the 
+     *     specified bounds. Note that this may result in a zoom that does 
+     *     not exactly contain the entire extent.
+     *     Default is false.
+     * 
+     * Returns:
+     * {Integer} A suitable zoom level for the specified bounds.
+     *           If no baselayer is set, returns null.
+     */
+    getZoomForExtent: function (bounds, closest) {
+        var zoom = null;
+        if (this.baseLayer != null) {
+            zoom = this.baseLayer.getZoomForExtent(bounds, closest);
+        }
+        return zoom;
+    },
+
+    /**
+     * APIMethod: getResolutionForZoom
+     * 
+     * Parameter:
+     * zoom - {Float}
+     * 
+     * Returns:
+     * {Float} A suitable resolution for the specified zoom.  If no baselayer
+     *     is set, returns null.
+     */
+    getResolutionForZoom: function(zoom) {
+        var resolution = null;
+        if(this.baseLayer) {
+            resolution = this.baseLayer.getResolutionForZoom(zoom);
+        }
+        return resolution;
+    },
+
+    /**
+     * APIMethod: getZoomForResolution
+     * 
+     * Parameter:
+     * resolution - {Float}
+     * closest - {Boolean} Find the zoom level that corresponds to the absolute 
+     *     closest resolution, which may result in a zoom whose corresponding
+     *     resolution is actually smaller than we would have desired (if this
+     *     is being called from a getZoomForExtent() call, then this means that
+     *     the returned zoom index might not actually contain the entire 
+     *     extent specified... but it'll be close).
+     *     Default is false.
+     * 
+     * Returns:
+     * {Integer} A suitable zoom level for the specified resolution.
+     *           If no baselayer is set, returns null.
+     */
+    getZoomForResolution: function(resolution, closest) {
+        var zoom = null;
+        if (this.baseLayer != null) {
+            zoom = this.baseLayer.getZoomForResolution(resolution, closest);
+        }
+        return zoom;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                  Zooming Functions                   */
+  /*                                                      */
+  /*    The following functions, all publicly exposed     */
+  /*       in the API, are all merely wrappers to the     */
+  /*               the setCenter() function               */
+  /*                                                      */
+  /********************************************************/
+  
+    /** 
+     * APIMethod: zoomTo
+     * Zoom to a specific zoom level
+     * 
+     * Parameters:
+     * zoom - {Integer}
+     */
+    zoomTo: function(zoom) {
+        if (this.isValidZoomLevel(zoom)) {
+            this.setCenter(null, zoom);
+        }
+    },
+    
+    /**
+     * APIMethod: zoomIn
+     * 
+     */
+    zoomIn: function() {
+        this.zoomTo(this.getZoom() + 1);
+    },
+    
+    /**
+     * APIMethod: zoomOut
+     * 
+     */
+    zoomOut: function() {
+        this.zoomTo(this.getZoom() - 1);
+    },
+
+    /**
+     * APIMethod: zoomToExtent
+     * Zoom to the passed in bounds, recenter
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * closest - {Boolean} Find the zoom level that most closely fits the 
+     *     specified bounds. Note that this may result in a zoom that does 
+     *     not exactly contain the entire extent.
+     *     Default is false.
+     * 
+     */
+    zoomToExtent: function(bounds, closest) {
+        var center = bounds.getCenterLonLat();
+        if (this.baseLayer.wrapDateLine) {
+            var maxExtent = this.getMaxExtent();
+
+            //fix straddling bounds (in the case of a bbox that straddles the 
+            // dateline, it's left and right boundaries will appear backwards. 
+            // we fix this by allowing a right value that is greater than the
+            // max value at the dateline -- this allows us to pass a valid 
+            // bounds to calculate zoom)
+            //
+            bounds = bounds.clone();
+            while (bounds.right < bounds.left) {
+                bounds.right += maxExtent.getWidth();
+            }
+            //if the bounds was straddling (see above), then the center point 
+            // we got from it was wrong. So we take our new bounds and ask it
+            // for the center. Because our new bounds is at least partially 
+            // outside the bounds of maxExtent, the new calculated center 
+            // might also be. We don't want to pass a bad center value to 
+            // setCenter, so we have it wrap itself across the date line.
+            //
+            center = bounds.getCenterLonLat().wrapDateLine(maxExtent);
+        }
+        this.setCenter(center, this.getZoomForExtent(bounds, closest));
+    },
+
+    /** 
+     * APIMethod: zoomToMaxExtent
+     * Zoom to the full extent and recenter.
+     *
+     * Parameters:
+     * options - 
+     * 
+     * Allowed Options:
+     * restricted - {Boolean} True to zoom to restricted extent if it is 
+     *     set. Defaults to true.
+     */
+    zoomToMaxExtent: function(options) {
+        //restricted is true by default
+        var restricted = (options) ? options.restricted : true;
+
+        var maxExtent = this.getMaxExtent({
+            'restricted': restricted 
+        });
+        this.zoomToExtent(maxExtent);
+    },
+
+    /** 
+     * APIMethod: zoomToScale
+     * Zoom to a specified scale 
+     * 
+     * Parameters:
+     * scale - {float}
+     * closest - {Boolean} Find the zoom level that most closely fits the 
+     *     specified scale. Note that this may result in a zoom that does 
+     *     not exactly contain the entire extent.
+     *     Default is false.
+     * 
+     */
+    zoomToScale: function(scale, closest) {
+        var res = OpenLayers.Util.getResolutionFromScale(scale, 
+                                                         this.baseLayer.units);
+        var size = this.getSize();
+        var w_deg = size.w * res;
+        var h_deg = size.h * res;
+        var center = this.getCachedCenter();
+
+        var extent = new OpenLayers.Bounds(center.lon - w_deg / 2,
+                                           center.lat - h_deg / 2,
+                                           center.lon + w_deg / 2,
+                                           center.lat + h_deg / 2);
+        this.zoomToExtent(extent, closest);
+    },
+    
+  /********************************************************/
+  /*                                                      */
+  /*             Translation Functions                    */
+  /*                                                      */
+  /*      The following functions translate between       */
+  /*           LonLat, LayerPx, and ViewPortPx            */
+  /*                                                      */
+  /********************************************************/
+      
+  //
+  // TRANSLATION: LonLat <-> ViewPortPx
+  //
+
+    /**
+     * Method: getLonLatFromViewPortPx
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view 
+     *                       port <OpenLayers.Pixel>, translated into lon/lat
+     *                       by the current base layer.
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        var lonlat = null; 
+        if (this.baseLayer != null) {
+            lonlat = this.baseLayer.getLonLatFromViewPortPx(viewPortPx);
+        }
+        return lonlat;
+    },
+
+    /**
+     * APIMethod: getViewPortPxFromLonLat
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in 
+     *                      <OpenLayers.LonLat>, translated into view port 
+     *                      pixels by the current base layer.
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        var px = null; 
+        if (this.baseLayer != null) {
+            px = this.baseLayer.getViewPortPxFromLonLat(lonlat);
+        }
+        return px;
+    },
+
+    
+  //
+  // CONVENIENCE TRANSLATION FUNCTIONS FOR API
+  //
+
+    /**
+     * APIMethod: getLonLatFromPixel
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} An OpenLayers.LonLat corresponding to the given
+     *                       OpenLayers.Pixel, translated into lon/lat by the 
+     *                       current base layer
+     */
+    getLonLatFromPixel: function (px) {
+        return this.getLonLatFromViewPortPx(px);
+    },
+
+    /**
+     * APIMethod: getPixelFromLonLat
+     * Returns a pixel location given a map location.  The map location is
+     *     translated to an integer pixel location (in viewport pixel
+     *     coordinates) by the current base layer.
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>} A map location.
+     * 
+     * Returns: 
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel corresponding to the 
+     *     <OpenLayers.LonLat> translated into view port pixels by the current
+     *     base layer.
+     */
+    getPixelFromLonLat: function (lonlat) {
+        var px = this.getViewPortPxFromLonLat(lonlat);
+        px.x = Math.round(px.x);
+        px.y = Math.round(px.y);
+        return px;
+    },
+    
+    /**
+     * Method: getGeodesicPixelSize
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} The pixel to get the geodesic length for. If
+     *     not provided, the center pixel of the map viewport will be used.
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} The geodesic size of the pixel in kilometers.
+     */
+    getGeodesicPixelSize: function(px) {
+        var lonlat = px ? this.getLonLatFromPixel(px) : (
+            this.getCachedCenter() || new OpenLayers.LonLat(0, 0));
+        var res = this.getResolution();
+        var left = lonlat.add(-res / 2, 0);
+        var right = lonlat.add(res / 2, 0);
+        var bottom = lonlat.add(0, -res / 2);
+        var top = lonlat.add(0, res / 2);
+        var dest = new OpenLayers.Projection("EPSG:4326");
+        var source = this.getProjectionObject() || dest;
+        if(!source.equals(dest)) {
+            left.transform(source, dest);
+            right.transform(source, dest);
+            bottom.transform(source, dest);
+            top.transform(source, dest);
+        }
+        
+        return new OpenLayers.Size(
+            OpenLayers.Util.distVincenty(left, right),
+            OpenLayers.Util.distVincenty(bottom, top)
+        );
+    },
+
+
+
+  //
+  // TRANSLATION: ViewPortPx <-> LayerPx
+  //
+
+    /**
+     * APIMethod: getViewPortPxFromLayerPx
+     * 
+     * Parameters:
+     * layerPx - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} Layer Pixel translated into ViewPort Pixel 
+     *                      coordinates
+     */
+    getViewPortPxFromLayerPx:function(layerPx) {
+        var viewPortPx = null;
+        if (layerPx != null) {
+            var dX = parseInt(this.layerContainerDiv.style.left);
+            var dY = parseInt(this.layerContainerDiv.style.top);
+            viewPortPx = layerPx.add(dX, dY);            
+        }
+        return viewPortPx;
+    },
+    
+    /**
+     * APIMethod: getLayerPxFromViewPortPx
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} ViewPort Pixel translated into Layer Pixel 
+     *                      coordinates
+     */
+    getLayerPxFromViewPortPx:function(viewPortPx) {
+        var layerPx = null;
+        if (viewPortPx != null) {
+            var dX = -parseInt(this.layerContainerDiv.style.left);
+            var dY = -parseInt(this.layerContainerDiv.style.top);
+            layerPx = viewPortPx.add(dX, dY);
+            if (isNaN(layerPx.x) || isNaN(layerPx.y)) {
+                layerPx = null;
+            }
+        }
+        return layerPx;
+    },
+    
+  //
+  // TRANSLATION: LonLat <-> LayerPx
+  //
+
+    /**
+     * Method: getLonLatFromLayerPx
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>}
+     */
+    getLonLatFromLayerPx: function (px) {
+       //adjust for displacement of layerContainerDiv
+       px = this.getViewPortPxFromLayerPx(px);
+       return this.getLonLatFromViewPortPx(px);         
+    },
+    
+    /**
+     * APIMethod: getLayerPxFromLonLat
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>} lonlat
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in 
+     *                      <OpenLayers.LonLat>, translated into layer pixels 
+     *                      by the current base layer
+     */
+    getLayerPxFromLonLat: function (lonlat) {
+       //adjust for displacement of layerContainerDiv
+       var px = this.getPixelFromLonLat(lonlat);
+       return this.getLayerPxFromViewPortPx(px);         
+    },
+
+    CLASS_NAME: "OpenLayers.Map"
+});
+
+/**
+ * Constant: TILE_WIDTH
+ * {Integer} 256 Default tile width (unless otherwise specified)
+ */
+OpenLayers.Map.TILE_WIDTH = 256;
+/**
+ * Constant: TILE_HEIGHT
+ * {Integer} 256 Default tile height (unless otherwise specified)
+ */
+OpenLayers.Map.TILE_HEIGHT = 256;
+/* ======================================================================
+    OpenLayers/Layer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Map.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Layer
+ */
+OpenLayers.Layer = OpenLayers.Class({
+
+    /**
+     * APIProperty: id
+     * {String}
+     */
+    id: null,
+
+    /** 
+     * APIProperty: name
+     * {String}
+     */
+    name: null,
+
+    /** 
+     * APIProperty: div
+     * {DOMElement}
+     */
+    div: null,
+
+    /**
+     * Property: opacity
+     * {Float} The layer's opacity. Float number between 0.0 and 1.0.
+     */
+    opacity: null,
+
+    /**
+     * APIProperty: alwaysInRange
+     * {Boolean} If a layer's display should not be scale-based, this should 
+     *     be set to true. This will cause the layer, as an overlay, to always 
+     *     be 'active', by always returning true from the calculateInRange() 
+     *     function. 
+     * 
+     *     If not explicitly specified for a layer, its value will be 
+     *     determined on startup in initResolutions() based on whether or not 
+     *     any scale-specific properties have been set as options on the 
+     *     layer. If no scale-specific options have been set on the layer, we 
+     *     assume that it should always be in range.
+     * 
+     *     See #987 for more info.
+     */
+    alwaysInRange: null,   
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * layer.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * All event objects have at least the following properties:
+     * object - {Object} A reference to layer.events.object.
+     * element - {DOMElement} A reference to layer.events.element.
+     *
+     * Supported map event types:
+     * loadstart - Triggered when layer loading starts.
+     * loadend - Triggered when layer loading ends.
+     * loadcancel - Triggered when layer loading is canceled.
+     * visibilitychanged - Triggered when layer visibility is changed.
+     * move - Triggered when layer moves (triggered with every mousemove
+     *     during a drag).
+     * moveend - Triggered when layer is done moving, object passed as
+     *     argument has a zoomChanged boolean property which tells that the
+     *     zoom has changed.
+     * added - Triggered after the layer is added to a map.  Listeners will
+     *     receive an object with a *map* property referencing the map and a
+     *     *layer* property referencing the layer.
+     * removed - Triggered after the layer is removed from the map.  Listeners
+     *     will receive an object with a *map* property referencing the map and
+     *     a *layer* property referencing the layer.
+     */
+    EVENT_TYPES: ["loadstart", "loadend", "loadcancel", "visibilitychanged",
+                  "move", "moveend", "added", "removed"],
+
+    /**
+     * Constant: RESOLUTION_PROPERTIES
+     * {Array} The properties that are used for calculating resolutions
+     *     information.
+     */
+    RESOLUTION_PROPERTIES: [
+        'scales', 'resolutions',
+        'maxScale', 'minScale',
+        'maxResolution', 'minResolution',
+        'numZoomLevels', 'maxZoomLevel'
+    ],
+
+    /**
+     * APIProperty: events
+     * {<OpenLayers.Events>}
+     */
+    events: null,
+
+    /**
+     * APIProperty: map
+     * {<OpenLayers.Map>} This variable is set when the layer is added to 
+     *     the map, via the accessor function setMap().
+     */
+    map: null,
+    
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} Whether or not the layer is a base layer. This should be set 
+     *     individually by all subclasses. Default is false
+     */
+    isBaseLayer: false,
+ 
+    /**
+     * Property: alpha
+     * {Boolean} The layer's images have an alpha channel.  Default is false. 
+     */
+    alpha: false,
+
+    /** 
+     * APIProperty: displayInLayerSwitcher
+     * {Boolean} Display the layer's name in the layer switcher.  Default is
+     *     true.
+     */
+    displayInLayerSwitcher: true,
+
+    /**
+     * APIProperty: visibility
+     * {Boolean} The layer should be displayed in the map.  Default is true.
+     */
+    visibility: true,
+
+    /**
+     * APIProperty: attribution
+     * {String} Attribution string, displayed when an 
+     *     <OpenLayers.Control.Attribution> has been added to the map.
+     */
+    attribution: null, 
+
+    /** 
+     * Property: inRange
+     * {Boolean} The current map resolution is within the layer's min/max 
+     *     range. This is set in <OpenLayers.Map.setCenter> whenever the zoom 
+     *     changes.
+     */
+    inRange: false,
+    
+    /**
+     * Propery: imageSize
+     * {<OpenLayers.Size>} For layers with a gutter, the image is larger than 
+     *     the tile by twice the gutter in each dimension.
+     */
+    imageSize: null,
+    
+    /**
+     * Property: imageOffset
+     * {<OpenLayers.Pixel>} For layers with a gutter, the image offset 
+     *     represents displacement due to the gutter.
+     */
+    imageOffset: null,
+
+  // OPTIONS
+
+    /** 
+     * Property: options
+     * {Object} An optional object whose properties will be set on the layer.
+     *     Any of the layer properties can be set as a property of the options
+     *     object and sent to the constructor when the layer is created.
+     */
+    options: null,
+
+    /**
+     * APIProperty: eventListeners
+     * {Object} If set as an option at construction, the eventListeners
+     *     object will be registered with <OpenLayers.Events.on>.  Object
+     *     structure must be a listeners object as shown in the example for
+     *     the events.on method.
+     */
+    eventListeners: null,
+
+    /**
+     * APIProperty: gutter
+     * {Integer} Determines the width (in pixels) of the gutter around image
+     *     tiles to ignore.  By setting this property to a non-zero value,
+     *     images will be requested that are wider and taller than the tile
+     *     size by a value of 2 x gutter.  This allows artifacts of rendering
+     *     at tile edges to be ignored.  Set a gutter value that is equal to
+     *     half the size of the widest symbol that needs to be displayed.
+     *     Defaults to zero.  Non-tiled layers always have zero gutter.
+     */ 
+    gutter: 0, 
+
+    /**
+     * APIProperty: projection
+     * {<OpenLayers.Projection>} or {<String>} Set in the layer options to
+     *     override the default projection string this layer - also set maxExtent,
+     *     maxResolution, and units if appropriate. Can be either a string or
+     *     an <OpenLayers.Projection> object when created -- will be converted
+     *     to an object when setMap is called if a string is passed.  
+     */
+    projection: null,    
+    
+    /**
+     * APIProperty: units
+     * {String} The layer map units.  Defaults to 'degrees'.  Possible values
+     *     are 'degrees' (or 'dd'), 'm', 'ft', 'km', 'mi', 'inches'.
+     */
+    units: null,
+
+    /**
+     * APIProperty: scales
+     * {Array}  An array of map scales in descending order.  The values in the
+     *     array correspond to the map scale denominator.  Note that these
+     *     values only make sense if the display (monitor) resolution of the
+     *     client is correctly guessed by whomever is configuring the
+     *     application.  In addition, the units property must also be set.
+     *     Use <resolutions> instead wherever possible.
+     */
+    scales: null,
+
+    /**
+     * APIProperty: resolutions
+     * {Array} A list of map resolutions (map units per pixel) in descending
+     *     order.  If this is not set in the layer constructor, it will be set
+     *     based on other resolution related properties (maxExtent,
+     *     maxResolution, maxScale, etc.).
+     */
+    resolutions: null,
+    
+    /**
+     * APIProperty: maxExtent
+     * {<OpenLayers.Bounds>}  The center of these bounds will not stray outside
+     *     of the viewport extent during panning.  In addition, if
+     *     <displayOutsideMaxExtent> is set to false, data will not be
+     *     requested that falls completely outside of these bounds.
+     */
+    maxExtent: null,
+    
+    /**
+     * APIProperty: minExtent
+     * {<OpenLayers.Bounds>}
+     */
+    minExtent: null,
+    
+    /**
+     * APIProperty: maxResolution
+     * {Float} Default max is 360 deg / 256 px, which corresponds to
+     *     zoom level 0 on gmaps.  Specify a different value in the layer 
+     *     options if you are not using a geographic projection and 
+     *     displaying the whole world.
+     */
+    maxResolution: null,
+
+    /**
+     * APIProperty: minResolution
+     * {Float}
+     */
+    minResolution: null,
+
+    /**
+     * APIProperty: numZoomLevels
+     * {Integer}
+     */
+    numZoomLevels: null,
+    
+    /**
+     * APIProperty: minScale
+     * {Float}
+     */
+    minScale: null,
+    
+    /**
+     * APIProperty: maxScale
+     * {Float}
+     */
+    maxScale: null,
+
+    /**
+     * APIProperty: displayOutsideMaxExtent
+     * {Boolean} Request map tiles that are completely outside of the max 
+     *     extent for this layer. Defaults to false.
+     */
+    displayOutsideMaxExtent: false,
+
+    /**
+     * APIProperty: wrapDateLine
+     * {Boolean} #487 for more info.   
+     */
+    wrapDateLine: false,
+    
+    /**
+     * APIProperty: transitionEffect
+     * {String} The transition effect to use when the map is panned or
+     *     zoomed.  
+     *
+     * There are currently two supported values:
+     *  - *null* No transition effect (the default).
+     *  - *resize*  Existing tiles are resized on zoom to provide a visual
+     *    effect of the zoom having taken place immediately.  As the
+     *    new tiles become available, they are drawn over top of the
+     *    resized tiles.
+     */
+    transitionEffect: null,
+    
+    /**
+     * Property: SUPPORTED_TRANSITIONS
+     * {Array} An immutable (that means don't change it!) list of supported 
+     *     transitionEffect values.
+     */
+    SUPPORTED_TRANSITIONS: ['resize'],
+
+    /**
+     * Property: metadata
+     * {Object} This object can be used to store additional information on a
+     *     layer object.
+     */
+    metadata: {},
+    
+    /**
+     * Constructor: OpenLayers.Layer
+     *
+     * Parameters:
+     * name - {String} The layer name
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+
+        this.addOptions(options);
+
+        this.name = name;
+        
+        if (this.id == null) {
+
+            this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+
+            this.div = OpenLayers.Util.createDiv(this.id);
+            this.div.style.width = "100%";
+            this.div.style.height = "100%";
+            this.div.dir = "ltr";
+
+            this.events = new OpenLayers.Events(this, this.div, 
+                                                this.EVENT_TYPES);
+            if(this.eventListeners instanceof Object) {
+                this.events.on(this.eventListeners);
+            }
+
+        }
+
+        if (this.wrapDateLine) {
+            this.displayOutsideMaxExtent = true;
+        }
+    },
+    
+    /**
+     * Method: destroy
+     * Destroy is a destructor: this is to alleviate cyclic references which
+     *     the Javascript garbage cleaner can not take care of on its own.
+     *
+     * Parameters:
+     * setNewBaseLayer - {Boolean} Set a new base layer when this layer has
+     *     been destroyed.  Default is true.
+     */
+    destroy: function(setNewBaseLayer) {
+        if (setNewBaseLayer == null) {
+            setNewBaseLayer = true;
+        }
+        if (this.map != null) {
+            this.map.removeLayer(this, setNewBaseLayer);
+        }
+        this.projection = null;
+        this.map = null;
+        this.name = null;
+        this.div = null;
+        this.options = null;
+
+        if (this.events) {
+            if(this.eventListeners) {
+                this.events.un(this.eventListeners);
+            }
+            this.events.destroy();
+        }
+        this.eventListeners = null;
+        this.events = null;
+    },
+    
+   /**
+    * Method: clone
+    *
+    * Parameters:
+    * obj - {<OpenLayers.Layer>} The layer to be cloned
+    *
+    * Returns:
+    * {<OpenLayers.Layer>} An exact clone of this <OpenLayers.Layer>
+    */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer(this.name, this.getOptions());
+        }
+        
+        // catch any randomly tagged-on properties
+        OpenLayers.Util.applyDefaults(obj, this);
+        
+        // a cloned layer should never have its map property set
+        //  because it has not been added to a map yet. 
+        obj.map = null;
+        
+        return obj;
+    },
+    
+    /**
+     * Method: getOptions
+     * Extracts an object from the layer with the properties that were set as
+     *     options, but updates them with the values currently set on the
+     *     instance.
+     * 
+     * Returns:
+     * {Object} the <options> of the layer, representing the current state.
+     */
+    getOptions: function() {
+        var options = {};
+        for(var o in this.options) {
+            options[o] = this[o];
+        }
+        return options;
+    },
+    
+    /** 
+     * APIMethod: setName
+     * Sets the new layer name for this layer.  Can trigger a changelayer event
+     *     on the map.
+     *
+     * Parameters:
+     * newName - {String} The new name.
+     */
+    setName: function(newName) {
+        if (newName != this.name) {
+            this.name = newName;
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "name"
+                });
+            }
+        }
+    },    
+    
+   /**
+    * APIMethod: addOptions
+    * 
+    * Parameters:
+    * newOptions - {Object}
+    * reinitialize - {Boolean} If set to true, and if resolution options of the
+    *     current baseLayer were changed, the map will be recentered to make
+    *     sure that it is displayed with a valid resolution, and a
+    *     changebaselayer event will be triggered.
+    */
+    addOptions: function (newOptions, reinitialize) {
+
+        if (this.options == null) {
+            this.options = {};
+        }
+
+        // update our copy for clone
+        OpenLayers.Util.extend(this.options, newOptions);
+
+        // add new options to this
+        OpenLayers.Util.extend(this, newOptions);
+
+        // make sure this.projection references a projection object
+        if(typeof this.projection == "string") {
+            this.projection = new OpenLayers.Projection(this.projection);
+        }
+
+        // get the units from the projection, if we have a projection
+        // and it it has units
+        if(this.projection && this.projection.getUnits()) {
+            this.units = this.projection.getUnits();
+        }
+
+        // re-initialize resolutions if necessary, i.e. if any of the
+        // properties of the "properties" array defined below is set
+        // in the new options
+        if(this.map) {
+            // store current resolution so we can try to restore it later
+            var resolution = this.map.getResolution();
+            var properties = this.RESOLUTION_PROPERTIES.concat(
+                ["projection", "units", "minExtent", "maxExtent"]
+            );
+            for(var o in newOptions) {
+                if(newOptions.hasOwnProperty(o) &&
+                   OpenLayers.Util.indexOf(properties, o) >= 0) {
+
+                    this.initResolutions();
+                    if (reinitialize && this.map.baseLayer === this) {
+                        // update map position, and restore previous resolution
+                        this.map.setCenter(this.map.getCenter(),
+                            this.map.getZoomForResolution(resolution),
+                            false, true
+                        );
+                        // trigger a changebaselayer event to make sure that
+                        // all controls (especially
+                        // OpenLayers.Control.PanZoomBar) get notified of the
+                        // new options
+                        this.map.events.triggerEvent("changebaselayer", {
+                            layer: this
+                        });
+                    }
+                    break;
+                }
+            }
+        }
+    },
+
+    /**
+     * APIMethod: onMapResize
+     * This function can be implemented by subclasses
+     */
+    onMapResize: function() {
+        //this function can be implemented by subclasses  
+    },
+
+    /**
+     * APIMethod: redraw
+     * Redraws the layer.  Returns true if the layer was redrawn, false if not.
+     *
+     * Returns:
+     * {Boolean} The layer was redrawn.
+     */
+    redraw: function() {
+        var redrawn = false;
+        if (this.map) {
+
+            // min/max Range may have changed
+            this.inRange = this.calculateInRange();
+
+            // map's center might not yet be set
+            var extent = this.getExtent();
+
+            if (extent && this.inRange && this.visibility) {
+                var zoomChanged = true;
+                this.moveTo(extent, zoomChanged, false);
+                this.events.triggerEvent("moveend",
+                    {"zoomChanged": zoomChanged});
+                redrawn = true;
+            }
+        }
+        return redrawn;
+    },
+
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to
+     *     do some init work in that case.
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        var display = this.visibility;
+        if (!this.isBaseLayer) {
+            display = display && this.inRange;
+        }
+        this.display(display);
+    },
+
+    /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector. To be implemented by subclasses.
+     *
+     * Parameters:
+     * dx - {Number} The x coord of the displacement vector.
+     * dy - {Number} The y coord of the displacement vector.
+     */
+    moveByPx: function(dx, dy) {
+    },
+
+    /**
+     * Method: setMap
+     * Set the map property for the layer. This is done through an accessor
+     *     so that subclasses can override this and take special action once 
+     *     they have their map variable set. 
+     * 
+     *     Here we take care to bring over any of the necessary default 
+     *     properties from the map. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        if (this.map == null) {
+        
+            this.map = map;
+            
+            // grab some essential layer data from the map if it hasn't already
+            //  been set
+            this.maxExtent = this.maxExtent || this.map.maxExtent;
+            this.minExtent = this.minExtent || this.map.minExtent;
+
+            this.projection = this.projection || this.map.projection;
+            if (typeof this.projection == "string") {
+                this.projection = new OpenLayers.Projection(this.projection);
+            }
+
+            // Check the projection to see if we can get units -- if not, refer
+            // to properties.
+            this.units = this.projection.getUnits() ||
+                         this.units || this.map.units;
+            
+            this.initResolutions();
+            
+            if (!this.isBaseLayer) {
+                this.inRange = this.calculateInRange();
+                var show = ((this.visibility) && (this.inRange));
+                this.div.style.display = show ? "" : "none";
+            }
+            
+            // deal with gutters
+            this.setTileSize();
+        }
+    },
+    
+    /**
+     * Method: afterAdd
+     * Called at the end of the map.addLayer sequence.  At this point, the map
+     *     will have a base layer.  To be overridden by subclasses.
+     */
+    afterAdd: function() {
+    },
+    
+    /**
+     * APIMethod: removeMap
+     * Just as setMap() allows each layer the possibility to take a 
+     *     personalized action on being added to the map, removeMap() allows
+     *     each layer to take a personalized action on being removed from it. 
+     *     For now, this will be mostly unused, except for the EventPane layer,
+     *     which needs this hook so that it can remove the special invisible
+     *     pane. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        //to be overridden by subclasses
+    },
+    
+    /**
+     * APIMethod: getImageSize
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} optional tile bounds, can be used
+     *     by subclasses that have to deal with different tile sizes at the
+     *     layer extent edges (e.g. Zoomify)
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} The size that the image should be, taking into 
+     *     account gutters.
+     */ 
+    getImageSize: function(bounds) { 
+        return (this.imageSize || this.tileSize); 
+    },    
+  
+    /**
+     * APIMethod: setTileSize
+     * Set the tile size based on the map size.  This also sets layer.imageSize
+     *     and layer.imageOffset for use by Tile.Image.
+     * 
+     * Parameters:
+     * size - {<OpenLayers.Size>}
+     */
+    setTileSize: function(size) {
+        var tileSize = (size) ? size :
+                                ((this.tileSize) ? this.tileSize :
+                                                   this.map.getTileSize());
+        this.tileSize = tileSize;
+        if(this.gutter) {
+          // layers with gutters need non-null tile sizes
+          //if(tileSize == null) {
+          //    OpenLayers.console.error("Error in layer.setMap() for " +
+          //                              this.name + ": layers with " +
+          //                              "gutters need non-null tile sizes");
+          //}
+            this.imageOffset = new OpenLayers.Pixel(-this.gutter, 
+                                                    -this.gutter); 
+            this.imageSize = new OpenLayers.Size(tileSize.w + (2*this.gutter), 
+                                                 tileSize.h + (2*this.gutter)); 
+        }
+    },
+
+    /**
+     * APIMethod: getVisibility
+     * 
+     * Returns:
+     * {Boolean} The layer should be displayed (if in range).
+     */
+    getVisibility: function() {
+        return this.visibility;
+    },
+
+    /** 
+     * APIMethod: setVisibility
+     * Set the visibility flag for the layer and hide/show & redraw 
+     *     accordingly. Fire event unless otherwise specified
+     * 
+     * Note that visibility is no longer simply whether or not the layer's
+     *     style.display is set to "block". Now we store a 'visibility' state 
+     *     property on the layer class, this allows us to remember whether or 
+     *     not we *desire* for a layer to be visible. In the case where the 
+     *     map's resolution is out of the layer's range, this desire may be 
+     *     subverted.
+     * 
+     * Parameters:
+     * visibility - {Boolean} Whether or not to display the layer (if in range)
+     */
+    setVisibility: function(visibility) {
+        if (visibility != this.visibility) {
+            this.visibility = visibility;
+            this.display(visibility);
+            this.redraw();
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "visibility"
+                });
+            }
+            this.events.triggerEvent("visibilitychanged");
+        }
+    },
+
+    /** 
+     * APIMethod: display
+     * Hide or show the Layer. This is designed to be used internally, and 
+     *     is not generally the way to enable or disable the layer. For that,
+     *     use the setVisibility function instead..
+     * 
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(display) {
+        if (display != (this.div.style.display != "none")) {
+            this.div.style.display = (display && this.calculateInRange()) ? "block" : "none";
+        }
+    },
+
+    /**
+     * APIMethod: calculateInRange
+     * 
+     * Returns:
+     * {Boolean} The layer is displayable at the current map's current
+     *     resolution. Note that if 'alwaysInRange' is true for the layer, 
+     *     this function will always return true.
+     */
+    calculateInRange: function() {
+        var inRange = false;
+
+        if (this.alwaysInRange) {
+            inRange = true;
+        } else {
+            if (this.map) {
+                var resolution = this.map.getResolution();
+                inRange = ( (resolution >= this.minResolution) &&
+                            (resolution <= this.maxResolution) );
+            }
+        }
+        return inRange;
+    },
+
+    /** 
+     * APIMethod: setIsBaseLayer
+     * 
+     * Parameters:
+     * isBaseLayer - {Boolean}
+     */
+    setIsBaseLayer: function(isBaseLayer) {
+        if (isBaseLayer != this.isBaseLayer) {
+            this.isBaseLayer = isBaseLayer;
+            if (this.map != null) {
+                this.map.events.triggerEvent("changebaselayer", {
+                    layer: this
+                });
+            }
+        }
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /********************************************************/
+  
+    /** 
+     * Method: initResolutions
+     * This method's responsibility is to set up the 'resolutions' array 
+     *     for the layer -- this array is what the layer will use to interface
+     *     between the zoom levels of the map and the resolution display 
+     *     of the layer.
+     * 
+     * The user has several options that determine how the array is set up.
+     *  
+     * For a detailed explanation, see the following wiki from the 
+     *     openlayers.org homepage:
+     *     http://trac.openlayers.org/wiki/SettingZoomLevels
+     */
+    initResolutions: function() {
+
+        // ok we want resolutions, here's our strategy:
+        //
+        // 1. if resolutions are defined in the layer config, use them
+        // 2. else, if scales are defined in the layer config then derive
+        //    resolutions from these scales
+        // 3. else, attempt to calculate resolutions from maxResolution,
+        //    minResolution, numZoomLevels, maxZoomLevel set in the
+        //    layer config
+        // 4. if we still don't have resolutions, and if resolutions
+        //    are defined in the same, use them
+        // 5. else, if scales are defined in the map then derive
+        //    resolutions from these scales
+        // 6. else, attempt to calculate resolutions from maxResolution,
+        //    minResolution, numZoomLevels, maxZoomLevel set in the
+        //    map
+        // 7. hope for the best!
+
+        var i, len, p;
+        var props = {}, alwaysInRange = true;
+
+        // get resolution data from layer config
+        // (we also set alwaysInRange in the layer as appropriate)
+        for(i=0, len=this.RESOLUTION_PROPERTIES.length; i<len; i++) {
+            p = this.RESOLUTION_PROPERTIES[i];
+            props[p] = this.options[p];
+            if(alwaysInRange && this.options[p]) {
+                alwaysInRange = false;
+            }
+        }
+        if(this.alwaysInRange == null) {
+            this.alwaysInRange = alwaysInRange;
+        }
+
+        // if we don't have resolutions then attempt to derive them from scales
+        if(props.resolutions == null) {
+            props.resolutions = this.resolutionsFromScales(props.scales);
+        }
+
+        // if we still don't have resolutions then attempt to calculate them
+        if(props.resolutions == null) {
+            props.resolutions = this.calculateResolutions(props);
+        }
+
+        // if we couldn't calculate resolutions then we look at we have
+        // in the map
+        if(props.resolutions == null) {
+            for(i=0, len=this.RESOLUTION_PROPERTIES.length; i<len; i++) {
+                p = this.RESOLUTION_PROPERTIES[i];
+                props[p] = this.options[p] != null ?
+                    this.options[p] : this.map[p];
+            }
+            if(props.resolutions == null) {
+                props.resolutions = this.resolutionsFromScales(props.scales);
+            }
+            if(props.resolutions == null) {
+                props.resolutions = this.calculateResolutions(props);
+            }
+        }
+
+        // ok, we new need to set properties in the instance
+
+        // get maxResolution from the config if it's defined there
+        var maxResolution;
+        if(this.options.maxResolution &&
+           this.options.maxResolution !== "auto") {
+            maxResolution = this.options.maxResolution;
+        }
+        if(this.options.minScale) {
+            maxResolution = OpenLayers.Util.getResolutionFromScale(
+                this.options.minScale, this.units);
+        }
+
+        // get minResolution from the config if it's defined there
+        var minResolution;
+        if(this.options.minResolution &&
+           this.options.minResolution !== "auto") {
+            minResolution = this.options.minResolution;
+        }
+        if(this.options.maxScale) {
+            minResolution = OpenLayers.Util.getResolutionFromScale(
+                this.options.maxScale, this.units);
+        }
+
+        if(props.resolutions) {
+
+            //sort resolutions array descendingly
+            props.resolutions.sort(function(a, b) {
+                return (b - a);
+            });
+
+            // if we still don't have a maxResolution get it from the
+            // resolutions array
+            if(!maxResolution) {
+                maxResolution = props.resolutions[0];
+            }
+
+            // if we still don't have a minResolution get it from the
+            // resolutions array
+            if(!minResolution) {
+                var lastIdx = props.resolutions.length - 1;
+                minResolution = props.resolutions[lastIdx];
+            }
+        }
+
+        this.resolutions = props.resolutions;
+        if(this.resolutions) {
+            len = this.resolutions.length;
+            this.scales = new Array(len);
+            for(i=0; i<len; i++) {
+                this.scales[i] = OpenLayers.Util.getScaleFromResolution(
+                    this.resolutions[i], this.units);
+            }
+            this.numZoomLevels = len;
+        }
+        this.minResolution = minResolution;
+        if(minResolution) {
+            this.maxScale = OpenLayers.Util.getScaleFromResolution(
+                minResolution, this.units);
+        }
+        this.maxResolution = maxResolution;
+        if(maxResolution) {
+            this.minScale = OpenLayers.Util.getScaleFromResolution(
+                maxResolution, this.units);
+        }
+    },
+
+    /**
+     * Method: resolutionsFromScales
+     * Derive resolutions from scales.
+     *
+     * Parameters:
+     * scales - {Array(Number)} Scales
+     *
+     * Returns
+     * {Array(Number)} Resolutions
+     */
+    resolutionsFromScales: function(scales) {
+        if(scales == null) {
+            return;
+        }
+        var resolutions, i, len;
+        len = scales.length;
+        resolutions = new Array(len);
+        for(i=0; i<len; i++) {
+            resolutions[i] = OpenLayers.Util.getResolutionFromScale(
+                scales[i], this.units);
+        }
+        return resolutions;
+    },
+
+    /**
+     * Method: calculateResolutions
+     * Calculate resolutions based on the provided properties.
+     *
+     * Parameters:
+     * props - {Object} Properties
+     *
+     * Return:
+     * {Array({Number})} Array of resolutions.
+     */
+    calculateResolutions: function(props) {
+
+        var viewSize, wRes, hRes;
+
+        // determine maxResolution
+        var maxResolution = props.maxResolution;
+        if(props.minScale != null) {
+            maxResolution =
+                OpenLayers.Util.getResolutionFromScale(props.minScale,
+                                                       this.units);
+        } else if(maxResolution == "auto" && this.maxExtent != null) {
+            viewSize = this.map.getSize();
+            wRes = this.maxExtent.getWidth() / viewSize.w;
+            hRes = this.maxExtent.getHeight() / viewSize.h;
+            maxResolution = Math.max(wRes, hRes);
+        }
+
+        // determine minResolution
+        var minResolution = props.minResolution;
+        if(props.maxScale != null) {
+            minResolution =
+                OpenLayers.Util.getResolutionFromScale(props.maxScale,
+                                                       this.units);
+        } else if(props.minResolution == "auto" && this.minExtent != null) {
+            viewSize = this.map.getSize();
+            wRes = this.minExtent.getWidth() / viewSize.w;
+            hRes = this.minExtent.getHeight()/ viewSize.h;
+            minResolution = Math.max(wRes, hRes);
+        }
+
+        // determine numZoomLevels
+        var maxZoomLevel = props.maxZoomLevel;
+        var numZoomLevels = props.numZoomLevels;
+        if(typeof minResolution === "number" &&
+           typeof maxResolution === "number" && numZoomLevels === undefined) {
+            var ratio = maxResolution / minResolution;
+            numZoomLevels = Math.floor(Math.log(ratio) / Math.log(2)) + 1;
+        } else if(numZoomLevels === undefined && maxZoomLevel != null) {
+            numZoomLevels = maxZoomLevel + 1;
+        }
+
+        // are we able to calculate resolutions?
+        if(typeof numZoomLevels !== "number" || numZoomLevels <= 0 ||
+           (typeof maxResolution !== "number" &&
+                typeof minResolution !== "number")) {
+            return;
+        }
+
+        // now we have numZoomLevels and at least one of maxResolution
+        // or minResolution, we can populate the resolutions array
+
+        var resolutions = new Array(numZoomLevels);
+        var base = 2;
+        if(typeof minResolution == "number" &&
+           typeof maxResolution == "number") {
+            // if maxResolution and minResolution are set, we calculate
+            // the base for exponential scaling that starts at
+            // maxResolution and ends at minResolution in numZoomLevels
+            // steps.
+            base = Math.pow(
+                    (maxResolution / minResolution),
+                (1 / (numZoomLevels - 1))
+            );
+        }
+
+        var i;
+        if(typeof maxResolution === "number") {
+            for(i=0; i<numZoomLevels; i++) {
+                resolutions[i] = maxResolution / Math.pow(base, i);
+            }
+        } else {
+            for(i=0; i<numZoomLevels; i++) {
+                resolutions[numZoomLevels - 1 - i] =
+                    minResolution * Math.pow(base, i);
+            }
+        }
+
+        return resolutions;
+    },
+
+    /**
+     * APIMethod: getResolution
+     * 
+     * Returns:
+     * {Float} The currently selected resolution of the map, taken from the
+     *     resolutions array, indexed by current zoom level.
+     */
+    getResolution: function() {
+        var zoom = this.map.getZoom();
+        return this.getResolutionForZoom(zoom);
+    },
+
+    /** 
+     * APIMethod: getExtent
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
+     *     bounds of the current viewPort.
+     */
+    getExtent: function() {
+        // just use stock map calculateBounds function -- passing no arguments
+        //  means it will user map's current center & resolution
+        //
+        return this.map.calculateBounds();
+    },
+
+    /**
+     * APIMethod: getZoomForExtent
+     * 
+     * Parameters:
+     * extent - {<OpenLayers.Bounds>}
+     * closest - {Boolean} Find the zoom level that most closely fits the 
+     *     specified bounds. Note that this may result in a zoom that does 
+     *     not exactly contain the entire extent.
+     *     Default is false.
+     *
+     * Returns:
+     * {Integer} The index of the zoomLevel (entry in the resolutions array) 
+     *     for the passed-in extent. We do this by calculating the ideal 
+     *     resolution for the given extent (based on the map size) and then 
+     *     calling getZoomForResolution(), passing along the 'closest'
+     *     parameter.
+     */
+    getZoomForExtent: function(extent, closest) {
+        var viewSize = this.map.getSize();
+        var idealResolution = Math.max( extent.getWidth()  / viewSize.w,
+                                        extent.getHeight() / viewSize.h );
+
+        return this.getZoomForResolution(idealResolution, closest);
+    },
+    
+    /** 
+     * Method: getDataExtent
+     * Calculates the max extent which includes all of the data for the layer.
+     *     This function is to be implemented by subclasses.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getDataExtent: function () {
+        //to be implemented by subclasses
+    },
+
+    /**
+     * APIMethod: getResolutionForZoom
+     * 
+     * Parameter:
+     * zoom - {Float}
+     * 
+     * Returns:
+     * {Float} A suitable resolution for the specified zoom.
+     */
+    getResolutionForZoom: function(zoom) {
+        zoom = Math.max(0, Math.min(zoom, this.resolutions.length - 1));
+        var resolution;
+        if(this.map.fractionalZoom) {
+            var low = Math.floor(zoom);
+            var high = Math.ceil(zoom);
+            resolution = this.resolutions[low] -
+                ((zoom-low) * (this.resolutions[low]-this.resolutions[high]));
+        } else {
+            resolution = this.resolutions[Math.round(zoom)];
+        }
+        return resolution;
+    },
+
+    /**
+     * APIMethod: getZoomForResolution
+     * 
+     * Parameters:
+     * resolution - {Float}
+     * closest - {Boolean} Find the zoom level that corresponds to the absolute 
+     *     closest resolution, which may result in a zoom whose corresponding
+     *     resolution is actually smaller than we would have desired (if this
+     *     is being called from a getZoomForExtent() call, then this means that
+     *     the returned zoom index might not actually contain the entire 
+     *     extent specified... but it'll be close).
+     *     Default is false.
+     * 
+     * Returns:
+     * {Integer} The index of the zoomLevel (entry in the resolutions array) 
+     *     that corresponds to the best fit resolution given the passed in 
+     *     value and the 'closest' specification.
+     */
+    getZoomForResolution: function(resolution, closest) {
+        var zoom, i, len;
+        if(this.map.fractionalZoom) {
+            var lowZoom = 0;
+            var highZoom = this.resolutions.length - 1;
+            var highRes = this.resolutions[lowZoom];
+            var lowRes = this.resolutions[highZoom];
+            var res;
+            for(i=0, len=this.resolutions.length; i<len; ++i) {
+                res = this.resolutions[i];
+                if(res >= resolution) {
+                    highRes = res;
+                    lowZoom = i;
+                }
+                if(res <= resolution) {
+                    lowRes = res;
+                    highZoom = i;
+                    break;
+                }
+            }
+            var dRes = highRes - lowRes;
+            if(dRes > 0) {
+                zoom = lowZoom + ((highRes - resolution) / dRes);
+            } else {
+                zoom = lowZoom;
+            }
+        } else {
+            var diff;
+            var minDiff = Number.POSITIVE_INFINITY;
+            for(i=0, len=this.resolutions.length; i<len; i++) {            
+                if (closest) {
+                    diff = Math.abs(this.resolutions[i] - resolution);
+                    if (diff > minDiff) {
+                        break;
+                    }
+                    minDiff = diff;
+                } else {
+                    if (this.resolutions[i] < resolution) {
+                        break;
+                    }
+                }
+            }
+            zoom = Math.max(0, i-1);
+        }
+        return zoom;
+    },
+    
+    /**
+     * APIMethod: getLonLatFromViewPortPx
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in 
+     *     view port <OpenLayers.Pixel>, translated into lon/lat by the layer.
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        var lonlat = null;
+        var map = this.map;
+        if (viewPortPx != null && map.minPx) {
+            var res = map.getResolution();
+            var maxExtent = map.getMaxExtent({restricted: true});
+            var lon = (viewPortPx.x - map.minPx.x) * res + maxExtent.left;
+            var lat = (map.minPx.y - viewPortPx.y) * res + maxExtent.top;
+            lonlat = new OpenLayers.LonLat(lon, lat);
+
+            if (this.wrapDateLine) {
+                lonlat = lonlat.wrapDateLine(this.maxExtent);
+            }
+        }
+        return lonlat;
+    },
+
+    /**
+     * APIMethod: getViewPortPxFromLonLat
+     * Returns a pixel location given a map location.  This method will return
+     *     fractional pixel values.
+     * 
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns: 
+     * {<OpenLayers.Pixel>} An <OpenLayers.Pixel> which is the passed-in 
+     *     <OpenLayers.LonLat>,translated into view port pixels.
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        var px = null; 
+        if (lonlat != null) {
+            var resolution = this.map.getResolution();
+            var extent = this.map.getExtent();
+            px = new OpenLayers.Pixel(
+                (1/resolution * (lonlat.lon - extent.left)),
+                (1/resolution * (extent.top - lonlat.lat))
+            );    
+        }
+        return px;
+    },
+    
+    /**
+     * APIMethod: setOpacity
+     * Sets the opacity for the entire layer (all images)
+     * 
+     * Parameter:
+     * opacity - {Float}
+     */
+    setOpacity: function(opacity) {
+        if (opacity != this.opacity) {
+            this.opacity = opacity;
+            for(var i=0, len=this.div.childNodes.length; i<len; ++i) {
+                var element = this.div.childNodes[i].firstChild;
+                OpenLayers.Util.modifyDOMElement(element, null, null, null, 
+                                                 null, null, null, opacity);
+            }
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "opacity"
+                });
+            }
+        }
+    },
+
+    /**
+     * Method: getZIndex
+     * 
+     * Returns: 
+     * {Integer} the z-index of this layer
+     */    
+    getZIndex: function () {
+        return this.div.style.zIndex;
+    },
+
+    /**
+     * Method: setZIndex
+     * 
+     * Parameters: 
+     * zIndex - {Integer}
+     */    
+    setZIndex: function (zIndex) {
+        this.div.style.zIndex = zIndex;
+    },
+
+    /**
+     * Method: adjustBounds
+     * This function will take a bounds, and if wrapDateLine option is set
+     *     on the layer, it will return a bounds which is wrapped around the 
+     *     world. We do not wrap for bounds which *cross* the 
+     *     maxExtent.left/right, only bounds which are entirely to the left 
+     *     or entirely to the right.
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     */
+    adjustBounds: function (bounds) {
+
+        if (this.gutter) {
+            // Adjust the extent of a bounds in map units by the 
+            // layer's gutter in pixels.
+            var mapGutter = this.gutter * this.map.getResolution();
+            bounds = new OpenLayers.Bounds(bounds.left - mapGutter,
+                                           bounds.bottom - mapGutter,
+                                           bounds.right + mapGutter,
+                                           bounds.top + mapGutter);
+        }
+
+        if (this.wrapDateLine) {
+            // wrap around the date line, within the limits of rounding error
+            var wrappingOptions = { 
+                'rightTolerance':this.getResolution(),
+                'leftTolerance':this.getResolution()
+            };    
+            bounds = bounds.wrapDateLine(this.maxExtent, wrappingOptions);
+                              
+        }
+        return bounds;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer"
+});
+/* ======================================================================
+    OpenLayers/Layer/SphericalMercator.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.SphericalMercator
+ * A mixin for layers that wraps up the pieces neccesary to have a coordinate
+ *     conversion for working with commercial APIs which use a spherical
+ *     mercator projection.  Using this layer as a base layer, additional
+ *     layers can be used as overlays if they are in the same projection.
+ *
+ * A layer is given properties of this object by setting the sphericalMercator
+ *     property to true.
+ *
+ * More projection information:
+ *  - http://spatialreference.org/ref/user/google-projection/
+ *
+ * Proj4 Text:
+ *     +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0
+ *     +k=1.0 +units=m +nadgrids=@null +no_defs
+ *
+ * WKT:
+ *     900913=PROJCS["WGS84 / Simple Mercator", GEOGCS["WGS 84",
+ *     DATUM["WGS_1984", SPHEROID["WGS_1984", 6378137.0, 298.257223563]], 
+ *     PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], 
+ *     AXIS["Longitude", EAST], AXIS["Latitude", NORTH]],
+ *     PROJECTION["Mercator_1SP_Google"], 
+ *     PARAMETER["latitude_of_origin", 0.0], PARAMETER["central_meridian", 0.0], 
+ *     PARAMETER["scale_factor", 1.0], PARAMETER["false_easting", 0.0], 
+ *     PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["x", EAST],
+ *     AXIS["y", NORTH], AUTHORITY["EPSG","900913"]]
+ */
+OpenLayers.Layer.SphericalMercator = {
+
+    /**
+     * Method: getExtent
+     * Get the map's extent.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} The map extent.
+     */
+    getExtent: function() {
+        var extent = null;
+        if (this.sphericalMercator) {
+            extent = this.map.calculateBounds();
+        } else {
+            extent = OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);
+        }
+        return extent;
+    },
+
+    /**
+     * Method: getLonLatFromViewPortPx
+     * Get a map location from a pixel location
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     *  {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view
+     *  port OpenLayers.Pixel, translated into lon/lat by map lib
+     *  If the map lib is not loaded or not centered, returns null
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this, arguments);
+    },
+    
+    /**
+     * Method: getViewPortPxFromLonLat
+     * Get a pixel location from a map location
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
+     * OpenLayers.LonLat, translated into view port pixels by map lib
+     * If map lib is not loaded or not centered, returns null
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this, arguments);
+    },
+
+    /** 
+     * Method: initMercatorParameters 
+     * Set up the mercator parameters on the layer: resolutions,
+     *     projection, units.
+     */
+    initMercatorParameters: function() {
+        // set up properties for Mercator - assume EPSG:900913
+        this.RESOLUTIONS = [];
+        var maxResolution = 156543.03390625;
+        for(var zoom=0; zoom<=this.MAX_ZOOM_LEVEL; ++zoom) {
+            this.RESOLUTIONS[zoom] = maxResolution / Math.pow(2, zoom);
+        }
+        this.units = "m";
+        this.projection = this.projection || "EPSG:900913";
+    },
+
+    /**
+     * APIMethod: forwardMercator
+     * Given a lon,lat in EPSG:4326, return a point in Spherical Mercator.
+     *
+     * Parameters:
+     * lon - {float} 
+     * lat - {float}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} The coordinates transformed to Mercator.
+     */
+    forwardMercator: function(lon, lat) {
+        var x = lon * 20037508.34 / 180;
+        var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
+
+        y = y * 20037508.34 / 180;
+        
+        return new OpenLayers.LonLat(x, y);
+    },
+
+    /**
+     * APIMethod: inverseMercator
+     * Given a x,y in Spherical Mercator, return a point in EPSG:4326.
+     *
+     * Parameters:
+     * x - {float} A map x in Spherical Mercator.
+     * y - {float} A map y in Spherical Mercator.
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} The coordinates transformed to EPSG:4326.
+     */
+    inverseMercator: function(x, y) {
+
+        var lon = (x / 20037508.34) * 180;
+        var lat = (y / 20037508.34) * 180;
+
+        lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
+        
+        return new OpenLayers.LonLat(lon, lat);
+    },
+
+    /**
+     * Method: projectForward 
+     * Given an object with x and y properties in EPSG:4326, modify the x,y
+     * properties on the object to be the Spherical Mercator projected
+     * coordinates.
+     *
+     * Parameters:
+     * point - {Object} An object with x and y properties. 
+     * 
+     * Returns:
+     * {Object} The point, with the x and y properties transformed to spherical
+     * mercator.
+     */
+    projectForward: function(point) {
+        var lonlat = OpenLayers.Layer.SphericalMercator.forwardMercator(point.x, point.y);
+        point.x = lonlat.lon;
+        point.y = lonlat.lat;
+        return point;
+    },
+    
+    /**
+     * Method: projectInverse
+     * Given an object with x and y properties in Spherical Mercator, modify
+     * the x,y properties on the object to be the unprojected coordinates.
+     *
+     * Parameters:
+     * point - {Object} An object with x and y properties. 
+     * 
+     * Returns:
+     * {Object} The point, with the x and y properties transformed from
+     * spherical mercator to unprojected coordinates..
+     */
+    projectInverse: function(point) {
+        var lonlat = OpenLayers.Layer.SphericalMercator.inverseMercator(point.x, point.y);
+        point.x = lonlat.lon;
+        point.y = lonlat.lat;
+        return point;
+    }
+
+};
+
+/**
+ * Note: Transforms for web mercator <-> EPSG:4326
+ * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
+ * OpenLayers originally started referring to EPSG:900913 as web mercator.
+ * The EPSG has declared EPSG:3857 to be web mercator.  
+ * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as 
+ * equivalent.  See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084
+ */
+(function() {
+    
+    // list of equivalent codes for web mercator
+    var codes = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"];
+    
+    var add = OpenLayers.Projection.addTransform;
+    var merc = OpenLayers.Layer.SphericalMercator;
+    var same = OpenLayers.Projection.nullTransform;
+    
+    var i, len, code, other, j;
+    for (i=0, len=codes.length; i<len; ++i) {
+        code = codes[i];
+        add("EPSG:4326", code, merc.projectForward);
+        add(code, "EPSG:4326", merc.projectInverse);
+        for (j=i+1; j<len; ++j) {
+            other = codes[j];
+            add(code, other, same);
+            add(other, code, same);
+        }
+    }
+    
+})();
+/* ======================================================================
+    OpenLayers/Layer/EventPane.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.EventPane
+ * Base class for 3rd party layers.  Create a new event pane layer with the
+ * <OpenLayers.Layer.EventPane> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.EventPane = OpenLayers.Class(OpenLayers.Layer, {
+    
+    /**
+     * APIProperty: smoothDragPan
+     * {Boolean} smoothDragPan determines whether non-public/internal API
+     *     methods are used for better performance while dragging EventPane 
+     *     layers. When not in sphericalMercator mode, the smoother dragging 
+     *     doesn't actually move north/south directly with the number of 
+     *     pixels moved, resulting in a slight offset when you drag your mouse 
+     *     north south with this option on. If this visual disparity bothers 
+     *     you, you should turn this option off, or use spherical mercator. 
+     *     Default is on.
+     */
+    smoothDragPan: true,
+
+    /**
+     * Property: isBaseLayer
+     * {Boolean} EventPaned layers are always base layers, by necessity.
+     */ 
+    isBaseLayer: true,
+
+    /**
+     * APIProperty: isFixed
+     * {Boolean} EventPaned layers are fixed by default.
+     */ 
+    isFixed: true,
+
+    /**
+     * Property: pane
+     * {DOMElement} A reference to the element that controls the events.
+     */
+    pane: null,
+
+
+    /**
+     * Property: mapObject
+     * {Object} This is the object which will be used to load the 3rd party library
+     * in the case of the google layer, this will be of type GMap, 
+     * in the case of the ve layer, this will be of type VEMap
+     */ 
+    mapObject: null,
+
+
+    /**
+     * Constructor: OpenLayers.Layer.EventPane
+     * Create a new event pane layer
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.prototype.initialize.apply(this, arguments);
+        if (this.pane == null) {
+            this.pane = OpenLayers.Util.createDiv(this.div.id + "_EventPane");
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Deconstruct this layer.
+     */
+    destroy: function() {
+        this.mapObject = null;
+        this.pane = null;
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments); 
+    },
+
+    
+    /**
+     * Method: setMap
+     * Set the map property for the layer. This is done through an accessor
+     * so that subclasses can override this and take special action once 
+     * they have their map variable set. 
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+        
+        this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1;
+        this.pane.style.display = this.div.style.display;
+        this.pane.style.width="100%";
+        this.pane.style.height="100%";
+        if (OpenLayers.BROWSER_NAME == "msie") {
+            this.pane.style.background = 
+                "url(" + OpenLayers.Util.getImagesLocation() + "blank.gif)";
+        }
+
+        if (this.isFixed) {
+            this.map.eventsDiv.appendChild(this.pane);
+        } else {
+            this.map.layerContainerDiv.appendChild(this.pane);
+        }
+
+        // once our layer has been added to the map, we can load it
+        this.loadMapObject();
+    
+        // if map didn't load, display warning
+        if (this.mapObject == null) {
+            this.loadWarningMessage();
+        }
+    },
+
+    /**
+     * APIMethod: removeMap
+     * On being removed from the map, we'll like to remove the invisible 'pane'
+     *     div that we added to it on creation. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        if (this.pane && this.pane.parentNode) {
+            this.pane.parentNode.removeChild(this.pane);
+        }
+        OpenLayers.Layer.prototype.removeMap.apply(this, arguments);
+    },
+  
+    /**
+     * Method: loadWarningMessage
+     * If we can't load the map lib, then display an error message to the 
+     *     user and tell them where to go for help.
+     * 
+     *     This function sets up the layout for the warning message. Each 3rd
+     *     party layer must implement its own getWarningHTML() function to 
+     *     provide the actual warning message.
+     */
+    loadWarningMessage:function() {
+
+        this.div.style.backgroundColor = "darkblue";
+
+        var viewSize = this.map.getSize();
+        
+        var msgW = Math.min(viewSize.w, 300);
+        var msgH = Math.min(viewSize.h, 200);
+        var size = new OpenLayers.Size(msgW, msgH);
+
+        var centerPx = new OpenLayers.Pixel(viewSize.w/2, viewSize.h/2);
+
+        var topLeft = centerPx.add(-size.w/2, -size.h/2);            
+
+        var div = OpenLayers.Util.createDiv(this.name + "_warning", 
+                                            topLeft, 
+                                            size,
+                                            null,
+                                            null,
+                                            null,
+                                            "auto");
+
+        div.style.padding = "7px";
+        div.style.backgroundColor = "yellow";
+
+        div.innerHTML = this.getWarningHTML();
+        this.div.appendChild(div);
+    },
+  
+    /** 
+     * Method: getWarningHTML
+     * To be implemented by subclasses.
+     * 
+     * Returns:
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        //should be implemented by subclasses
+        return "";
+    },
+  
+    /**
+     * Method: display
+     * Set the display on the pane
+     *
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(display) {
+        OpenLayers.Layer.prototype.display.apply(this, arguments);
+        this.pane.style.display = this.div.style.display;
+    },
+  
+    /**
+     * Method: setZIndex
+     * Set the z-index order for the pane.
+     * 
+     * Parameters:
+     * zIndex - {int}
+     */
+    setZIndex: function (zIndex) {
+        OpenLayers.Layer.prototype.setZIndex.apply(this, arguments);
+        this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1;
+    },
+    
+    /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector. To be implemented by subclasses.
+     *
+     * Parameters:
+     * dx - {Number} The x coord of the displacement vector.
+     * dy - {Number} The y coord of the displacement vector.
+     */
+    moveByPx: function(dx, dy) {
+        OpenLayers.Layer.prototype.moveByPx.apply(this, arguments);
+        
+        if (this.dragPanMapObject) {
+            this.dragPanMapObject(dx, -dy);
+        } else {
+            this.moveTo(this.map.getCachedCenter());
+        }
+    },
+
+    /**
+     * Method: moveTo
+     * Handle calls to move the layer.
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean}
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+
+        if (this.mapObject != null) {
+
+            var newCenter = this.map.getCenter();
+            var newZoom = this.map.getZoom();
+
+            if (newCenter != null) {
+
+                var moOldCenter = this.getMapObjectCenter();
+                var oldCenter = this.getOLLonLatFromMapObjectLonLat(moOldCenter);
+
+                var moOldZoom = this.getMapObjectZoom();
+                var oldZoom= this.getOLZoomFromMapObjectZoom(moOldZoom);
+
+                if ( !(newCenter.equals(oldCenter)) || 
+                     !(newZoom == oldZoom) ) {
+
+                    if (!zoomChanged && oldCenter && this.dragPanMapObject && 
+                        this.smoothDragPan) {
+                        var oldPx = this.map.getViewPortPxFromLonLat(oldCenter);
+                        var newPx = this.map.getViewPortPxFromLonLat(newCenter);
+                        this.dragPanMapObject(newPx.x-oldPx.x, oldPx.y-newPx.y);
+                    } else {
+                        var center = this.getMapObjectLonLatFromOLLonLat(newCenter);
+                        var zoom = this.getMapObjectZoomFromOLZoom(newZoom);
+                        this.setMapObjectCenter(center, zoom, dragging);
+                    }
+                }
+            }
+        }
+    },
+
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /********************************************************/
+
+    /**
+     * Method: getLonLatFromViewPortPx
+     * Get a map location from a pixel location
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     *  {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view
+     *  port OpenLayers.Pixel, translated into lon/lat by map lib
+     *  If the map lib is not loaded or not centered, returns null
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        var lonlat = null;
+        if ( (this.mapObject != null) && 
+             (this.getMapObjectCenter() != null) ) {
+            var moPixel = this.getMapObjectPixelFromOLPixel(viewPortPx);
+            var moLonLat = this.getMapObjectLonLatFromMapObjectPixel(moPixel);
+            lonlat = this.getOLLonLatFromMapObjectLonLat(moLonLat);
+        }
+        return lonlat;
+    },
+
+ 
+    /**
+     * Method: getViewPortPxFromLonLat
+     * Get a pixel location from a map location
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
+     * OpenLayers.LonLat, translated into view port pixels by map lib
+     * If map lib is not loaded or not centered, returns null
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        var viewPortPx = null;
+        if ( (this.mapObject != null) && 
+             (this.getMapObjectCenter() != null) ) {
+
+            var moLonLat = this.getMapObjectLonLatFromOLLonLat(lonlat);
+            var moPixel = this.getMapObjectPixelFromMapObjectLonLat(moLonLat);
+        
+            viewPortPx = this.getOLPixelFromMapObjectPixel(moPixel);
+        }
+        return viewPortPx;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*               Translation Functions                  */
+  /*                                                      */
+  /*   The following functions translate Map Object and   */
+  /*            OL formats for Pixel, LonLat              */
+  /*                                                      */
+  /********************************************************/
+
+  //
+  // TRANSLATION: MapObject LatLng <-> OpenLayers.LonLat
+  //
+
+    /**
+     * Method: getOLLonLatFromMapObjectLonLat
+     * Get an OL style map location from a 3rd party style map location
+     *
+     * Parameters
+     * moLonLat - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} An OpenLayers.LonLat, translated from the passed in 
+     *          MapObject LonLat
+     *          Returns null if null value is passed in
+     */
+    getOLLonLatFromMapObjectLonLat: function(moLonLat) {
+        var olLonLat = null;
+        if (moLonLat != null) {
+            var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
+            var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
+            olLonLat = new OpenLayers.LonLat(lon, lat);
+        }
+        return olLonLat;
+    },
+
+    /**
+     * Method: getMapObjectLonLatFromOLLonLat
+     * Get a 3rd party map location from an OL map location.
+     *
+     * Parameters:
+     * olLonLat - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {Object} A MapObject LonLat, translated from the passed in 
+     *          OpenLayers.LonLat
+     *          Returns null if null value is passed in
+     */
+    getMapObjectLonLatFromOLLonLat: function(olLonLat) {
+        var moLatLng = null;
+        if (olLonLat != null) {
+            moLatLng = this.getMapObjectLonLatFromLonLat(olLonLat.lon,
+                                                         olLonLat.lat);
+        }
+        return moLatLng;
+    },
+
+
+  //
+  // TRANSLATION: MapObject Pixel <-> OpenLayers.Pixel
+  //
+
+    /**
+     * Method: getOLPixelFromMapObjectPixel
+     * Get an OL pixel location from a 3rd party pixel location.
+     *
+     * Parameters:
+     * moPixel - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel, translated from the passed in 
+     *          MapObject Pixel
+     *          Returns null if null value is passed in
+     */
+    getOLPixelFromMapObjectPixel: function(moPixel) {
+        var olPixel = null;
+        if (moPixel != null) {
+            var x = this.getXFromMapObjectPixel(moPixel);
+            var y = this.getYFromMapObjectPixel(moPixel);
+            olPixel = new OpenLayers.Pixel(x, y);
+        }
+        return olPixel;
+    },
+
+    /**
+     * Method: getMapObjectPixelFromOLPixel
+     * Get a 3rd party pixel location from an OL pixel location
+     *
+     * Parameters:
+     * olPixel - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {Object} A MapObject Pixel, translated from the passed in 
+     *          OpenLayers.Pixel
+     *          Returns null if null value is passed in
+     */
+    getMapObjectPixelFromOLPixel: function(olPixel) {
+        var moPixel = null;
+        if (olPixel != null) {
+            moPixel = this.getMapObjectPixelFromXY(olPixel.x, olPixel.y);
+        }
+        return moPixel;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.EventPane"
+});
+/* ======================================================================
+    OpenLayers/Layer/FixedZoomLevels.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.FixedZoomLevels
+ *   Some Layers will already have established zoom levels (like google 
+ *    or ve). Instead of trying to determine them and populate a resolutions[]
+ *    Array with those values, we will hijack the resolution functionality
+ *    here.
+ * 
+ *   When you subclass FixedZoomLevels: 
+ * 
+ *   The initResolutions() call gets nullified, meaning no resolutions[] array 
+ *    is set up. Which would be a big problem getResolution() in Layer, since 
+ *    it merely takes map.zoom and indexes into resolutions[]... but....
+ * 
+ *   The getResolution() call is also overridden. Instead of using the 
+ *    resolutions[] array, we simply calculate the current resolution based
+ *    on the current extent and the current map size. But how will we be able
+ *    to calculate the current extent without knowing the resolution...?
+ *  
+ *   The getExtent() function is also overridden. Instead of calculating extent
+ *    based on the center point and the current resolution, we instead 
+ *    calculate the extent by getting the lonlats at the top-left and 
+ *    bottom-right by using the getLonLatFromViewPortPx() translation function,
+ *    taken from the pixel locations (0,0) and the size of the map. But how 
+ *    will we be able to do lonlat-px translation without resolution....?
+ * 
+ *   The getZoomForResolution() method is overridden. Instead of indexing into
+ *    the resolutions[] array, we call OpenLayers.Layer.getExent(), passing in
+ *    the desired resolution. With this extent, we then call getZoomForExtent() 
+ * 
+ * 
+ *   Whenever you implement a layer using OpenLayers.Layer.FixedZoomLevels, 
+ *    it is your responsibility to provide the following three functions:
+ * 
+ *   - getLonLatFromViewPortPx
+ *   - getViewPortPxFromLonLat
+ *   - getZoomForExtent
+ * 
+ *  ...those three functions should generally be provided by any reasonable 
+ *  API that you might be working from.
+ *
+ */
+OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({
+      
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /*    The following functions must all be implemented   */
+  /*                  by all base layers                  */
+  /*                                                      */
+  /********************************************************/
+    
+    /**
+     * Constructor: OpenLayers.Layer.FixedZoomLevels
+     * Create a new fixed zoom levels layer.
+     */
+    initialize: function() {
+        //this class is only just to add the following functions... 
+        // nothing to actually do here... but it is probably a good
+        // idea to have layers that use these functions call this 
+        // inititalize() anyways, in case at some point we decide we 
+        // do want to put some functionality or state in here. 
+    },
+    
+    /**
+     * Method: initResolutions
+     * Populate the resolutions array
+     */
+    initResolutions: function() {
+
+        var props = new Array('minZoomLevel', 'maxZoomLevel', 'numZoomLevels');
+          
+        for(var i=0, len=props.length; i<len; i++) {
+            var property = props[i];
+            this[property] = (this.options[property] != null)  
+                                     ? this.options[property] 
+                                     : this.map[property];
+        }
+
+        if ( (this.minZoomLevel == null) ||
+             (this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){
+            this.minZoomLevel = this.MIN_ZOOM_LEVEL;
+        }        
+
+        //
+        // At this point, we know what the minimum desired zoom level is, and
+        //  we must calculate the total number of zoom levels. 
+        //  
+        //  Because we allow for the setting of either the 'numZoomLevels'
+        //   or the 'maxZoomLevel' properties... on either the layer or the  
+        //   map, we have to define some rules to see which we take into
+        //   account first in this calculation. 
+        //
+        // The following is the precedence list for these properties:
+        // 
+        // (1) numZoomLevels set on layer
+        // (2) maxZoomLevel set on layer
+        // (3) numZoomLevels set on map
+        // (4) maxZoomLevel set on map*
+        // (5) none of the above*
+        //
+        // *Note that options (4) and (5) are only possible if the user 
+        //  _explicitly_ sets the 'numZoomLevels' property on the map to 
+        //  null, since it is set by default to 16. 
+        //
+
+        //
+        // Note to future: In 3.0, I think we should remove the default 
+        // value of 16 for map.numZoomLevels. Rather, I think that value 
+        // should be set as a default on the Layer.WMS class. If someone
+        // creates a 3rd party layer and does not specify any 'minZoomLevel', 
+        // 'maxZoomLevel', or 'numZoomLevels', and has not explicitly 
+        // specified any of those on the map object either.. then I think
+        // it is fair to say that s/he wants all the zoom levels available.
+        // 
+        // By making map.numZoomLevels *null* by default, that will be the 
+        // case. As it is, I don't feel comfortable changing that right now
+        // as it would be a glaring API change and actually would probably
+        // break many peoples' codes. 
+        //
+
+        //the number of zoom levels we'd like to have.
+        var desiredZoomLevels;
+
+        //this is the maximum number of zoom levels the layer will allow, 
+        // given the specified starting minimum zoom level.
+        var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1;
+
+        if ( ((this.options.numZoomLevels == null) && 
+              (this.options.maxZoomLevel != null)) // (2)
+              ||
+             ((this.numZoomLevels == null) &&
+              (this.maxZoomLevel != null)) // (4)
+           ) {
+            //calculate based on specified maxZoomLevel (on layer or map)
+            desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
+        } else {
+            //calculate based on specified numZoomLevels (on layer or map)
+            // this covers cases (1) and (3)
+            desiredZoomLevels = this.numZoomLevels;
+        }
+
+        if (desiredZoomLevels != null) {
+            //Now that we know what we would *like* the number of zoom levels
+            // to be, based on layer or map options, we have to make sure that
+            // it does not conflict with the actual limit, as specified by 
+            // the constants on the layer itself (and calculated into the
+            // 'limitZoomLevels' variable). 
+            this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels);
+        } else {
+            // case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was 
+            // set on either the layer or the map. So we just use the 
+            // maximum limit as calculated by the layer's constants.
+            this.numZoomLevels = limitZoomLevels;
+        }
+
+        //now that the 'numZoomLevels' is appropriately, safely set, 
+        // we go back and re-calculate the 'maxZoomLevel'.
+        this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1;
+
+        if (this.RESOLUTIONS != null) {
+            var resolutionsIndex = 0;
+            this.resolutions = [];
+            for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) {
+                this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i];            
+            }
+            this.maxResolution = this.resolutions[0];
+            this.minResolution = this.resolutions[this.resolutions.length - 1];
+        }       
+    },
+    
+    /**
+     * APIMethod: getResolution
+     * Get the current map resolution
+     * 
+     * Returns:
+     * {Float} Map units per Pixel
+     */
+    getResolution: function() {
+
+        if (this.resolutions != null) {
+            return OpenLayers.Layer.prototype.getResolution.apply(this, arguments);
+        } else {
+            var resolution = null;
+            
+            var viewSize = this.map.getSize();
+            var extent = this.getExtent();
+            
+            if ((viewSize != null) && (extent != null)) {
+                resolution = Math.max( extent.getWidth()  / viewSize.w,
+                                       extent.getHeight() / viewSize.h );
+            }
+            return resolution;
+        }
+     },
+
+    /**
+     * APIMethod: getExtent
+     * Calculates using px-> lonlat translation functions on tl and br 
+     *     corners of viewport
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
+     *                       bounds of the current viewPort.
+     */
+    getExtent: function () {
+        var extent = null;
+        
+        
+        var size = this.map.getSize();
+        
+        var tlPx = new OpenLayers.Pixel(0,0);
+        var tlLL = this.getLonLatFromViewPortPx(tlPx);
+
+        var brPx = new OpenLayers.Pixel(size.w, size.h);
+        var brLL = this.getLonLatFromViewPortPx(brPx);
+        
+        if ((tlLL != null) && (brLL != null)) {
+            extent = new OpenLayers.Bounds(tlLL.lon, 
+                                       brLL.lat, 
+                                       brLL.lon, 
+                                       tlLL.lat);
+        }
+
+        return extent;
+    },
+
+    /**
+     * Method: getZoomForResolution
+     * Get the zoom level for a given resolution
+     *
+     * Parameters:
+     * resolution - {Float}
+     *
+     * Returns:
+     * {Integer} A suitable zoom level for the specified resolution.
+     *           If no baselayer is set, returns null.
+     */
+    getZoomForResolution: function(resolution) {
+      
+        if (this.resolutions != null) {
+            return OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments);
+        } else {
+            var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []);
+            return this.getZoomForExtent(extent);
+        }
+    },
+
+
+
+    
+    /********************************************************/
+    /*                                                      */
+    /*             Translation Functions                    */
+    /*                                                      */
+    /*    The following functions translate GMaps and OL    */ 
+    /*     formats for Pixel, LonLat, Bounds, and Zoom      */
+    /*                                                      */
+    /********************************************************/
+    
+    
+    //
+    // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom
+    //
+  
+    /**
+     * Method: getOLZoomFromMapObjectZoom
+     * Get the OL zoom index from the map object zoom level
+     *
+     * Parameters:
+     * moZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} An OpenLayers Zoom level, translated from the passed in zoom
+     *           Returns null if null value is passed in
+     */
+    getOLZoomFromMapObjectZoom: function(moZoom) {
+        var zoom = null;
+        if (moZoom != null) {
+            zoom = moZoom - this.minZoomLevel;
+            if (this.map.baseLayer !== this) {
+                zoom = this.map.baseLayer.getZoomForResolution(
+                    this.getResolutionForZoom(zoom)
+                )
+            }
+        }
+        return zoom;
+    },
+    
+    /**
+     * Method: getMapObjectZoomFromOLZoom
+     * Get the map object zoom level from the OL zoom level
+     *
+     * Parameters:
+     * olZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} A MapObject level, translated from the passed in olZoom
+     *           Returns null if null value is passed in
+     */
+    getMapObjectZoomFromOLZoom: function(olZoom) {
+        var zoom = null; 
+        if (olZoom != null) {
+            zoom = olZoom + this.minZoomLevel;
+            if (this.map.baseLayer !== this) {
+                zoom = this.getZoomForResolution(
+                    this.map.baseLayer.getResolutionForZoom(zoom)
+                );
+            }
+        }
+        return zoom;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels"
+});
+
+/* ======================================================================
+    OpenLayers/Layer/Google.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/SphericalMercator.js
+ * @requires OpenLayers/Layer/EventPane.js
+ * @requires OpenLayers/Layer/FixedZoomLevels.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Google
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.SphericalMercator>
+ *  - <OpenLayers.Layer.EventPane>
+ *  - <OpenLayers.Layer.FixedZoomLevels>
+ */
+OpenLayers.Layer.Google = OpenLayers.Class(
+    OpenLayers.Layer.EventPane, 
+    OpenLayers.Layer.FixedZoomLevels, {
+    
+    /** 
+     * Constant: MIN_ZOOM_LEVEL
+     * {Integer} 0 
+     */
+    MIN_ZOOM_LEVEL: 0,
+    
+    /** 
+     * Constant: MAX_ZOOM_LEVEL
+     * {Integer} 21
+     */
+    MAX_ZOOM_LEVEL: 21,
+
+    /** 
+     * Constant: RESOLUTIONS
+     * {Array(Float)} Hardcode these resolutions so that they are more closely
+     *                tied with the standard wms projection
+     */
+    RESOLUTIONS: [
+        1.40625, 
+        0.703125, 
+        0.3515625, 
+        0.17578125, 
+        0.087890625, 
+        0.0439453125,
+        0.02197265625, 
+        0.010986328125, 
+        0.0054931640625, 
+        0.00274658203125,
+        0.001373291015625, 
+        0.0006866455078125, 
+        0.00034332275390625,
+        0.000171661376953125, 
+        0.0000858306884765625, 
+        0.00004291534423828125,
+        0.00002145767211914062, 
+        0.00001072883605957031,
+        0.00000536441802978515, 
+        0.00000268220901489257,
+        0.0000013411045074462891,
+        0.00000067055225372314453
+    ],
+
+    /**
+     * APIProperty: type
+     * {GMapType}
+     */
+    type: null,
+
+    /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
+     * APIProperty: sphericalMercator
+     * {Boolean} Should the map act as a mercator-projected map? This will
+     *     cause all interactions with the map to be in the actual map 
+     *     projection, which allows support for vector drawing, overlaying 
+     *     other maps, etc. 
+     */
+    sphericalMercator: false, 
+    
+    /**
+     * Property: version
+     * {Number} The version of the Google Maps API
+     */
+    version: null,
+
+    /** 
+     * Constructor: OpenLayers.Layer.Google
+     * 
+     * Parameters:
+     * name - {String} A name for the layer.
+     * options - {Object} An optional object whose properties will be set
+     *     on the layer.
+     */
+    initialize: function(name, options) {
+        options = options || {};
+        if(!options.version) {
+            options.version = typeof GMap2 === "function" ? "2" : "3";
+        }
+        var mixin = OpenLayers.Layer.Google["v" +
+            options.version.replace(/\./g, "_")];
+        if (mixin) {
+            OpenLayers.Util.applyDefaults(options, mixin);
+        } else {
+            throw "Unsupported Google Maps API version: " + options.version;
+        }
+
+        OpenLayers.Util.applyDefaults(options, mixin.DEFAULTS);
+        if (options.maxExtent) {
+            options.maxExtent = options.maxExtent.clone();
+        }
+
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this,
+            [name, options]);
+        OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
+            [name, options]);
+
+        if (this.sphericalMercator) {
+            OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
+            this.initMercatorParameters();
+        }    
+    },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Google>} An exact clone of this layer
+     */
+    clone: function() {
+        /**
+         * This method isn't intended to be called by a subclass and it
+         * doesn't call the same method on the superclass.  We don't call
+         * the super's clone because we don't want properties that are set
+         * on this layer after initialize (i.e. this.mapObject etc.).
+         */
+        return new OpenLayers.Layer.Google(
+            this.name, this.getOptions()
+        );
+    },
+
+    /**
+     * APIMethod: setVisibility
+     * Set the visibility flag for the layer and hide/show & redraw 
+     *     accordingly. Fire event unless otherwise specified
+     * 
+     * Note that visibility is no longer simply whether or not the layer's
+     *     style.display is set to "block". Now we store a 'visibility' state 
+     *     property on the layer class, this allows us to remember whether or 
+     *     not we *desire* for a layer to be visible. In the case where the 
+     *     map's resolution is out of the layer's range, this desire may be 
+     *     subverted.
+     * 
+     * Parameters:
+     * visible - {Boolean} Display the layer (if in range)
+     */
+    setVisibility: function(visible) {
+        // sharing a map container, opacity has to be set per layer
+        var opacity = this.opacity == null ? 1 : this.opacity;
+        OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this, arguments);
+        this.setOpacity(opacity);
+    },
+    
+    /** 
+     * APIMethod: display
+     * Hide or show the Layer
+     * 
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(visible) {
+        if (!this._dragging) {
+            this.setGMapVisibility(visible);
+        }
+        OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments);
+    },
+    
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * bound - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to
+     *     do some init work in that case.
+     * dragging - {Boolean}
+     */
+    moveTo: function(bounds, zoomChanged, dragging) {
+        this._dragging = dragging;
+        OpenLayers.Layer.EventPane.prototype.moveTo.apply(this, arguments);
+        delete this._dragging;
+    },
+    
+    /**
+     * APIMethod: setOpacity
+     * Sets the opacity for the entire layer (all images)
+     * 
+     * Parameter:
+     * opacity - {Float}
+     */
+    setOpacity: function(opacity) {
+        if (opacity !== this.opacity) {
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "opacity"
+                });
+            }
+            this.opacity = opacity;
+        }
+        // Though this layer's opacity may not change, we're sharing a container
+        // and need to update the opacity for the entire container.
+        if (this.getVisibility()) {
+            var container = this.getMapContainer();
+            OpenLayers.Util.modifyDOMElement(
+                container, null, null, null, null, null, null, opacity
+            );
+        }
+    },
+
+    /**
+     * APIMethod: destroy
+     * Clean up this layer.
+     */
+    destroy: function() {
+        /**
+         * We have to override this method because the event pane destroy
+         * deletes the mapObject reference before removing this layer from
+         * the map.
+         */
+        if (this.map) {
+            this.setGMapVisibility(false);
+            var cache = OpenLayers.Layer.Google.cache[this.map.id];
+            if (cache && cache.count <= 1) {
+                this.removeGMapElements();
+            }            
+        }
+        OpenLayers.Layer.EventPane.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: removeGMapElements
+     * Remove all elements added to the dom.  This should only be called if
+     * this is the last of the Google layers for the given map.
+     */
+    removeGMapElements: function() {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // remove shared elements from dom
+            var container = this.mapObject && this.getMapContainer();                
+            if (container && container.parentNode) {
+                container.parentNode.removeChild(container);
+            }
+            var termsOfUse = cache.termsOfUse;
+            if (termsOfUse && termsOfUse.parentNode) {
+                termsOfUse.parentNode.removeChild(termsOfUse);
+            }
+            var poweredBy = cache.poweredBy;
+            if (poweredBy && poweredBy.parentNode) {
+                poweredBy.parentNode.removeChild(poweredBy);
+            }
+        }
+    },
+
+    /**
+     * APIMethod: removeMap
+     * On being removed from the map, also remove termsOfUse and poweredBy divs
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        // hide layer before removing
+        if (this.visibility && this.mapObject) {
+            this.setGMapVisibility(false);
+        }
+        // check to see if last Google layer in this map
+        var cache = OpenLayers.Layer.Google.cache[map.id];
+        if (cache) {
+            if (cache.count <= 1) {
+                this.removeGMapElements();
+                delete OpenLayers.Layer.Google.cache[map.id];
+            } else {
+                // decrement the layer count
+                --cache.count;
+            }
+        }
+        // remove references to gmap elements
+        delete this.termsOfUse;
+        delete this.poweredBy;
+        delete this.mapObject;
+        delete this.dragObject;
+        OpenLayers.Layer.EventPane.prototype.removeMap.apply(this, arguments);
+    },
+    
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
+     * APIMethod: getOLBoundsFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} An <OpenLayers.Bounds>, translated from the 
+     *                       passed-in MapObject Bounds.
+     *                       Returns null if null value is passed in.
+     */
+    getOLBoundsFromMapObjectBounds: function(moBounds) {
+        var olBounds = null;
+        if (moBounds != null) {
+            var sw = moBounds.getSouthWest();
+            var ne = moBounds.getNorthEast();
+            if (this.sphericalMercator) {
+                sw = this.forwardMercator(sw.lng(), sw.lat());
+                ne = this.forwardMercator(ne.lng(), ne.lat());
+            } else {
+                sw = new OpenLayers.LonLat(sw.lng(), sw.lat()); 
+                ne = new OpenLayers.LonLat(ne.lng(), ne.lat()); 
+            }    
+            olBounds = new OpenLayers.Bounds(sw.lon, 
+                                             sw.lat, 
+                                             ne.lon, 
+                                             ne.lat );
+        }
+        return olBounds;
+    },
+
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n("googleWarning");
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.getCenter();
+    },
+
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.getZoom();
+    },
+
+  
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon :
+          moLonLat.lng();  
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        var lat = this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat :
+          moLonLat.lat(); 
+        return lat;  
+    },
+    
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.Google"
+});
+
+/**
+ * Property: OpenLayers.Layer.Google.cache
+ * {Object} Cache for elements that should only be created once per map.
+ */
+OpenLayers.Layer.Google.cache = {};
+
+
+/**
+ * Constant: OpenLayers.Layer.Google.v2
+ * 
+ * Mixin providing functionality specific to the Google Maps API v2.
+ */
+OpenLayers.Layer.Google.v2 = {
+    
+    /**
+     * Property: termsOfUse
+     * {DOMElement} Div for Google's copyright and terms of use link
+     */
+    termsOfUse: null, 
+
+    /**
+     * Property: poweredBy
+     * {DOMElement} Div for Google's powered by logo and link
+     */
+    poweredBy: null, 
+
+    /**
+     * Property: dragObject
+     * {GDraggableObject} Since 2.93, Google has exposed the ability to get
+     *     the maps GDraggableObject. We can now use this for smooth panning
+     */
+    dragObject: null, 
+    
+    /** 
+     * Method: loadMapObject
+     * Load the GMap and register appropriate event listeners. If we can't 
+     *     load GMap2, then display a warning message.
+     */
+    loadMapObject:function() {
+        if (!this.type) {
+            this.type = G_NORMAL_MAP;
+        }
+        var mapObject, termsOfUse, poweredBy;
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // there are already Google layers added to this map
+            mapObject = cache.mapObject;
+            termsOfUse = cache.termsOfUse;
+            poweredBy = cache.poweredBy;
+            // increment the layer count
+            ++cache.count;
+        } else {
+            // this is the first Google layer for this map
+
+            var container = this.map.viewPortDiv;
+            var div = document.createElement("div");
+            div.id = this.map.id + "_GMap2Container";
+            div.style.position = "absolute";
+            div.style.width = "100%";
+            div.style.height = "100%";
+            container.appendChild(div);
+
+            // create GMap and shuffle elements
+            try {
+                mapObject = new GMap2(div);
+                
+                // move the ToS and branding stuff up to the container div
+                termsOfUse = div.lastChild;
+                container.appendChild(termsOfUse);
+                termsOfUse.style.zIndex = "1100";
+                termsOfUse.style.right = "";
+                termsOfUse.style.bottom = "";
+                termsOfUse.className = "olLayerGoogleCopyright";
+
+                poweredBy = div.lastChild;
+                container.appendChild(poweredBy);
+                poweredBy.style.zIndex = "1100";
+                poweredBy.style.right = "";
+                poweredBy.style.bottom = "";
+                poweredBy.className = "olLayerGooglePoweredBy gmnoprint";
+                
+            } catch (e) {
+                throw(e);
+            }
+            // cache elements for use by any other google layers added to
+            // this same map
+            OpenLayers.Layer.Google.cache[this.map.id] = {
+                mapObject: mapObject,
+                termsOfUse: termsOfUse,
+                poweredBy: poweredBy,
+                count: 1
+            };
+        }
+
+        this.mapObject = mapObject;
+        this.termsOfUse = termsOfUse;
+        this.poweredBy = poweredBy;
+        
+        // ensure this layer type is one of the mapObject types
+        if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
+                                    this.type) === -1) {
+            this.mapObject.addMapType(this.type);
+        }
+
+        //since v 2.93 getDragObject is now available.
+        if(typeof mapObject.getDragObject == "function") {
+            this.dragObject = mapObject.getDragObject();
+        } else {
+            this.dragPanMapObject = null;
+        }
+        
+        if(this.isBaseLayer === false) {
+            this.setGMapVisibility(this.div.style.display !== "none");
+        }
+
+    },
+
+    /**
+     * APIMethod: onMapResize
+     */
+    onMapResize: function() {
+        // workaround for resizing of invisible or not yet fully loaded layers
+        // where GMap2.checkResize() does not work. We need to load the GMap
+        // for the old div size, then checkResize(), and then call
+        // layer.moveTo() to trigger GMap.setCenter() (which will finish
+        // the GMap initialization).
+        if(this.visibility && this.mapObject.isLoaded()) {
+            this.mapObject.checkResize();
+        } else {
+            if(!this._resized) {
+                var layer = this;
+                var handle = GEvent.addListener(this.mapObject, "load", function() {
+                    GEvent.removeListener(handle);
+                    delete layer._resized;
+                    layer.mapObject.checkResize();
+                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
+                });
+            }
+            this._resized = true;
+        }
+    },
+
+    /**
+     * Method: setGMapVisibility
+     * Display the GMap container and associated elements.
+     * 
+     * Parameters:
+     * visible - {Boolean} Display the GMap elements.
+     */
+    setGMapVisibility: function(visible) {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            var container = this.mapObject.getContainer();
+            if (visible === true) {
+                this.mapObject.setMapType(this.type);
+                container.style.display = "";
+                this.termsOfUse.style.left = "";
+                this.termsOfUse.style.display = "";
+                this.poweredBy.style.display = "";            
+                cache.displayed = this.id;
+            } else {
+                if (cache.displayed === this.id) {
+                    delete cache.displayed;
+                }
+                if (!cache.displayed) {
+                    container.style.display = "none";
+                    this.termsOfUse.style.display = "none";
+                    // move ToU far to the left in addition to setting display
+                    // to "none", because at the end of the GMap2 load
+                    // sequence, display: none will be unset and ToU would be
+                    // visible after loading a map with a google layer that is
+                    // initially hidden. 
+                    this.termsOfUse.style.left = "-9999px";
+                    this.poweredBy.style.display = "none";
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: getMapContainer
+     * 
+     * Returns:
+     * {DOMElement} the GMap container's div
+     */
+    getMapContainer: function() {
+        return this.mapObject.getContainer();
+    },
+
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
+     * APIMethod: getMapObjectBoundsFromOLBounds
+     * 
+     * Parameters:
+     * olBounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {Object} A MapObject Bounds, translated from olBounds
+     *          Returns null if null value is passed in
+     */
+    getMapObjectBoundsFromOLBounds: function(olBounds) {
+        var moBounds = null;
+        if (olBounds != null) {
+            var sw = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.bottom, olBounds.left) : 
+              new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
+            var ne = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.top, olBounds.right) : 
+              new OpenLayers.LonLat(olBounds.top, olBounds.right);
+            moBounds = new GLatLngBounds(new GLatLng(sw.lat, sw.lon),
+                                         new GLatLng(ne.lat, ne.lon));
+        }
+        return moBounds;
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.setCenter(center, zoom); 
+    },
+   
+    /**
+     * APIMethod: dragPanMapObject
+     * 
+     * Parameters:
+     * dX - {Integer}
+     * dY - {Integer}
+     */
+    dragPanMapObject: function(dX, dY) {
+        this.dragObject.moveBy(new GSize(-dX, dY));
+    },
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        return this.mapObject.fromContainerPixelToLatLng(moPixel);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        return this.mapObject.fromLatLngToContainerPixel(moLonLat);
+    },
+
+  
+  // Bounds
+  
+    /** 
+     * APIMethod: getMapObjectZoomFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object} MapObject Bounds format
+     * 
+     * Returns:
+     * {Object} MapObject Zoom for specified MapObject Bounds
+     */
+    getMapObjectZoomFromMapObjectBounds: function(moBounds) {
+        return this.mapObject.getBoundsZoomLevel(moBounds);
+    },
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var gLatLng;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            gLatLng = new GLatLng(lonlat.lat, lonlat.lon);
+        } else {
+            gLatLng = new GLatLng(lat, lon);
+        }
+        return gLatLng;
+    },
+
+  // Pixel
+    
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new GPoint(x, y);
+    }
+    
+};
+/* ======================================================================
+    OpenLayers/Format/WFST.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Function: OpenLayers.Format.WFST
+ * Used to create a versioned WFS protocol.  Default version is 1.0.0.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A WFST format of the given version.
+ */
+OpenLayers.Format.WFST = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Format.WFST.DEFAULTS
+    );
+    var cls = OpenLayers.Format.WFST["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported WFST version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Format.WFST.DEFAULTS
+ * {Object} Default properties for the WFST format.
+ */
+OpenLayers.Format.WFST.DEFAULTS = {
+    "version": "1.0.0"
+};
+/* ======================================================================
+    OpenLayers/Format/WFST/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/WFST.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1
+ * Superclass for WFST parsers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance",
+        wfs: "http://www.opengis.net/wfs",
+        gml: "http://www.opengis.net/gml",
+        ogc: "http://www.opengis.net/ogc",
+        ows: "http://www.opengis.net/ows"
+    },
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "wfs",
+
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: null,
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocations: null,
+    
+    /**
+     * APIProperty: srsName
+     * {String} URI for spatial reference system.
+     */
+    srsName: null,
+
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from GML.  Default is true.
+     */
+    extractAttributes: true,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */ 
+    xy: true,
+
+    /**
+     * Property: stateName
+     * {Object} Maps feature states to node names.
+     */
+    stateName: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.WFST.v1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.WFST.v1_0_0> or <OpenLayers.Format.WFST.v1_1_0>
+     *     constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        // set state name mapping
+        this.stateName = {};
+        this.stateName[OpenLayers.State.INSERT] = "wfs:Insert";
+        this.stateName[OpenLayers.State.UPDATE] = "wfs:Update";
+        this.stateName[OpenLayers.State.DELETE] = "wfs:Delete";
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: getSrsName
+     */
+    getSrsName: function(feature, options) {
+        var srsName = options && options.srsName;
+        if(!srsName) {
+            if(feature && feature.layer) {
+                srsName = feature.layer.projection.getCode();
+            } else {
+                srsName = this.srsName;
+            }
+        }
+        return srsName;
+    },
+
+    /**
+     * APIMethod: read
+     * Parse the response from a transaction.  Because WFS is split into
+     *     Transaction requests (create, update, and delete) and GetFeature
+     *     requests (read), this method handles parsing of both types of
+     *     responses.
+     *
+     * Parameters:
+     * data - {String | Document} The WFST document to read
+     * options - {Object} Options for the reader
+     *
+     * Valid options properties:
+     * output - {String} either "features" or "object". The default is
+     *     "features", which means that the method will return an array of
+     *     features. If set to "object", an object with a "features" property
+     *     and other properties read by the parser will be returned.
+     *
+     * Returns:
+     * {Array | Object} Output depending on the output option.
+     */
+    read: function(data, options) {
+        options = options || {};
+        OpenLayers.Util.applyDefaults(options, {
+            output: "features"
+        });
+        
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var obj = {};
+        if(data) {
+            this.readNode(data, obj, true);
+        }
+        if(obj.features && options.output === "features") {
+            obj = obj.features;
+        }
+        return obj;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wfs": {
+            "FeatureCollection": function(node, obj) {
+                obj.features = [];
+                this.readChildNodes(node, obj);
+            }
+        }
+    },
+    
+    /**
+     * Method: write
+     * Given an array of features, write a WFS transaction.  This assumes
+     *     the features have a state property that determines the operation
+     *     type - insert, update, or delete.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} A list of features. See
+     *     below for a more detailed description of the influence of the
+     *     feature's *modified* property.
+     * options - {Object}
+     *
+     * feature.modified rules:
+     * If a feature has a modified property set, the following checks will be
+     * made before a feature's geometry or attribute is included in an Update
+     * transaction:
+     * - *modified* is not set at all: The geometry and all attributes will be
+     *     included.
+     * - *modified.geometry* is set (null or a geometry): The geometry will be
+     *     included. If *modified.attributes* is not set, all attributes will
+     *     be included.
+     * - *modified.attributes* is set: Only the attributes set (i.e. to null or
+     *     a value) in *modified.attributes* will be included. 
+     *     If *modified.geometry* is not set, the geometry will not be included.
+     *
+     * Valid options include:
+     * - *multi* {Boolean} If set to true, geometries will be casted to
+     *   Multi geometries before writing.
+     *
+     * Returns:
+     * {String} A serialized WFS transaction.
+     */
+    write: function(features, options) {
+        var node = this.writeNode("wfs:Transaction", {
+            features:features,
+            options: options
+        });
+        var value = this.schemaLocationAttr();
+        if(value) {
+            this.setAttributeNS(
+                node, this.namespaces["xsi"], "xsi:schemaLocation",  value
+            );
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "wfs": {
+            "GetFeature": function(options) {
+                var node = this.createElementNSPlus("wfs:GetFeature", {
+                    attributes: {
+                        service: "WFS",
+                        version: this.version,
+                        handle: options && options.handle,
+                        outputFormat: options && options.outputFormat,
+                        maxFeatures: options && options.maxFeatures,
+                        "xsi:schemaLocation": this.schemaLocationAttr(options)
+                    }
+                });
+                if (typeof this.featureType == "string") {
+                    this.writeNode("Query", options, node);
+                } else {
+                    for (var i=0,len = this.featureType.length; i<len; i++) { 
+                        options.featureType = this.featureType[i]; 
+                        this.writeNode("Query", options, node); 
+                    } 
+                }
+                return node;
+            },
+            "Transaction": function(obj) {
+                obj = obj || {};
+                var options = obj.options || {};
+                var node = this.createElementNSPlus("wfs:Transaction", {
+                    attributes: {
+                        service: "WFS",
+                        version: this.version,
+                        handle: options.handle
+                    }
+                });
+                var i, len;
+                var features = obj.features;
+                if(features) {
+                    // temporarily re-assigning geometry types
+                    if (options.multi === true) {
+                        OpenLayers.Util.extend(this.geometryTypes, {
+                            "OpenLayers.Geometry.Point": "MultiPoint",
+                            "OpenLayers.Geometry.LineString": (this.multiCurve === true) ? "MultiCurve": "MultiLineString",
+                            "OpenLayers.Geometry.Polygon": (this.multiSurface === true) ? "MultiSurface" : "MultiPolygon"
+                        });
+                    }
+                    var name, feature;
+                    for(i=0, len=features.length; i<len; ++i) {
+                        feature = features[i];
+                        name = this.stateName[feature.state];
+                        if(name) {
+                            this.writeNode(name, {
+                                feature: feature, 
+                                options: options
+                            }, node);
+                        }
+                    }
+                    // switch back to original geometry types assignment
+                    if (options.multi === true) {
+                        this.setGeometryTypes();
+                    }
+                }
+                if (options.nativeElements) {
+                    for (i=0, len=options.nativeElements.length; i<len; ++i) {
+                        this.writeNode("wfs:Native", 
+                            options.nativeElements[i], node);
+                    }
+                }
+                return node;
+            },
+            "Native": function(nativeElement) {
+                var node = this.createElementNSPlus("wfs:Native", {
+                    attributes: {
+                        vendorId: nativeElement.vendorId,
+                        safeToIgnore: nativeElement.safeToIgnore
+                    },
+                    value: nativeElement.value
+                });
+                return node;
+            },
+            "Insert": function(obj) {
+                var feature = obj.feature;
+                var options = obj.options;
+                var node = this.createElementNSPlus("wfs:Insert", {
+                    attributes: {
+                        handle: options && options.handle
+                    }
+                });
+                this.srsName = this.getSrsName(feature);
+                this.writeNode("feature:_typeName", feature, node);
+                return node;
+            },
+            "Update": function(obj) {
+                var feature = obj.feature;
+                var options = obj.options;
+                var node = this.createElementNSPlus("wfs:Update", {
+                    attributes: {
+                        handle: options && options.handle,
+                        typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+                            this.featureType
+                    }
+                });
+                if(this.featureNS) {
+                    node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+                }
+                
+                // add in geometry
+                var modified = feature.modified;
+                if (this.geometryName !== null && (!modified || modified.geometry !== undefined)) {
+                    this.srsName = this.getSrsName(feature);
+                    this.writeNode(
+                        "Property", {name: this.geometryName, value: feature.geometry}, node
+                    );
+                }
+        
+                // add in attributes
+                for(var key in feature.attributes) {
+                    if(feature.attributes[key] !== undefined &&
+                                (!modified || !modified.attributes ||
+                                (modified.attributes && modified.attributes[key] !== undefined))) {
+                        this.writeNode(
+                            "Property", {name: key, value: feature.attributes[key]}, node
+                        );
+                    }
+                }
+                
+                // add feature id filter
+                this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
+                    fids: [feature.fid]
+                }), node);
+        
+                return node;
+            },
+            "Property": function(obj) {
+                var node = this.createElementNSPlus("wfs:Property");
+                this.writeNode("Name", obj.name, node);
+                if(obj.value !== null) {
+                    this.writeNode("Value", obj.value, node);
+                }
+                return node;
+            },
+            "Name": function(name) {
+                return this.createElementNSPlus("wfs:Name", {value: name});
+            },
+            "Value": function(obj) {
+                var node;
+                if(obj instanceof OpenLayers.Geometry) {
+                    node = this.createElementNSPlus("wfs:Value");
+                    var geom = this.writeNode("feature:_geometry", obj).firstChild;
+                    node.appendChild(geom);
+                } else {
+                    node = this.createElementNSPlus("wfs:Value", {value: obj});                
+                }
+                return node;
+            },
+            "Delete": function(obj) {
+                var feature = obj.feature;
+                var options = obj.options;
+                var node = this.createElementNSPlus("wfs:Delete", {
+                    attributes: {
+                        handle: options && options.handle,
+                        typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+                            this.featureType
+                    }
+                });
+                if(this.featureNS) {
+                    node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+                }
+                this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
+                    fids: [feature.fid]
+                }), node);
+                return node;
+            }
+        }
+    },
+
+    /**
+     * Method: schemaLocationAttr
+     * Generate the xsi:schemaLocation attribute value.
+     *
+     * Returns:
+     * {String} The xsi:schemaLocation attribute or undefined if none.
+     */
+    schemaLocationAttr: function(options) {
+        options = OpenLayers.Util.extend({
+            featurePrefix: this.featurePrefix,
+            schema: this.schema
+        }, options);
+        var schemaLocations = OpenLayers.Util.extend({}, this.schemaLocations);
+        if(options.schema) {
+            schemaLocations[options.featurePrefix] = options.schema;
+        }
+        var parts = [];
+        var uri;
+        for(var key in schemaLocations) {
+            uri = this.namespaces[key];
+            if(uri) {
+                parts.push(uri + " " + schemaLocations[key]);
+            }
+        }
+        var value = parts.join(" ") || undefined;
+        return value;
+    },
+    
+    /**
+     * Method: setFilterProperty
+     * Set the property of each spatial filter.
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter>}
+     */
+    setFilterProperty: function(filter) {
+        if(filter.filters) {
+            for(var i=0, len=filter.filters.length; i<len; ++i) {
+                this.setFilterProperty(filter.filters[i]);
+            }
+        } else {
+            if(filter instanceof OpenLayers.Filter.Spatial) {
+                // got a spatial filter, set its property
+                filter.property = this.geometryName;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WFST.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/GML/v3.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/Base.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML.v3
+ * Parses GML version 3.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.GML.Base>
+ */
+OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
+    
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.  The writers
+     *     conform with the Simple Features Profile for GML.
+     */
+    schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",
+
+    /**
+     * Property: curve
+     * {Boolean} Write gml:Curve instead of gml:LineString elements.  This also
+     *     affects the elements in multi-part geometries.  Default is false.
+     *     To write gml:Curve elements instead of gml:LineString, set curve
+     *     to true in the options to the contstructor (cannot be changed after
+     *     instantiation).
+     */
+    curve: false,
+    
+    /**
+     * Property: multiCurve
+     * {Boolean} Write gml:MultiCurve instead of gml:MultiLineString.  Since
+     *     the latter is deprecated in GML 3, the default is true.  To write
+     *     gml:MultiLineString instead of gml:MultiCurve, set multiCurve to
+     *     false in the options to the constructor (cannot be changed after
+     *     instantiation).
+     */
+    multiCurve: true,
+    
+    /**
+     * Property: surface
+     * {Boolean} Write gml:Surface instead of gml:Polygon elements.  This also
+     *     affects the elements in multi-part geometries.  Default is false.
+     *     To write gml:Surface elements instead of gml:Polygon, set surface
+     *     to true in the options to the contstructor (cannot be changed after
+     *     instantiation).
+     */
+    surface: false,
+
+    /**
+     * Property: multiSurface
+     * {Boolean} Write gml:multiSurface instead of gml:MultiPolygon.  Since
+     *     the latter is deprecated in GML 3, the default is true.  To write
+     *     gml:MultiPolygon instead of gml:multiSurface, set multiSurface to
+     *     false in the options to the constructor (cannot be changed after
+     *     instantiation).
+     */
+    multiSurface: true,
+
+    /**
+     * Constructor: OpenLayers.Format.GML.v3
+     * Create a parser for GML v3.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (required).
+     * geometryName - {String} Geometry element name.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "featureMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Curve": function(node, container) {
+                var obj = {points: []};
+                this.readChildNodes(node, obj);
+                if(!container.components) {
+                    container.components = [];
+                }
+                container.components.push(
+                    new OpenLayers.Geometry.LineString(obj.points)
+                );
+            },
+            "segments": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "LineStringSegment": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                if(obj.points) {
+                    Array.prototype.push.apply(container.points, obj.points);
+                }
+            },
+            "pos": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, ""
+                );
+                var coords = str.split(this.regExes.splitSpace);
+                var point;
+                if(this.xy) {
+                    point = new OpenLayers.Geometry.Point(
+                        coords[0], coords[1], coords[2]
+                    );
+                } else {
+                    point = new OpenLayers.Geometry.Point(
+                        coords[1], coords[0], coords[2]
+                    );
+                }
+                obj.points = [point];
+            },
+            "posList": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, ""
+                );
+                var coords = str.split(this.regExes.splitSpace);
+                var dim = parseInt(node.getAttribute("dimension")) || 2;
+                var j, x, y, z;
+                var numPoints = coords.length / dim;
+                var points = new Array(numPoints);
+                for(var i=0, len=coords.length; i<len; i += dim) {
+                    x = coords[i];
+                    y = coords[i+1];
+                    z = (dim == 2) ? undefined : coords[i+2];
+                    if (this.xy) {
+                        points[i/dim] = new OpenLayers.Geometry.Point(x, y, z);
+                    } else {
+                        points[i/dim] = new OpenLayers.Geometry.Point(y, x, z);
+                    }
+                }
+                obj.points = points;
+            },
+            "Surface": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "patches": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "PolygonPatch": function(node, obj) {
+                this.readers.gml.Polygon.apply(this, [node, obj]);
+            },
+            "exterior": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                container.outer = obj.components[0];
+            },
+            "interior": function(node, container) {
+                var obj = {};
+                this.readChildNodes(node, obj);
+                container.inner.push(obj.components[0]);
+            },
+            "MultiCurve": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                if(obj.components.length > 0) {
+                    container.components = [
+                        new OpenLayers.Geometry.MultiLineString(obj.components)
+                    ];
+                }
+            },
+            "curveMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "MultiSurface": function(node, container) {
+                var obj = {components: []};
+                this.readChildNodes(node, obj);
+                if(obj.components.length > 0) {
+                    container.components = [
+                        new OpenLayers.Geometry.MultiPolygon(obj.components)
+                    ];
+                }
+            },
+            "surfaceMember": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "surfaceMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "pointMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "lineStringMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "polygonMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "geometryMembers": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Envelope": function(node, container) {
+                var obj = {points: new Array(2)};
+                this.readChildNodes(node, obj);
+                if(!container.components) {
+                    container.components = [];
+                }
+                var min = obj.points[0];
+                var max = obj.points[1];
+                container.components.push(
+                    new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
+                );
+            },
+            "lowerCorner": function(node, container) {
+                var obj = {};
+                this.readers.gml.pos.apply(this, [node, obj]);
+                container.points[0] = obj.points[0];
+            },
+            "upperCorner": function(node, container) {
+                var obj = {};
+                this.readers.gml.pos.apply(this, [node, obj]);
+                container.points[1] = obj.points[0];
+            }
+        }, OpenLayers.Format.GML.Base.prototype.readers["gml"]),            
+        "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
+        "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
+    },
+    
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+     *     An array of features or a single feature.
+     *
+     * Returns:
+     * {String} Given an array of features, a doc with a gml:featureMembers
+     *     element will be returned.  Given a single feature, a doc with a
+     *     gml:featureMember element will be returned.
+     */
+    write: function(features) {
+        var name;
+        if(OpenLayers.Util.isArray(features)) {
+            name = "featureMembers";
+        } else {
+            name = "featureMember";
+        }
+        var root = this.writeNode("gml:" + name, features);
+        this.setAttributeNS(
+            root, this.namespaces["xsi"],
+            "xsi:schemaLocation", this.schemaLocation
+        );
+
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "featureMembers": function(features) {
+                var node = this.createElementNSPlus("gml:featureMembers");
+                for(var i=0, len=features.length; i<len; ++i) {
+                    this.writeNode("feature:_typeName", features[i], node);
+                }
+                return node;
+            },
+            "Point": function(geometry) {
+                var node = this.createElementNSPlus("gml:Point");
+                this.writeNode("pos", geometry, node);
+                return node;
+            },
+            "pos": function(point) {
+                // only 2d for simple features profile
+                var pos = (this.xy) ?
+                    (point.x + " " + point.y) : (point.y + " " + point.x);
+                return this.createElementNSPlus("gml:pos", {
+                    value: pos
+                });
+            },
+            "LineString": function(geometry) {
+                var node = this.createElementNSPlus("gml:LineString");
+                this.writeNode("posList", geometry.components, node);
+                return node;
+            },
+            "Curve": function(geometry) {
+                var node = this.createElementNSPlus("gml:Curve");
+                this.writeNode("segments", geometry, node);
+                return node;
+            },
+            "segments": function(geometry) {
+                var node = this.createElementNSPlus("gml:segments");
+                this.writeNode("LineStringSegment", geometry, node);
+                return node;
+            },
+            "LineStringSegment": function(geometry) {
+                var node = this.createElementNSPlus("gml:LineStringSegment");
+                this.writeNode("posList", geometry.components, node);
+                return node;
+            },
+            "posList": function(points) {
+                // only 2d for simple features profile
+                var len = points.length;
+                var parts = new Array(len);
+                var point;
+                for(var i=0; i<len; ++i) {
+                    point = points[i];
+                    if(this.xy) {
+                        parts[i] = point.x + " " + point.y;
+                    } else {
+                        parts[i] = point.y + " " + point.x;
+                    }
+                }
+                return this.createElementNSPlus("gml:posList", {
+                    value: parts.join(" ")
+                }); 
+            },
+            "Surface": function(geometry) {
+                var node = this.createElementNSPlus("gml:Surface");
+                this.writeNode("patches", geometry, node);
+                return node;
+            },
+            "patches": function(geometry) {
+                var node = this.createElementNSPlus("gml:patches");
+                this.writeNode("PolygonPatch", geometry, node);
+                return node;
+            },
+            "PolygonPatch": function(geometry) {
+                var node = this.createElementNSPlus("gml:PolygonPatch", {
+                    attributes: {interpolation: "planar"}
+                });
+                this.writeNode("exterior", geometry.components[0], node);
+                for(var i=1, len=geometry.components.length; i<len; ++i) {
+                    this.writeNode(
+                        "interior", geometry.components[i], node
+                    );
+                }
+                return node;
+            },
+            "Polygon": function(geometry) {
+                var node = this.createElementNSPlus("gml:Polygon");
+                this.writeNode("exterior", geometry.components[0], node);
+                for(var i=1, len=geometry.components.length; i<len; ++i) {
+                    this.writeNode(
+                        "interior", geometry.components[i], node
+                    );
+                }
+                return node;
+            },
+            "exterior": function(ring) {
+                var node = this.createElementNSPlus("gml:exterior");
+                this.writeNode("LinearRing", ring, node);
+                return node;
+            },
+            "interior": function(ring) {
+                var node = this.createElementNSPlus("gml:interior");
+                this.writeNode("LinearRing", ring, node);
+                return node;
+            },
+            "LinearRing": function(ring) {
+                var node = this.createElementNSPlus("gml:LinearRing");
+                this.writeNode("posList", ring.components, node);
+                return node;
+            },
+            "MultiCurve": function(geometry) {
+                var node = this.createElementNSPlus("gml:MultiCurve");
+                var components = geometry.components || [geometry];
+                for(var i=0, len=components.length; i<len; ++i) {
+                    this.writeNode("curveMember", components[i], node);
+                }
+                return node;
+            },
+            "curveMember": function(geometry) {
+                var node = this.createElementNSPlus("gml:curveMember");
+                if(this.curve) {
+                    this.writeNode("Curve", geometry, node);
+                } else {
+                    this.writeNode("LineString", geometry, node);
+                }
+                return node;
+            },
+            "MultiSurface": function(geometry) {
+                var node = this.createElementNSPlus("gml:MultiSurface");
+                var components = geometry.components || [geometry];
+                for(var i=0, len=components.length; i<len; ++i) {
+                    this.writeNode("surfaceMember", components[i], node);
+                }
+                return node;
+            },
+            "surfaceMember": function(polygon) {
+                var node = this.createElementNSPlus("gml:surfaceMember");
+                if(this.surface) {
+                    this.writeNode("Surface", polygon, node);
+                } else {
+                    this.writeNode("Polygon", polygon, node);
+                }
+                return node;
+            },
+            "Envelope": function(bounds) {
+                var node = this.createElementNSPlus("gml:Envelope");
+                this.writeNode("lowerCorner", bounds, node);
+                this.writeNode("upperCorner", bounds, node);
+                // srsName attribute is required for gml:Envelope
+                if(this.srsName) {
+                    node.setAttribute("srsName", this.srsName);
+                }
+                return node;
+            },
+            "lowerCorner": function(bounds) {
+                // only 2d for simple features profile
+                var pos = (this.xy) ?
+                    (bounds.left + " " + bounds.bottom) :
+                    (bounds.bottom + " " + bounds.left);
+                return this.createElementNSPlus("gml:lowerCorner", {
+                    value: pos
+                });
+            },
+            "upperCorner": function(bounds) {
+                // only 2d for simple features profile
+                var pos = (this.xy) ?
+                    (bounds.right + " " + bounds.top) :
+                    (bounds.top + " " + bounds.right);
+                return this.createElementNSPlus("gml:upperCorner", {
+                    value: pos
+                });
+            }
+        }, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
+        "feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
+        "wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
+    },
+
+    /**
+     * Function: setGeometryTypes
+     * Sets the <geometryTypes> mapping.
+     */
+    setGeometryTypes: function() {
+        this.geometryTypes = {
+            "OpenLayers.Geometry.Point": "Point",
+            "OpenLayers.Geometry.MultiPoint": "MultiPoint",
+            "OpenLayers.Geometry.LineString": (this.curve === true) ? "Curve": "LineString",
+            "OpenLayers.Geometry.MultiLineString": (this.multiCurve === false) ? "MultiLineString" : "MultiCurve",
+            "OpenLayers.Geometry.Polygon": (this.surface === true) ? "Surface" : "Polygon",
+            "OpenLayers.Geometry.MultiPolygon": (this.multiSurface === false) ? "MultiPolygon" : "MultiSurface",
+            "OpenLayers.Geometry.Collection": "GeometryCollection"
+        };
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.GML.v3" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/Filter/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/Filter/v1.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1_1_0
+ * Write ogc:Filter version 1.1.0.
+ *
+ * Differences from the v1.0.0 parser:
+ *  - uses GML v3 instead of GML v2
+ *  - reads matchCase attribute on ogc:PropertyIsEqual and
+ *        ogc:PropertyIsNotEqual elements.
+ *  - writes matchCase attribute from comparison filters of type EQUAL_TO,
+ *        NOT_EQUAL_TO and LIKE.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.Filter.v1>
+ */
+OpenLayers.Format.Filter.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.GML.v3, OpenLayers.Format.Filter.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.1.0
+     */
+    VERSION: "1.1.0",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/ogc/filter/1.1.0/filter.xsd
+     */
+    schemaLocation: "http://www.opengis.net/ogc/filter/1.1.0/filter.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.Filter.v1_1_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.Filter> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.GML.v3.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ogc": OpenLayers.Util.applyDefaults({
+            "PropertyIsEqualTo": function(node, obj) {
+                var matchCase = node.getAttribute("matchCase");
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                    matchCase: !(matchCase === "false" || matchCase === "0")
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsNotEqualTo": function(node, obj) {
+                var matchCase = node.getAttribute("matchCase");
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+                    matchCase: !(matchCase === "false" || matchCase === "0")
+                });
+                this.readChildNodes(node, filter);
+                obj.filters.push(filter);
+            },
+            "PropertyIsLike": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LIKE
+                });
+                this.readChildNodes(node, filter);
+                var wildCard = node.getAttribute("wildCard");
+                var singleChar = node.getAttribute("singleChar");
+                var esc = node.getAttribute("escapeChar");
+                filter.value2regex(wildCard, singleChar, esc);
+                obj.filters.push(filter);
+            }
+        }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),
+        "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+        "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"]        
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ogc": OpenLayers.Util.applyDefaults({
+            "PropertyIsEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsEqualTo", {
+                    attributes: {matchCase: filter.matchCase}
+                });
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsNotEqualTo": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo", {
+                    attributes: {matchCase: filter.matchCase}
+                });
+                // no ogc:expression handling for PropertyName for now
+                this.writeNode("PropertyName", filter, node);
+                // handle Literals or Functions for now
+                this.writeOgcExpression(filter.value, node);
+                return node;
+            },
+            "PropertyIsLike": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsLike", {
+                    attributes: {
+                        matchCase: filter.matchCase,
+                        wildCard: "*", singleChar: ".", escapeChar: "!"
+                    }
+                });
+                // no ogc:expression handling for now
+                this.writeNode("PropertyName", filter, node);
+                // convert regex string to ogc string
+                this.writeNode("Literal", filter.regex2value(), node);
+                return node;
+            },
+            "BBOX": function(filter) {
+                var node = this.createElementNSPlus("ogc:BBOX");
+                // PropertyName is optional in 1.1.0
+                filter.property && this.writeNode("PropertyName", filter, node);
+                var box = this.writeNode("gml:Envelope", filter.value);
+                if(filter.projection) {
+                    box.setAttribute("srsName", filter.projection);
+                }
+                node.appendChild(box); 
+                return node;
+            },
+            "SortBy": function(sortProperties) {
+                var node = this.createElementNSPlus("ogc:SortBy");
+                for (var i=0,l=sortProperties.length;i<l;i++) {
+                    this.writeNode(
+                        "ogc:SortProperty",
+                        sortProperties[i],
+                        node
+                    );
+                }
+                return node;
+            }, 
+            "SortProperty": function(sortProperty) {
+                var node = this.createElementNSPlus("ogc:SortProperty");
+                this.writeNode(
+                    "ogc:PropertyName",
+                    sortProperty,
+                    node
+                );
+                this.writeNode(
+                    "ogc:SortOrder",
+                    (sortProperty.order == 'DESC') ? 'DESC' : 'ASC',
+                    node
+                );
+                return node;
+            },
+            "SortOrder": function(value) {
+                var node = this.createElementNSPlus("ogc:SortOrder", {
+                    value: value
+                });
+                return node;
+            }
+        }, OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),
+        "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+        "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"]
+    },
+
+    /**
+     * Method: writeSpatial
+     *
+     * Read a {<OpenLayers.Filter.Spatial>} filter and converts it into XML.
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter.Spatial>} The filter.
+     * name - {String} Name of the generated XML element.
+     *
+     * Returns:
+     * {DOMElement} The created XML element.
+     */
+    writeSpatial: function(filter, name) {
+        var node = this.createElementNSPlus("ogc:"+name);
+        this.writeNode("PropertyName", filter, node);
+        if(filter.value instanceof OpenLayers.Filter.Function) {
+            this.writeNode("Function", filter.value, node);
+        } else {
+        var child;
+        if(filter.value instanceof OpenLayers.Geometry) {
+            child = this.writeNode("feature:_geometry", filter.value).firstChild;
+        } else {
+            child = this.writeNode("gml:Envelope", filter.value);
+        }
+        if(filter.projection) {
+            child.setAttribute("srsName", filter.projection);
+        }
+        node.appendChild(child);
+        }
+        return node;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Filter.v1_1_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WFST/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFST/v1.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1_1_0
+ * A format for creating WFS v1.1.0 transactions.  Create a new instance with the
+ *     <OpenLayers.Format.WFST.v1_1_0> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.Filter.v1_1_0>
+ *  - <OpenLayers.Format.WFST.v1>
+ */
+OpenLayers.Format.WFST.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.Filter.v1_1_0, OpenLayers.Format.WFST.v1, {
+    
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: "1.1.0",
+    
+    /**
+     * Property: schemaLocations
+     * {Object} Properties are namespace aliases, values are schema locations.
+     */
+    schemaLocations: {
+        "wfs": "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.WFST.v1_1_0
+     * A class for parsing and generating WFS v1.1.0 transactions.
+     *
+     * To read additional information like hit count (numberOfFeatures) from
+     * the  FeatureCollection, call the <OpenLayers.Format.WFST.v1.read> method
+     * with {output: "object"} as 2nd argument. Note that it is possible to
+     * just request the hit count from a WFS 1.1.0 server with the
+     * resultType="hits" request parameter.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (optional).
+     * featurePrefix - {String} Feature namespace alias (optional - only used
+     *     if featureNS is provided).  Default is 'feature'.
+     * geometryName - {String} Name of geometry attribute.  Default is 'the_geom'.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: readNode
+     * Shorthand for applying one of the named readers given the node
+     *     namespace and local name.  Readers take two args (node, obj) and
+     *     generally extend or modify the second.
+     *
+     * Parameters:
+     * node - {DOMElement} The node to be read (required).
+     * obj - {Object} The object to be modified (optional).
+     * first - {Boolean} Should be set to true for the first node read. This
+     *     is usually the readNode call in the read method. Without this being
+     *     set, auto-configured properties will stick on subsequent reads.
+     *
+     * Returns:
+     * {Object} The input object, modified (or a new one if none was provided).
+     */
+    readNode: function(node, obj, first) {
+        // Not the superclass, only the mixin classes inherit from
+        // Format.GML.v3. We need this because we don't want to get readNode
+        // from the superclass's superclass, which is OpenLayers.Format.XML.
+        return OpenLayers.Format.GML.v3.prototype.readNode.apply(this, [node, obj]);
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wfs": OpenLayers.Util.applyDefaults({
+            "FeatureCollection": function(node, obj) {
+                obj.numberOfFeatures = parseInt(node.getAttribute(
+                    "numberOfFeatures"));
+                OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(
+                    this, arguments);
+            },
+            "TransactionResponse": function(node, obj) {
+                obj.insertIds = [];
+                obj.success = false;
+                this.readChildNodes(node, obj);
+            },
+            "TransactionSummary": function(node, obj) {
+                // this is a limited test of success
+                obj.success = true;
+            },
+            "InsertResults": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Feature": function(node, container) {
+                var obj = {fids: []};
+                this.readChildNodes(node, obj);
+                container.insertIds.push(obj.fids[0]);
+            }
+        }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),
+        "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+        "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"],
+        "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"],
+        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "wfs": OpenLayers.Util.applyDefaults({
+            "GetFeature": function(options) {
+                var node = OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this, arguments);
+                options && this.setAttributes(node, {
+                    resultType: options.resultType,
+                    startIndex: options.startIndex,
+                    count: options.count
+                });
+                return node;
+            },
+            "Query": function(options) {
+                options = OpenLayers.Util.extend({
+                    featureNS: this.featureNS,
+                    featurePrefix: this.featurePrefix,
+                    featureType: this.featureType,
+                    srsName: this.srsName
+                }, options);
+                var prefix = options.featurePrefix;
+                var node = this.createElementNSPlus("wfs:Query", {
+                    attributes: {
+                        typeName: (prefix ? prefix + ":" : "") +
+                            options.featureType,
+                        srsName: options.srsName
+                    }
+                });
+                if(options.featureNS) {
+                    node.setAttribute("xmlns:" + prefix, options.featureNS);
+                }
+                if(options.propertyNames) {
+                    for(var i=0,len = options.propertyNames.length; i<len; i++) {
+                        this.writeNode(
+                            "wfs:PropertyName", 
+                            {property: options.propertyNames[i]},
+                            node
+                        );
+                    }
+                }
+                if(options.filter) {
+                    this.setFilterProperty(options.filter);
+                    this.writeNode("ogc:Filter", options.filter, node);
+                }
+                return node;
+            },
+            "PropertyName": function(obj) {
+                return this.createElementNSPlus("wfs:PropertyName", {
+                    value: obj.property
+                });
+            }            
+        }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),
+        "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+        "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"],
+        "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WFST.v1_1_0" 
+});
+/* ======================================================================
+    OpenLayers/Format/WFSCapabilities.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities
+ * Read WFS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WFSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.1.0".
+     */
+    defaultVersion: "1.1.0",
+ 
+    /**
+     * APIProperty: errorProperty
+     * {String} Which property of the returned object to check for in order to
+     * determine whether or not parsing has failed. In the case that the
+     * errorProperty is undefined on the returned object, the document will be
+     * run through an OGCExceptionReport parser.
+     */
+    errorProperty: "service",
+
+    /**
+     * Constructor: OpenLayers.Format.WFSCapabilities
+     * Create a new parser for WFS capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    
+    CLASS_NAME: "OpenLayers.Format.WFSCapabilities" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WFSCapabilities/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities.v1
+ * Abstract class not to be instantiated directly.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFSCapabilities.v1 = OpenLayers.Class(
+    OpenLayers.Format.WFSCapabilities, {
+    
+    /**
+     * Constructor: OpenLayers.Format.WFSCapabilities.v1_1
+     * Create an instance of one of the subclasses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var capabilities = {};
+        var root = data.documentElement;
+        this.runChildNodes(capabilities, root);
+        return capabilities;
+    },
+    
+    /**
+     * Method: runChildNodes
+     */
+    runChildNodes: function(obj, node) {
+        var children = node.childNodes;
+        var childNode, processor;
+        for(var i=0; i<children.length; ++i) {
+            childNode = children[i];
+            if(childNode.nodeType == 1) {
+                processor = this["read_cap_" + childNode.nodeName];
+                if(processor) {
+                    processor.apply(this, [obj, childNode]);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: read_cap_FeatureTypeList
+     */
+    read_cap_FeatureTypeList: function(request, node) {
+        var featureTypeList = {
+            featureTypes: []
+        };
+        this.runChildNodes(featureTypeList, node);
+        request.featureTypeList = featureTypeList;
+    },
+    
+    /**
+     * Method: read_cap_FeatureType
+     */
+    read_cap_FeatureType: function(featureTypeList, node, parentLayer) {
+        var featureType = {};
+        this.runChildNodes(featureType, node);
+        featureTypeList.featureTypes.push(featureType);
+    },
+    
+    /**
+     * Method: read_cap_Name
+     */
+    read_cap_Name: function(obj, node) {
+        var name = this.getChildValue(node);
+        if(name) {
+            var parts = name.split(":");
+            obj.name = parts.pop();
+            if(parts.length > 0) {
+                obj.featureNS = this.lookupNamespaceURI(node, parts[0]);
+            }
+        }
+    },
+
+    /**
+     * Method: read_cap_Title
+     */
+    read_cap_Title: function(obj, node) {
+        var title = this.getChildValue(node);
+        if(title) {
+            obj.title = title;
+        }
+    },
+
+    /**
+     * Method: read_cap_Abstract
+     */
+    read_cap_Abstract: function(obj, node) {
+        var abst = this.getChildValue(node);
+        if(abst) {
+            obj["abstract"] = abst;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/VirtualEarth.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/SphericalMercator.js
+ * @requires OpenLayers/Layer/EventPane.js
+ * @requires OpenLayers/Layer/FixedZoomLevels.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.VirtualEarth
+ * Instances of OpenLayers.Layer.VirtualEarth are used to display the data from
+ *     the Bing Maps AJAX Control (see e.g. 
+ *     http://msdn.microsoft.com/library/bb429619.aspx). Create a VirtualEarth 
+ *     layer with the <OpenLayers.Layer.VirtualEarth> constructor.
+ *     
+ * Inherits from:
+ *  - <OpenLayers.Layer.EventPane>
+ *  - <OpenLayers.Layer.FixedZoomLevels>
+ */
+OpenLayers.Layer.VirtualEarth = OpenLayers.Class(
+    OpenLayers.Layer.EventPane,
+    OpenLayers.Layer.FixedZoomLevels, {
+    
+    /** 
+     * Constant: MIN_ZOOM_LEVEL
+     * {Integer} 1 
+     */
+    MIN_ZOOM_LEVEL: 1,
+    
+    /** 
+     * Constant: MAX_ZOOM_LEVEL
+     * {Integer} 19
+     */
+    MAX_ZOOM_LEVEL: 19,
+
+    /** 
+     * Constant: RESOLUTIONS
+     * {Array(Float)} Hardcode these resolutions so that they are more closely
+     *                tied with the standard wms projection
+     */
+    RESOLUTIONS: [
+        1.40625, 
+        0.703125, 
+        0.3515625, 
+        0.17578125, 
+        0.087890625, 
+        0.0439453125,
+        0.02197265625, 
+        0.010986328125, 
+        0.0054931640625, 
+        0.00274658203125,
+        0.001373291015625, 
+        0.0006866455078125, 
+        0.00034332275390625, 
+        0.000171661376953125, 
+        0.0000858306884765625, 
+        0.00004291534423828125,
+        0.00002145767211914062, 
+        0.00001072883605957031,
+        0.00000536441802978515
+    ],
+
+    /**
+     * APIProperty: type
+     * {VEMapType}
+     */
+    type: null,
+
+    /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
+     * APIProperty: sphericalMercator
+     * {Boolean} Should the map act as a mercator-projected map? This will
+     *     cause all interactions with the map to be in the actual map
+     *     projection, which allows support for vector drawing, overlaying
+     *     other maps, etc. 
+     */
+    sphericalMercator: false,
+    
+    /**
+     * APIProperty: animationEnabled
+     * {Boolean} If set to true, the transition between zoom levels will be
+     *     animated. Set to false to match the zooming experience of other
+     *     layer types. Default is true.
+     */
+    animationEnabled: true, 
+
+    /** 
+     * Constructor: OpenLayers.Layer.VirtualEarth
+     * Creates a new instance of a OpenLayers.Layer.VirtualEarth. If you use an
+     *     instance of OpenLayers.Layer.VirtualEarth in you map, you should set 
+     *     the <OpenLayers.Map> option restrictedExtent to a meaningful value,
+     *     e.g.:
+     * (code)
+     * var map = new OpenLayers.Map( 'map', {
+     *     // other map options
+     *     restrictedExtent : OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508)
+     * } );
+     * 
+     * var veLayer = new OpenLayers.Layer.VirtualEarth (
+     *     "Virtual Earth Layer"
+     * );
+     * 
+     * map.addLayer( veLayer );
+     * (end)
+     * 
+     * Parameters:
+     * name - {String}
+     * options - {Object}
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
+        OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
+                                                                    arguments);
+        if(this.sphericalMercator) {
+            OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
+            this.initMercatorParameters();
+        }
+    },
+    
+    /**
+     * Method: loadMapObject
+     */
+    loadMapObject:function() {
+
+        // create div and set to same size as map
+        var veDiv = OpenLayers.Util.createDiv(this.name);
+        var sz = this.map.getSize();
+        veDiv.style.width = sz.w + "px";
+        veDiv.style.height = sz.h + "px";
+        this.div.appendChild(veDiv);
+
+        try { // crash prevention
+            this.mapObject = new VEMap(this.name);
+        } catch (e) { }
+
+        if (this.mapObject != null) {
+            try { // this is to catch a Mozilla bug without falling apart
+
+                // The fourth argument is whether the map is 'fixed' -- not 
+                // draggable. See: 
+                // http://blogs.msdn.com/virtualearth/archive/2007/09/28/locking-a-virtual-earth-map.aspx
+                //
+                this.mapObject.LoadMap(null, null, this.type, true);
+                this.mapObject.AttachEvent("onmousedown", OpenLayers.Function.True);
+
+            } catch (e) { }
+            this.mapObject.HideDashboard();
+            if(typeof this.mapObject.SetAnimationEnabled == "function") {
+                this.mapObject.SetAnimationEnabled(this.animationEnabled);
+            }
+        }
+
+        //can we do smooth panning? this is an unpublished method, so we need 
+        // to be careful
+        if ( !this.mapObject ||
+             !this.mapObject.vemapcontrol ||
+             !this.mapObject.vemapcontrol.PanMap ||
+             (typeof this.mapObject.vemapcontrol.PanMap != "function")) {
+
+            this.dragPanMapObject = null;
+        }
+
+    },
+
+    /**
+     * Method: onMapResize
+     */
+    onMapResize: function() {
+        this.mapObject.Resize(this.map.size.w, this.map.size.h);
+    },
+
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n(
+            "getLayerWarning", {'layerType':'VE', 'layerLib':'VirtualEarth'}
+        );
+    },
+
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.SetCenterAndZoom(center, zoom); 
+    },
+   
+    /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.GetCenter();
+    },
+
+    /**
+     * APIMethod: dragPanMapObject
+     * 
+     * Parameters:
+     * dX - {Integer}
+     * dY - {Integer}
+     */
+    dragPanMapObject: function(dX, dY) {
+        this.mapObject.vemapcontrol.PanMap(dX, -dY);
+    },
+
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.GetZoomLevel();
+    },
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        //the conditional here is to test if we are running the v6 of VE
+        return (typeof VEPixel != 'undefined') 
+            ? this.mapObject.PixelToLatLong(moPixel)
+            : this.mapObject.PixelToLatLong(moPixel.x, moPixel.y);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        return this.mapObject.LatLongToPixel(moLonLat);
+    },
+
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.Longitude, moLonLat.Latitude).lon :
+            moLonLat.Longitude;
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.Longitude, moLonLat.Latitude).lat :
+            moLonLat.Latitude;
+    },
+
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var veLatLong;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            veLatLong = new VELatLong(lonlat.lat, lonlat.lon);
+        } else {
+            veLatLong = new VELatLong(lat, lon);
+        }
+        return veLatLong;
+    },
+
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        //the conditional here is to test if we are running the v6 of VE
+        return (typeof VEPixel != 'undefined') ? new VEPixel(x, y)
+                         : new Msn.VE.Pixel(x, y);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.VirtualEarth"
+});
+/* ======================================================================
+    OpenLayers/Control/Panel.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Panel
+ * The Panel control is a container for other controls. With it toolbars
+ * may be composed.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, {
+    /**
+     * Property: controls
+     * {Array(<OpenLayers.Control>)}
+     */
+    controls: null,    
+    
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /** 
+     * APIProperty: defaultControl
+     * {<OpenLayers.Control>} The control which is activated when the control is
+     * activated (turned on), which also happens at instantiation.
+     * If <saveState> is true, <defaultControl> will be nullified after the
+     * first activation of the panel.
+     */
+    defaultControl: null,
+    
+    /**
+     * APIProperty: saveState
+     * {Boolean} If set to true, the active state of this panel's controls will
+     * be stored on panel deactivation, and restored on reactivation. Default
+     * is false.
+     */
+    saveState: false,
+      
+    /**
+     * APIProperty: allowDepress
+     * {Boolean} If is true the <OpenLayers.Control.TYPE_TOOL> controls can 
+     *     be deactivated by clicking the icon that represents them.  Default 
+     *     is false.
+     */
+    allowDepress: false,
+    
+    /**
+     * Property: activeState
+     * {Object} stores the active state of this panel's controls.
+     */
+    activeState: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Panel
+     * Create a new control panel.
+     *
+     * Each control in the panel is represented by an icon. When clicking 
+     *     on an icon, the <activateControl> method is called.
+     *
+     * Specific properties for controls on a panel:
+     * type - {Number} One of <OpenLayers.Control.TYPE_TOOL>,
+     *     <OpenLayers.Control.TYPE_TOGGLE>, <OpenLayers.Control.TYPE_BUTTON>.
+     *     If not provided, <OpenLayers.Control.TYPE_TOOL> is assumed.
+     * title - {string} Text displayed when mouse is over the icon that 
+     *     represents the control.     
+     *
+     * The <OpenLayers.Control.type> of a control determines the behavior when
+     * clicking its icon:
+     * <OpenLayers.Control.TYPE_TOOL> - The control is activated and other
+     *     controls of this type in the same panel are deactivated. This is
+     *     the default type.
+     * <OpenLayers.Control.TYPE_TOGGLE> - The active state of the control is
+     *     toggled.
+     * <OpenLayers.Control.TYPE_BUTTON> - The
+     *     <OpenLayers.Control.Button.trigger> method of the control is called,
+     *     but its active state is not changed.
+     *
+     * If a control is <OpenLayers.Control.active>, it will be drawn with the
+     * olControl[Name]ItemActive class, otherwise with the
+     * olControl[Name]ItemInactive class.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.controls = [];
+        this.activeState = {};
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+        for (var ctl, i = this.controls.length - 1; i >= 0; i--) {
+            ctl = this.controls[i];
+            if (ctl.events) {
+                ctl.events.un({
+                    activate: this.iconOn,
+                    deactivate: this.iconOff
+                });
+            }
+            OpenLayers.Event.stopObservingElement(ctl.panel_div);
+            ctl.panel_div = null;
+        }
+        this.activeState = null;
+    },
+
+    /**
+     * APIMethod: activate
+     */
+    activate: function() {
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            var control;
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                control = this.controls[i];
+                if (control === this.defaultControl ||
+                            (this.saveState && this.activeState[control.id])) {
+                    control.activate();
+                }
+            }    
+            if (this.saveState === true) {
+                this.defaultControl = null;
+            }
+            this.redraw();
+            return true;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            var control;
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                control = this.controls[i];
+                this.activeState[control.id] = control.deactivate();
+            }    
+            this.redraw();
+            return true;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: draw
+     *
+     * Returns:
+     * {DOMElement}
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        this.addControlsToMap(this.controls);
+        return this.div;
+    },
+
+    /**
+     * Method: redraw
+     */
+    redraw: function() {
+        for (var l=this.div.childNodes.length, i=l-1; i>=0; i--) {
+            this.div.removeChild(this.div.childNodes[i]);
+        }
+        this.div.innerHTML = "";
+        if (this.active) {
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                this.div.appendChild(this.controls[i].panel_div);
+            }
+        }
+    },
+
+    /**
+     * APIMethod: activateControl
+     * This method is called when the user click on the icon representing a 
+     *     control in the panel.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>}
+     */
+    activateControl: function (control) {
+        if (!this.active) { return false; }
+        if (control.type == OpenLayers.Control.TYPE_BUTTON) {
+            control.trigger();
+            return;
+        }
+        if (control.type == OpenLayers.Control.TYPE_TOGGLE) {
+            if (control.active) {
+                control.deactivate();
+            } else {
+                control.activate();
+            }
+            return;
+        }
+        if (this.allowDepress && control.active) {
+            control.deactivate();
+        } else {
+            var c;
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                c = this.controls[i];
+                if (c != control &&
+                   (c.type === OpenLayers.Control.TYPE_TOOL || c.type == null)) {
+                    c.deactivate();
+                }
+            }
+            control.activate();
+        }
+    },
+
+    /**
+     * APIMethod: addControls
+     * To build a toolbar, you add a set of controls to it. addControls
+     * lets you add a single control or a list of controls to the 
+     * Control Panel.
+     *
+     * Parameters:
+     * controls - {<OpenLayers.Control>} Controls to add in the panel.
+     */    
+    addControls: function(controls) {
+        if (!(OpenLayers.Util.isArray(controls))) {
+            controls = [controls];
+        }
+        this.controls = this.controls.concat(controls);
+        
+        // Give each control a panel_div which will be used later.
+        // Access to this div is via the panel_div attribute of the 
+        // control added to the panel.
+        // Also, stop mousedowns and clicks, but don't stop mouseup,
+        // since they need to pass through.
+        for (var i=0, len=controls.length; i<len; i++) {
+            var element = document.createElement("div");
+            element.className = controls[i].displayClass + "ItemInactive";
+            controls[i].panel_div = element;
+            if (controls[i].title != "") {
+                controls[i].panel_div.title = controls[i].title;
+            }
+            OpenLayers.Event.observe(controls[i].panel_div, "click", 
+                OpenLayers.Function.bind(this.onClick, this, controls[i]));
+            OpenLayers.Event.observe(controls[i].panel_div, "dblclick", 
+                OpenLayers.Function.bind(this.onDoubleClick, this, controls[i]));
+            OpenLayers.Event.observe(controls[i].panel_div, "mousedown", 
+                OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));
+        }    
+
+        if (this.map) { // map.addControl() has already been called on the panel
+            this.addControlsToMap(controls);
+            this.redraw();
+        }
+    },
+   
+    /**
+     * Method: addControlsToMap
+     * Only for internal use in draw() and addControls() methods.
+     *
+     * Parameters:
+     * controls - {Array(<OpenLayers.Control>)} Controls to add into map.
+     */         
+    addControlsToMap: function (controls) {
+        var control;
+        for (var i=0, len=controls.length; i<len; i++) {
+            control = controls[i];
+            if (control.autoActivate === true) {
+                control.autoActivate = false;
+                this.map.addControl(control);
+                control.autoActivate = true;
+            } else {
+                this.map.addControl(control);
+                control.deactivate();
+            }
+            control.events.on({
+                activate: this.iconOn,
+                deactivate: this.iconOff
+            });
+        }  
+    },
+
+    /**
+     * Method: iconOn
+     * Internal use, for use only with "controls[i].events.on/un".
+     */
+     iconOn: function() {
+        var d = this.panel_div; // "this" refers to a control on panel!
+        d.className = d.className.replace(/ItemInactive$/, "ItemActive");
+    },
+
+    /**
+     * Method: iconOff
+     * Internal use, for use only with "controls[i].events.on/un".
+     */
+     iconOff: function() {
+        var d = this.panel_div; // "this" refers to a control on panel!
+        d.className = d.className.replace(/ItemActive$/, "ItemInactive");
+    },
+
+    /**
+     * Method: onClick
+     */
+    onClick: function (ctrl, evt) {
+        OpenLayers.Event.stop(evt ? evt : window.event);
+        this.activateControl(ctrl);
+    },
+
+    /**
+     * Method: onDoubleClick
+     */
+    onDoubleClick: function(ctrl, evt) {
+        OpenLayers.Event.stop(evt ? evt : window.event);
+    },
+
+    /**
+     * APIMethod: getControlsBy
+     * Get a list of controls with properties matching the given criteria.
+     *
+     * Parameter:
+     * property - {String} A control property to be matched.
+     * match - {String | Object} A string to match.  Can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     match.test(control[property]) evaluates to true, the control will be
+     *     included in the array returned.  If no controls are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Control>)} A list of controls matching the given criteria.
+     *     An empty array is returned if no matches are found.
+     */
+    getControlsBy: function(property, match) {
+        var test = (typeof match.test == "function");
+        var found = OpenLayers.Array.filter(this.controls, function(item) {
+            return item[property] == match || (test && match.test(item[property]));
+        });
+        return found;
+    },
+
+    /**
+     * APIMethod: getControlsByName
+     * Get a list of contorls with names matching the given name.
+     *
+     * Parameter:
+     * match - {String | Object} A control name.  The name can also be a regular
+     *     expression literal or object.  In addition, it can be any object
+     *     with a method named test.  For reqular expressions or other, if
+     *     name.test(control.name) evaluates to true, the control will be included
+     *     in the list of controls returned.  If no controls are found, an empty
+     *     array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Control>)} A list of controls matching the given name.
+     *     An empty array is returned if no matches are found.
+     */
+    getControlsByName: function(match) {
+        return this.getControlsBy("name", match);
+    },
+
+    /**
+     * APIMethod: getControlsByClass
+     * Get a list of controls of a given type (CLASS_NAME).
+     *
+     * Parameter:
+     * match - {String | Object} A control class name.  The type can also be a
+     *     regular expression literal or object.  In addition, it can be any
+     *     object with a method named test.  For reqular expressions or other,
+     *     if type.test(control.CLASS_NAME) evaluates to true, the control will
+     *     be included in the list of controls returned.  If no controls are
+     *     found, an empty array is returned.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Control>)} A list of controls matching the given type.
+     *     An empty array is returned if no matches are found.
+     */
+    getControlsByClass: function(match) {
+        return this.getControlsBy("CLASS_NAME", match);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Panel"
+});
+
+/* ======================================================================
+    OpenLayers/Control/ZoomIn.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ZoomIn
+ * The ZoomIn control is a button to increase the zoom level of a map.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ZoomIn = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: type
+     * {String} The type of <OpenLayers.Control> -- When added to a 
+     *     <Control.Panel>, 'type' is used by the panel to determine how to 
+     *     handle our events.
+     */
+    type: OpenLayers.Control.TYPE_BUTTON,
+    
+    /**
+     * Method: trigger
+     */
+    trigger: function(){
+        this.map.zoomIn();
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ZoomIn"
+});
+/* ======================================================================
+    OpenLayers/Control/ZoomOut.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ZoomOut
+ * The ZoomOut control is a button to decrease the zoom level of a map.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ZoomOut = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: type
+     * {String} The type of <OpenLayers.Control> -- When added to a 
+     *     <Control.Panel>, 'type' is used by the panel to determine how to 
+     *     handle our events.
+     */
+    type: OpenLayers.Control.TYPE_BUTTON,
+    
+    /**
+     * Method: trigger
+     */
+    trigger: function(){
+        this.map.zoomOut();
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ZoomOut"
+});
+/* ======================================================================
+    OpenLayers/Control/ZoomToMaxExtent.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ZoomToMaxExtent 
+ * The ZoomToMaxExtent control is a button that zooms out to the maximum
+ * extent of the map. It is designed to be used with a 
+ * <OpenLayers.Control.Panel>.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ZoomToMaxExtent = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: type
+     * {String} The type of <OpenLayers.Control> -- When added to a 
+     *     <Control.Panel>, 'type' is used by the panel to determine how to 
+     *     handle our events.
+     */
+    type: OpenLayers.Control.TYPE_BUTTON,
+    
+    /*
+     * Method: trigger
+     * Do the zoom.
+     */
+    trigger: function() {
+        if (this.map) {
+            this.map.zoomToMaxExtent();
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ZoomToMaxExtent"
+});
+/* ======================================================================
+    OpenLayers/Control/ZoomPanel.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/Panel.js
+ * @requires OpenLayers/Control/ZoomIn.js
+ * @requires OpenLayers/Control/ZoomOut.js
+ * @requires OpenLayers/Control/ZoomToMaxExtent.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ZoomPanel
+ * The ZoomPanel control is a compact collecton of 3 zoom controls: a 
+ * <OpenLayers.Control.ZoomIn>, a <OpenLayers.Control.ZoomToMaxExtent>, and a
+ * <OpenLayers.Control.ZoomOut>. By default it is drawn in the upper left 
+ * corner of the map.
+ *
+ * Note: 
+ * If you wish to use this class with the default images and you want 
+ *       it to look nice in ie6, you should add the following, conditionally
+ *       added css stylesheet to your HTML file:
+ * 
+ * (code)
+ * <!--[if lte IE 6]>
+ *   <link rel="stylesheet" href="../theme/default/ie6-style.css" type="text/css" />
+ * <![endif]-->
+ * (end)
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control.Panel>
+ */
+OpenLayers.Control.ZoomPanel = OpenLayers.Class(OpenLayers.Control.Panel, {
+
+    /**
+     * Constructor: OpenLayers.Control.ZoomPanel 
+     * Add the three zooming controls.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
+        this.addControls([
+            new OpenLayers.Control.ZoomIn(),
+            new OpenLayers.Control.ZoomToMaxExtent(),
+            new OpenLayers.Control.ZoomOut()
+        ]);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ZoomPanel"
+});
+/* ======================================================================
+    OpenLayers/Layer/HTTPRequest.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.HTTPRequest
+ * 
+ * Inherits from: 
+ *  - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.HTTPRequest = OpenLayers.Class(OpenLayers.Layer, {
+
+    /** 
+     * Constant: URL_HASH_FACTOR
+     * {Float} Used to hash URL param strings for multi-WMS server selection.
+     *         Set to the Golden Ratio per Knuth's recommendation.
+     */
+    URL_HASH_FACTOR: (Math.sqrt(5) - 1) / 2,
+
+    /** 
+     * Property: url
+     * {Array(String) or String} This is either an array of url strings or 
+     *                           a single url string. 
+     */
+    url: null,
+
+    /** 
+     * Property: params
+     * {Object} Hashtable of key/value parameters
+     */
+    params: null,
+    
+    /** 
+     * APIProperty: reproject
+     * *Deprecated*. See http://docs.openlayers.org/library/spherical_mercator.html
+     * for information on the replacement for this functionality. 
+     * {Boolean} Whether layer should reproject itself based on base layer 
+     *           locations. This allows reprojection onto commercial layers. 
+     *           Default is false: Most layers can't reproject, but layers 
+     *           which can create non-square geographic pixels can, like WMS.
+     *           
+     */
+    reproject: false,
+
+    /**
+     * Constructor: OpenLayers.Layer.HTTPRequest
+     * 
+     * Parameters:
+     * name - {String}
+     * url - {Array(String) or String}
+     * params - {Object}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, params, options) {
+        OpenLayers.Layer.prototype.initialize.apply(this, [name, options]);
+        this.url = url;
+        this.params = OpenLayers.Util.extend( {}, params);
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.url = null;
+        this.params = null;
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments); 
+    },
+    
+    /**
+     * APIMethod: clone
+     * 
+     * Parameters:
+     * obj - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.HTTPRequest>} An exact clone of this 
+     *                                  <OpenLayers.Layer.HTTPRequest>
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.HTTPRequest(this.name,
+                                                   this.url,
+                                                   this.params,
+                                                   this.getOptions());
+        }
+        
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        
+        return obj;
+    },
+
+    /** 
+     * APIMethod: setUrl
+     * 
+     * Parameters:
+     * newUrl - {String}
+     */
+    setUrl: function(newUrl) {
+        this.url = newUrl;
+    },
+
+    /**
+     * APIMethod: mergeNewParams
+     * 
+     * Parameters:
+     * newParams - {Object}
+     *
+     * Returns:
+     * redrawn: {Boolean} whether the layer was actually redrawn.
+     */
+    mergeNewParams:function(newParams) {
+        this.params = OpenLayers.Util.extend(this.params, newParams);
+        var ret = this.redraw();
+        if(this.map != null) {
+            this.map.events.triggerEvent("changelayer", {
+                layer: this,
+                property: "params"
+            });
+        }
+        return ret;
+    },
+
+    /**
+     * APIMethod: redraw
+     * Redraws the layer.  Returns true if the layer was redrawn, false if not.
+     *
+     * Parameters:
+     * force - {Boolean} Force redraw by adding random parameter.
+     *
+     * Returns:
+     * {Boolean} The layer was redrawn.
+     */
+    redraw: function(force) { 
+        if (force) {
+            return this.mergeNewParams({"_olSalt": Math.random()});
+        } else {
+            return OpenLayers.Layer.prototype.redraw.apply(this, []);
+        }
+    },
+    
+    /**
+     * Method: selectUrl
+     * selectUrl() implements the standard floating-point multiplicative
+     *     hash function described by Knuth, and hashes the contents of the 
+     *     given param string into a float between 0 and 1. This float is then
+     *     scaled to the size of the provided urls array, and used to select
+     *     a URL.
+     *
+     * Parameters:
+     * paramString - {String}
+     * urls - {Array(String)}
+     * 
+     * Returns:
+     * {String} An entry from the urls array, deterministically selected based
+     *          on the paramString.
+     */
+    selectUrl: function(paramString, urls) {
+        var product = 1;
+        for (var i=0, len=paramString.length; i<len; i++) { 
+            product *= paramString.charCodeAt(i) * this.URL_HASH_FACTOR; 
+            product -= Math.floor(product); 
+        }
+        return urls[Math.floor(product * urls.length)];
+    },
+
+    /** 
+     * Method: getFullRequestString
+     * Combine url with layer's params and these newParams. 
+     *   
+     *    does checking on the serverPath variable, allowing for cases when it 
+     *     is supplied with trailing ? or &, as well as cases where not. 
+     *
+     *    return in formatted string like this:
+     *        "server?key1=value1&key2=value2&key3=value3"
+     * 
+     * WARNING: The altUrl parameter is deprecated and will be removed in 3.0.
+     *
+     * Parameters:
+     * newParams - {Object}
+     * altUrl - {String} Use this as the url instead of the layer's url
+     *   
+     * Returns: 
+     * {String}
+     */
+    getFullRequestString:function(newParams, altUrl) {
+
+        // if not altUrl passed in, use layer's url
+        var url = altUrl || this.url;
+        
+        // create a new params hashtable with all the layer params and the 
+        // new params together. then convert to string
+        var allParams = OpenLayers.Util.extend({}, this.params);
+        allParams = OpenLayers.Util.extend(allParams, newParams);
+        var paramsString = OpenLayers.Util.getParameterString(allParams);
+        
+        // if url is not a string, it should be an array of strings, 
+        // in which case we will deterministically select one of them in 
+        // order to evenly distribute requests to different urls.
+        //
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(paramsString, url);
+        }   
+ 
+        // ignore parameters that are already in the url search string
+        var urlParams = 
+            OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));
+        for(var key in allParams) {
+            if(key.toUpperCase() in urlParams) {
+                delete allParams[key];
+            }
+        }
+        paramsString = OpenLayers.Util.getParameterString(allParams);
+        
+        return OpenLayers.Util.urlAppend(url, paramsString);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.HTTPRequest"
+});
+/* ======================================================================
+    OpenLayers/Layer/Grid.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/HTTPRequest.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Grid
+ * Base class for layers that use a lattice of tiles.  Create a new grid
+ * layer with the <OpenLayers.Layer.Grid> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.HTTPRequest>
+ */
+OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
+    
+    /**
+     * APIProperty: tileSize
+     * {<OpenLayers.Size>}
+     */
+    tileSize: null,
+
+    /**
+     * Property: tileOriginCorner
+     * {String} If the <tileOrigin> property is not provided, the tile origin 
+     *     will be derived from the layer's <maxExtent>.  The corner of the 
+     *     <maxExtent> used is determined by this property.  Acceptable values
+     *     are "tl" (top left), "tr" (top right), "bl" (bottom left), and "br"
+     *     (bottom right).  Default is "bl".
+     */
+    tileOriginCorner: "bl",
+    
+    /**
+     * APIProperty: tileOrigin
+     * {<OpenLayers.LonLat>} Optional origin for aligning the grid of tiles.
+     *     If provided, requests for tiles at all resolutions will be aligned
+     *     with this location (no tiles shall overlap this location).  If
+     *     not provided, the grid of tiles will be aligned with the layer's
+     *     <maxExtent>.  Default is ``null``.
+     */
+    tileOrigin: null,
+    
+    /** APIProperty: tileOptions
+     *  {Object} optional configuration options for <OpenLayers.Tile> instances
+     *  created by this Layer, if supported by the tile class.
+     */
+    tileOptions: null,
+    
+    /**
+     * Property: grid
+     * {Array(Array(<OpenLayers.Tile>))} This is an array of rows, each row is 
+     *     an array of tiles.
+     */
+    grid: null,
+
+    /**
+     * APIProperty: singleTile
+     * {Boolean} Moves the layer into single-tile mode, meaning that one tile 
+     *     will be loaded. The tile's size will be determined by the 'ratio'
+     *     property. When the tile is dragged such that it does not cover the 
+     *     entire viewport, it is reloaded.
+     */
+    singleTile: false,
+
+    /** APIProperty: ratio
+     *  {Float} Used only when in single-tile mode, this specifies the 
+     *          ratio of the size of the single tile to the size of the map.
+     */
+    ratio: 1.5,
+
+    /**
+     * APIProperty: buffer
+     * {Integer} Used only when in gridded mode, this specifies the number of 
+     *           extra rows and colums of tiles on each side which will
+     *           surround the minimum grid tiles to cover the map.
+     *           For very slow loading layers, a larger value may increase
+     *           performance somewhat when dragging, but will increase bandwidth
+     *           use significantly. 
+     */
+    buffer: 0,
+
+    /**
+     * APIProperty: numLoadingTiles
+     * {Integer} How many tiles are still loading?
+     */
+    numLoadingTiles: 0,
+
+    /**
+     * APIProperty: tileLoadingDelay
+     * {Integer} - Number of milliseconds before we shift and load
+     *     tiles. Default is 100.
+     */
+    tileLoadingDelay: 100,
+
+    /**
+     * Property: timerId
+     * {Number} - The id of the tileLoadingDelay timer.
+     */
+    timerId: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.Grid
+     * Create a new grid layer
+     *
+     * Parameters:
+     * name - {String}
+     * url - {String}
+     * params - {Object}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, params, options) {
+        OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this, 
+                                                                arguments);
+        
+        //grid layers will trigger 'tileloaded' when each new tile is 
+        // loaded, as a means of progress update to listeners.
+        // listeners can access 'numLoadingTiles' if they wish to keep track
+        // of the loading progress
+        //
+        this.events.addEventType("tileloaded");
+
+        this.grid = [];
+        
+        this._moveGriddedTiles = OpenLayers.Function.bind(
+            this.moveGriddedTiles, this
+        );
+    },
+
+    /**
+     * Method: removeMap
+     * Called when the layer is removed from the map.
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>} The map.
+     */
+    removeMap: function(map) {
+        if(this.timerId != null) {
+            window.clearTimeout(this.timerId);
+            this.timerId = null;
+        }
+    },
+
+    /**
+     * APIMethod: destroy
+     * Deconstruct the layer and clear the grid.
+     */
+    destroy: function() {
+        this.clearGrid();
+        this.grid = null;
+        this.tileSize = null;
+        OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments); 
+    },
+
+    /**
+     * Method: clearGrid
+     * Go through and remove all tiles from the grid, calling
+     *    destroy() on each of them to kill circular references
+     */
+    clearGrid:function() {
+        if (this.grid) {
+            for(var iRow=0, len=this.grid.length; iRow<len; iRow++) {
+                var row = this.grid[iRow];
+                for(var iCol=0, clen=row.length; iCol<clen; iCol++) {
+                    var tile = row[iCol];
+                    this.removeTileMonitoringHooks(tile);
+                    tile.destroy();
+                }
+            }
+            this.grid = [];
+        }
+    },
+
+    /**
+     * APIMethod: clone
+     * Create a clone of this layer
+     *
+     * Parameters:
+     * obj - {Object} Is this ever used?
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.Grid>} An exact clone of this OpenLayers.Layer.Grid
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Grid(this.name,
+                                            this.url,
+                                            this.params,
+                                            this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        if (this.tileSize != null) {
+            obj.tileSize = this.tileSize.clone();
+        }
+        
+        // we do not want to copy reference to grid, so we make a new array
+        obj.grid = [];
+
+        return obj;
+    },    
+
+    /**
+     * Method: moveTo
+     * This function is called whenever the map is moved. All the moving
+     * of actual 'tiles' is done by the map, but moveTo's role is to accept
+     * a bounds and make sure the data that that bounds requires is pre-loaded.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean}
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this, arguments);
+        
+        bounds = bounds || this.map.getExtent();
+
+        if (bounds != null) {
+             
+            // if grid is empty or zoom has changed, we *must* re-tile
+            var forceReTile = !this.grid.length || zoomChanged;
+
+            // total bounds of the tiles
+            var tilesBounds = this.getTilesBounds();            
+      
+            if (this.singleTile) {
+                
+                // We want to redraw whenever even the slightest part of the 
+                //  current bounds is not contained by our tile.
+                //  (thus, we do not specify partial -- its default is false)
+                if ( forceReTile || 
+                     (!dragging && !tilesBounds.containsBounds(bounds))) {
+                    this.initSingleTile(bounds);
+                }
+            } else {
+             
+                // if the bounds have changed such that they are not even 
+                //  *partially* contained by our tiles (IE user has 
+                //  programmatically panned to the other side of the earth) 
+                //  then we want to reTile (thus, partial true).  
+                //
+                if (forceReTile || !tilesBounds.containsBounds(bounds, true)) {
+                    this.initGriddedTiles(bounds);
+                } else {
+                    this.scheduleMoveGriddedTiles();
+                }
+            }
+        }
+    },
+
+    /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector.
+     *
+     * Parameters:
+     * dx - {Number}
+     * dy - {Number}
+     */
+    moveByPx: function(dx, dy) {
+        if (!this.singleTile) {
+            this.scheduleMoveGriddedTiles();
+        }
+    },
+
+    /**
+     * Method: scheduleMoveGriddedTiles
+     * Schedule the move of tiles.
+     */
+    scheduleMoveGriddedTiles: function() {
+        if (this.timerId != null) {
+            window.clearTimeout(this.timerId);
+        }
+        this.timerId = window.setTimeout(
+            this._moveGriddedTiles,
+            this.tileLoadingDelay
+        );
+    },
+    
+    /**
+     * APIMethod: setTileSize
+     * Check if we are in singleTile mode and if so, set the size as a ratio
+     *     of the map size (as specified by the layer's 'ratio' property).
+     * 
+     * Parameters:
+     * size - {<OpenLayers.Size>}
+     */
+    setTileSize: function(size) { 
+        if (this.singleTile) {
+            size = this.map.getSize();
+            size.h = parseInt(size.h * this.ratio);
+            size.w = parseInt(size.w * this.ratio);
+        } 
+        OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this, [size]);
+    },
+        
+    /**
+     * Method: getGridBounds
+     * Deprecated. This function will be removed in 3.0. Please use 
+     *     getTilesBounds() instead.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object representing the bounds of all the
+     * currently loaded tiles (including those partially or not at all seen 
+     * onscreen)
+     */
+    getGridBounds: function() {
+        var msg = "The getGridBounds() function is deprecated. It will be " +
+                  "removed in 3.0. Please use getTilesBounds() instead.";
+        OpenLayers.Console.warn(msg);
+        return this.getTilesBounds();
+    },
+
+    /**
+     * APIMethod: getTilesBounds
+     * Return the bounds of the tile grid.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object representing the bounds of all the
+     *     currently loaded tiles (including those partially or not at all seen 
+     *     onscreen).
+     */
+    getTilesBounds: function() {    
+        var bounds = null; 
+        
+        if (this.grid.length) {
+            var bottom = this.grid.length - 1;
+            var bottomLeftTile = this.grid[bottom][0];
+    
+            var right = this.grid[0].length - 1; 
+            var topRightTile = this.grid[0][right];
+    
+            bounds = new OpenLayers.Bounds(bottomLeftTile.bounds.left, 
+                                           bottomLeftTile.bounds.bottom,
+                                           topRightTile.bounds.right, 
+                                           topRightTile.bounds.top);
+            
+        }   
+        return bounds;
+    },
+
+    /**
+     * Method: initSingleTile
+     * 
+     * Parameters: 
+     * bounds - {<OpenLayers.Bounds>}
+     */
+    initSingleTile: function(bounds) {
+
+        //determine new tile bounds
+        var center = bounds.getCenterLonLat();
+        var tileWidth = bounds.getWidth() * this.ratio;
+        var tileHeight = bounds.getHeight() * this.ratio;
+                                       
+        var tileBounds = 
+            new OpenLayers.Bounds(center.lon - (tileWidth/2),
+                                  center.lat - (tileHeight/2),
+                                  center.lon + (tileWidth/2),
+                                  center.lat + (tileHeight/2));
+  
+        var ul = new OpenLayers.LonLat(tileBounds.left, tileBounds.top);
+        var px = this.map.getLayerPxFromLonLat(ul);
+
+        if (!this.grid.length) {
+            this.grid[0] = [];
+        }
+
+        var tile = this.grid[0][0];
+        if (!tile) {
+            tile = this.addTile(tileBounds, px);
+            
+            this.addTileMonitoringHooks(tile);
+            tile.draw();
+            this.grid[0][0] = tile;
+        } else {
+            tile.moveTo(tileBounds, px);
+        }           
+        
+        //remove all but our single tile
+        this.removeExcessTiles(1,1);
+    },
+
+    /** 
+     * Method: calculateGridLayout
+     * Generate parameters for the grid layout.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * origin - {<OpenLayers.LonLat>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, origin, resolution) {
+        var tilelon = resolution * this.tileSize.w;
+        var tilelat = resolution * this.tileSize.h;
+        
+        var offsetlon = bounds.left - origin.lon;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = origin.lon + tilecol * tilelon;
+        
+        var offsetlat = bounds.top - (origin.lat + tilelat);  
+        var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = -tilerowremain * this.tileSize.h;
+        var tileoffsetlat = origin.lat + tilerow * tilelat;
+        
+        return { 
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+
+    },
+    
+    /**
+     * Method: getTileOrigin
+     * Determine the origin for aligning the grid of tiles.  If a <tileOrigin>
+     *     property is supplied, that will be returned.  Otherwise, the origin
+     *     will be derived from the layer's <maxExtent> property.  In this case,
+     *     the tile origin will be the corner of the <maxExtent> given by the 
+     *     <tileOriginCorner> property.
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} The tile origin.
+     */
+    getTileOrigin: function() {
+        var origin = this.tileOrigin;
+        if (!origin) {
+            var extent = this.getMaxExtent();
+            var edges = ({
+                "tl": ["left", "top"],
+                "tr": ["right", "top"],
+                "bl": ["left", "bottom"],
+                "br": ["right", "bottom"]
+            })[this.tileOriginCorner];
+            origin = new OpenLayers.LonLat(extent[edges[0]], extent[edges[1]]);
+        }
+        return origin;
+    },
+
+    /**
+     * Method: initGriddedTiles
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     */
+    initGriddedTiles:function(bounds) {
+        
+        // work out mininum number of rows and columns; this is the number of
+        // tiles required to cover the viewport plus at least one for panning
+
+        var viewSize = this.map.getSize();
+        var minRows = Math.ceil(viewSize.h/this.tileSize.h) + 
+                      Math.max(1, 2 * this.buffer);
+        var minCols = Math.ceil(viewSize.w/this.tileSize.w) +
+                      Math.max(1, 2 * this.buffer);
+        
+        var origin = this.getTileOrigin();
+        var resolution = this.map.getResolution();
+        
+        var tileLayout = this.calculateGridLayout(bounds, origin, resolution);
+
+        var tileoffsetx = Math.round(tileLayout.tileoffsetx); // heaven help us
+        var tileoffsety = Math.round(tileLayout.tileoffsety);
+
+        var tileoffsetlon = tileLayout.tileoffsetlon;
+        var tileoffsetlat = tileLayout.tileoffsetlat;
+        
+        var tilelon = tileLayout.tilelon;
+        var tilelat = tileLayout.tilelat;
+
+        this.origin = new OpenLayers.Pixel(tileoffsetx, tileoffsety);
+
+        var startX = tileoffsetx; 
+        var startLon = tileoffsetlon;
+
+        var rowidx = 0;
+        
+        var layerContainerDivLeft = parseInt(this.map.layerContainerDiv.style.left);
+        var layerContainerDivTop = parseInt(this.map.layerContainerDiv.style.top);
+        
+    
+        do {
+            var row = this.grid[rowidx++];
+            if (!row) {
+                row = [];
+                this.grid.push(row);
+            }
+
+            tileoffsetlon = startLon;
+            tileoffsetx = startX;
+            var colidx = 0;
+ 
+            do {
+                var tileBounds = 
+                    new OpenLayers.Bounds(tileoffsetlon, 
+                                          tileoffsetlat, 
+                                          tileoffsetlon + tilelon,
+                                          tileoffsetlat + tilelat);
+
+                var x = tileoffsetx;
+                x -= layerContainerDivLeft;
+
+                var y = tileoffsety;
+                y -= layerContainerDivTop;
+
+                var px = new OpenLayers.Pixel(x, y);
+                var tile = row[colidx++];
+                if (!tile) {
+                    tile = this.addTile(tileBounds, px);
+                    this.addTileMonitoringHooks(tile);
+                    row.push(tile);
+                } else {
+                    tile.moveTo(tileBounds, px, false);
+                }
+     
+                tileoffsetlon += tilelon;       
+                tileoffsetx += this.tileSize.w;
+            } while ((tileoffsetlon <= bounds.right + tilelon * this.buffer)
+                     || colidx < minCols);
+             
+            tileoffsetlat -= tilelat;
+            tileoffsety += this.tileSize.h;
+        } while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer)
+                || rowidx < minRows);
+        
+        //shave off exceess rows and colums
+        this.removeExcessTiles(rowidx, colidx);
+
+        //now actually draw the tiles
+        this.spiralTileLoad();
+    },
+
+    /**
+     * Method: getMaxExtent
+     * Get this layer's maximum extent. (Implemented as a getter for
+     *     potential specific implementations in sub-classes.)
+     *
+     * Returns:
+     * {OpenLayers.Bounds}
+     */
+    getMaxExtent: function() {
+        return this.maxExtent;
+    },
+    
+    /**
+     * Method: spiralTileLoad
+     *   Starts at the top right corner of the grid and proceeds in a spiral 
+     *    towards the center, adding tiles one at a time to the beginning of a 
+     *    queue. 
+     * 
+     *   Once all the grid's tiles have been added to the queue, we go back 
+     *    and iterate through the queue (thus reversing the spiral order from 
+     *    outside-in to inside-out), calling draw() on each tile. 
+     */
+    spiralTileLoad: function() {
+        var tileQueue = [];
+ 
+        var directions = ["right", "down", "left", "up"];
+
+        var iRow = 0;
+        var iCell = -1;
+        var direction = OpenLayers.Util.indexOf(directions, "right");
+        var directionsTried = 0;
+        
+        while( directionsTried < directions.length) {
+
+            var testRow = iRow;
+            var testCell = iCell;
+
+            switch (directions[direction]) {
+                case "right":
+                    testCell++;
+                    break;
+                case "down":
+                    testRow++;
+                    break;
+                case "left":
+                    testCell--;
+                    break;
+                case "up":
+                    testRow--;
+                    break;
+            } 
+    
+            // if the test grid coordinates are within the bounds of the 
+            //  grid, get a reference to the tile.
+            var tile = null;
+            if ((testRow < this.grid.length) && (testRow >= 0) &&
+                (testCell < this.grid[0].length) && (testCell >= 0)) {
+                tile = this.grid[testRow][testCell];
+            }
+            
+            if ((tile != null) && (!tile.queued)) {
+                //add tile to beginning of queue, mark it as queued.
+                tileQueue.unshift(tile);
+                tile.queued = true;
+                
+                //restart the directions counter and take on the new coords
+                directionsTried = 0;
+                iRow = testRow;
+                iCell = testCell;
+            } else {
+                //need to try to load a tile in a different direction
+                direction = (direction + 1) % 4;
+                directionsTried++;
+            }
+        } 
+        
+        // now we go through and draw the tiles in forward order
+        for(var i=0, len=tileQueue.length; i<len; i++) {
+            var tile = tileQueue[i];
+            tile.draw();
+            //mark tile as unqueued for the next time (since tiles are reused)
+            tile.queued = false;       
+        }
+    },
+
+    /**
+     * APIMethod: addTile
+     * Create a tile, initialize it, and add it to the layer div. 
+     *
+     * Parameters
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.Tile>} The added OpenLayers.Tile
+     */
+    addTile:function(bounds, position) {
+        return new OpenLayers.Tile.Image(this, position, bounds, null, 
+                                         this.tileSize, this.tileOptions);
+    },
+    
+    /** 
+     * Method: addTileMonitoringHooks
+     * This function takes a tile as input and adds the appropriate hooks to 
+     *     the tile so that the layer can keep track of the loading tiles.
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    addTileMonitoringHooks: function(tile) {
+        
+        tile.onLoadStart = function() {
+            //if that was first tile then trigger a 'loadstart' on the layer
+            if (this.numLoadingTiles == 0) {
+                this.events.triggerEvent("loadstart");
+            }
+            this.numLoadingTiles++;
+        };
+        tile.events.register("loadstart", this, tile.onLoadStart);
+      
+        tile.onLoadEnd = function() {
+            this.numLoadingTiles--;
+            this.events.triggerEvent("tileloaded");
+            //if that was the last tile, then trigger a 'loadend' on the layer
+            if (this.numLoadingTiles == 0) {
+                this.events.triggerEvent("loadend");
+            }
+        };
+        tile.events.register("loadend", this, tile.onLoadEnd);
+        tile.events.register("unload", this, tile.onLoadEnd);
+    },
+
+    /** 
+     * Method: removeTileMonitoringHooks
+     * This function takes a tile as input and removes the tile hooks 
+     *     that were added in addTileMonitoringHooks()
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    removeTileMonitoringHooks: function(tile) {
+        tile.unload();
+        tile.events.un({
+            "loadstart": tile.onLoadStart,
+            "loadend": tile.onLoadEnd,
+            "unload": tile.onLoadEnd,
+            scope: this
+        });
+    },
+    
+    /**
+     * Method: moveGriddedTiles
+     */
+    moveGriddedTiles: function() {
+        var shifted = true;
+        var buffer = this.buffer || 1;
+        var tlLayer = this.grid[0][0].position;
+        var offsetX = parseInt(this.map.layerContainerDiv.style.left);
+        var offsetY = parseInt(this.map.layerContainerDiv.style.top);
+        var tlViewPort = tlLayer.add(offsetX, offsetY);
+        if (tlViewPort.x > -this.tileSize.w * (buffer - 1)) {
+            this.shiftColumn(true);
+        } else if (tlViewPort.x < -this.tileSize.w * buffer) {
+            this.shiftColumn(false);
+        } else if (tlViewPort.y > -this.tileSize.h * (buffer - 1)) {
+            this.shiftRow(true);
+        } else if (tlViewPort.y < -this.tileSize.h * buffer) {
+            this.shiftRow(false);
+        } else {
+            shifted = false;
+        }
+        if (shifted) {
+            // we may have other row or columns to shift, schedule it
+            // with a setTimeout, to give the user a chance to sneak
+            // in moveTo's
+            this.timerId = window.setTimeout(this._moveGriddedTiles, 0);
+        }
+    },
+
+    /**
+     * Method: shiftRow
+     * Shifty grid work
+     *
+     * Parameters:
+     * prepend - {Boolean} if true, prepend to beginning.
+     *                          if false, then append to end
+     */
+    shiftRow:function(prepend) {
+        var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1);
+        var grid = this.grid;
+        var modelRow = grid[modelRowIndex];
+
+        var resolution = this.map.getResolution();
+        var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h;
+        var deltaLat = resolution * -deltaY;
+
+        var row = (prepend) ? grid.pop() : grid.shift();
+
+        for (var i=0, len=modelRow.length; i<len; i++) {
+            var modelTile = modelRow[i];
+            var bounds = modelTile.bounds.clone();
+            var position = modelTile.position.clone();
+            bounds.bottom = bounds.bottom + deltaLat;
+            bounds.top = bounds.top + deltaLat;
+            position.y = position.y + deltaY;
+            row[i].moveTo(bounds, position);
+        }
+
+        if (prepend) {
+            grid.unshift(row);
+        } else {
+            grid.push(row);
+        }
+    },
+
+    /**
+     * Method: shiftColumn
+     * Shift grid work in the other dimension
+     *
+     * Parameters:
+     * prepend - {Boolean} if true, prepend to beginning.
+     *                          if false, then append to end
+     */
+    shiftColumn: function(prepend) {
+        var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w;
+        var resolution = this.map.getResolution();
+        var deltaLon = resolution * deltaX;
+
+        for (var i=0, len=this.grid.length; i<len; i++) {
+            var row = this.grid[i];
+            var modelTileIndex = (prepend) ? 0 : (row.length - 1);
+            var modelTile = row[modelTileIndex];
+            
+            var bounds = modelTile.bounds.clone();
+            var position = modelTile.position.clone();
+            bounds.left = bounds.left + deltaLon;
+            bounds.right = bounds.right + deltaLon;
+            position.x = position.x + deltaX;
+
+            var tile = prepend ? this.grid[i].pop() : this.grid[i].shift();
+            tile.moveTo(bounds, position);
+            if (prepend) {
+                row.unshift(tile);
+            } else {
+                row.push(tile);
+            }
+        }
+    },
+    
+    /**
+     * Method: removeExcessTiles
+     * When the size of the map or the buffer changes, we may need to
+     *     remove some excess rows and columns.
+     * 
+     * Parameters:
+     * rows - {Integer} Maximum number of rows we want our grid to have.
+     * columns - {Integer} Maximum number of columns we want our grid to have.
+     */
+    removeExcessTiles: function(rows, columns) {
+        
+        // remove extra rows
+        while (this.grid.length > rows) {
+            var row = this.grid.pop();
+            for (var i=0, l=row.length; i<l; i++) {
+                var tile = row[i];
+                this.removeTileMonitoringHooks(tile);
+                tile.destroy();
+            }
+        }
+        
+        // remove extra columns
+        while (this.grid[0].length > columns) {
+            for (var i=0, l=this.grid.length; i<l; i++) {
+                var row = this.grid[i];
+                var tile = row.pop();
+                this.removeTileMonitoringHooks(tile);
+                tile.destroy();
+            }
+        }
+    },
+
+    /**
+     * Method: onMapResize
+     * For singleTile layers, this will set a new tile size according to the
+     * dimensions of the map pane.
+     */
+    onMapResize: function() {
+        if (this.singleTile) {
+            this.clearGrid();
+            this.setTileSize();
+        }
+    },
+    
+    /**
+     * APIMethod: getTileBounds
+     * Returns The tile bounds for a layer given a pixel location.
+     *
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>} The location in the viewport.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} Bounds of the tile at the given pixel location.
+     */
+    getTileBounds: function(viewPortPx) {
+        var maxExtent = this.maxExtent;
+        var resolution = this.getResolution();
+        var tileMapWidth = resolution * this.tileSize.w;
+        var tileMapHeight = resolution * this.tileSize.h;
+        var mapPoint = this.getLonLatFromViewPortPx(viewPortPx);
+        var tileLeft = maxExtent.left + (tileMapWidth *
+                                         Math.floor((mapPoint.lon -
+                                                     maxExtent.left) /
+                                                    tileMapWidth));
+        var tileBottom = maxExtent.bottom + (tileMapHeight *
+                                             Math.floor((mapPoint.lat -
+                                                         maxExtent.bottom) /
+                                                        tileMapHeight));
+        return new OpenLayers.Bounds(tileLeft, tileBottom,
+                                     tileLeft + tileMapWidth,
+                                     tileBottom + tileMapHeight);
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.Grid"
+});
+/* ======================================================================
+    OpenLayers/Tile.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/*
+ * Class: OpenLayers.Tile 
+ * This is a class designed to designate a single tile, however
+ *     it is explicitly designed to do relatively little. Tiles store 
+ *     information about themselves -- such as the URL that they are related
+ *     to, and their size - but do not add themselves to the layer div 
+ *     automatically, for example. Create a new tile with the 
+ *     <OpenLayers.Tile> constructor, or a subclass. 
+ * 
+ * TBD 3.0 - remove reference to url in above paragraph
+ * 
+ */
+OpenLayers.Tile = OpenLayers.Class({
+    
+    /** 
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types
+     */
+    EVENT_TYPES: [ "loadstart", "loadend", "reload", "unload"],
+    
+    /**
+     * APIProperty: events
+     * {<OpenLayers.Events>} An events object that handles all 
+     *                       events on the tile.
+     */
+    events: null,
+
+    /**
+     * Property: id 
+     * {String} null
+     */
+    id: null,
+    
+    /** 
+     * Property: layer 
+     * {<OpenLayers.Layer>} layer the tile is attached to 
+     */
+    layer: null,
+    
+    /**
+     * Property: url
+     * {String} url of the request.
+     *
+     * TBD 3.0 
+     * Deprecated. The base tile class does not need an url. This should be 
+     * handled in subclasses. Does not belong here.
+     */
+    url: null,
+
+    /** 
+     * APIProperty: bounds 
+     * {<OpenLayers.Bounds>} null
+     */
+    bounds: null,
+    
+    /** 
+     * Property: size 
+     * {<OpenLayers.Size>} null
+     */
+    size: null,
+    
+    /** 
+     * Property: position 
+     * {<OpenLayers.Pixel>} Top Left pixel of the tile
+     */    
+    position: null,
+
+    /**
+     * Property: isLoading
+     * {Boolean} Is the tile loading?
+     */
+    isLoading: false,
+        
+    /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor.
+     *             there is no need for the base tile class to have a url.
+     * 
+     * Constructor: OpenLayers.Tile
+     * Constructor for a new <OpenLayers.Tile> instance.
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} layer that the tile will go in.
+     * position - {<OpenLayers.Pixel>}
+     * bounds - {<OpenLayers.Bounds>}
+     * url - {<String>}
+     * size - {<OpenLayers.Size>}
+     * options - {Object}
+     */   
+    initialize: function(layer, position, bounds, url, size, options) {
+        this.layer = layer;
+        this.position = position.clone();
+        this.bounds = bounds.clone();
+        this.url = url;
+        if (size) {
+            this.size = size.clone();
+        }
+
+        //give the tile a unique id based on its BBOX.
+        this.id = OpenLayers.Util.createUniqueID("Tile_");
+        
+        this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
+
+        OpenLayers.Util.extend(this, options);
+    },
+
+    /**
+     * Method: unload
+     * Call immediately before destroying if you are listening to tile
+     * events, so that counters are properly handled if tile is still
+     * loading at destroy-time. Will only fire an event if the tile is
+     * still loading.
+     */
+    unload: function() {
+       if (this.isLoading) { 
+           this.isLoading = false; 
+           this.events.triggerEvent("unload"); 
+       }
+    },
+    
+    /** 
+     * APIMethod: destroy
+     * Nullify references to prevent circular references and memory leaks.
+     */
+    destroy:function() {
+        this.layer  = null;
+        this.bounds = null;
+        this.size = null;
+        this.position = null;
+        
+        this.events.destroy();
+        this.events = null;
+    },
+    
+    /**
+     * Method: clone
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Tile>} The tile to be cloned
+     *
+     * Returns:
+     * {<OpenLayers.Tile>} An exact clone of this <OpenLayers.Tile>
+     */
+    clone: function (obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Tile(this.layer, 
+                                      this.position, 
+                                      this.bounds, 
+                                      this.url, 
+                                      this.size);
+        } 
+        
+        // catch any randomly tagged-on properties
+        OpenLayers.Util.applyDefaults(obj, this);
+        
+        return obj;
+    },
+
+    /**
+     * Method: draw
+     * Clear whatever is currently in the tile, then return whether or not 
+     *     it should actually be re-drawn.
+     * 
+     * Returns:
+     * {Boolean} Whether or not the tile should actually be drawn. Note that 
+     *     this is not really the best way of doing things, but such is 
+     *     the way the code has been developed. Subclasses call this and
+     *     depend on the return to know if they should draw or not.
+     */
+    draw: function() {
+        var maxExtent = this.layer.maxExtent;
+        var withinMaxExtent = (maxExtent &&
+                               this.bounds.intersectsBounds(maxExtent, false));
+ 
+        // The only case where we *wouldn't* want to draw the tile is if the 
+        // tile is outside its layer's maxExtent.
+        this.shouldDraw = (withinMaxExtent || this.layer.displayOutsideMaxExtent);
+                
+        //clear tile's contents and mark as not drawn
+        this.clear();
+        
+        return this.shouldDraw;
+    },
+    
+    /** 
+     * Method: moveTo
+     * Reposition the tile.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     * redraw - {Boolean} Call draw method on tile after moving.
+     *     Default is true
+     */
+    moveTo: function (bounds, position, redraw) {
+        if (redraw == null) {
+            redraw = true;
+        }
+
+        this.bounds = bounds.clone();
+        this.position = position.clone();
+        if (redraw) {
+            this.draw();
+        }
+    },
+
+    /** 
+     * Method: clear
+     * Clear the tile of any bounds/position-related data so that it can 
+     *     be reused in a new location. To be implemented by subclasses.
+     */
+    clear: function() {
+        // to be implemented by subclasses
+    },
+    
+    /**   
+     * Method: getBoundsFromBaseLayer
+     * Take the pixel locations of the corner of the tile, and pass them to 
+     *     the base layer and ask for the location of those pixels, so that 
+     *     displaying tiles over Google works fine.
+     *
+     * Parameters:
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * bounds - {<OpenLayers.Bounds>} 
+     */
+    getBoundsFromBaseLayer: function(position) {
+        var msg = OpenLayers.i18n('reprojectDeprecated',
+                                              {'layerName':this.layer.name});
+        OpenLayers.Console.warn(msg);
+        var topLeft = this.layer.map.getLonLatFromLayerPx(position); 
+        var bottomRightPx = position.clone();
+        bottomRightPx.x += this.size.w;
+        bottomRightPx.y += this.size.h;
+        var bottomRight = this.layer.map.getLonLatFromLayerPx(bottomRightPx); 
+        // Handle the case where the base layer wraps around the date line.
+        // Google does this, and it breaks WMS servers to request bounds in 
+        // that fashion.  
+        if (topLeft.lon > bottomRight.lon) {
+            if (topLeft.lon < 0) {
+                topLeft.lon = -180 - (topLeft.lon+180);
+            } else {
+                bottomRight.lon = 180+bottomRight.lon+180;
+            }        
+        }
+        var bounds = new OpenLayers.Bounds(topLeft.lon, 
+                                       bottomRight.lat, 
+                                       bottomRight.lon, 
+                                       topLeft.lat);  
+        return bounds;
+    },        
+        
+    /** 
+     * Method: showTile
+     * Show the tile only if it should be drawn.
+     */
+    showTile: function() { 
+        if (this.shouldDraw) {
+            this.show();
+        }
+    },
+    
+    /** 
+     * Method: show
+     * Show the tile.  To be implemented by subclasses.
+     */
+    show: function() { },
+    
+    /** 
+     * Method: hide
+     * Hide the tile.  To be implemented by subclasses.
+     */
+    hide: function() { },
+    
+    CLASS_NAME: "OpenLayers.Tile"
+});
+/* ======================================================================
+    OpenLayers/Tile/Image.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Tile.js
+ */
+
+/**
+ * Class: OpenLayers.Tile.Image
+ * Instances of OpenLayers.Tile.Image are used to manage the image tiles
+ * used by various layers.  Create a new image tile with the
+ * <OpenLayers.Tile.Image> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Tile>
+ */
+OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
+
+    /** 
+     * Property: url
+     * {String} The URL of the image being requested. No default. Filled in by
+     * layer.getURL() function. 
+     */
+    url: null,
+    
+    /** 
+     * Property: imgDiv
+     * {DOMElement} The div element which wraps the image.
+     */
+    imgDiv: null,
+
+    /**
+     * Property: frame
+     * {DOMElement} The image element is appended to the frame.  Any gutter on
+     * the image will be hidden behind the frame. 
+     */ 
+    frame: null, 
+    
+    /**
+     * Property: layerAlphaHack
+     * {Boolean} True if the png alpha hack needs to be applied on the layer's div.
+     */
+    layerAlphaHack: null,
+    
+    /**
+     * Property: isBackBuffer
+     * {Boolean} Is this tile a back buffer tile?
+     */
+    isBackBuffer: false,
+    
+    /**
+     * Property: isFirstDraw
+     * {Boolean} Is this the first time the tile is being drawn?
+     *     This is used to force resetBackBuffer to synchronize
+     *     the backBufferTile with the foreground tile the first time
+     *     the foreground tile loads so that if the user zooms
+     *     before the layer has fully loaded, the backBufferTile for
+     *     tiles that have been loaded can be used.
+     */
+    isFirstDraw: true,
+        
+    /**
+     * Property: backBufferTile
+     * {<OpenLayers.Tile>} A clone of the tile used to create transition
+     *     effects when the tile is moved or changes resolution.
+     */
+    backBufferTile: null,
+    
+    /**
+     * APIProperty: maxGetUrlLength
+     * {Number} If set, requests that would result in GET urls with more
+     * characters than the number provided will be made using form-encoded
+     * HTTP POST. It is good practice to avoid urls that are longer than 2048
+     * characters.
+     *
+     * Caution:
+     * Older versions of Gecko based browsers (e.g. Firefox < 3.5) and
+     * Opera < 10.0 do not fully support this option.
+     *
+     * Note:
+     * Do not use this option for layers that have a transitionEffect
+     * configured - IFrame tiles from POST requests can not be resized.
+     */
+    maxGetUrlLength: null,
+    
+    /** TBD 3.0 - reorder the parameters to the init function to remove 
+     *             URL. the getUrl() function on the layer gets called on 
+     *             each draw(), so no need to specify it here.
+     * 
+     * Constructor: OpenLayers.Tile.Image
+     * Constructor for a new <OpenLayers.Tile.Image> instance.
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} layer that the tile will go in.
+     * position - {<OpenLayers.Pixel>}
+     * bounds - {<OpenLayers.Bounds>}
+     * url - {<String>} Deprecated. Remove me in 3.0.
+     * size - {<OpenLayers.Size>}
+     * options - {Object}
+     */   
+    initialize: function(layer, position, bounds, url, size, options) {
+        OpenLayers.Tile.prototype.initialize.apply(this, arguments);
+
+        if (this.maxGetUrlLength != null) {
+            OpenLayers.Util.extend(this, OpenLayers.Tile.Image.IFrame);
+        }
+
+        this.url = url; //deprecated remove me
+        
+        this.frame = document.createElement('div'); 
+        this.frame.style.overflow = 'hidden'; 
+        this.frame.style.position = 'absolute'; 
+
+        this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack();        
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        if (this.imgDiv != null)  {
+            this.removeImgDiv();
+        }
+        this.imgDiv = null;
+        if ((this.frame != null) && (this.frame.parentNode == this.layer.div)) { 
+            this.layer.div.removeChild(this.frame); 
+        }
+        this.frame = null; 
+        
+        /* clean up the backBufferTile if it exists */
+        if (this.backBufferTile) {
+            this.backBufferTile.destroy();
+            this.backBufferTile = null;
+        }
+        
+        this.layer.events.unregister("loadend", this, this.resetBackBuffer);
+        
+        OpenLayers.Tile.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: clone
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Tile.Image>} The tile to be cloned
+     *
+     * Returns:
+     * {<OpenLayers.Tile.Image>} An exact clone of this <OpenLayers.Tile.Image>
+     */
+    clone: function (obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Tile.Image(this.layer, 
+                                            this.position, 
+                                            this.bounds, 
+                                            this.url, 
+                                            this.size);        
+        } 
+        
+        //pick up properties from superclass
+        obj = OpenLayers.Tile.prototype.clone.apply(this, [obj]);
+        
+        //dont want to directly copy the image div
+        obj.imgDiv = null;
+            
+        
+        return obj;
+    },
+    
+    /**
+     * Method: draw
+     * Check that a tile should be drawn, and draw it.
+     * 
+     * Returns:
+     * {Boolean} Always returns true.
+     */
+    draw: function() {
+        if (this.layer != this.layer.map.baseLayer && this.layer.reproject) {
+            this.bounds = this.getBoundsFromBaseLayer(this.position);
+        }
+        var drawTile = OpenLayers.Tile.prototype.draw.apply(this, arguments);
+        
+        if ((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) || 
+            this.layer.singleTile) {
+            if (drawTile) {
+                //we use a clone of this tile to create a double buffer for visual
+                //continuity.  The backBufferTile is used to create transition
+                //effects while the tile in the grid is repositioned and redrawn
+                if (!this.backBufferTile) {
+                    this.backBufferTile = this.clone();
+                    this.backBufferTile.hide();
+                    // this is important.  It allows the backBuffer to place itself
+                    // appropriately in the DOM.  The Image subclass needs to put
+                    // the backBufferTile behind the main tile so the tiles can
+                    // load over top and display as soon as they are loaded.
+                    this.backBufferTile.isBackBuffer = true;
+                    
+                    // potentially end any transition effects when the tile loads
+                    this.events.register('loadend', this, this.resetBackBuffer);
+                    
+                    // clear transition back buffer tile only after all tiles in
+                    // this layer have loaded to avoid visual glitches
+                    this.layer.events.register("loadend", this, this.resetBackBuffer);
+                }
+                // run any transition effects
+                this.startTransition();
+            } else {
+                // if we aren't going to draw the tile, then the backBuffer should
+                // be hidden too!
+                if (this.backBufferTile) {
+                    this.backBufferTile.clear();
+                }
+            }
+        } else {
+            if (drawTile && this.isFirstDraw) {
+                this.events.register('loadend', this, this.showTile);
+                this.isFirstDraw = false;
+            }   
+        }    
+        
+        if (!drawTile) {
+            return false;
+        }
+        
+        if (this.isLoading) {
+            //if we're already loading, send 'reload' instead of 'loadstart'.
+            this.events.triggerEvent("reload"); 
+        } else {
+            this.isLoading = true;
+            this.events.triggerEvent("loadstart");
+        }
+        
+        return this.renderTile();
+    },
+    
+    /** 
+     * Method: resetBackBuffer
+     * Triggered by two different events, layer loadend, and tile loadend.
+     *     In any of these cases, we check to see if we can hide the 
+     *     backBufferTile yet and update its parameters to match the 
+     *     foreground tile.
+     *
+     * Basic logic:
+     *  - If the backBufferTile hasn't been drawn yet, reset it
+     *  - If layer is still loading, show foreground tile but don't hide
+     *    the backBufferTile yet
+     *  - If layer is done loading, reset backBuffer tile and show 
+     *    foreground tile
+     */
+    resetBackBuffer: function() {
+        this.showTile();
+        if (this.backBufferTile && 
+            (this.isFirstDraw || !this.layer.numLoadingTiles)) {
+            this.isFirstDraw = false;
+            // check to see if the backBufferTile is within the max extents
+            // before rendering it 
+            var maxExtent = this.layer.maxExtent;
+            var withinMaxExtent = (maxExtent &&
+                                   this.bounds.intersectsBounds(maxExtent, false));
+            if (withinMaxExtent) {
+                this.backBufferTile.position = this.position;
+                this.backBufferTile.bounds = this.bounds;
+                this.backBufferTile.size = this.size;
+                this.backBufferTile.imageSize = this.layer.getImageSize(this.bounds) || this.size;
+                this.backBufferTile.imageOffset = this.layer.imageOffset;
+                this.backBufferTile.resolution = this.layer.getResolution();
+                this.backBufferTile.renderTile();
+            }
+
+            this.backBufferTile.hide();
+        }
+    },
+    
+    /**
+     * Method: renderTile
+     * Internal function to actually initialize the image tile,
+     *     position it correctly, and set its url.
+     */
+    renderTile: function() {
+        if (this.layer.async) {
+            this.initImgDiv();
+            // Asyncronous image requests call the asynchronous getURL method
+            // on the layer to fetch an image that covers 'this.bounds', in the scope of
+            // 'this', setting the 'url' property of the layer itself, and running
+            // the callback 'positionFrame' when the image request returns.
+            this.layer.getURLasync(this.bounds, this, "url", this.positionImage);
+        } else {
+            // syncronous image requests get the url and position the frame immediately,
+            // and don't wait for an image request to come back.
+          
+            this.url = this.layer.getURL(this.bounds);
+
+            this.initImgDiv();
+          
+            // position the frame immediately
+            this.positionImage(); 
+        }
+        return true;
+    },
+
+    /**
+     * Method: positionImage
+     * Using the properties currenty set on the layer, position the tile correctly.
+     * This method is used both by the async and non-async versions of the Tile.Image
+     * code.
+     */
+     positionImage: function() {
+        // if the this layer doesn't exist at the point the image is
+        // returned, do not attempt to use it for size computation
+        if (this.layer === null) {
+            return;
+        }
+        // position the frame 
+        OpenLayers.Util.modifyDOMElement(this.frame, 
+                                          null, this.position, this.size);   
+
+        var imageSize = this.layer.getImageSize(this.bounds); 
+        if (this.layerAlphaHack) {
+            OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,
+                    null, null, imageSize, this.url);
+        } else {
+            OpenLayers.Util.modifyDOMElement(this.imgDiv,
+                    null, null, imageSize) ;
+            this.imgDiv.src = this.url;
+        }
+    },
+
+    /** 
+     * Method: clear
+     *  Clear the tile of any bounds/position-related data so that it can 
+     *   be reused in a new location.
+     */
+    clear: function() {
+        if(this.imgDiv) {
+            this.hide();
+            if (OpenLayers.Tile.Image.useBlankTile) { 
+                this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
+            }    
+        }
+    },
+
+    /**
+     * Method: initImgDiv
+     * Creates the imgDiv property on the tile.
+     */
+    initImgDiv: function() {
+        if (this.imgDiv == null) {
+            var offset = this.layer.imageOffset; 
+            var size = this.layer.getImageSize(this.bounds); 
+
+            if (this.layerAlphaHack) {
+                this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
+                                                               offset,
+                                                               size,
+                                                               null,
+                                                               "relative",
+                                                               null,
+                                                               null,
+                                                               null,
+                                                               true);
+            } else {
+                this.imgDiv = OpenLayers.Util.createImage(null,
+                                                          offset,
+                                                          size,
+                                                          null,
+                                                          "relative",
+                                                          null,
+                                                          null,
+                                                          true);
+            }
+
+            // needed for changing to a different server for onload error
+            if (OpenLayers.Util.isArray(this.layer.url)) {
+                this.imgDiv.urls = this.layer.url.slice();
+            }
+      
+            this.imgDiv.className = 'olTileImage';
+
+            /* checkImgURL used to be used to called as a work around, but it
+               ended up hiding problems instead of solving them and broke things
+               like relative URLs. See discussion on the dev list:
+               http://openlayers.org/pipermail/dev/2007-January/000205.html
+
+            OpenLayers.Event.observe( this.imgDiv, "load",
+                OpenLayers.Function.bind(this.checkImgURL, this) );
+            */
+            this.frame.style.zIndex = this.isBackBuffer ? 0 : 1;
+            this.frame.appendChild(this.imgDiv); 
+            this.layer.div.appendChild(this.frame); 
+
+            if(this.layer.opacity != null) {
+
+                OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, null,
+                                                 null, null, null, 
+                                                 this.layer.opacity);
+            }
+
+            // we need this reference to check back the viewRequestID
+            this.imgDiv.map = this.layer.map;
+
+            //bind a listener to the onload of the image div so that we 
+            // can register when a tile has finished loading.
+            var onload = function() {
+
+                //normally isLoading should always be true here but there are some 
+                // right funky conditions where loading and then reloading a tile
+                // with the same url *really*fast*. this check prevents sending 
+                // a 'loadend' if the msg has already been sent
+                //
+                if (this.isLoading) { 
+                    this.isLoading = false; 
+                    this.events.triggerEvent("loadend"); 
+                }
+            };
+
+            if (this.layerAlphaHack) { 
+                OpenLayers.Event.observe(this.imgDiv.childNodes[0], 'load', 
+                                         OpenLayers.Function.bind(onload, this));    
+            } else { 
+                OpenLayers.Event.observe(this.imgDiv, 'load', 
+                                     OpenLayers.Function.bind(onload, this)); 
+            } 
+
+
+            // Bind a listener to the onerror of the image div so that we
+            // can registere when a tile has finished loading with errors.
+            var onerror = function() {
+
+                // If we have gone through all image reload attempts, it is time
+                // to realize that we are done with this image. Since
+                // OpenLayers.Util.onImageLoadError already has taken care about
+                // the error, we can continue as if the image was loaded
+                // successfully.
+                if (this.imgDiv._attempts > OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
+                    onload.call(this);
+                }
+            };
+            OpenLayers.Event.observe(this.imgDiv, "error",
+                                     OpenLayers.Function.bind(onerror, this));
+        }
+        
+        this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
+    },
+
+    /**
+     * Method: removeImgDiv
+     * Removes the imgDiv from the DOM and stops listening to events on it.
+     */
+    removeImgDiv: function() {
+        // unregister the "load" and "error" handlers. Only the "error" handler if
+        // this.layerAlphaHack is true.
+        OpenLayers.Event.stopObservingElement(this.imgDiv);
+        
+        if (this.imgDiv.parentNode == this.frame) {
+            this.frame.removeChild(this.imgDiv);
+            this.imgDiv.map = null;
+        }
+        this.imgDiv.urls = null;
+
+        var child = this.imgDiv.firstChild;
+        //check for children (alphaHack img or IFrame)
+        if (child) {
+            OpenLayers.Event.stopObservingElement(child);
+            this.imgDiv.removeChild(child);
+            delete child;
+        } else {
+            // abort any currently loading image
+            this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
+        }
+    },
+
+    /**
+     * Method: checkImgURL
+     * Make sure that the image that just loaded is the one this tile is meant
+     * to display, since panning/zooming might have changed the tile's URL in
+     * the meantime. If the tile URL did change before the image loaded, set
+     * the imgDiv display to 'none', as either (a) it will be reset to visible
+     * when the new URL loads in the image, or (b) we don't want to display
+     * this tile after all because its new bounds are outside our maxExtent.
+     * 
+     * This function should no longer  be neccesary with the improvements to
+     * Grid.js in OpenLayers 2.3. The lack of a good isEquivilantURL function
+     * caused problems in 2.2, but it's possible that with the improved 
+     * isEquivilant URL function, this might be neccesary at some point.
+     * 
+     * See discussion in the thread at 
+     * http://openlayers.org/pipermail/dev/2007-January/000205.html
+     */
+    checkImgURL: function () {
+        // Sometimes our image will load after it has already been removed
+        // from the map, in which case this check is not needed.  
+        if (this.layer) {
+            var loaded = this.layerAlphaHack ? this.imgDiv.firstChild.src : this.imgDiv.src;
+            if (!OpenLayers.Util.isEquivalentUrl(loaded, this.url)) {
+                this.hide();
+            }
+        }
+    },
+    
+    /**
+     * Method: startTransition
+     * This method is invoked on tiles that are backBuffers for tiles in the
+     *     grid.  The grid tile is about to be cleared and a new tile source
+     *     loaded.  This is where the transition effect needs to be started
+     *     to provide visual continuity.
+     */
+    startTransition: function() {
+        // backBufferTile has to be valid and ready to use
+        if (!this.backBufferTile || !this.backBufferTile.imgDiv) {
+            return;
+        }
+
+        // calculate the ratio of change between the current resolution of the
+        // backBufferTile and the layer.  If several animations happen in a
+        // row, then the backBufferTile will scale itself appropriately for
+        // each request.
+        var ratio = 1;
+        if (this.backBufferTile.resolution) {
+            ratio = this.backBufferTile.resolution / this.layer.getResolution();
+        }
+        
+        // if the ratio is not the same as it was last time (i.e. we are
+        // zooming), then we need to adjust the backBuffer tile
+        if (ratio != 1) {
+            if (this.layer.transitionEffect == 'resize') {
+                // In this case, we can just immediately resize the 
+                // backBufferTile.
+                var upperLeft = new OpenLayers.LonLat(
+                    this.backBufferTile.bounds.left, 
+                    this.backBufferTile.bounds.top
+                );
+                var size = new OpenLayers.Size(
+                    this.backBufferTile.size.w * ratio,
+                    this.backBufferTile.size.h * ratio
+                );
+
+                var px = this.layer.map.getLayerPxFromLonLat(upperLeft);
+                OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame, 
+                                                 null, px, size);
+                var imageSize = this.backBufferTile.imageSize;
+                imageSize = new OpenLayers.Size(imageSize.w * ratio, 
+                                                imageSize.h * ratio);
+                var imageOffset = this.backBufferTile.imageOffset;
+                if(imageOffset) {
+                    imageOffset = new OpenLayers.Pixel(
+                        imageOffset.x * ratio, imageOffset.y * ratio
+                    );
+                }
+
+                OpenLayers.Util.modifyDOMElement(
+                    this.backBufferTile.imgDiv, null, imageOffset, imageSize
+                ) ;
+
+                this.backBufferTile.show();
+            }
+        } else {
+            // default effect is just to leave the existing tile
+            // until the new one loads if this is a singleTile and
+            // there was no change in resolution.  Otherwise we
+            // don't bother to show the backBufferTile at all
+            if (this.layer.singleTile) {
+                this.backBufferTile.show();
+            } else {
+                this.backBufferTile.hide();
+            }
+        }
+
+    },
+    
+    /** 
+     * Method: show
+     * Show the tile by showing its frame.
+     */
+    show: function() {
+        this.frame.style.display = '';
+        // Force a reflow on gecko based browsers to actually show the element
+        // before continuing execution.
+        if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, 
+                this.layer.transitionEffect) != -1) {
+            if (OpenLayers.IS_GECKO === true) { 
+                this.frame.scrollLeft = this.frame.scrollLeft; 
+            } 
+        }
+    },
+    
+    /** 
+     * Method: hide
+     * Hide the tile by hiding its frame.
+     */
+    hide: function() {
+        this.frame.style.display = 'none';
+    },
+    
+    CLASS_NAME: "OpenLayers.Tile.Image"
+  }
+);
+
+OpenLayers.Tile.Image.useBlankTile = ( 
+    OpenLayers.BROWSER_NAME == "safari" || 
+    OpenLayers.BROWSER_NAME == "opera"); 
+/* ======================================================================
+    OpenLayers/Format/ArcXML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ * @requires OpenLayers/Geometry/LinearRing.js
+ */
+
+/**
+ * Class: OpenLayers.Format.ArcXML
+ * Read/Wite ArcXML. Create a new instance with the <OpenLayers.Format.ArcXML>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.ArcXML = OpenLayers.Class(OpenLayers.Format.XML, {
+
+    /**
+     * Property: fontStyleKeys
+     * {Array} List of keys used in font styling.
+     */
+    fontStyleKeys: [
+        'antialiasing', 'blockout', 'font', 'fontcolor','fontsize', 'fontstyle',
+        'glowing', 'interval', 'outline', 'printmode', 'shadow', 'transparency'
+    ],
+
+    /**
+     * Property: request
+     * A get_image request destined for an ArcIMS server.
+     */
+    request: null,
+    
+    /**
+     * Property: response
+     * A parsed response from an ArcIMS server.
+     */
+    response: null,
+
+    /**
+     * Constructor: OpenLayers.Format.ArcXML
+     * Create a new parser/writer for ArcXML.  Create an instance of this class
+     *    to begin authoring a request to an ArcIMS service.  This is used
+     *    primarily by the ArcIMS layer, but could be used to do other wild
+     *    stuff, like geocoding.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        this.request = new OpenLayers.Format.ArcXML.Request();
+        this.response = new OpenLayers.Format.ArcXML.Response();
+
+        if (options) {
+            if (options.requesttype == "feature") {
+                this.request.get_image = null;
+            
+                var qry = this.request.get_feature.query;
+                this.addCoordSys(qry.featurecoordsys, options.featureCoordSys);
+                this.addCoordSys(qry.filtercoordsys, options.filterCoordSys);
+            
+                if (options.polygon) {
+                    qry.isspatial = true;
+                    qry.spatialfilter.polygon = options.polygon;
+                } else if (options.envelope) {
+                    qry.isspatial = true;
+                    qry.spatialfilter.envelope = {minx:0, miny:0, maxx:0, maxy:0};
+                    this.parseEnvelope(qry.spatialfilter.envelope, options.envelope);
+                }
+            } else if (options.requesttype == "image") {
+                this.request.get_feature = null;
+            
+                var props = this.request.get_image.properties;
+                this.parseEnvelope(props.envelope, options.envelope);
+            
+                this.addLayers(props.layerlist, options.layers);
+                this.addImageSize(props.imagesize, options.tileSize);
+                this.addCoordSys(props.featurecoordsys, options.featureCoordSys);
+                this.addCoordSys(props.filtercoordsys, options.filterCoordSys);
+            } else {
+                // if an arcxml object is being created with no request type, it is
+                // probably going to consume a response, so do not throw an error if
+                // the requesttype is not defined
+                this.request = null;
+            }
+        }
+        
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: parseEnvelope
+     * Parse an array of coordinates into an ArcXML envelope structure.
+     *
+     * Parameters:
+     * env - {Object} An envelope object that will contain the parsed coordinates.
+     * arr - {Array(double)} An array of coordinates in the order: [ minx, miny, maxx, maxy ]
+     */
+    parseEnvelope: function(env, arr) {
+        if (arr && arr.length == 4) {          
+            env.minx = arr[0];
+            env.miny = arr[1];
+            env.maxx = arr[2];
+            env.maxy = arr[3];
+        }
+    },
+    
+    /** 
+     * Method: addLayers
+     * Add a collection of layers to another collection of layers. Each layer in the list is tuple of
+     * { id, visible }.  These layer collections represent the 
+     * /ARCXML/REQUEST/get_image/PROPERTIES/LAYERLIST/LAYERDEF items in ArcXML
+     *
+     * TODO: Add support for dynamic layer rendering.
+     *
+     * Parameters:
+     * ll - {Array({id,visible})} A list of layer definitions.
+     * lyrs - {Array({id,visible})} A list of layer definitions.
+     */
+    addLayers: function(ll, lyrs) {
+        for(var lind = 0, len=lyrs.length; lind < len; lind++) {
+            ll.push(lyrs[lind]);
+        }
+    },
+    
+    /**
+     * Method: addImageSize
+     * Set the size of the requested image.
+     *
+     * Parameters:
+     * imsize - {Object} An ArcXML imagesize object.
+     * olsize - {OpenLayers.Size} The image size to set.
+     */
+    addImageSize: function(imsize, olsize) {
+        if (olsize !== null) {
+            imsize.width = olsize.w;
+            imsize.height = olsize.h;
+            imsize.printwidth = olsize.w;
+            imsize.printheight = olsize.h;
+        }
+    },
+
+    /**
+     * Method: addCoordSys
+     * Add the coordinate system information to an object. The object may be 
+     *
+     * Parameters:
+     * featOrFilt - {Object} A featurecoordsys or filtercoordsys ArcXML structure.
+     * fsys - {String} or {OpenLayers.Projection} or {filtercoordsys} or 
+     * {featurecoordsys} A projection representation. If it's a {String}, 
+     * the value is assumed to be the SRID.  If it's a {OpenLayers.Projection} 
+     * AND Proj4js is available, the projection number and name are extracted 
+     * from there.  If it's a filter or feature ArcXML structure, it is copied.
+     */
+    addCoordSys: function(featOrFilt, fsys) {
+        if (typeof fsys == "string") {
+            featOrFilt.id = parseInt(fsys);
+            featOrFilt.string = fsys;
+        }
+        // is this a proj4js instance?
+        else if (typeof fsys == "object" && fsys.proj !== null){
+            featOrFilt.id = fsys.proj.srsProjNumber;
+            featOrFilt.string = fsys.proj.srsCode;
+        } else {
+            featOrFilt = fsys;
+        }
+    },
+
+    /**
+     * APIMethod: iserror
+     * Check to see if the response from the server was an error.
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse. If nothing is supplied,
+     * the current response is examined.
+     *
+     * Returns:
+     * {Boolean} true if the response was an error.
+     */
+    iserror: function(data) {
+        var ret = null; 
+        
+        if (!data) {
+            ret = (this.response.error !== '');
+        } else {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+            var errorNodes = data.documentElement.getElementsByTagName("ERROR");
+            ret = (errorNodes !== null && errorNodes.length > 0);
+        }
+
+        return ret;
+    },
+
+    /**
+     * APIMethod: read
+     * Read data from a string, and return an response. 
+     * 
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {OpenLayers.Format.ArcXML.Response} An ArcXML response. Note that this response
+     *     data may change in the future. 
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        
+        var arcNode = null;
+        if (data && data.documentElement) {
+            if(data.documentElement.nodeName == "ARCXML") {
+                arcNode = data.documentElement;
+            } else {
+                arcNode = data.documentElement.getElementsByTagName("ARCXML")[0];
+            }
+        }
+          
+        // in Safari, arcNode will be there but will have a child named 
+        // parsererror
+        if (!arcNode || arcNode.firstChild.nodeName === 'parsererror') {
+            var error, source;
+            try {
+                error = data.firstChild.nodeValue;
+                source = data.firstChild.childNodes[1].firstChild.nodeValue;
+            } catch (err) {
+                // pass
+            }
+            throw {
+                message: "Error parsing the ArcXML request", 
+                error: error,
+                source: source
+            };
+        }
+        
+        var response = this.parseResponse(arcNode);
+        return response;
+    },
+    
+    /**
+     * APIMethod: write
+     * Generate an ArcXml document string for sending to an ArcIMS server. 
+     * 
+     * Returns:
+     * {String} A string representing the ArcXML document request.
+     */
+    write: function(request) {       
+        if (!request) {
+            request = this.request;
+        }    
+        var root = this.createElementNS("", "ARCXML");
+        root.setAttribute("version","1.1");
+
+        var reqElem = this.createElementNS("", "REQUEST");
+        
+        if (request.get_image != null) {
+            var getElem = this.createElementNS("", "GET_IMAGE");
+            reqElem.appendChild(getElem);
+
+            var propElem = this.createElementNS("", "PROPERTIES");
+            getElem.appendChild(propElem);
+
+            var props = request.get_image.properties;
+            if (props.featurecoordsys != null) {
+                var feat = this.createElementNS("", "FEATURECOORDSYS");
+                propElem.appendChild(feat);
+                
+                if (props.featurecoordsys.id === 0) {
+                    feat.setAttribute("string", props.featurecoordsys['string']);
+                }
+                else {
+                    feat.setAttribute("id", props.featurecoordsys.id);
+                }
+            }
+          
+            if (props.filtercoordsys != null) {
+                var filt = this.createElementNS("", "FILTERCOORDSYS");
+                propElem.appendChild(filt);
+
+                if (props.filtercoordsys.id === 0) {
+                    filt.setAttribute("string", props.filtercoordsys.string);
+                }
+                else {
+                    filt.setAttribute("id", props.filtercoordsys.id);
+                }
+            }
+          
+            if (props.envelope != null) {
+                var env = this.createElementNS("", "ENVELOPE");
+                propElem.appendChild(env);
+
+                env.setAttribute("minx", props.envelope.minx);
+                env.setAttribute("miny", props.envelope.miny);
+                env.setAttribute("maxx", props.envelope.maxx);
+                env.setAttribute("maxy", props.envelope.maxy);
+            }        
+          
+            var imagesz = this.createElementNS("", "IMAGESIZE");
+            propElem.appendChild(imagesz);
+          
+            imagesz.setAttribute("height", props.imagesize.height);
+            imagesz.setAttribute("width", props.imagesize.width);
+          
+            if (props.imagesize.height != props.imagesize.printheight ||
+                 props.imagesize.width != props.imagesize.printwidth) {
+                imagesz.setAttribute("printheight", props.imagesize.printheight);
+                imagesz.setArrtibute("printwidth", props.imagesize.printwidth);
+            }
+          
+            if (props.background != null) {
+                var backgrnd = this.createElementNS("", "BACKGROUND");
+                propElem.appendChild(backgrnd);
+            
+                backgrnd.setAttribute("color", 
+                    props.background.color.r + "," + 
+                    props.background.color.g + "," + 
+                    props.background.color.b);
+              
+                if (props.background.transcolor !== null) {
+                    backgrnd.setAttribute("transcolor", 
+                        props.background.transcolor.r + "," + 
+                        props.background.transcolor.g + "," + 
+                        props.background.transcolor.b);
+                }
+            }
+          
+            if (props.layerlist != null && props.layerlist.length > 0) {
+                var layerlst = this.createElementNS("", "LAYERLIST");
+                propElem.appendChild(layerlst);
+            
+                for (var ld = 0; ld < props.layerlist.length; ld++) {
+                    var ldef = this.createElementNS("", "LAYERDEF");
+                    layerlst.appendChild(ldef);
+              
+                    ldef.setAttribute("id", props.layerlist[ld].id);
+                    ldef.setAttribute("visible", props.layerlist[ld].visible);
+              
+                    if (typeof props.layerlist[ld].query == "object") {
+                        var query = props.layerlist[ld].query;
+
+                        if (query.where.length < 0) {
+                            continue;
+                        }
+                  
+                        var queryElem = null;
+                        if (typeof query.spatialfilter == "boolean" && query.spatialfilter) {
+                            // handle spatial filter madness
+                            queryElem = this.createElementNS("", "SPATIALQUERY");
+                        }
+                        else {
+                            queryElem = this.createElementNS("", "QUERY");
+                        }
+                
+                        queryElem.setAttribute("where", query.where);
+                
+                        if (typeof query.accuracy == "number" && query.accuracy > 0) {
+                            queryElem.setAttribute("accuracy", query.accuracy);
+                        }
+                        if (typeof query.featurelimit == "number" && query.featurelimit < 2000) {
+                            queryElem.setAttribute("featurelimit", query.featurelimit);
+                        }
+                        if (typeof query.subfields == "string" && query.subfields != "#ALL#") {
+                            queryElem.setAttribute("subfields", query.subfields);
+                        }
+                        if (typeof query.joinexpression == "string" && query.joinexpression.length > 0) {
+                            queryElem.setAttribute("joinexpression", query.joinexpression);
+                        }
+                        if (typeof query.jointables == "string" && query.jointables.length > 0) {
+                            queryElem.setAttribute("jointables", query.jointables);
+                        }
+
+                        ldef.appendChild(queryElem);
+                    }
+              
+                    if (typeof props.layerlist[ld].renderer == "object") {
+                        this.addRenderer(ldef, props.layerlist[ld].renderer);                  
+                    }
+                }
+            }
+        } else if (request.get_feature != null) {
+            var getElem = this.createElementNS("", "GET_FEATURES");
+            getElem.setAttribute("outputmode", "newxml");
+            getElem.setAttribute("checkesc", "true");
+          
+            if (request.get_feature.geometry) {
+                getElem.setAttribute("geometry", request.get_feature.geometry);
+            }
+            else {
+                getElem.setAttribute("geometry", "false");
+            }
+          
+            if (request.get_feature.compact) {
+                getElem.setAttribute("compact", request.get_feature.compact);
+            }
+          
+            if (request.get_feature.featurelimit == "number") {
+                getElem.setAttribute("featurelimit", request.get_feature.featurelimit);
+            }
+          
+            getElem.setAttribute("globalenvelope", "true");
+            reqElem.appendChild(getElem);
+          
+            if (request.get_feature.layer != null && request.get_feature.layer.length > 0) {
+                var lyrElem = this.createElementNS("", "LAYER");
+                lyrElem.setAttribute("id", request.get_feature.layer);
+                getElem.appendChild(lyrElem);
+            }
+          
+            var fquery = request.get_feature.query;
+            if (fquery != null) {
+                var qElem = null;
+                if (fquery.isspatial) {
+                    qElem = this.createElementNS("", "SPATIALQUERY");
+                } else {
+                    qElem = this.createElementNS("", "QUERY");
+                }
+                getElem.appendChild(qElem);
+                
+                if (typeof fquery.accuracy == "number") {
+                    qElem.setAttribute("accuracy", fquery.accuracy);
+                }
+                //qElem.setAttribute("featurelimit", "5");
+            
+                if (fquery.featurecoordsys != null) {
+                    var fcsElem1 = this.createElementNS("", "FEATURECOORDSYS");
+              
+                    if (fquery.featurecoordsys.id == 0) {
+                        fcsElem1.setAttribute("string", fquery.featurecoordsys.string);
+                    } else {
+                        fcsElem1.setAttribute("id", fquery.featurecoordsys.id);
+                    }
+                    qElem.appendChild(fcsElem1);
+                }
+            
+                if (fquery.filtercoordsys != null) {
+                    var fcsElem2 = this.createElementNS("", "FILTERCOORDSYS");
+              
+                    if (fquery.filtercoordsys.id === 0) {
+                        fcsElem2.setAttribute("string", fquery.filtercoordsys.string);
+                    } else {
+                        fcsElem2.setAttribute("id", fquery.filtercoordsys.id);
+                    }
+                    qElem.appendChild(fcsElem2);
+                }
+            
+                if (fquery.buffer > 0) {   
+                    var bufElem = this.createElementNS("", "BUFFER");
+                    bufElem.setAttribute("distance", fquery.buffer);
+                    qElem.appendChild(bufElem);
+                }
+            
+                if (fquery.isspatial) {
+                    var spfElem = this.createElementNS("", "SPATIALFILTER");
+                    spfElem.setAttribute("relation", fquery.spatialfilter.relation);
+                    qElem.appendChild(spfElem);
+              
+                    if (fquery.spatialfilter.envelope) {
+                        var envElem = this.createElementNS("", "ENVELOPE"); 
+                        envElem.setAttribute("minx", fquery.spatialfilter.envelope.minx);
+                        envElem.setAttribute("miny", fquery.spatialfilter.envelope.miny);
+                        envElem.setAttribute("maxx", fquery.spatialfilter.envelope.maxx);
+                        envElem.setAttribute("maxy", fquery.spatialfilter.envelope.maxy);
+                        spfElem.appendChild(envElem);
+                    } else if(typeof fquery.spatialfilter.polygon == "object") {
+                        spfElem.appendChild(this.writePolygonGeometry(fquery.spatialfilter.polygon));                
+                    }
+                }
+            
+                if (fquery.where != null && fquery.where.length > 0) {
+                    qElem.setAttribute("where", fquery.where);
+                }
+            }
+        }
+
+        root.appendChild(reqElem);
+
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    },
+    
+    
+    addGroupRenderer: function(ldef, toprenderer) {
+        var topRelem = this.createElementNS("", "GROUPRENDERER");
+        ldef.appendChild(topRelem);
+      
+        for (var rind = 0; rind < toprenderer.length; rind++) {
+            var renderer = toprenderer[rind];
+            this.addRenderer(topRelem, renderer);
+        }
+    },
+    
+    
+    addRenderer: function(topRelem, renderer) {
+        if (OpenLayers.Util.isArray(renderer)) {
+            this.addGroupRenderer(topRelem, renderer);
+        } else {
+            var renderElem = this.createElementNS("", renderer.type.toUpperCase() + "RENDERER");
+            topRelem.appendChild(renderElem);
+          
+            if (renderElem.tagName == "VALUEMAPRENDERER") {
+                this.addValueMapRenderer(renderElem, renderer);
+            } else if (renderElem.tagName == "VALUEMAPLABELRENDERER") {
+                this.addValueMapLabelRenderer(renderElem, renderer);
+            } else if (renderElem.tagName == "SIMPLELABELRENDERER") {
+                this.addSimpleLabelRenderer(renderElem, renderer);
+            } else if (renderElem.tagName == "SCALEDEPENDENTRENDERER") {
+                this.addScaleDependentRenderer(renderElem, renderer);
+            }
+        }             
+    },
+    
+    
+    addScaleDependentRenderer: function(renderElem, renderer) {
+        if (typeof renderer.lower == "string" || typeof renderer.lower == "number") {
+            renderElem.setAttribute("lower", renderer.lower);
+        }
+        if (typeof renderer.upper == "string" || typeof renderer.upper == "number") {
+            renderElem.setAttribute("upper", renderer.upper);
+        }
+        
+        this.addRenderer(renderElem, renderer.renderer);
+    },
+    
+    
+    addValueMapLabelRenderer: function(renderElem, renderer) {
+        renderElem.setAttribute("lookupfield", renderer.lookupfield);
+        renderElem.setAttribute("labelfield", renderer.labelfield);
+      
+        if (typeof renderer.exacts == "object") {
+            for (var ext=0, extlen=renderer.exacts.length; ext<extlen; ext++) {
+                var exact = renderer.exacts[ext];
+          
+                var eelem = this.createElementNS("", "EXACT");
+          
+                if (typeof exact.value == "string") {
+                    eelem.setAttribute("value", exact.value);
+                }
+                if (typeof exact.label == "string") {
+                    eelem.setAttribute("label", exact.label);
+                }
+                if (typeof exact.method == "string") {
+                    eelem.setAttribute("method", exact.method);
+                }
+
+                renderElem.appendChild(eelem);
+            
+                if (typeof exact.symbol == "object") {
+                    var selem = null;
+                
+                    if (exact.symbol.type == "text") {
+                        selem = this.createElementNS("", "TEXTSYMBOL");
+                    }
+                
+                    if (selem != null) {
+                        var keys = this.fontStyleKeys;
+                        for (var i = 0, len = keys.length; i < len; i++) {
+                            var key = keys[i];
+                            if (exact.symbol[key]) {
+                                selem.setAttribute(key, exact.symbol[key]);
+                            }
+                        }    
+                        eelem.appendChild(selem);
+                    }
+                }
+            } // for each exact
+        }      
+    },
+    
+    addValueMapRenderer: function(renderElem, renderer) {
+        renderElem.setAttribute("lookupfield", renderer.lookupfield);
+        
+        if (typeof renderer.ranges == "object") {
+            for(var rng=0, rnglen=renderer.ranges.length; rng<rnglen; rng++) {
+                var range = renderer.ranges[rng];
+                
+                var relem = this.createElementNS("", "RANGE");
+                relem.setAttribute("lower", range.lower);
+                relem.setAttribute("upper", range.upper);
+                
+                renderElem.appendChild(relem);
+                
+                if (typeof range.symbol == "object") {
+                    var selem = null;
+              
+                    if (range.symbol.type == "simplepolygon") {
+                        selem = this.createElementNS("", "SIMPLEPOLYGONSYMBOL");
+                    }
+              
+                    if (selem != null) {
+                        if (typeof range.symbol.boundarycolor == "string") {
+                            selem.setAttribute("boundarycolor", range.symbol.boundarycolor);
+                        }
+                        if (typeof range.symbol.fillcolor == "string") {
+                            selem.setAttribute("fillcolor", range.symbol.fillcolor);
+                        }
+                        if (typeof range.symbol.filltransparency == "number") {
+                            selem.setAttribute("filltransparency", range.symbol.filltransparency);
+                        }
+                        relem.appendChild(selem);
+                    }   
+                }
+            } // for each range
+        } else if (typeof renderer.exacts == "object") {
+            for (var ext=0, extlen=renderer.exacts.length; ext<extlen; ext++) {
+                var exact = renderer.exacts[ext];
+          
+                var eelem = this.createElementNS("", "EXACT");
+                if (typeof exact.value == "string") {
+                    eelem.setAttribute("value", exact.value);
+                }
+                if (typeof exact.label == "string") {
+                    eelem.setAttribute("label", exact.label);
+                }
+                if (typeof exact.method == "string") {
+                    eelem.setAttribute("method", exact.method);
+                }
+            
+                renderElem.appendChild(eelem);
+            
+                if (typeof exact.symbol == "object") {
+                    var selem = null;
+            
+                    if (exact.symbol.type == "simplemarker") {
+                        selem = this.createElementNS("", "SIMPLEMARKERSYMBOL");
+                    }
+            
+                    if (selem != null) {
+                        if (typeof exact.symbol.antialiasing == "string") {
+                            selem.setAttribute("antialiasing", exact.symbol.antialiasing);
+                        }
+                        if (typeof exact.symbol.color == "string") {
+                            selem.setAttribute("color", exact.symbol.color);
+                        }
+                        if (typeof exact.symbol.outline == "string") {
+                            selem.setAttribute("outline", exact.symbol.outline);
+                        }
+                        if (typeof exact.symbol.overlap == "string") {
+                            selem.setAttribute("overlap", exact.symbol.overlap);
+                        }
+                        if (typeof exact.symbol.shadow == "string") {
+                            selem.setAttribute("shadow", exact.symbol.shadow);
+                        }
+                        if (typeof exact.symbol.transparency == "number") {
+                            selem.setAttribute("transparency", exact.symbol.transparency);
+                        }
+                        //if (typeof exact.symbol.type == "string")
+                        //    selem.setAttribute("type", exact.symbol.type);
+                        if (typeof exact.symbol.usecentroid == "string") {
+                            selem.setAttribute("usecentroid", exact.symbol.usecentroid);
+                        }
+                        if (typeof exact.symbol.width == "number") {
+                            selem.setAttribute("width", exact.symbol.width);
+                        }
+                
+                        eelem.appendChild(selem);
+                    }
+                }
+            } // for each exact
+        }
+    },
+    
+    
+    addSimpleLabelRenderer: function(renderElem, renderer) {
+        renderElem.setAttribute("field", renderer.field);
+        var keys = ['featureweight', 'howmanylabels', 'labelbufferratio', 
+                    'labelpriorities', 'labelweight', 'linelabelposition',
+                    'rotationalangles'];
+        for (var i=0, len=keys.length; i<len; i++) {
+            var key = keys[i];
+            if (renderer[key]) {
+                renderElem.setAttribute(key, renderer[key]);
+            }
+        }     
+           
+        if (renderer.symbol.type == "text") {
+            var symbol = renderer.symbol;
+            var selem = this.createElementNS("", "TEXTSYMBOL");
+            renderElem.appendChild(selem);
+          
+            var keys = this.fontStyleKeys;
+            for (var i=0, len=keys.length; i<len; i++) {
+                var key = keys[i];
+                if (symbol[key]) {
+                    selem.setAttribute(key, renderer[key]);
+                }
+            }    
+        }    
+    },
+    
+    writePolygonGeometry: function(polygon) {
+        if (!(polygon instanceof OpenLayers.Geometry.Polygon)) {
+            throw { 
+                message:'Cannot write polygon geometry to ArcXML with an ' +
+                    polygon.CLASS_NAME + ' object.',
+                geometry: polygon
+            };
+        }
+        
+        var polyElem = this.createElementNS("", "POLYGON");
+      
+        for (var ln=0, lnlen=polygon.components.length; ln<lnlen; ln++) {
+            var ring = polygon.components[ln];
+            var ringElem = this.createElementNS("", "RING");
+        
+            for (var rn=0, rnlen=ring.components.length; rn<rnlen; rn++) {
+                var point = ring.components[rn];
+                var pointElem = this.createElementNS("", "POINT");
+            
+                pointElem.setAttribute("x", point.x);
+                pointElem.setAttribute("y", point.y);
+            
+                ringElem.appendChild(pointElem);
+            }
+        
+            polyElem.appendChild(ringElem);
+        }
+      
+        return polyElem;
+    },
+    
+    /**
+     * Method: parseResponse
+     * Take an ArcXML response, and parse in into this object's internal properties.
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} The ArcXML response, as either a string or the
+     * top level DOMElement of the response.
+     */
+    parseResponse: function(data) {
+        if(typeof data == "string") { 
+            var newData = new OpenLayers.Format.XML();
+            data = newData.read(data);
+        }
+        var response = new OpenLayers.Format.ArcXML.Response();
+        
+        var errorNode = data.getElementsByTagName("ERROR");
+        
+        if (errorNode != null && errorNode.length > 0) {
+            response.error = this.getChildValue(errorNode, "Unknown error.");
+        } else {
+            var responseNode = data.getElementsByTagName("RESPONSE");
+          
+            if (responseNode == null || responseNode.length == 0) {
+                response.error = "No RESPONSE tag found in ArcXML response.";
+                return response;
+            }
+          
+            var rtype = responseNode[0].firstChild.nodeName;
+            if (rtype == "#text") {
+                rtype = responseNode[0].firstChild.nextSibling.nodeName;
+            }
+          
+            if (rtype == "IMAGE") {
+                var envelopeNode = data.getElementsByTagName("ENVELOPE");
+                var outputNode = data.getElementsByTagName("OUTPUT");
+                
+                if (envelopeNode == null || envelopeNode.length == 0) {
+                    response.error = "No ENVELOPE tag found in ArcXML response.";
+                } else if (outputNode == null || outputNode.length == 0) {
+                    response.error = "No OUTPUT tag found in ArcXML response.";
+                } else {
+                    var envAttr = this.parseAttributes(envelopeNode[0]);            
+                    var outputAttr = this.parseAttributes(outputNode[0]);
+                  
+                    if (typeof outputAttr.type == "string") {
+                        response.image = { 
+                            envelope: envAttr, 
+                            output: { 
+                                type: outputAttr.type, 
+                                data: this.getChildValue(outputNode[0])
+                            }
+                        };
+                    } else {
+                        response.image = { envelope: envAttr, output: outputAttr };
+                    }
+                }
+            } else if (rtype == "FEATURES") {
+                var features = responseNode[0].getElementsByTagName("FEATURES");
+            
+                // get the feature count
+                var featureCount = features[0].getElementsByTagName("FEATURECOUNT");
+                response.features.featurecount = featureCount[0].getAttribute("count");
+            
+                if (response.features.featurecount > 0) {
+                    // get the feature envelope
+                    var envelope = features[0].getElementsByTagName("ENVELOPE");
+                    response.features.envelope = this.parseAttributes(envelope[0], typeof(0));
+
+                    // get the field values per feature
+                    var featureList = features[0].getElementsByTagName("FEATURE");
+                    for (var fn = 0; fn < featureList.length; fn++) {
+                        var feature = new OpenLayers.Feature.Vector();
+                        var fields = featureList[fn].getElementsByTagName("FIELD");
+
+                        for (var fdn = 0; fdn < fields.length; fdn++) {
+                            var fieldName = fields[fdn].getAttribute("name");
+                            var fieldValue = fields[fdn].getAttribute("value");
+                            feature.attributes[ fieldName ] = fieldValue;
+                        }
+
+                        var geom = featureList[fn].getElementsByTagName("POLYGON");
+
+                        if (geom.length > 0) {
+                            // if there is a polygon, create an openlayers polygon, and assign
+                            // it to the .geometry property of the feature
+                            var ring = geom[0].getElementsByTagName("RING");
+
+                            var polys = [];
+                            for (var rn = 0; rn < ring.length; rn++) {
+                                var linearRings = [];
+                                linearRings.push(this.parsePointGeometry(ring[rn]));
+
+                                var holes = ring[rn].getElementsByTagName("HOLE");
+                                for (var hn = 0; hn < holes.length; hn++) {
+                                    linearRings.push(this.parsePointGeometry(holes[hn]));
+                                }
+                                holes = null;
+                                polys.push(new OpenLayers.Geometry.Polygon(linearRings));
+                                linearRings = null;
+                            }
+                            ring = null;
+                          
+                            if (polys.length == 1) {
+                                feature.geometry = polys[0];
+                            } else
+                            {
+                                feature.geometry = new OpenLayers.Geometry.MultiPolygon(polys);
+                            }
+                        }
+
+                        response.features.feature.push(feature);
+                    }
+                }
+            } else {
+                response.error = "Unidentified response type.";
+            }
+        }
+        return response;
+    },
+    
+    
+    /**
+     * Method: parseAttributes
+     *
+     * Parameters:
+     * node - {<DOMElement>} An element to parse attributes from.
+     *
+     * Returns:
+     * {Object} An attributes object, with properties set to attribute values.
+     */
+    parseAttributes: function(node,type) {
+        var attributes = {};
+        for(var attr = 0; attr < node.attributes.length; attr++) {
+            if (type == "number") {
+                attributes[node.attributes[attr].nodeName] = parseFloat(node.attributes[attr].nodeValue);
+            } else {
+                attributes[node.attributes[attr].nodeName] = node.attributes[attr].nodeValue;
+            }
+        }
+        return attributes;
+    },
+    
+    
+    /**
+     * Method: parsePointGeometry
+     *
+     * Parameters:
+     * node - {<DOMElement>} An element to parse <COORDS> or <POINT> arcxml data from.
+     *
+     * Returns:
+     * {OpenLayers.Geometry.LinearRing} A linear ring represented by the node's points.
+     */
+    parsePointGeometry: function(node) {
+        var ringPoints = [];
+        var coords = node.getElementsByTagName("COORDS");
+
+        if (coords.length > 0) {
+            // if coords is present, it's the only coords item
+            var coordArr = this.getChildValue(coords[0]);
+            coordArr = coordArr.split(/;/);
+            for (var cn = 0; cn < coordArr.length; cn++) {
+                var coordItems = coordArr[cn].split(/ /);
+                ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(coordItems[0]), parseFloat(coordItems[1])));
+            }
+            coords = null;
+        } else {
+            var point = node.getElementsByTagName("POINT");
+            if (point.length > 0) {
+                for (var pn = 0; pn < point.length; pn++) {
+                    ringPoints.push(
+                        new OpenLayers.Geometry.Point(
+                            parseFloat(point[pn].getAttribute("x")),
+                            parseFloat(point[pn].getAttribute("y"))
+                        )
+                    );
+                }
+            }
+            point = null;
+        }
+
+        return new OpenLayers.Geometry.LinearRing(ringPoints);      
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.ArcXML" 
+});
+
+OpenLayers.Format.ArcXML.Request = OpenLayers.Class({
+    initialize: function(params) {
+        var defaults = {
+            get_image: {
+                properties: {
+                    background: null,
+                    /*{ 
+                        color: { r:255, g:255, b:255 },
+                        transcolor: null
+                    },*/
+                    draw: true,
+                    envelope: {
+                        minx: 0, 
+                        miny: 0, 
+                        maxx: 0, 
+                        maxy: 0
+                    },
+                    featurecoordsys: { 
+                        id:0, 
+                        string:"",
+                        datumtransformid:0,
+                        datumtransformstring:""
+                    },
+                    filtercoordsys:{
+                        id:0,
+                        string:"",
+                        datumtransformid:0,
+                        datumtransformstring:""
+                    },
+                    imagesize:{
+                        height:0,
+                        width:0,
+                        dpi:96,
+                        printheight:0,
+                        printwidth:0,
+                        scalesymbols:false
+                    },
+                    layerlist:[],
+                    /* no support for legends */
+                    output:{
+                        baseurl:"",
+                        legendbaseurl:"",
+                        legendname:"",
+                        legendpath:"",
+                        legendurl:"",
+                        name:"",
+                        path:"",
+                        type:"jpg",
+                        url:""
+                    }
+                }
+            },
+
+            get_feature: {
+                layer: "",
+                query: {
+                    isspatial: false,
+                    featurecoordsys: {
+                        id:0,
+                        string:"",
+                        datumtransformid:0,
+                        datumtransformstring:""
+                    },
+                    filtercoordsys: {
+                        id:0,
+                        string:"",
+                        datumtransformid:0,
+                        datumtransformstring:""
+                    },
+                    buffer:0,
+                    where:"",
+                    spatialfilter: {
+                        relation: "envelope_intersection",
+                        envelope: null
+                    }
+                }
+            },
+      
+            environment: {
+                separators: {
+                    cs:" ",
+                    ts:";"
+                }
+            },
+      
+            layer: [],
+            workspaces: []
+        };
+      
+        return OpenLayers.Util.extend(this, defaults);      
+    },
+  
+    CLASS_NAME: "OpenLayers.Format.ArcXML.Request"
+});
+
+OpenLayers.Format.ArcXML.Response = OpenLayers.Class({  
+    initialize: function(params) {
+        var defaults = {
+            image: {
+                envelope:null,
+                output:''
+            },
+      
+            features: {
+                featurecount: 0,
+                envelope: null,
+                feature: []
+            },
+      
+            error:''
+        };
+  
+        return OpenLayers.Util.extend(this, defaults);
+    },
+  
+    CLASS_NAME: "OpenLayers.Format.ArcXML.Response"
+});
+/* ======================================================================
+    OpenLayers/Layer/ArcIMS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ * @requires OpenLayers/Format/ArcXML.js
+ * @requires OpenLayers/Request.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.ArcIMS
+ * Instances of OpenLayers.Layer.ArcIMS are used to display data from ESRI ArcIMS
+ *     Mapping Services. Create a new ArcIMS layer with the <OpenLayers.Layer.ArcIMS>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.ArcIMS = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Constant: DEFAULT_PARAMS
+     * {Object} Default query string parameters.
+     */
+    DEFAULT_PARAMS: { 
+        ClientVersion: "9.2",
+        ServiceName: ''
+    },
+    
+    /**
+     * APIProperty: tileSize
+     * {<OpenLayers.Size>} Size for tiles.  Default is 512x512.
+     */
+    tileSize: null,
+    
+    /**
+     * APIProperty: featureCoordSys
+     * {String} Code for feature coordinate system.  Default is "4326".
+     */
+    featureCoordSys: "4326",
+    
+    /**
+     * APIProperty: filterCoordSys
+     * {String} Code for filter coordinate system.  Default is "4326".
+     */
+    filterCoordSys: "4326",
+    
+    /**
+     * APIProperty: layers
+     * {Array} An array of objects with layer properties.
+     */
+    layers: null,
+    
+    /**
+     * APIProperty: async
+     * {Boolean} Request images asynchronously.  Default is true.
+     */
+    async: true,
+    
+    /**
+     * APIProperty: name
+     * {String} Layer name.  Default is "ArcIMS".
+     */
+    name: "ArcIMS",
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} The layer is a base layer.  Default is true.
+     */
+    isBaseLayer: true,
+
+    /**
+     * Constant: DEFAULT_OPTIONS
+     * {Object} Default layers properties.
+     */
+    DEFAULT_OPTIONS: {
+        tileSize: new OpenLayers.Size(512, 512),
+        featureCoordSys: "4326",
+        filterCoordSys: "4326",
+        layers: null,
+        isBaseLayer: true,
+        async: true,
+        name: "ArcIMS"
+    }, 
+ 
+    /**
+     * Constructor: OpenLayers.Layer.ArcIMS
+     * Create a new ArcIMS layer object.
+     *
+     * Example:
+     * (code)
+     * var arcims = new OpenLayers.Layer.ArcIMS(
+     *     "Global Sample",
+     *     "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap", 
+     *     {
+     *         service: "OpenLayers_Sample", 
+     *         layers: [
+     *             // layers to manipulate
+     *             {id: "1", visible: true}
+     *         ]
+     *     }
+     * );
+     * (end)
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the ArcIMS server
+     * options - {Object} Optional object with properties to be set on the
+     *     layer.
+     */
+    initialize: function(name, url, options) {
+        
+        this.tileSize = new OpenLayers.Size(512, 512);
+
+        // parameters
+        this.params = OpenLayers.Util.applyDefaults(
+            {ServiceName: options.serviceName},
+            this.DEFAULT_PARAMS
+        );
+        this.options = OpenLayers.Util.applyDefaults(
+            options, this.DEFAULT_OPTIONS
+        );
+          
+        OpenLayers.Layer.Grid.prototype.initialize.apply(
+            this, [name, url, this.params, options]
+        );
+
+        //layer is transparent        
+        if (this.transparent) {
+            
+            // unless explicitly set in options, make layer an overlay
+            if (!this.isBaseLayer) {
+                this.isBaseLayer = false;
+            } 
+            
+            // jpegs can never be transparent, so intelligently switch the 
+            //  format, depending on the browser's capabilities
+            if (this.format == "image/jpeg") {
+                this.format = OpenLayers.Util.alphaHack() ? "image/gif" : "image/png";
+            }
+        }
+
+        // create an empty layer list if no layers specified in the options
+        if (this.options.layers === null) {
+            this.options.layers = [];
+        }
+    },    
+
+    
+    /**
+     * Method: destroy
+     * Destroy this layer
+     */
+    destroy: function() {
+        // for now, nothing special to do here. 
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);  
+    },   
+    
+    
+    /**
+     * Method: getURL
+     * Return an image url this layer.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
+     *     request.
+     *
+     * Returns:
+     * {String} A string with the map image's url.
+     */
+    getURL: function(bounds) {
+        var url = "";
+        bounds = this.adjustBounds(bounds);
+        
+        // create an arcxml request to generate the image
+        var axlReq = new OpenLayers.Format.ArcXML( 
+            OpenLayers.Util.extend(this.options, {
+                requesttype: "image",
+                envelope: bounds.toArray(),
+                tileSize: this.tileSize
+            })
+        );
+        
+        // create a synchronous ajax request to get an arcims image
+        var req = new OpenLayers.Request.POST({
+            url: this.getFullRequestString(),
+            data: axlReq.write(),
+            async: false
+        });
+        
+        // if the response exists
+        if (req != null) {
+            var doc = req.responseXML;
+
+            if (!doc || !doc.documentElement) {            
+                doc = req.responseText;
+            }
+
+            // create a new arcxml format to read the response
+            var axlResp = new OpenLayers.Format.ArcXML();
+            var arcxml = axlResp.read(doc);
+            url = this.getUrlOrImage(arcxml.image.output);
+        }
+        
+        return url;
+    },
+    
+    
+    /**
+     * Method: getURLasync
+     * Get an image url this layer asynchronously, and execute a callback
+     *     when the image url is generated.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
+     *     request.
+     * scope - {Object} The scope of the callback method.
+     * prop - {String} The name of the property in the scoped object to 
+     *     recieve the image url.
+     * callback - {Function} Function to call when image url is retrieved.
+     */
+    getURLasync: function(bounds, scope, prop, callback) {
+        bounds = this.adjustBounds(bounds);
+        
+        // create an arcxml request to generate the image
+        var axlReq = new OpenLayers.Format.ArcXML(  
+            OpenLayers.Util.extend(this.options, { 
+                requesttype: "image",
+                envelope: bounds.toArray(),
+                tileSize: this.tileSize
+            })
+        );
+        
+        // create an asynchronous ajax request to get an arcims image
+        OpenLayers.Request.POST({
+            url: this.getFullRequestString(),
+            async: true,
+            data: axlReq.write(),
+            callback: function(req) {
+                // process the response from ArcIMS, and call the callback function
+                // to set the image URL
+                var doc = req.responseXML;
+                if (!doc || !doc.documentElement) {            
+                    doc = req.responseText;
+                }
+
+                // create a new arcxml format to read the response
+                var axlResp = new OpenLayers.Format.ArcXML();
+                var arcxml = axlResp.read(doc);
+                
+                scope[prop] = this.getUrlOrImage(arcxml.image.output);
+
+                // call the callback function to recieve the updated property on the
+                // scoped object
+                callback.apply(scope);
+            },
+            scope: this
+        });
+    },
+    
+    /**
+     * Method: getUrlOrImage
+     * Extract a url or image from the ArcXML image output.
+     *
+     * Parameters:
+     * output - {Object} The image.output property of the object returned from
+     *     the ArcXML format read method.
+     *
+     * Returns:
+     * {String} A URL for an image (potentially with the data protocol).
+     */
+    getUrlOrImage: function(output) {
+        var ret = "";
+        if(output.url) {
+            // If the image response output url is a string, then the image
+            // data is not inline.
+            ret = output.url;
+        } else if(output.data) {
+            // The image data is inline and base64 encoded, create a data
+            // url for the image.  This will only work for small images,
+            // due to browser url length limits.
+            ret = "data:image/" + output.type + 
+                  ";base64," + output.data;
+        }
+        return ret;
+    },
+    
+    /**
+     * Method: setLayerQuery
+     * Set the query definition on this layer. Query definitions are used to
+     *     render parts of the spatial data in an image, and can be used to
+     *     filter features or layers in the ArcIMS service.
+     *
+     * Parameters:
+     * id - {String} The ArcIMS layer ID.
+     * queryDef - {Object} The query definition to apply to this layer.
+     */
+    setLayerQuery: function(id, querydef) {
+        // find the matching layer, if it exists
+        for (var lyr = 0; lyr < this.options.layers.length; lyr++) {
+            if (id == this.options.layers[lyr].id) {
+                // replace this layer definition
+                this.options.layers[lyr].query = querydef;
+                return;
+            }
+        }
+      
+        // no layer found, create a new definition
+        this.options.layers.push({id: id, visible: true, query: querydef});
+    },
+    
+    /**
+     * Method: getFeatureInfo
+     * Get feature information from ArcIMS.  Using the applied geometry, apply
+     *     the options to the query (buffer, area/envelope intersection), and
+     *     query the ArcIMS service.
+     *
+     * A note about accuracy:
+     * ArcIMS interprets the accuracy attribute in feature requests to be
+     *     something like the 'modulus' operator on feature coordinates,
+     *     applied to the database geometry of the feature.  It doesn't round,
+     *     so your feature coordinates may be up to (1 x accuracy) offset from
+     *     the actual feature coordinates.  If the accuracy of the layer is not
+     *     specified, the accuracy will be computed to be approximately 1
+     *     feature coordinate per screen  pixel.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.LonLat>} or {<OpenLayers.Geometry.Polygon>} The
+     *     geometry to use when making the query. This should be a closed
+     *     polygon for behavior approximating a free selection.
+     * layer - {Object} The ArcIMS layer definition. This is an anonymous object
+     *     that looks like:
+     * (code)
+     * {
+     *     id: "ArcXML layer ID",  // the ArcXML layer ID
+     *     query: {
+     *         where: "STATE = 'PA'",  // the where clause of the query
+     *         accuracy: 100           // the accuracy of the returned feature
+     *     }
+     * }
+     * (end)
+     * options - {Object} Object with non-default properties to set on the layer.
+     *     Supported properties are buffer, callback, scope, and any other
+     *     properties applicable to the ArcXML format.  Set the 'callback' and
+     *     'scope' for an object and function to recieve the parsed features
+     *     from ArcIMS.
+     */
+    getFeatureInfo: function(geometry, layer, options) {
+        // set the buffer to 1 unit (dd/m/ft?) by default
+        var buffer = options.buffer || 1;
+        // empty callback by default
+        var callback = options.callback || function() {};
+        // default scope is window (global)
+        var scope = options.scope || window;
+
+        // apply these option to the request options
+        var requestOptions = {};
+        OpenLayers.Util.extend(requestOptions, this.options);
+
+        // this is a feature request
+        requestOptions.requesttype = "feature";
+
+        if (geometry instanceof OpenLayers.LonLat) {
+            // create an envelope if the geometry is really a lon/lat
+            requestOptions.polygon = null;
+            requestOptions.envelope = [ 
+                geometry.lon - buffer, 
+                geometry.lat - buffer,
+                geometry.lon + buffer,
+                geometry.lat + buffer
+            ];
+        } else if (geometry instanceof OpenLayers.Geometry.Polygon) {
+            // use the polygon assigned, and empty the envelope
+            requestOptions.envelope = null;
+            requestOptions.polygon = geometry;
+        }
+      
+        // create an arcxml request to get feature requests
+        var arcxml = new OpenLayers.Format.ArcXML(requestOptions);
+
+        // apply any get feature options to the arcxml request
+        OpenLayers.Util.extend(arcxml.request.get_feature, options);
+
+        arcxml.request.get_feature.layer = layer.id;
+        if (typeof layer.query.accuracy == "number") {
+            // set the accuracy if it was specified
+            arcxml.request.get_feature.query.accuracy = layer.query.accuracy;
+        } else {
+            // guess that the accuracy is 1 per screen pixel
+            var mapCenter = this.map.getCenter();
+            var viewPx = this.map.getViewPortPxFromLonLat(mapCenter);
+            viewPx.x++;
+            var mapOffCenter = this.map.getLonLatFromPixel(viewPx);
+            arcxml.request.get_feature.query.accuracy = mapOffCenter.lon - mapCenter.lon;
+        }
+        
+        // set the get_feature query to be the same as the layer passed in
+        arcxml.request.get_feature.query.where = layer.query.where;
+        
+        // use area_intersection
+        arcxml.request.get_feature.query.spatialfilter.relation = "area_intersection";
+      
+        // create a new asynchronous request to get the feature info
+        OpenLayers.Request.POST({
+            url: this.getFullRequestString({'CustomService': 'Query'}),
+            data: arcxml.write(),
+            callback: function(request) {
+                // parse the arcxml response
+                var response = arcxml.parseResponse(request.responseText);
+                
+                if (!arcxml.iserror()) {
+                    // if the arcxml is not an error, call the callback with the features parsed
+                    callback.call(scope, response.features);
+                } else {
+                    // if the arcxml is an error, return null features selected
+                    callback.call(scope, null);
+                }
+            }
+        });
+    },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.ArcIMS>} An exact clone of this layer
+     */
+    clone: function (obj) {
+
+        if (obj == null) {
+            obj = new OpenLayers.Layer.ArcIMS(this.name,
+                                           this.url,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.ArcIMS"
+});
+/* ======================================================================
+    OpenLayers/Format/WMSGetFeatureInfo.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSGetFeatureInfo
+ * Class to read GetFeatureInfo responses from Web Mapping Services
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, {
+
+    /**
+     * APIProperty: layerIdentifier
+     * {String} All xml nodes containing this search criteria will populate an
+     *     internal array of layer nodes.
+     */ 
+    layerIdentifier: '_layer',
+
+    /**
+     * APIProperty: featureIdentifier
+     * {String} All xml nodes containing this search criteria will populate an 
+     *     internal array of feature nodes for each layer node found.
+     */
+    featureIdentifier: '_feature',
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Property: gmlFormat
+     * {<OpenLayers.Format.GML>} internal GML format for parsing geometries
+     *     in msGMLOutput
+     */
+    gmlFormat: null,
+
+    /**
+     * Constructor: OpenLayers.Format.WMSGetFeatureInfo
+     * Create a new parser for WMS GetFeatureInfo responses
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read WMS GetFeatureInfo data from a string, and return an array of features
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+     */
+    read: function(data) {
+        var result;
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        if(root) {
+            var scope = this;
+            var read = this["read_" + root.nodeName];
+            if(read) {
+                result = read.call(this, root);
+            } else {
+                // fall-back to GML since this is a common output format for WMS
+                // GetFeatureInfo responses
+                result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data);
+            }
+        } else {
+            result = data;
+        }
+        return result;
+    },
+    
+    
+    /**
+     * Method: read_msGMLOutput
+     * Parse msGMLOutput nodes.
+     *
+     * Parameters:
+     * data - {DOMElement}
+     *
+     * Returns:
+     * {Array}
+     */
+    read_msGMLOutput: function(data) {
+        var response = [];
+        var layerNodes = this.getSiblingNodesByTagCriteria(data,
+            this.layerIdentifier);
+        if (layerNodes) {
+            for (var i=0, len=layerNodes.length; i<len; ++i) {
+                var node = layerNodes[i];
+                var layerName = node.nodeName;
+                if (node.prefix) {
+                    layerName = layerName.split(':')[1];
+                }
+                var layerName = layerName.replace(this.layerIdentifier, '');
+                var featureNodes = this.getSiblingNodesByTagCriteria(node, 
+                    this.featureIdentifier);
+                if (featureNodes) {
+                    for (var j = 0; j < featureNodes.length; j++) {
+                        var featureNode = featureNodes[j];
+                        var geomInfo = this.parseGeometry(featureNode);
+                        var attributes = this.parseAttributes(featureNode);
+                        var feature = new OpenLayers.Feature.Vector(geomInfo.geometry, 
+                            attributes, null);
+                        feature.bounds = geomInfo.bounds;
+                        feature.type = layerName;
+                        response.push(feature);
+                    }
+                }
+            }
+        }
+        return response;
+    },
+    
+    /**
+     * Method: read_FeatureInfoResponse
+     * Parse FeatureInfoResponse nodes.
+     *
+     * Parameters:
+     * data - {DOMElement}
+     *
+     * Returns:
+     * {Array}
+     */
+    read_FeatureInfoResponse: function(data) {
+        var response = [];
+        var featureNodes = this.getElementsByTagNameNS(data, '*',
+            'FIELDS');
+
+        for(var i=0, len=featureNodes.length;i<len;i++) {
+            var featureNode = featureNodes[i];
+            var geom = null;
+
+            // attributes can be actual attributes on the FIELDS tag, 
+            // or FIELD children
+            var attributes = {};
+            var j;
+            var jlen = featureNode.attributes.length;
+            if (jlen > 0) {
+                for(j=0; j<jlen; j++) {
+                    var attribute = featureNode.attributes[j];
+                    attributes[attribute.nodeName] = attribute.nodeValue;
+                }
+            } else {
+                var nodes = featureNode.childNodes;
+                for (j=0, jlen=nodes.length; j<jlen; ++j) {
+                    var node = nodes[j];
+                    if (node.nodeType != 3) {
+                        attributes[node.getAttribute("name")] = 
+                            node.getAttribute("value");
+                    }
+                }
+            }
+
+            response.push(
+                new OpenLayers.Feature.Vector(geom, attributes, null)
+            );
+        }
+        return response;
+    },
+
+    /**
+     * Method: getSiblingNodesByTagCriteria
+     * Recursively searches passed xml node and all it's descendant levels for 
+     *     nodes whose tagName contains the passed search string. This returns an 
+     *     array of all sibling nodes which match the criteria from the highest 
+     *     hierarchial level from which a match is found.
+     * 
+     * Parameters:
+     * node - {DOMElement} An xml node
+     * criteria - {String} Search string which will match some part of a tagName 
+     *                                       
+     * Returns:
+     * Array({DOMElement)) An array of sibling xml nodes
+     */                
+    getSiblingNodesByTagCriteria: function(node, criteria){
+        var nodes = [];
+        var children, tagName, n, matchNodes, child;
+        if (node && node.hasChildNodes()) {
+            children = node.childNodes;
+            n = children.length;
+
+            for(var k=0; k<n; k++){
+                child = children[k];
+                while (child && child.nodeType != 1) {
+                    child = child.nextSibling;
+                    k++;
+                }
+                tagName = (child ? child.nodeName : '');
+                if (tagName.length > 0 && tagName.indexOf(criteria) > -1) {
+                    nodes.push(child);
+                } else {
+                    matchNodes = this.getSiblingNodesByTagCriteria(
+                        child, criteria);
+
+                    if(matchNodes.length > 0){
+                        (nodes.length == 0) ? 
+                            nodes = matchNodes : nodes.push(matchNodes);
+                    }
+                }
+            }
+
+        }
+        return nodes;
+    },
+
+    /**
+     * Method: parseAttributes
+     *
+     * Parameters:
+     * node - {<DOMElement>}
+     *
+     * Returns:
+     * {Object} An attributes object.
+     * 
+     * Notes:
+     * Assumes that attributes are direct child xml nodes of the passed node
+     * and contain only a single text node. 
+     */    
+    parseAttributes: function(node){
+        var attributes = {};
+        if (node.nodeType == 1) {
+            var children = node.childNodes;
+            var n = children.length;
+            for (var i = 0; i < n; ++i) {
+                var child = children[i];
+                if (child.nodeType == 1) {
+                    var grandchildren = child.childNodes;
+                    var name = (child.prefix) ?
+                        child.nodeName.split(":")[1] : child.nodeName;
+                    if (grandchildren.length == 0) {
+                        attributes[name] = null
+                    } else if (grandchildren.length == 1) {
+                        var grandchild = grandchildren[0];
+                        if (grandchild.nodeType == 3 ||
+                            grandchild.nodeType == 4) {
+                            var value = grandchild.nodeValue.replace(
+                                this.regExes.trimSpace, "");
+                            attributes[name] = value;
+                        }
+                    }
+                }
+            }
+        }
+        return attributes;
+    },
+
+    /**
+     * Method: parseGeometry
+     * Parse the geometry and the feature bounds out of the node using 
+     *     Format.GML
+     *
+     * Parameters:
+     * node - {<DOMElement>}
+     *
+     * Returns:
+     * {Object} An object containing the geometry and the feature bounds
+    */
+    parseGeometry: function(node) {
+        // we need to use the old Format.GML parser since we do not know the 
+        // geometry name
+        if (!this.gmlFormat) {
+            this.gmlFormat = new OpenLayers.Format.GML();
+        }
+        var feature = this.gmlFormat.parseFeature(node);
+        var geometry, bounds = null;
+        if (feature) {
+            geometry = feature.geometry && feature.geometry.clone();
+            bounds = feature.bounds && feature.bounds.clone();
+            feature.destroy();
+        }
+        return {geometry: geometry, bounds: bounds};
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo"
+    
+});
+/* ======================================================================
+    OpenLayers/Format/OWSCommon/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_1_0
+ * Parser for OWS Common version 1.1.0.
+ */
+OpenLayers.Format.OWSCommon.v1_1_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": OpenLayers.Util.applyDefaults({
+            "ExceptionReport": function(node, obj) {
+                obj.exceptionReport = {
+                    version: node.getAttribute('version'),
+                    language: node.getAttribute('xml:lang'),
+                    exceptions: []
+                };
+                this.readChildNodes(node, obj.exceptionReport);
+            },
+            "AllowedValues": function(node, parameter) {
+                parameter.allowedValues = {};
+                this.readChildNodes(node, parameter.allowedValues);
+            },
+            "AnyValue": function(node, parameter) {
+                parameter.anyValue = true;
+            },
+            "DataType": function(node, parameter) {
+                parameter.dataType = this.getChildValue(node);
+            },
+            "Range": function(node, allowedValues) {
+                allowedValues.range = {};
+                this.readChildNodes(node, allowedValues.range);
+            },
+            "MinimumValue": function(node, range) {
+                range.minValue = this.getChildValue(node);
+            },
+            "MaximumValue": function(node, range) {
+                range.maxValue = this.getChildValue(node);
+            },
+            "Identifier": function(node, obj) {
+            	obj.identifier = this.getChildValue(node);
+            },
+            "SupportedCRS": function(node, obj) {
+                obj.supportedCRS = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ows": OpenLayers.Util.applyDefaults({
+            "Range": function(range) {
+                var node = this.createElementNSPlus("ows:Range", {
+                    attributes: {
+                        'ows:rangeClosure': range.closure
+                    }
+                });
+                this.writeNode("ows:MinimumValue", range.minValue, node);
+                this.writeNode("ows:MaximumValue", range.maxValue, node);
+                return node;
+            },
+            "MinimumValue": function(minValue) {
+                var node = this.createElementNSPlus("ows:MinimumValue", {
+                    value: minValue
+                });
+                return node;
+            },
+            "MaximumValue": function(maxValue) {
+                var node = this.createElementNSPlus("ows:MaximumValue", {
+                    value: maxValue
+                });
+                return node;
+            },
+            "Value": function(value) {
+                var node = this.createElementNSPlus("ows:Value", {
+                    value: value
+                });
+                return node;
+            }
+        }, OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"])
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
+
+});
+/* ======================================================================
+    OpenLayers/Format/WCSGetCoverage.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSGetCoverage version 1.1.0
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WCSGetCoverage = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        wcs: "http://www.opengis.net/wcs/1.1",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 1.1.2
+     */
+    VERSION: "1.1.2",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/wcs/1.1 http://schemas.opengis.net/wcs/1.1/wcsGetCoverage.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.WCSGetCoverage
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} A WCS GetCoverage request XML string.
+     */
+    write: function(options) {
+        var node = this.writeNode("wcs:GetCoverage", options);
+        this.setAttributeNS(
+            node, this.namespaces.xsi,
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    }, 
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "wcs": {
+            "GetCoverage": function(options) {
+                var node = this.createElementNSPlus("wcs:GetCoverage", {
+                    attributes: {
+                        version: options.version || this.VERSION,
+                        service: 'WCS'
+                    } 
+                }); 
+                this.writeNode("ows:Identifier", options.identifier, node);
+                this.writeNode("wcs:DomainSubset", options.domainSubset, node);
+                this.writeNode("wcs:Output", options.output, node);
+                return node; 
+            },
+            "DomainSubset": function(domainSubset) {
+                var node = this.createElementNSPlus("wcs:DomainSubset", {});
+                this.writeNode("ows:BoundingBox", domainSubset.boundingBox, node);
+                if (domainSubset.temporalSubset) {
+                    this.writeNode("wcs:TemporalSubset", domainSubset.temporalSubset, node);
+                }
+                return node;
+            },
+            "TemporalSubset": function(temporalSubset) {
+                var node = this.createElementNSPlus("wcs:TemporalSubset", {});
+                for (var i=0, len=temporalSubset.timePeriods.length; i<len; ++i) {
+                    this.writeNode("wcs:TimePeriod", temporalSubset.timePeriods[i], node);
+                }
+                return node;
+            },
+            "TimePeriod": function(timePeriod) {
+                var node = this.createElementNSPlus("wcs:TimePeriod", {});
+                this.writeNode("wcs:BeginPosition", timePeriod.begin, node);
+                this.writeNode("wcs:EndPosition", timePeriod.end, node);
+                if (timePeriod.resolution) {
+                    this.writeNode("wcs:TimeResolution", timePeriod.resolution, node);
+                }
+                return node;
+            },
+            "BeginPosition": function(begin) {
+                var node = this.createElementNSPlus("wcs:BeginPosition", {
+                    value: begin
+                });
+                return node;
+            },
+            "EndPosition": function(end) {
+                var node = this.createElementNSPlus("wcs:EndPosition", {
+                    value: end
+                });
+                return node;
+            },
+            "TimeResolution": function(resolution) {
+                var node = this.createElementNSPlus("wcs:TimeResolution", {
+                    value: resolution
+                });
+                return node;
+            },
+            "Output": function(output) {
+                var node = this.createElementNSPlus("wcs:Output", {
+                    attributes: {
+                        format: output.format,
+                        store: output.store
+                    }
+                });
+                if (output.gridCRS) {
+                    this.writeNode("wcs:GridCRS", output.gridCRS, node);
+                }
+                return node;
+            },
+            "GridCRS": function(gridCRS) {
+                var node = this.createElementNSPlus("wcs:GridCRS", {});
+                this.writeNode("wcs:GridBaseCRS", gridCRS.baseCRS, node);
+                if (gridCRS.type) {
+                    this.writeNode("wcs:GridType", gridCRS.type, node);
+                }
+                if (gridCRS.origin) {
+                    this.writeNode("wcs:GridOrigin", gridCRS.origin, node);
+                }
+                this.writeNode("wcs:GridOffsets", gridCRS.offsets, node);
+                if (gridCRS.CS) {
+                    this.writeNode("wcs:GridCS", gridCRS.CS, node);
+                }
+                return node;
+            },
+            "GridBaseCRS": function(baseCRS) {
+                return this.createElementNSPlus("wcs:GridBaseCRS", {
+                    value: baseCRS
+                });
+            },
+            "GridOrigin": function(origin) {
+                return this.createElementNSPlus("wcs:GridOrigin", {
+                    value: origin
+                });
+            },
+            "GridType": function(type) {
+                return this.createElementNSPlus("wcs:GridType", {
+                    value: type
+                });
+            },
+            "GridOffsets": function(offsets) {
+                return this.createElementNSPlus("wcs:GridOffsets", {
+                    value: offsets
+                });
+            },
+            "GridCS": function(CS) {
+                return this.createElementNSPlus("wcs:GridCS", {
+                    value: CS
+                });
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WCSGetCoverage" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WPSExecute.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/Format/WCSGetCoverage.js
+ * @requires OpenLayers/Format/WFST/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSExecute version 1.0.0
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSExecute = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        gml: "http://www.opengis.net/gml",
+        wps: "http://www.opengis.net/wps/1.0.0",
+        wfs: "http://www.opengis.net/wfs",
+        ogc: "http://www.opengis.net/ogc",
+        wcs: "http://www.opengis.net/wcs",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",
+
+    schemaLocationAttr: function(options) {
+        return undefined;
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.WPSExecute
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} An WPS Execute request XML string.
+     */
+    write: function(options) {
+        var doc;
+        if (window.ActiveXObject) {
+            doc = new ActiveXObject("Microsoft.XMLDOM");
+            this.xmldom = doc;
+        } else {
+            doc = document.implementation.createDocument("", "", null);
+        }
+        var node = this.writeNode("wps:Execute", options, doc);
+        this.setAttributeNS(
+            node, this.namespaces.xsi,
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    }, 
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "wps": {
+            "Execute": function(options) {
+                var node = this.createElementNSPlus("wps:Execute", {
+                    attributes: {
+                        version: this.VERSION,
+                        service: 'WPS'
+                    } 
+                }); 
+                this.writeNode("ows:Identifier", options.identifier, node);
+                this.writeNode("wps:DataInputs", options.dataInputs, node);
+                this.writeNode("wps:ResponseForm", options.responseForm, node);
+                return node; 
+            },
+            "ResponseForm": function(responseForm) {
+                var node = this.createElementNSPlus("wps:ResponseForm", {});
+                if (responseForm.rawDataOutput) {
+                    this.writeNode("wps:RawDataOutput", responseForm.rawDataOutput, node);
+                }
+                if (responseForm.responseDocument) {
+                    this.writeNode("wps:ResponseDocument", responseForm.responseDocument, node);
+                }
+                return node;
+            },
+            "ResponseDocument": function(responseDocument) {
+                var node = this.createElementNSPlus("wps:ResponseDocument", {
+                    attributes: {
+                        storeExecuteResponse: responseDocument.storeExecuteResponse,
+                        lineage: responseDocument.lineage,
+                        status: responseDocument.status
+                    }
+                });
+                if (responseDocument.output) {
+                    this.writeNode("wps:Output", responseDocument.output, node);
+                }
+                return node;
+            },
+            "Output": function(output) {
+                var node = this.createElementNSPlus("wps:Output", {
+                    attributes: {
+                        asReference: output.asReference
+                    }
+                });
+                this.writeNode("ows:Identifier", output.identifier, node);
+                this.writeNode("ows:Title", output.title, node);
+                this.writeNode("ows:Abstract", output["abstract"], node);
+                return node;
+            },
+            "RawDataOutput": function(rawDataOutput) {
+                var node = this.createElementNSPlus("wps:RawDataOutput", {
+                    attributes: {
+                        mimeType: rawDataOutput.mimeType
+                    }
+                });
+                this.writeNode("ows:Identifier", rawDataOutput.identifier, node);
+                return node;
+            },
+            "DataInputs": function(dataInputs) {
+                var node = this.createElementNSPlus("wps:DataInputs", {});
+                for (var i=0, ii=dataInputs.length; i<ii; ++i) {
+                    this.writeNode("wps:Input", dataInputs[i], node);
+                }
+                return node;
+            },
+            "Input": function(input) {
+                var node = this.createElementNSPlus("wps:Input", {});
+                this.writeNode("ows:Identifier", input.identifier, node);
+                if (input.title) {
+                    this.writeNode("ows:Title", input.title, node);
+                }
+                if (input.data) {
+                    this.writeNode("wps:Data", input.data, node);
+                }
+                if (input.reference) {
+                    this.writeNode("wps:Reference", input.reference, node);
+                }
+                return node;
+            },
+            "Data": function(data) {
+                var node = this.createElementNSPlus("wps:Data", {});
+                if (data.literalData) {
+                    this.writeNode("wps:LiteralData", data.literalData, node);
+                } else if (data.complexData) {
+                    this.writeNode("wps:ComplexData", data.complexData, node);
+                }
+                return node;
+            },
+            "LiteralData": function(literalData) {
+                var node = this.createElementNSPlus("wps:LiteralData", {
+                    attributes: {
+                        uom: literalData.uom
+                    },
+                    value: literalData.value
+                });
+                return node;
+            },
+            "ComplexData": function(complexData) {
+                var node = this.createElementNSPlus("wps:ComplexData", {
+                    attributes: {
+                        mimeType: complexData.mimeType,
+                        encoding: complexData.encoding,
+                        schema: complexData.schema
+                    } 
+                });
+                node.appendChild(
+                    this.getXMLDoc().createCDATASection(complexData.value)
+                );
+                return node;
+            },
+            "Reference": function(reference) {
+                var node = this.createElementNSPlus("wps:Reference", {
+                    attributes: {
+                        mimeType: reference.mimeType,
+                        "xlink:href": reference.href,
+                        method: reference.method,
+                        encoding: reference.encoding,
+                        schema: reference.schema
+                    }
+                });
+                if (reference.body) {
+                    this.writeNode("wps:Body", reference.body, node);
+                }
+                return node;
+            },
+            "Body": function(body) {
+                var node = this.createElementNSPlus("wps:Body", {});
+                if (body.wcs) {
+                    this.writeNode("wcs:GetCoverage", body.wcs, node);
+                }
+                else if (body.wfs) {
+                    // OpenLayers.Format.WFST expects these to be on the 
+                    // instance and not in the options
+                    this.featureType = body.wfs.featureType;
+                    this.version = body.wfs.version;
+                    this.writeNode("wfs:GetFeature", body.wfs, node);
+                } else {
+                    this.writeNode("wps:Execute", body, node);
+                }
+                return node;                
+            }
+        },
+        "wcs": OpenLayers.Format.WCSGetCoverage.prototype.writers.wcs,
+        "wfs": OpenLayers.Format.WFST.v1_1_0.prototype.writers.wfs,
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WPSExecute" 
+
+});
+/* ======================================================================
+    OpenLayers/Control/PanZoom.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.PanZoom
+ * The PanZoom is a visible control, composed of a
+ * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomPanel>. By
+ * default it is drawn in the upper left corner of the map.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, {
+
+    /** 
+     * APIProperty: slideFactor
+     * {Integer} Number of pixels by which we'll pan the map in any direction 
+     *     on clicking the arrow buttons.  If you want to pan by some ratio
+     *     of the map dimensions, use <slideRatio> instead.
+     */
+    slideFactor: 50,
+
+    /** 
+     * APIProperty: slideRatio
+     * {Number} The fraction of map width/height by which we'll pan the map            
+     *     on clicking the arrow buttons.  Default is null.  If set, will
+     *     override <slideFactor>. E.g. if slideRatio is .5, then the Pan Up
+     *     button will pan up half the map height. 
+     */
+    slideRatio: null,
+
+    /** 
+     * Property: buttons
+     * {Array(DOMElement)} Array of Button Divs 
+     */
+    buttons: null,
+
+    /** 
+     * Property: position
+     * {<OpenLayers.Pixel>} 
+     */
+    position: null,
+
+    /**
+     * Constructor: OpenLayers.Control.PanZoom
+     * 
+     * Parameters:
+     * options - {Object}
+     */
+    initialize: function(options) {
+        this.position = new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,
+                                             OpenLayers.Control.PanZoom.Y);
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.removeButtons();
+        this.buttons = null;
+        this.position = null;
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: draw
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} 
+     * 
+     * Returns:
+     * {DOMElement} A reference to the container div for the PanZoom control.
+     */
+    draw: function(px) {
+        // initialize our internal div
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        px = this.position;
+
+        // place the controls
+        this.buttons = [];
+
+        var sz = new OpenLayers.Size(18,18);
+        var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
+
+        this._addButton("panup", "north-mini.png", centered, sz);
+        px.y = centered.y+sz.h;
+        this._addButton("panleft", "west-mini.png", px, sz);
+        this._addButton("panright", "east-mini.png", px.add(sz.w, 0), sz);
+        this._addButton("pandown", "south-mini.png", 
+                        centered.add(0, sz.h*2), sz);
+        this._addButton("zoomin", "zoom-plus-mini.png", 
+                        centered.add(0, sz.h*3+5), sz);
+        this._addButton("zoomworld", "zoom-world-mini.png", 
+                        centered.add(0, sz.h*4+5), sz);
+        this._addButton("zoomout", "zoom-minus-mini.png", 
+                        centered.add(0, sz.h*5+5), sz);
+        return this.div;
+    },
+    
+    /**
+     * Method: _addButton
+     * 
+     * Parameters:
+     * id - {String} 
+     * img - {String} 
+     * xy - {<OpenLayers.Pixel>} 
+     * sz - {<OpenLayers.Size>} 
+     * 
+     * Returns:
+     * {DOMElement} A Div (an alphaImageDiv, to be precise) that contains the
+     *     image of the button, and has all the proper event handlers set.
+     */
+    _addButton:function(id, img, xy, sz) {
+        var imgLocation = OpenLayers.Util.getImagesLocation() + img;
+        var btn = OpenLayers.Util.createAlphaImageDiv(
+                                    this.id + "_" + id, 
+                                    xy, sz, imgLocation, "absolute");
+        btn.style.cursor = "pointer";
+        //we want to add the outer div
+        this.div.appendChild(btn);
+
+        OpenLayers.Event.observe(btn, "mousedown", 
+            OpenLayers.Function.bindAsEventListener(this.buttonDown, btn));
+        OpenLayers.Event.observe(btn, "dblclick", 
+            OpenLayers.Function.bindAsEventListener(this.doubleClick, btn));
+        OpenLayers.Event.observe(btn, "click", 
+            OpenLayers.Function.bindAsEventListener(this.doubleClick, btn));
+        btn.action = id;
+        btn.map = this.map;
+    
+        if(!this.slideRatio){
+            var slideFactorPixels = this.slideFactor;
+            var getSlideFactor = function() {
+                return slideFactorPixels;
+            };
+        } else {
+            var slideRatio = this.slideRatio;
+            var getSlideFactor = function(dim) {
+                return this.map.getSize()[dim] * slideRatio;
+            };
+        }
+
+        btn.getSlideFactor = getSlideFactor;
+
+        //we want to remember/reference the outer div
+        this.buttons.push(btn);
+        return btn;
+    },
+    
+    /**
+     * Method: _removeButton
+     * 
+     * Parameters:
+     * btn - {Object}
+     */
+    _removeButton: function(btn) {
+        OpenLayers.Event.stopObservingElement(btn);
+        btn.map = null;
+        btn.getSlideFactor = null;
+        this.div.removeChild(btn);
+        OpenLayers.Util.removeItem(this.buttons, btn);
+    },
+    
+    /**
+     * Method: removeButtons
+     */
+    removeButtons: function() {
+        for(var i=this.buttons.length-1; i>=0; --i) {
+            this._removeButton(this.buttons[i]);
+        }
+    },
+    
+    /**
+     * Method: doubleClick
+     *
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {Boolean}
+     */
+    doubleClick: function (evt) {
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+    
+    /**
+     * Method: buttonDown
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    buttonDown: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+
+        switch (this.action) {
+            case "panup": 
+                this.map.pan(0, -this.getSlideFactor("h"));
+                break;
+            case "pandown": 
+                this.map.pan(0, this.getSlideFactor("h"));
+                break;
+            case "panleft": 
+                this.map.pan(-this.getSlideFactor("w"), 0);
+                break;
+            case "panright": 
+                this.map.pan(this.getSlideFactor("w"), 0);
+                break;
+            case "zoomin": 
+                this.map.zoomIn(); 
+                break;
+            case "zoomout": 
+                this.map.zoomOut(); 
+                break;
+            case "zoomworld": 
+                this.map.zoomToMaxExtent(); 
+                break;
+        }
+
+        OpenLayers.Event.stop(evt);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.PanZoom"
+});
+
+/**
+ * Constant: X
+ * {Integer}
+ */
+OpenLayers.Control.PanZoom.X = 4;
+
+/**
+ * Constant: Y
+ * {Integer}
+ */
+OpenLayers.Control.PanZoom.Y = 4;
+/* ======================================================================
+    OpenLayers/Control/PanZoomBar.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control/PanZoom.js
+ */
+
+/**
+ * Class: OpenLayers.Control.PanZoomBar
+ * The PanZoomBar is a visible control composed of a
+ * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>. 
+ * By default it is displayed in the upper left corner of the map as 4
+ * directional arrows above a vertical slider.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control.PanZoom>
+ */
+OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
+
+    /** 
+     * APIProperty: zoomStopWidth
+     */
+    zoomStopWidth: 18,
+
+    /** 
+     * APIProperty: zoomStopHeight
+     */
+    zoomStopHeight: 11,
+
+    /** 
+     * Property: slider
+     */
+    slider: null,
+
+    /** 
+     * Property: sliderEvents
+     * {<OpenLayers.Events>}
+     */
+    sliderEvents: null,
+
+    /** 
+     * Property: zoombarDiv
+     * {DOMElement}
+     */
+    zoombarDiv: null,
+
+    /** 
+     * Property: divEvents
+     * {<OpenLayers.Events>}
+     */
+    divEvents: null,
+
+    /** 
+     * APIProperty: zoomWorldIcon
+     * {Boolean}
+     */
+    zoomWorldIcon: false,
+
+    /**
+     * APIProperty: panIcons
+     * {Boolean} Set this property to false not to display the pan icons. If
+     * false the zoom world icon is placed under the zoom bar. Defaults to
+     * true.
+     */
+    panIcons: true,
+
+    /**
+     * APIProperty: forceFixedZoomLevel
+     * {Boolean} Force a fixed zoom level even though the map has 
+     *     fractionalZoom
+     */
+    forceFixedZoomLevel: false,
+
+    /**
+     * Property: mouseDragStart
+     * {<OpenLayers.Pixel>}
+     */
+    mouseDragStart: null,
+
+    /**
+     * Property: deltaY
+     * {Number} The cumulative vertical pixel offset during a zoom bar drag.
+     */
+    deltaY: null,
+
+    /**
+     * Property: zoomStart
+     * {<OpenLayers.Pixel>}
+     */
+    zoomStart: null,
+
+    /**
+     * Constructor: OpenLayers.Control.PanZoomBar
+     */ 
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+
+        this._removeZoomBar();
+
+        this.map.events.un({
+            "changebaselayer": this.redraw,
+            scope: this
+        });
+
+        OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
+
+        delete this.mouseDragStart;
+        delete this.zoomStart;
+    },
+    
+    /**
+     * Method: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
+        this.map.events.register("changebaselayer", this, this.redraw);
+    },
+
+    /** 
+     * Method: redraw
+     * clear the div and start over.
+     */
+    redraw: function() {
+        if (this.div != null) {
+            this.removeButtons();
+            this._removeZoomBar();
+        }  
+        this.draw();
+    },
+    
+    /**
+    * Method: draw 
+    *
+    * Parameters:
+    * px - {<OpenLayers.Pixel>} 
+    */
+    draw: function(px) {
+        // initialize our internal div
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        px = this.position.clone();
+
+        // place the controls
+        this.buttons = [];
+
+        var sz = new OpenLayers.Size(18,18);
+        if (this.panIcons) {
+            var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
+            var wposition = sz.w;
+
+            if (this.zoomWorldIcon) {
+                centered = new OpenLayers.Pixel(px.x+sz.w, px.y);
+            }
+
+            this._addButton("panup", "north-mini.png", centered, sz);
+            px.y = centered.y+sz.h;
+            this._addButton("panleft", "west-mini.png", px, sz);
+            if (this.zoomWorldIcon) {
+                this._addButton("zoomworld", "zoom-world-mini.png", px.add(sz.w, 0), sz);
+
+                wposition *= 2;
+            }
+            this._addButton("panright", "east-mini.png", px.add(wposition, 0), sz);
+            this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz);
+            this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz);
+            centered = this._addZoomBar(centered.add(0, sz.h*4 + 5));
+            this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
+        }
+        else {
+            this._addButton("zoomin", "zoom-plus-mini.png", px, sz);
+            centered = this._addZoomBar(px.add(0, sz.h));
+            this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
+            if (this.zoomWorldIcon) {
+                centered = centered.add(0, sz.h+3);
+                this._addButton("zoomworld", "zoom-world-mini.png", centered, sz);
+            }
+        }
+        return this.div;
+    },
+
+    /** 
+    * Method: _addZoomBar
+    * 
+    * Parameters:
+    * location - {<OpenLayers.Pixel>} where zoombar drawing is to start.
+    */
+    _addZoomBar:function(centered) {
+        var imgLocation = OpenLayers.Util.getImagesLocation();
+        
+        var id = this.id + "_" + this.map.id;
+        var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
+        var slider = OpenLayers.Util.createAlphaImageDiv(id,
+                       centered.add(-1, zoomsToEnd * this.zoomStopHeight), 
+                       new OpenLayers.Size(20,9), 
+                       imgLocation+"slider.png",
+                       "absolute");
+        slider.style.cursor = "move";
+        this.slider = slider;
+        
+        this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
+                                            {includeXY: true});
+        this.sliderEvents.on({
+            "touchstart": this.zoomBarDown,
+            "touchmove": this.zoomBarDrag,
+            "touchend": this.zoomBarUp,
+            "mousedown": this.zoomBarDown,
+            "mousemove": this.zoomBarDrag,
+            "mouseup": this.zoomBarUp,
+            "dblclick": this.doubleClick,
+            "click": this.doubleClick
+        });
+        
+        var sz = new OpenLayers.Size();
+        sz.h = this.zoomStopHeight * this.map.getNumZoomLevels();
+        sz.w = this.zoomStopWidth;
+        var div = null;
+        
+        if (OpenLayers.Util.alphaHack()) {
+            var id = this.id + "_" + this.map.id;
+            div = OpenLayers.Util.createAlphaImageDiv(id, centered,
+                                      new OpenLayers.Size(sz.w, 
+                                              this.zoomStopHeight),
+                                      imgLocation + "zoombar.png", 
+                                      "absolute", null, "crop");
+            div.style.height = sz.h + "px";
+        } else {
+            div = OpenLayers.Util.createDiv(
+                        'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
+                        centered,
+                        sz,
+                        imgLocation+"zoombar.png");
+        }
+        div.style.cursor = "pointer";
+        this.zoombarDiv = div;
+        
+        this.divEvents = new OpenLayers.Events(this, div, null, true, 
+                                                {includeXY: true});
+        this.divEvents.on({
+            "touchmove": this.passEventToSlider,
+            "mousedown": this.divClick,
+            "mousemove": this.passEventToSlider,
+            "dblclick": this.doubleClick,
+            "click": this.doubleClick
+        });
+        
+        this.div.appendChild(div);
+
+        this.startTop = parseInt(div.style.top);
+        this.div.appendChild(slider);
+
+        this.map.events.register("zoomend", this, this.moveZoomBar);
+
+        centered = centered.add(0, 
+            this.zoomStopHeight * this.map.getNumZoomLevels());
+        return centered; 
+    },
+    
+    /**
+     * Method: _removeZoomBar
+     */
+    _removeZoomBar: function() {
+        this.sliderEvents.un({
+            "touchmove": this.zoomBarDrag,
+            "mousedown": this.zoomBarDown,
+            "mousemove": this.zoomBarDrag,
+            "mouseup": this.zoomBarUp,
+            "dblclick": this.doubleClick,
+            "click": this.doubleClick
+        });
+        this.sliderEvents.destroy();
+
+        this.divEvents.un({
+            "touchmove": this.passEventToSlider,
+            "mousedown": this.divClick,
+            "mousemove": this.passEventToSlider,
+            "dblclick": this.doubleClick,
+            "click": this.doubleClick
+        });
+        this.divEvents.destroy();
+        
+        this.div.removeChild(this.zoombarDiv);
+        this.zoombarDiv = null;
+        this.div.removeChild(this.slider);
+        this.slider = null;
+        
+        this.map.events.unregister("zoomend", this, this.moveZoomBar);
+    },
+    
+    /**
+     * Method: passEventToSlider
+     * This function is used to pass events that happen on the div, or the map,
+     * through to the slider, which then does its moving thing.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    passEventToSlider:function(evt) {
+        this.sliderEvents.handleBrowserEvent(evt);
+    },
+    
+    /**
+     * Method: divClick
+     * Picks up on clicks directly on the zoombar div
+     *           and sets the zoom level appropriately.
+     */
+    divClick: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        var levels = evt.xy.y / this.zoomStopHeight;
+        if(this.forceFixedZoomLevel || !this.map.fractionalZoom) {
+            levels = Math.floor(levels);
+        }    
+        var zoom = (this.map.getNumZoomLevels() - 1) - levels; 
+        zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
+        this.map.zoomTo(zoom);
+        OpenLayers.Event.stop(evt);
+    },
+    
+    /*
+     * Method: zoomBarDown
+     * event listener for clicks on the slider
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    zoomBarDown:function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
+            return;
+        }
+        this.map.events.on({
+            "touchmove": this.passEventToSlider,
+            "mousemove": this.passEventToSlider,
+            "mouseup": this.passEventToSlider,
+            scope: this
+        });
+        this.mouseDragStart = evt.xy.clone();
+        this.zoomStart = evt.xy.clone();
+        this.div.style.cursor = "move";
+        // reset the div offsets just in case the div moved
+        this.zoombarDiv.offsets = null; 
+        OpenLayers.Event.stop(evt);
+    },
+    
+    /*
+     * Method: zoomBarDrag
+     * This is what happens when a click has occurred, and the client is
+     * dragging.  Here we must ensure that the slider doesn't go beyond the
+     * bottom/top of the zoombar div, as well as moving the slider to its new
+     * visual location
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    zoomBarDrag:function(evt) {
+        if (this.mouseDragStart != null) {
+            var deltaY = this.mouseDragStart.y - evt.xy.y;
+            var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
+            if ((evt.clientY - offsets[1]) > 0 && 
+                (evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) {
+                var newTop = parseInt(this.slider.style.top) - deltaY;
+                this.slider.style.top = newTop+"px";
+                this.mouseDragStart = evt.xy.clone();
+            }
+            // set cumulative displacement
+            this.deltaY = this.zoomStart.y - evt.xy.y;
+            OpenLayers.Event.stop(evt);
+        }
+    },
+    
+    /*
+     * Method: zoomBarUp
+     * Perform cleanup when a mouseup event is received -- discover new zoom
+     * level and switch to it.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    zoomBarUp:function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
+            return;
+        }
+        if (this.mouseDragStart) {
+            this.div.style.cursor="";
+            this.map.events.un({
+                "touchmove": this.passEventToSlider,
+                "mouseup": this.passEventToSlider,
+                "mousemove": this.passEventToSlider,
+                scope: this
+            });
+            var zoomLevel = this.map.zoom;
+            if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
+                zoomLevel += this.deltaY/this.zoomStopHeight;
+                zoomLevel = Math.min(Math.max(zoomLevel, 0), 
+                                     this.map.getNumZoomLevels() - 1);
+            } else {
+                zoomLevel += this.deltaY/this.zoomStopHeight;
+                zoomLevel = Math.max(Math.round(zoomLevel), 0);      
+            }
+            this.map.zoomTo(zoomLevel);
+            this.mouseDragStart = null;
+            this.zoomStart = null;
+            this.deltaY = 0;
+            OpenLayers.Event.stop(evt);
+        }
+    },
+    
+    /*
+    * Method: moveZoomBar
+    * Change the location of the slider to match the current zoom level.
+    */
+    moveZoomBar:function() {
+        var newTop = 
+            ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) * 
+            this.zoomStopHeight + this.startTop + 1;
+        this.slider.style.top = newTop + "px";
+    },    
+    
+    CLASS_NAME: "OpenLayers.Control.PanZoomBar"
+});
+/* ======================================================================
+    OpenLayers/Format/WFSCapabilities/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities/v1_1_0
+ * Read WFS Capabilities version 1.1.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WFSCapabilities>
+ */
+OpenLayers.Format.WFSCapabilities.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.WFSCapabilities.v1, {
+    
+    /**
+     * Constructor: OpenLayers.Format.WFSCapabilities.v1_1_0
+     * Create a new parser for WFS capabilities version 1.1.0.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Method: read_cap_DefaultSRS
+     */
+    read_cap_DefaultSRS: function(obj, node) {
+        var defaultSRS = this.getChildValue(node);
+        if (defaultSRS) {
+            obj.srs = defaultSRS;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_1_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/Image.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+ 
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Image
+ * Instances of OpenLayers.Layer.Image are used to display data from a web
+ * accessible image as a map layer.  Create a new image layer with the
+ * <OpenLayers.Layer.Image> constructor.  Inherits from <OpenLayers.Layer>.
+ */
+OpenLayers.Layer.Image = OpenLayers.Class(OpenLayers.Layer, {
+
+    /**
+     * Property: isBaseLayer
+     * {Boolean} The layer is a base layer.  Default is true.  Set this property
+     * in the layer options
+     */
+    isBaseLayer: true,
+    
+    /**
+     * Property: url
+     * {String} URL of the image to use
+     */
+    url: null,
+
+    /**
+     * Property: extent
+     * {<OpenLayers.Bounds>} The image bounds in map units.  This extent will
+     *     also be used as the default maxExtent for the layer.  If you wish
+     *     to have a maxExtent that is different than the image extent, set the
+     *     maxExtent property of the options argument (as with any other layer).
+     */
+    extent: null,
+    
+    /**
+     * Property: size
+     * {<OpenLayers.Size>} The image size in pixels
+     */
+    size: null,
+
+    /**
+     * Property: tile
+     * {<OpenLayers.Tile.Image>}
+     */
+    tile: null,
+
+    /**
+     * Property: aspectRatio
+     * {Float} The ratio of height/width represented by a single pixel in the
+     * graphic
+     */
+    aspectRatio: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.Image
+     * Create a new image layer
+     *
+     * Parameters:
+     * name - {String} A name for the layer.
+     * url - {String} Relative or absolute path to the image
+     * extent - {<OpenLayers.Bounds>} The extent represented by the image
+     * size - {<OpenLayers.Size>} The size (in pixels) of the image
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, extent, size, options) {
+        this.url = url;
+        this.extent = extent;
+        this.maxExtent = extent;
+        this.size = size;
+        OpenLayers.Layer.prototype.initialize.apply(this, [name, options]);
+
+        this.aspectRatio = (this.extent.getHeight() / this.size.h) /
+                           (this.extent.getWidth() / this.size.w);
+    },    
+
+    /**
+     * Method: destroy
+     * Destroy this layer
+     */
+    destroy: function() {
+        if (this.tile) {
+            this.removeTileMonitoringHooks(this.tile);
+            this.tile.destroy();
+            this.tile = null;
+        }
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Paramters:
+     * obj - {Object} An optional layer (is this ever used?)
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Image>} An exact copy of this layer
+     */
+    clone: function(obj) {
+        
+        if(obj == null) {
+            obj = new OpenLayers.Layer.Image(this.name,
+                                               this.url,
+                                               this.extent,
+                                               this.size,
+                                               this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },    
+    
+    /**
+     * APIMethod: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        /**
+         * If nothing to do with resolutions has been set, assume a single
+         * resolution determined by ratio*extent/size - if an image has a
+         * pixel aspect ratio different than one (as calculated above), the
+         * image will be stretched in one dimension only.
+         */
+        if( this.options.maxResolution == null ) {
+            this.options.maxResolution = this.aspectRatio *
+                                         this.extent.getWidth() /
+                                         this.size.w;
+        }
+        OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+    },
+
+    /** 
+     * Method: moveTo
+     * Create the tile for the image or resize it for the new resolution
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean}
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+
+        var firstRendering = (this.tile == null);
+
+        if(zoomChanged || firstRendering) {
+
+            //determine new tile size
+            this.setTileSize();
+
+            //determine new position (upper left corner of new bounds)
+            var ul = new OpenLayers.LonLat(this.extent.left, this.extent.top);
+            var ulPx = this.map.getLayerPxFromLonLat(ul);
+
+            if(firstRendering) {
+                //create the new tile
+                this.tile = new OpenLayers.Tile.Image(this, ulPx, this.extent, 
+                                                      null, this.tileSize);
+                this.addTileMonitoringHooks(this.tile);
+            } else {
+                //just resize the tile and set it's new position
+                this.tile.size = this.tileSize.clone();
+                this.tile.position = ulPx.clone();
+            }
+            this.tile.draw();
+        }
+    }, 
+
+    /**
+     * Set the tile size based on the map size.
+     */
+    setTileSize: function() {
+        var tileWidth = this.extent.getWidth() / this.map.getResolution();
+        var tileHeight = this.extent.getHeight() / this.map.getResolution();
+        this.tileSize = new OpenLayers.Size(tileWidth, tileHeight);
+    },
+
+    /** 
+     * Method: addTileMonitoringHooks
+     * This function takes a tile as input and adds the appropriate hooks to 
+     *     the tile so that the layer can keep track of the loading tiles.
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    addTileMonitoringHooks: function(tile) {
+        tile.onLoadStart = function() {
+            this.events.triggerEvent("loadstart");
+        };
+        tile.events.register("loadstart", this, tile.onLoadStart);
+      
+        tile.onLoadEnd = function() {
+            this.events.triggerEvent("loadend");
+        };
+        tile.events.register("loadend", this, tile.onLoadEnd);
+        tile.events.register("unload", this, tile.onLoadEnd);
+    },
+
+    /** 
+     * Method: removeTileMonitoringHooks
+     * This function takes a tile as input and removes the tile hooks 
+     *     that were added in <addTileMonitoringHooks>.
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    removeTileMonitoringHooks: function(tile) {
+        tile.unload();
+        tile.events.un({
+            "loadstart": tile.onLoadStart,
+            "loadend": tile.onLoadEnd,
+            "unload": tile.onLoadEnd,
+            scope: this
+        });
+    },
+    
+    /**
+     * APIMethod: setUrl
+     * 
+     * Parameters:
+     * newUrl - {String}
+     */
+    setUrl: function(newUrl) {
+        this.url = newUrl;
+        this.tile.draw();
+    },
+
+    /** 
+     * APIMethod: getURL
+     * The url we return is always the same (the image itself never changes)
+     *     so we can ignore the bounds parameter (it will always be the same, 
+     *     anyways) 
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     */
+    getURL: function(bounds) {
+        return this.url;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Image"
+});
+/* ======================================================================
+    OpenLayers/Strategy.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy
+ * Abstract vector layer strategy class.  Not to be instantiated directly.  Use
+ *     one of the strategy subclasses instead.
+ */
+OpenLayers.Strategy = OpenLayers.Class({
+    
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>} The layer this strategy belongs to.
+     */
+    layer: null,
+    
+    /**
+     * Property: options
+     * {Object} Any options sent to the constructor.
+     */
+    options: null,
+
+    /** 
+     * Property: active 
+     * {Boolean} The control is active.
+     */
+    active: null,
+
+    /**
+     * Property: autoActivate
+     * {Boolean} The creator of the strategy can set autoActivate to false
+     *      to fully control when the protocol is activated and deactivated.
+     *      Defaults to true.
+     */
+    autoActivate: true,
+
+    /**
+     * Property: autoDestroy
+     * {Boolean} The creator of the strategy can set autoDestroy to false
+     *      to fully control when the strategy is destroyed. Defaults to
+     *      true.
+     */
+    autoDestroy: true,
+
+    /**
+     * Constructor: OpenLayers.Strategy
+     * Abstract class for vector strategies.  Create instances of a subclass.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+        this.options = options;
+        // set the active property here, so that user cannot override it
+        this.active = false;
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up the strategy.
+     */
+    destroy: function() {
+        this.deactivate();
+        this.layer = null;
+        this.options = null;
+    },
+
+    /**
+     * Method: setLayer
+     * Called to set the <layer> property.
+     *
+     * Parameters:
+     * {<OpenLayers.Layer.Vector>}
+     */
+    setLayer: function(layer) {
+        this.layer = layer;
+    },
+    
+    /**
+     * Method: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated or false if
+     *      the strategy was already active.
+     */
+    activate: function() {
+        if (!this.active) {
+            this.active = true;
+            return true;
+        }
+        return false;
+    },
+    
+    /**
+     * Method: deactivate
+     * Deactivate the strategy.  Unregister any listeners, do appropriate
+     *     tear-down.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully deactivated or false if
+     *      the strategy was already inactive.
+     */
+    deactivate: function() {
+        if (this.active) {
+            this.active = false;
+            return true;
+        }
+        return false;
+    },
+   
+    CLASS_NAME: "OpenLayers.Strategy" 
+});
+/* ======================================================================
+    OpenLayers/Strategy/Save.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Save
+ * A strategy that commits newly created or modified features.  By default
+ *     the strategy waits for a call to <save> before persisting changes.  By
+ *     configuring the strategy with the <auto> option, changes can be saved
+ *     automatically.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Save = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * strategy.events.register(type, obj, listener);
+     * (end)
+     *
+     *  - *start* Triggered before saving
+     *  - *success* Triggered after a successful transaction
+     *  - *fail* Triggered after a failed transaction
+     *      
+     */
+    EVENT_TYPES: ["start", "success", "fail"],
+ 
+    /** 
+     * Property: events
+     * {<OpenLayers.Events>} Events instance for triggering this protocol
+     *    events.
+     */
+    events: null,
+    
+    /**
+     * APIProperty: auto
+     * {Boolean | Number} Auto-save.  Default is false.  If true, features will be
+     *     saved immediately after being added to the layer and with each
+     *     modification or deletion.  If auto is a number, features will be
+     *     saved on an interval provided by the value (in seconds).
+     */
+    auto: false,
+    
+    /**
+     * Property: timer
+     * {Number} The id of the timer.
+     */
+    timer: null,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Save
+     * Create a new Save strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Strategy.prototype.initialize.apply(this, [options]);
+        this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
+    },
+   
+    /**
+     * APIMethod: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            if(this.auto) {
+                if(typeof this.auto === "number") {
+                    this.timer = window.setInterval(
+                        OpenLayers.Function.bind(this.save, this),
+                        this.auto * 1000
+                    );
+                } else {
+                    this.layer.events.on({
+                        "featureadded": this.triggerSave,
+                        "afterfeaturemodified": this.triggerSave,
+                        scope: this
+                    });
+                }
+            }
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy.  Unregister any listeners, do appropriate
+     *     tear-down.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            if(this.auto) {
+                if(typeof this.auto === "number") {
+                    window.clearInterval(this.timer);
+                } else {
+                    this.layer.events.un({
+                        "featureadded": this.triggerSave,
+                        "afterfeaturemodified": this.triggerSave,
+                        scope: this
+                    });
+                }
+            }
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: triggerSave
+     * Registered as a listener.  Calls save if a feature has insert, update,
+     *     or delete state.
+     *
+     * Parameters:
+     * event - {Object} The event this function is listening for.
+     */
+    triggerSave: function(event) {
+        var feature = event.feature;
+        if(feature.state === OpenLayers.State.INSERT ||
+           feature.state === OpenLayers.State.UPDATE ||
+           feature.state === OpenLayers.State.DELETE) {
+            this.save([event.feature]);
+        }
+    },
+    
+    /**
+     * APIMethod: save
+     * Tell the layer protocol to commit unsaved features.  If the layer
+     *     projection differs from the map projection, features will be
+     *     transformed into the layer projection before being committed.
+     *
+     * Parameters:
+     * features - {Array} Features to be saved.  If null, then default is all
+     *     features in the layer.  Features are assumed to be in the map
+     *     projection.
+     */
+    save: function(features) {
+        if(!features) {
+            features = this.layer.features;
+        }
+        this.events.triggerEvent("start", {features:features});
+        var remote = this.layer.projection;
+        var local = this.layer.map.getProjectionObject();
+        if(!local.equals(remote)) {
+            var len = features.length;
+            var clones = new Array(len);
+            var orig, clone;
+            for(var i=0; i<len; ++i) {
+                orig = features[i];
+                clone = orig.clone();
+                clone.fid = orig.fid;
+                clone.state = orig.state;
+                if(orig.url) {
+                    clone.url = orig.url;
+                }
+                clone._original = orig;
+                clone.geometry.transform(local, remote);
+                clones[i] = clone;
+            }
+            features = clones;
+        }
+        this.layer.protocol.commit(features, {
+            callback: this.onCommit,
+            scope: this
+        });
+    },
+    
+    /**
+     * Method: onCommit
+     * Called after protocol commit.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} A response object.
+     */
+    onCommit: function(response) {
+        var evt = {"response": response};
+        if(response.success()) {
+            var features = response.reqFeatures;
+            // deal with inserts, updates, and deletes
+            var state, feature;
+            var destroys = [];
+            var insertIds = response.insertIds || [];
+            var j = 0;
+            for(var i=0, len=features.length; i<len; ++i) {
+                feature = features[i];
+                // if projection was different, we may be dealing with clones
+                feature = feature._original || feature;
+                state = feature.state;
+                if(state) {
+                    if(state == OpenLayers.State.DELETE) {
+                        destroys.push(feature);
+                    } else if(state == OpenLayers.State.INSERT) {
+                        feature.fid = insertIds[j];
+                        ++j;
+                    }
+                    feature.state = null;
+                }
+            }
+
+            if(destroys.length > 0) {
+                this.layer.destroyFeatures(destroys);
+            }
+
+            this.events.triggerEvent("success", evt);
+
+        } else {
+            this.events.triggerEvent("fail", evt);
+        }
+    },
+   
+    CLASS_NAME: "OpenLayers.Strategy.Save" 
+});
+/* ======================================================================
+    OpenLayers/Format/GPX.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GPX
+ * Read/write GPX parser. Create a new instance with the 
+ *     <OpenLayers.Format.GPX> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
+   /**
+    * APIProperty: extractWaypoints
+    * {Boolean} Extract waypoints from GPX. (default: true)
+    */
+    extractWaypoints: true,
+    
+   /**
+    * APIProperty: extractTracks
+    * {Boolean} Extract tracks from GPX. (default: true)
+    */
+    extractTracks: true,
+    
+   /**
+    * APIProperty: extractRoutes
+    * {Boolean} Extract routes from GPX. (default: true)
+    */
+    extractRoutes: true,
+    
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract feature attributes from GPX. (default: true)
+     *     NOTE: Attributes as part of extensions to the GPX standard may not
+     *     be extracted.
+     */
+    extractAttributes: true,
+    
+    /**
+     * Constructor: OpenLayers.Format.GPX
+     * Create a new parser for GPX.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        // GPX coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from a GPX doc
+     *
+     * Parameters:
+     * doc - {Element} 
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(doc) {
+        if (typeof doc == "string") { 
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+        var features = [];
+        
+        if(this.extractTracks) {
+            var tracks = doc.getElementsByTagName("trk");
+            for (var i=0, len=tracks.length; i<len; i++) {
+                // Attributes are only in trk nodes, not trkseg nodes
+                var attrs = {};
+                if(this.extractAttributes) {
+                    attrs = this.parseAttributes(tracks[i]);
+                }
+                
+                var segs = this.getElementsByTagNameNS(tracks[i], tracks[i].namespaceURI, "trkseg");
+                for (var j = 0, seglen = segs.length; j < seglen; j++) {
+                    // We don't yet support extraction of trkpt attributes
+                    // All trksegs of a trk get that trk's attributes
+                    var track = this.extractSegment(segs[j], "trkpt");
+                    features.push(new OpenLayers.Feature.Vector(track, attrs));
+                }
+            }
+        }
+        
+        if(this.extractRoutes) {
+            var routes = doc.getElementsByTagName("rte");
+            for (var k=0, klen=routes.length; k<klen; k++) {
+                var attrs = {};
+                if(this.extractAttributes) {
+                    attrs = this.parseAttributes(routes[k]);
+                }
+                var route = this.extractSegment(routes[k], "rtept");
+                features.push(new OpenLayers.Feature.Vector(route, attrs));
+            }
+        }
+        
+        if(this.extractWaypoints) {
+            var waypoints = doc.getElementsByTagName("wpt");
+            for (var l = 0, len = waypoints.length; l < len; l++) {
+                var attrs = {};
+                if(this.extractAttributes) {
+                    attrs = this.parseAttributes(waypoints[l]);
+                }
+                var wpt = new OpenLayers.Geometry.Point(waypoints[l].getAttribute("lon"), waypoints[l].getAttribute("lat"));
+                features.push(new OpenLayers.Feature.Vector(wpt, attrs));
+            }
+        }
+        
+        if (this.internalProjection && this.externalProjection) {
+            for (var g = 0, featLength = features.length; g < featLength; g++) {
+                features[g].geometry.transform(this.externalProjection,
+                                    this.internalProjection);
+            }
+        }
+        
+        return features;
+    },
+    
+   /**
+    * Method: extractSegment
+    *
+    * Parameters:
+    * segment - {DOMElement} a trkseg or rte node to parse
+    * segmentType - {String} nodeName of waypoints that form the line
+    *
+    * Returns:
+    * {<OpenLayers.Geometry.LineString>} A linestring geometry
+    */
+    extractSegment: function(segment, segmentType) {
+        var points = this.getElementsByTagNameNS(segment, segment.namespaceURI, segmentType);
+        var point_features = [];
+        for (var i = 0, len = points.length; i < len; i++) {
+            point_features.push(new OpenLayers.Geometry.Point(points[i].getAttribute("lon"), points[i].getAttribute("lat")));
+        }
+        return new OpenLayers.Geometry.LineString(point_features);
+    },
+    
+    /**
+     * Method: parseAttributes
+     *
+     * Parameters:
+     * node - {<DOMElement>}
+     *
+     * Returns:
+     * {Object} An attributes object.
+     */
+    parseAttributes: function(node) {
+        // node is either a wpt, trk or rte
+        // attributes are children of the form <attr>value</attr>
+        var attributes = {};
+        var attrNode = node.firstChild, value, name;
+        while(attrNode) {
+            if(attrNode.nodeType == 1) {
+                value = attrNode.firstChild;
+                if(value.nodeType == 3 || value.nodeType == 4) {
+                    name = (attrNode.prefix) ?
+                        attrNode.nodeName.split(":")[1] :
+                        attrNode.nodeName;
+                    if(name != "trkseg" && name != "rtept") {
+                        attributes[name] = value.nodeValue;
+                    }
+                }
+            }
+            attrNode = attrNode.nextSibling;
+        }
+        return attributes;
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.GPX"
+});
+/* ======================================================================
+    OpenLayers/Format/WFSDescribeFeatureType.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ *
+ * Class: OpenLayers.Format.WFSDescribeFeatureType
+ * Read WFS DescribeFeatureType response
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFSDescribeFeatureType = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xsd: "http://www.w3.org/2001/XMLSchema"
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.WFSDescribeFeatureType
+     * Create a new parser for WFS DescribeFeatureType responses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "xsd": {
+            "schema": function(node, obj) {
+                var complexTypes = [];
+                var customTypes = {};
+                var schema = {
+                    complexTypes: complexTypes,
+                    customTypes: customTypes
+                };
+                
+                this.readChildNodes(node, schema);
+
+                var attributes = node.attributes;
+                var attr, name;
+                for(var i=0, len=attributes.length; i<len; ++i) {
+                    attr = attributes[i];
+                    name = attr.name;
+                    if(name.indexOf("xmlns") == 0) {
+                        this.setNamespace(name.split(":")[1] || "", attr.value);
+                    } else {
+                        obj[name] = attr.value;
+                    }
+                }
+                obj.featureTypes = complexTypes;                
+                obj.targetPrefix = this.namespaceAlias[obj.targetNamespace];
+                
+                // map complexTypes to names of customTypes
+                var complexType, customType;
+                for(var i=0, len=complexTypes.length; i<len; ++i) {
+                    complexType = complexTypes[i];
+                    customType = customTypes[complexType.typeName];
+                    if(customTypes[complexType.typeName]) {
+                        complexType.typeName = customType.name;
+                    }
+                }
+            },
+            "complexType": function(node, obj) {
+                var complexType = {
+                    // this is a temporary typeName, it will be overwritten by
+                    // the schema reader with the metadata found in the
+                    // customTypes hash
+                    "typeName": node.getAttribute("name")
+                };
+                this.readChildNodes(node, complexType);
+                obj.complexTypes.push(complexType);
+            },
+            "complexContent": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "extension": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "sequence": function(node, obj) {
+                var sequence = {
+                    elements: []
+                };
+                this.readChildNodes(node, sequence);
+                obj.properties = sequence.elements;
+            },
+            "element": function(node, obj) {
+                if(obj.elements) {
+                    var element = {};
+                    var attributes = node.attributes;
+                    var attr;
+                    for(var i=0, len=attributes.length; i<len; ++i) {
+                        attr = attributes[i];
+                        element[attr.name] = attr.value;
+                    }
+                    
+                    var type = element.type;
+                    if(!type) {
+                        type = {};
+                        this.readChildNodes(node, type);
+                        element.restriction = type;
+                        element.type = type.base;
+                    }
+                    var fullType = type.base || type;
+                    element.localType = fullType.split(":").pop();
+                    obj.elements.push(element);
+                }
+                
+                if(obj.complexTypes) {
+                    var type = node.getAttribute("type");
+                    var localType = type.split(":").pop();
+                    obj.customTypes[localType] = {
+                        "name": node.getAttribute("name"),
+                        "type": type
+                    };
+                }
+            },
+            "simpleType": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "restriction": function(node, obj) {
+                obj.base = node.getAttribute("base");
+                this.readRestriction(node, obj);
+            }
+        }
+    },
+    
+    /**
+     * Method: readRestriction
+     * Reads restriction defined in the child nodes of a restriction element
+     * 
+     * Parameters:
+     * node {DOMElement} - the node to parse
+     * obj {Object} - the object that receives the read result
+     */
+    readRestriction: function(node, obj) {
+        var children = node.childNodes;
+        var child, nodeName, value;
+        for(var i=0, len=children.length; i<len; ++i) {
+            child = children[i];
+            if(child.nodeType == 1) {
+                nodeName = child.nodeName.split(":").pop();
+                value = child.getAttribute("value");
+                if(!obj[nodeName]) {
+                    obj[nodeName] = value;
+                } else {
+                    if(typeof obj[nodeName] == "string") {
+                        obj[nodeName] = [obj[nodeName]];
+                    }
+                    obj[nodeName].push(value);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement|String} A WFS DescribeFeatureType document.
+     *
+     * Returns:
+     * {Object} An object representing the WFS DescribeFeatureType response.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var schema = {};
+        this.readNode(data, schema);
+        
+        return schema;
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WFSDescribeFeatureType" 
+
+});
+/* ======================================================================
+    OpenLayers/Renderer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer 
+ * This is the base class for all renderers.
+ *
+ * This is based on a merger code written by Paul Spencer and Bertil Chapuis.
+ * It is largely composed of virtual functions that are to be implemented
+ * in technology-specific subclasses, but there is some generic code too.
+ * 
+ * The functions that *are* implemented here merely deal with the maintenance
+ *  of the size and extent variables, as well as the cached 'resolution' 
+ *  value. 
+ * 
+ * A note to the user that all subclasses should use getResolution() instead
+ *  of directly accessing this.resolution in order to correctly use the 
+ *  cacheing system.
+ *
+ */
+OpenLayers.Renderer = OpenLayers.Class({
+
+    /** 
+     * Property: container
+     * {DOMElement} 
+     */
+    container: null,
+    
+    /**
+     * Property: root
+     * {DOMElement}
+     */
+    root: null,
+
+    /** 
+     * Property: extent
+     * {<OpenLayers.Bounds>}
+     */
+    extent: null,
+
+    /**
+     * Property: locked
+     * {Boolean} If the renderer is currently in a state where many things
+     *     are changing, the 'locked' property is set to true. This means 
+     *     that renderers can expect at least one more drawFeature event to be
+     *     called with the 'locked' property set to 'true': In some renderers,
+     *     this might make sense to use as a 'only update local information'
+     *     flag. 
+     */  
+    locked: false,
+    
+    /** 
+     * Property: size
+     * {<OpenLayers.Size>} 
+     */
+    size: null,
+    
+    /**
+     * Property: resolution
+     * {Float} cache of current map resolution
+     */
+    resolution: null,
+    
+    /**
+     * Property: map  
+     * {<OpenLayers.Map>} Reference to the map -- this is set in Vector's setMap()
+     */
+    map: null,
+    
+    /**
+     * Constructor: OpenLayers.Renderer 
+     *
+     * Parameters:
+     * containerID - {<String>} 
+     * options - {Object} options for this renderer. See sublcasses for
+     *     supported options.
+     */
+    initialize: function(containerID, options) {
+        this.container = OpenLayers.Util.getElement(containerID);
+        OpenLayers.Util.extend(this, options);
+    },
+    
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.container = null;
+        this.extent = null;
+        this.size =  null;
+        this.resolution = null;
+        this.map = null;
+    },
+
+    /**
+     * APIMethod: supported
+     * This should be overridden by specific subclasses
+     * 
+     * Returns:
+     * {Boolean} Whether or not the browser supports the renderer class
+     */
+    supported: function() {
+        return false;
+    },    
+    
+    /**
+     * Method: setExtent
+     * Set the visible part of the layer.
+     *
+     * Resolution has probably changed, so we nullify the resolution 
+     * cache (this.resolution) -- this way it will be re-computed when 
+     * next it is needed.
+     * We nullify the resolution cache (this.resolution) if resolutionChanged
+     * is set to true - this way it will be re-computed on the next
+     * getResolution() request.
+     *
+     * Parameters:
+     * extent - {<OpenLayers.Bounds>}
+     * resolutionChanged - {Boolean}
+     */
+    setExtent: function(extent, resolutionChanged) {
+        this.extent = extent.clone();
+        if (resolutionChanged) {
+            this.resolution = null;
+        }
+    },
+    
+    /**
+     * Method: setSize
+     * Sets the size of the drawing surface.
+     * 
+     * Resolution has probably changed, so we nullify the resolution 
+     * cache (this.resolution) -- this way it will be re-computed when 
+     * next it is needed.
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} 
+     */
+    setSize: function(size) {
+        this.size = size.clone();
+        this.resolution = null;
+    },
+    
+    /** 
+     * Method: getResolution
+     * Uses cached copy of resolution if available to minimize computing
+     * 
+     * Returns:
+     * The current map's resolution
+     */
+    getResolution: function() {
+        this.resolution = this.resolution || this.map.getResolution();
+        return this.resolution;
+    },
+    
+    /**
+     * Method: drawFeature
+     * Draw the feature.  The optional style argument can be used
+     * to override the feature's own style.  This method should only
+     * be called from layer.drawFeature().
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     * style - {<Object>}
+     * 
+     * Returns:
+     * {Boolean} true if the feature has been drawn completely, false if not,
+     *     undefined if the feature had no geometry
+     */
+    drawFeature: function(feature, style) {
+        if(style == null) {
+            style = feature.style;
+        }
+        if (feature.geometry) {
+            var bounds = feature.geometry.getBounds();
+            if(bounds) {
+                if (!bounds.intersectsBounds(this.extent)) {
+                    style = {display: "none"};
+                }
+                var rendered = this.drawGeometry(feature.geometry, style, feature.id);
+                if(style.display != "none" && style.label && rendered !== false) {
+                    var location = feature.geometry.getCentroid(); 
+                    if(style.labelXOffset || style.labelYOffset) {
+                        var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset;
+                        var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset;
+                        var res = this.getResolution();
+                        location.move(xOffset*res, yOffset*res);
+                    }
+                    this.drawText(feature.id, style, location);
+                } else {
+                    this.removeText(feature.id);
+                }
+                return rendered;
+            }
+        }
+    },
+
+
+    /** 
+     * Method: drawGeometry
+     * 
+     * Draw a geometry.  This should only be called from the renderer itself.
+     * Use layer.drawFeature() from outside the renderer.
+     * virtual function
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} 
+     * style - {Object} 
+     * featureId - {<String>} 
+     */
+    drawGeometry: function(geometry, style, featureId) {},
+        
+    /**
+     * Method: drawText
+     * Function for drawing text labels.
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * featureId - {String}
+     * style -
+     * location - {<OpenLayers.Geometry.Point>}
+     */
+    drawText: function(featureId, style, location) {},
+
+    /**
+     * Method: removeText
+     * Function for removing text labels.
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * featureId - {String}
+     */
+    removeText: function(featureId) {},
+    
+    /**
+     * Method: clear
+     * Clear all vectors from the renderer.
+     * virtual function.
+     */    
+    clear: function() {},
+
+    /**
+     * Method: getFeatureIdFromEvent
+     * Returns a feature id from an event on the renderer.  
+     * How this happens is specific to the renderer.  This should be
+     * called from layer.getFeatureFromEvent().
+     * Virtual function.
+     * 
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     *
+     * Returns:
+     * {String} A feature id or null.
+     */
+    getFeatureIdFromEvent: function(evt) {},
+    
+    /**
+     * Method: eraseFeatures 
+     * This is called by the layer to erase features
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    eraseFeatures: function(features) {
+        if(!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        for(var i=0, len=features.length; i<len; ++i) {
+            var feature = features[i];
+            this.eraseGeometry(feature.geometry, feature.id);
+            this.removeText(feature.id);
+        }
+    },
+    
+    /**
+     * Method: eraseGeometry
+     * Remove a geometry from the renderer (by id).
+     * virtual function.
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} 
+     * featureId - {String}
+     */
+    eraseGeometry: function(geometry, featureId) {},
+    
+    /**
+     * Method: moveRoot
+     * moves this renderer's root to a (different) renderer.
+     * To be implemented by subclasses that require a common renderer root for
+     * feature selection.
+     * 
+     * Parameters:
+     * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
+     */
+    moveRoot: function(renderer) {},
+
+    /**
+     * Method: getRenderLayerId
+     * Gets the layer that this renderer's output appears on. If moveRoot was
+     * used, this will be different from the id of the layer containing the
+     * features rendered by this renderer.
+     * 
+     * Returns:
+     * {String} the id of the output layer.
+     */
+    getRenderLayerId: function() {
+        return this.container.id;
+    },
+    
+    /**
+     * Method: applyDefaultSymbolizer
+     * 
+     * Parameters:
+     * symbolizer - {Object}
+     * 
+     * Returns:
+     * {Object}
+     */
+    applyDefaultSymbolizer: function(symbolizer) {
+        var result = OpenLayers.Util.extend({},
+            OpenLayers.Renderer.defaultSymbolizer);
+        if(symbolizer.stroke === false) {
+            delete result.strokeWidth;
+            delete result.strokeColor;
+        }
+        if(symbolizer.fill === false) {
+            delete result.fillColor;
+        }
+        OpenLayers.Util.extend(result, symbolizer);
+        return result;
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer"
+});
+
+/**
+ * Constant: OpenLayers.Renderer.defaultSymbolizer
+ * {Object} Properties from this symbolizer will be applied to symbolizers
+ *     with missing properties. This can also be used to set a global
+ *     symbolizer default in OpenLayers. To be SLD 1.x compliant, add the
+ *     following code before rendering any vector features:
+ * (code)
+ * OpenLayers.Renderer.defaultSymbolizer = {
+ *     fillColor: "#808080",
+ *     fillOpacity: 1,
+ *     strokeColor: "#000000",
+ *     strokeOpacity: 1,
+ *     strokeWidth: 1,
+ *     pointRadius: 3,
+ *     graphicName: "square"
+ * };
+ * (end)
+ */
+OpenLayers.Renderer.defaultSymbolizer = {
+    fillColor: "#000000",
+    strokeColor: "#000000",
+    strokeWidth: 2,
+    fillOpacity: 1,
+    strokeOpacity: 1,
+    pointRadius: 0
+};
+    
+/* ======================================================================
+    OpenLayers/Renderer/Canvas.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer.Canvas 
+ * A renderer based on the 2D 'canvas' drawing element.
+ * 
+ * Inherits:
+ *  - <OpenLayers.Renderer>
+ */
+OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
+    
+    /**
+     * APIProperty: hitDetection
+     * {Boolean} Allow for hit detection of features.  Default is true.
+     */
+    hitDetection: true,
+    
+    /**
+     * Property: hitOverflow
+     * {Number} The method for converting feature identifiers to color values
+     *     supports 16777215 sequential values.  Two features cannot be 
+     *     predictably detected if their identifiers differ by more than this
+     *     value.  The hitOverflow allows for bigger numbers (but the 
+     *     difference in values is still limited).
+     */
+    hitOverflow: 0,
+
+    /**
+     * Property: canvas
+     * {Canvas} The canvas context object.
+     */
+    canvas: null, 
+    
+    /**
+     * Property: features
+     * {Object} Internal object of feature/style pairs for use in redrawing the layer.
+     */
+    features: null,
+    
+    /**
+     * Property: pendingRedraw
+     * {Boolean} The renderer needs a redraw call to render features added while
+     *     the renderer was locked.
+     */
+    pendingRedraw: false,
+    
+    /**
+     * Constructor: OpenLayers.Renderer.Canvas
+     *
+     * Parameters:
+     * containerID - {<String>}
+     * options - {Object} Optional properties to be set on the renderer.
+     */
+    initialize: function(containerID, options) {
+        OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
+        this.root = document.createElement("canvas");
+        this.container.appendChild(this.root);
+        this.canvas = this.root.getContext("2d");
+        this.features = {};
+        if (this.hitDetection) {
+            this.hitCanvas = document.createElement("canvas");
+            this.hitContext = this.hitCanvas.getContext("2d");
+        }
+    },
+    
+    /** 
+     * Method: eraseGeometry
+     * Erase a geometry from the renderer. Because the Canvas renderer has
+     *     'memory' of the features that it has drawn, we have to remove the
+     *     feature so it doesn't redraw.   
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * featureId - {String}
+     */
+    eraseGeometry: function(geometry, featureId) {
+        this.eraseFeatures(this.features[featureId][0]);
+    },
+
+    /**
+     * APIMethod: supported
+     * 
+     * Returns:
+     * {Boolean} Whether or not the browser supports the renderer class
+     */
+    supported: function() {
+        var canvas = document.createElement("canvas");
+        return !!canvas.getContext;
+    },    
+    
+    /**
+     * Method: setSize
+     * Sets the size of the drawing surface.
+     *
+     * Once the size is updated, redraw the canvas.
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} 
+     */
+    setSize: function(size) {
+        this.size = size.clone();
+        var root = this.root;
+        root.style.width = size.w + "px";
+        root.style.height = size.h + "px";
+        root.width = size.w;
+        root.height = size.h;
+        this.resolution = null;
+        if (this.hitDetection) {
+            var hitCanvas = this.hitCanvas;
+            hitCanvas.style.width = size.w + "px";
+            hitCanvas.style.height = size.h + "px";
+            hitCanvas.width = size.w;
+            hitCanvas.height = size.h;
+        }
+    },
+    
+    /**
+     * Method: drawFeature
+     * Draw the feature. Stores the feature in the features list,
+     * then redraws the layer. 
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     * style - {<Object>} 
+     *
+     * Returns:
+     * {Boolean} The feature has been drawn completely.  If the feature has no
+     *     geometry, undefined will be returned.  If the feature is not rendered
+     *     for other reasons, false will be returned.
+     */
+    drawFeature: function(feature, style) {
+        var rendered;
+        if (feature.geometry) {
+            style = this.applyDefaultSymbolizer(style || feature.style);
+            // don't render if display none or feature outside extent
+            var bounds = feature.geometry.getBounds();
+            rendered = (style.display !== "none") && !!bounds && 
+                bounds.intersectsBounds(this.extent);
+            if (rendered) {
+                // keep track of what we have rendered for redraw
+                this.features[feature.id] = [feature, style];
+            }
+            else {
+                // remove from features tracked for redraw
+                delete(this.features[feature.id]);
+            }
+            this.pendingRedraw = true;
+        }
+        if (this.pendingRedraw && !this.locked) {
+            this.redraw();
+            this.pendingRedraw = false;
+        }
+        return rendered;
+    },
+
+    /** 
+     * Method: drawGeometry
+     * Used when looping (in redraw) over the features; draws
+     * the canvas. 
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} 
+     * style - {Object} 
+     */
+    drawGeometry: function(geometry, style, featureId) {
+        var className = geometry.CLASS_NAME;
+        if ((className == "OpenLayers.Geometry.Collection") ||
+            (className == "OpenLayers.Geometry.MultiPoint") ||
+            (className == "OpenLayers.Geometry.MultiLineString") ||
+            (className == "OpenLayers.Geometry.MultiPolygon")) {
+            for (var i = 0; i < geometry.components.length; i++) {
+                this.drawGeometry(geometry.components[i], style, featureId);
+            }
+            return;
+        }
+        switch (geometry.CLASS_NAME) {
+            case "OpenLayers.Geometry.Point":
+                this.drawPoint(geometry, style, featureId);
+                break;
+            case "OpenLayers.Geometry.LineString":
+                this.drawLineString(geometry, style, featureId);
+                break;
+            case "OpenLayers.Geometry.LinearRing":
+                this.drawLinearRing(geometry, style, featureId);
+                break;
+            case "OpenLayers.Geometry.Polygon":
+                this.drawPolygon(geometry, style, featureId);
+                break;
+            default:
+                break;
+        }
+    },
+
+    /**
+     * Method: drawExternalGraphic
+     * Called to draw External graphics. 
+     * 
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>}
+     * style    - {Object}
+     * featureId - {String}
+     */ 
+    drawExternalGraphic: function(geometry, style, featureId) {
+        var img = new Image();
+
+        if (style.graphicTitle) {
+            img.title = style.graphicTitle;           
+        }
+
+        var width = style.graphicWidth || style.graphicHeight;
+        var height = style.graphicHeight || style.graphicWidth;
+        width = width ? width : style.pointRadius * 2;
+        height = height ? height : style.pointRadius * 2;
+        var xOffset = (style.graphicXOffset != undefined) ?
+           style.graphicXOffset : -(0.5 * width);
+        var yOffset = (style.graphicYOffset != undefined) ?
+           style.graphicYOffset : -(0.5 * height);
+
+        var opacity = style.graphicOpacity || style.fillOpacity;
+        
+        var onLoad = function() {
+            if(!this.features[featureId]) {
+                return;
+            }
+            var pt = this.getLocalXY(geometry);
+            var p0 = pt[0];
+            var p1 = pt[1];
+            if(!isNaN(p0) && !isNaN(p1)) {
+                var x = (p0 + xOffset) | 0;
+                var y = (p1 + yOffset) | 0;
+                var canvas = this.canvas;
+                canvas.globalAlpha = opacity;
+                var factor = OpenLayers.Renderer.Canvas.drawImageScaleFactor ||
+                    (OpenLayers.Renderer.Canvas.drawImageScaleFactor =
+                        /android 2.1/.test(navigator.userAgent.toLowerCase()) ?
+                            // 320 is the screen width of the G1 phone, for
+                            // which drawImage works out of the box.
+                            320 / window.screen.width : 1
+                    );
+                canvas.drawImage(
+                    img, x*factor, y*factor, width*factor, height*factor
+                );
+                if (this.hitDetection) {
+                    this.setHitContextStyle("fill", featureId);
+                    this.hitContext.fillRect(x, y, width, height);
+                }
+            }
+        };
+
+        img.onload = OpenLayers.Function.bind(onLoad, this);
+        img.src = style.externalGraphic;
+    },
+
+    /**
+     * Method: setCanvasStyle
+     * Prepare the canvas for drawing by setting various global settings.
+     *
+     * Parameters:
+     * type - {String} one of 'stroke', 'fill', or 'reset'
+     * style - {Object} Symbolizer hash
+     */
+    setCanvasStyle: function(type, style) {
+        if (type === "fill") {     
+            this.canvas.globalAlpha = style['fillOpacity'];
+            this.canvas.fillStyle = style['fillColor'];
+        } else if (type === "stroke") {  
+            this.canvas.globalAlpha = style['strokeOpacity'];
+            this.canvas.strokeStyle = style['strokeColor'];
+            this.canvas.lineWidth = style['strokeWidth'];
+        } else {
+            this.canvas.globalAlpha = 0;
+            this.canvas.lineWidth = 1;
+        }
+    },
+    
+    /**
+     * Method: featureIdToHex
+     * Convert a feature ID string into an RGB hex string.
+     *
+     * Parameters:
+     * featureId - {String} Feature id
+     *
+     * Returns:
+     * {String} RGB hex string.
+     */
+    featureIdToHex: function(featureId) {
+        var id = Number(featureId.split("_").pop()) + 1; // zero for no feature
+        if (id >= 16777216) {
+            this.hitOverflow = id - 16777215;
+            id = id % 16777216 + 1;
+        }
+        var hex = "000000" + id.toString(16);
+        var len = hex.length;
+        hex = "#" + hex.substring(len-6, len);
+        return hex;
+    },
+    
+    /**
+     * Method: setHitContextStyle
+     * Prepare the hit canvas for drawing by setting various global settings.
+     *
+     * Parameters:
+     * type - {String} one of 'stroke', 'fill', or 'reset'
+     * featureId - {String} The feature id.
+     * symbolizer - {<OpenLayers.Symbolizer>} The symbolizer.
+     */
+    setHitContextStyle: function(type, featureId, symbolizer) {
+        var hex = this.featureIdToHex(featureId);
+        if (type == "fill") {
+            this.hitContext.globalAlpha = 1.0;
+            this.hitContext.fillStyle = hex;
+        } else if (type == "stroke") {  
+            this.hitContext.globalAlpha = 1.0;
+            this.hitContext.strokeStyle = hex;
+            // bump up stroke width to deal with antialiasing
+            this.hitContext.lineWidth = symbolizer.strokeWidth + 2;
+        } else {
+            this.hitContext.globalAlpha = 0;
+            this.hitContext.lineWidth = 1;
+        }
+    },
+
+    /**
+     * Method: drawPoint
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>}
+     * style    - {Object}
+     * featureId - {String}
+     */ 
+    drawPoint: function(geometry, style, featureId) {
+        if(style.graphic !== false) {
+            if(style.externalGraphic) {
+                this.drawExternalGraphic(geometry, style, featureId);
+            } else {
+                var pt = this.getLocalXY(geometry);
+                var p0 = pt[0];
+                var p1 = pt[1];
+                if(!isNaN(p0) && !isNaN(p1)) {
+                    var twoPi = Math.PI*2;
+                    var radius = style.pointRadius;
+                    if(style.fill !== false) {
+                        this.setCanvasStyle("fill", style);
+                        this.canvas.beginPath();
+                        this.canvas.arc(p0, p1, radius, 0, twoPi, true);
+                        this.canvas.fill();
+                        if (this.hitDetection) {
+                            this.setHitContextStyle("fill", featureId, style);
+                            this.hitContext.beginPath();
+                            this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
+                            this.hitContext.fill();
+                        }
+                    }
+
+                    if(style.stroke !== false) {
+                        this.setCanvasStyle("stroke", style);
+                        this.canvas.beginPath();
+                        this.canvas.arc(p0, p1, radius, 0, twoPi, true);
+                        this.canvas.stroke();
+                        if (this.hitDetection) {
+                            this.setHitContextStyle("stroke", featureId, style);
+                            this.hitContext.beginPath();
+                            this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
+                            this.hitContext.stroke();
+                        }
+                        this.setCanvasStyle("reset");
+                    }
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: drawLineString
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>}
+     * style    - {Object}
+     * featureId - {String}
+     */ 
+    drawLineString: function(geometry, style, featureId) {
+        style = OpenLayers.Util.applyDefaults({fill: false}, style);
+        this.drawLinearRing(geometry, style, featureId);
+    },    
+    
+    /**
+     * Method: drawLinearRing
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>}
+     * style    - {Object}
+     * featureId - {String}
+     */ 
+    drawLinearRing: function(geometry, style, featureId) {
+        if (style.fill !== false) {
+            this.setCanvasStyle("fill", style);
+            this.renderPath(this.canvas, geometry, style, featureId, "fill");
+            if (this.hitDetection) {
+                this.setHitContextStyle("fill", featureId, style);
+                this.renderPath(this.hitContext, geometry, style, featureId, "fill");
+            }
+        }
+        if (style.stroke !== false) {
+            this.setCanvasStyle("stroke", style);
+            this.renderPath(this.canvas, geometry, style, featureId, "stroke");
+            if (this.hitDetection) {
+                this.setHitContextStyle("stroke", featureId, style);
+                this.renderPath(this.hitContext, geometry, style, featureId, "stroke");
+            }
+        }
+        this.setCanvasStyle("reset");
+    },
+    
+    /**
+     * Method: renderPath
+     * Render a path with stroke and optional fill.
+     */
+    renderPath: function(context, geometry, style, featureId, type) {
+        var components = geometry.components;
+        var len = components.length;
+        context.beginPath();
+        var start = this.getLocalXY(components[0]);
+        var x = start[0];
+        var y = start[1];
+        if (!isNaN(x) && !isNaN(y)) {
+            context.moveTo(start[0], start[1]);
+            for (var i=1; i<len; ++i) {
+                var pt = this.getLocalXY(components[i]);
+                context.lineTo(pt[0], pt[1]);
+            }
+            if (type === "fill") {
+                context.fill();
+            } else {
+                context.stroke();
+            }
+        }
+    },
+    
+    /**
+     * Method: drawPolygon
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * geometry - {<OpenLayers.Geometry>}
+     * style    - {Object}
+     * featureId - {String}
+     */ 
+    drawPolygon: function(geometry, style, featureId) {
+        var components = geometry.components;
+        var len = components.length;
+        this.drawLinearRing(components[0], style, featureId);
+        // erase inner rings
+        for (var i=1; i<len; ++i) {
+            /** 
+             * Note that this is overly agressive.  Here we punch holes through 
+             * all previously rendered features on the same canvas.  A better 
+             * solution for polygons with interior rings would be to draw the 
+             * polygon on a sketch canvas first.  We could erase all holes 
+             * there and then copy the drawing to the layer canvas. 
+             * TODO: http://trac.osgeo.org/openlayers/ticket/3130 
+             */
+            this.canvas.globalCompositeOperation = "destination-out";
+            if (this.hitDetection) {
+                this.hitContext.globalCompositeOperation = "destination-out";
+            }
+            this.drawLinearRing(
+                components[i], 
+                OpenLayers.Util.applyDefaults({stroke: false, fillOpacity: 1.0}, style),
+                featureId
+            );
+            this.canvas.globalCompositeOperation = "source-over";
+            if (this.hitDetection) {
+                this.hitContext.globalCompositeOperation = "source-over";
+            }
+            this.drawLinearRing(
+                components[i], 
+                OpenLayers.Util.applyDefaults({fill: false}, style),
+                featureId
+            );
+        }
+    },
+    
+    /**
+     * Method: drawText
+     * This method is only called by the renderer itself.
+     *
+     * Parameters:
+     * location - {<OpenLayers.Point>}
+     * style    - {Object}
+     */
+    drawText: function(location, style) {
+        style = OpenLayers.Util.extend({
+            fontColor: "#000000",
+            labelAlign: "cm"
+        }, style);
+        var pt = this.getLocalXY(location);
+
+        this.setCanvasStyle("reset");
+        this.canvas.fillStyle = style.fontColor;
+        this.canvas.globalAlpha = style.fontOpacity || 1.0;
+        var fontStyle = [style.fontStyle ? style.fontStyle : "normal",
+                         "normal", // "font-variant" not supported
+                         style.fontWeight ? style.fontWeight : "normal",
+                         style.fontSize ? style.fontSize : "1em",
+                         style.fontFamily ? style.fontFamily : "sans-serif"].join(" ");
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
+        if (this.canvas.fillText) {
+            // HTML5
+            this.canvas.font = fontStyle;
+            this.canvas.textAlign =
+                OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] ||
+                "center";
+            this.canvas.textBaseline =
+                OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]] ||
+                "middle";
+            var vfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
+            if (vfactor == null) {
+                vfactor = -.5;
+            }
+            var lineHeight =
+                this.canvas.measureText('Mg').height ||
+                this.canvas.measureText('xx').width;
+            pt[1] += lineHeight*vfactor*(numRows-1);
+            for (var i = 0; i < numRows; i++) {
+                this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i));
+            }
+        } else if (this.canvas.mozDrawText) {
+            // Mozilla pre-Gecko1.9.1 (<FF3.1)
+            this.canvas.mozTextStyle = fontStyle;
+            // No built-in text alignment, so we measure and adjust the position
+            var hfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]];
+            if (hfactor == null) {
+                hfactor = -.5;
+            }
+            var vfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
+            if (vfactor == null) {
+                vfactor = -.5;
+            }
+            var lineHeight = this.canvas.mozMeasureText('xx');
+            pt[1] += lineHeight*(1 + (vfactor*numRows));
+            for (var i = 0; i < numRows; i++) {
+                var x = pt[0] + (hfactor*this.canvas.mozMeasureText(labelRows[i]));
+                var y = pt[1] + (i*lineHeight);
+                this.canvas.translate(x, y);
+                this.canvas.mozDrawText(labelRows[i]);
+                this.canvas.translate(-x, -y);
+            }
+        }
+        this.setCanvasStyle("reset");
+    },
+    
+    /**
+     * Method: getLocalXY
+     * transform geographic xy into pixel xy
+     *
+     * Parameters: 
+     * point - {<OpenLayers.Geometry.Point>}
+     */
+    getLocalXY: function(point) {
+        var resolution = this.getResolution();
+        var extent = this.extent;
+        var x = (point.x / resolution + (-extent.left / resolution));
+        var y = ((extent.top / resolution) - point.y / resolution);
+        return [x, y];
+    },
+
+    /**
+     * Method: clear
+     * Clear all vectors from the renderer.
+     */    
+    clear: function() {
+        var height = this.root.height;
+        var width = this.root.width;
+        this.canvas.clearRect(0, 0, width, height);
+        this.features = {};
+        if (this.hitDetection) {
+            this.hitContext.clearRect(0, 0, width, height);
+        }
+    },
+
+    /**
+     * Method: getFeatureIdFromEvent
+     * Returns a feature id from an event on the renderer.  
+     * 
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector} A feature or null.  This method returns a 
+     *     feature instead of a feature id to avoid an unnecessary lookup on the
+     *     layer.
+     */
+    getFeatureIdFromEvent: function(evt) {
+        var feature = null;
+        if (this.hitDetection) {
+            // this dragging check should go in the feature handler
+            if (!this.map.dragging) {
+                var xy = evt.xy;
+                var x = xy.x | 0;
+                var y = xy.y | 0;
+                var data = this.hitContext.getImageData(x, y, 1, 1).data;
+                if (data[3] === 255) { // antialiased
+                    var id = data[2] + (256 * (data[1] + (256 * data[0])));
+                    if (id) {
+                        feature = this.features["OpenLayers.Feature.Vector_" + (id - 1 + this.hitOverflow)][0];
+                    }
+                }
+            }
+        }
+        return feature;
+    },
+    
+    /**
+     * Method: eraseFeatures 
+     * This is called by the layer to erase features; removes the feature from
+     *     the list, then redraws the layer.
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    eraseFeatures: function(features) {
+        if(!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        for(var i=0; i<features.length; ++i) {
+            delete this.features[features[i].id];
+        }
+        this.redraw();
+    },
+
+    /**
+     * Method: redraw
+     * The real 'meat' of the function: any time things have changed,
+     *     redraw() can be called to loop over all the data and (you guessed
+     *     it) redraw it.  Unlike Elements-based Renderers, we can't interact
+     *     with things once they're drawn, to remove them, for example, so
+     *     instead we have to just clear everything and draw from scratch.
+     */
+    redraw: function() {
+        if (!this.locked) {
+            var height = this.root.height;
+            var width = this.root.width;
+            this.canvas.clearRect(0, 0, width, height);
+            if (this.hitDetection) {
+                this.hitContext.clearRect(0, 0, width, height);
+            }
+            var labelMap = [];
+            var feature, style;
+            for (var id in this.features) {
+                if (!this.features.hasOwnProperty(id)) { continue; }
+                feature = this.features[id][0];
+                style = this.features[id][1];
+                this.drawGeometry(feature.geometry, style, feature.id);
+                if(style.label) {
+                    labelMap.push([feature, style]);
+                }
+            }
+            var item;
+            for (var i=0, len=labelMap.length; i<len; ++i) {
+                item = labelMap[i];
+                this.drawText(item[0].geometry.getCentroid(), item[1]);
+            }
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer.Canvas"
+});
+
+/**
+ * Constant: OpenLayers.Renderer.Canvas.LABEL_ALIGN
+ * {Object}
+ */
+OpenLayers.Renderer.Canvas.LABEL_ALIGN = {
+    "l": "left",
+    "r": "right",
+    "t": "top",
+    "b": "bottom"
+};
+
+/**
+ * Constant: OpenLayers.Renderer.Canvas.LABEL_FACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.Canvas.LABEL_FACTOR = {
+    "l": 0,
+    "r": -1,
+    "t": 0,
+    "b": -1
+};
+
+/**
+ * Constant: OpenLayers.Renderer.Canvas.drawImageScaleFactor
+ * {Number} Scale factor to apply to the canvas drawImage arguments. This
+ *     is always 1 except for Android 2.1 devices, to work around
+ *     http://code.google.com/p/android/issues/detail?id=5141.
+ */
+OpenLayers.Renderer.Canvas.drawImageScaleFactor = null;
+/* ======================================================================
+    OpenLayers/Format/OSM.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**  
+ * Class: OpenLayers.Format.OSM
+ * OSM parser. Create a new instance with the 
+ *     <OpenLayers.Format.OSM> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OSM = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * APIProperty: checkTags
+     * {Boolean} Should tags be checked to determine whether something
+     * should be treated as a seperate node. Will slow down parsing.
+     * Default is false.
+     */
+    checkTags: false,
+
+    /**
+     * Property: interestingTagsExclude
+     * {Array} List of tags to exclude from 'interesting' checks on nodes.
+     * Must be set when creating the format. Will only be used if checkTags
+     * is set.
+     */
+    interestingTagsExclude: null, 
+    
+    /**
+     * APIProperty: areaTags
+     * {Array} List of tags indicating that something is an area.  
+     * Must be set when creating the format. Will only be used if 
+     * checkTags is true.
+     */
+    areaTags: null, 
+    
+    /**
+     * Constructor: OpenLayers.Format.OSM
+     * Create a new parser for OSM.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        var layer_defaults = {
+          'interestingTagsExclude': ['source', 'source_ref', 
+              'source:ref', 'history', 'attribution', 'created_by'],
+          'areaTags': ['area', 'building', 'leisure', 'tourism', 'ruins',
+              'historic', 'landuse', 'military', 'natural', 'sport'] 
+        };
+          
+        layer_defaults = OpenLayers.Util.extend(layer_defaults, options);
+        
+        var interesting = {};
+        for (var i = 0; i < layer_defaults.interestingTagsExclude.length; i++) {
+            interesting[layer_defaults.interestingTagsExclude[i]] = true;
+        }
+        layer_defaults.interestingTagsExclude = interesting;
+        
+        var area = {};
+        for (var i = 0; i < layer_defaults.areaTags.length; i++) {
+            area[layer_defaults.areaTags[i]] = true;
+        }
+        layer_defaults.areaTags = area;
+
+        // OSM coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+        
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [layer_defaults]);
+    },
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from a OSM doc
+     
+     * Parameters:
+     * data - {Element} 
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(doc) {
+        if (typeof doc == "string") { 
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+
+        var nodes = this.getNodes(doc);
+        var ways = this.getWays(doc);
+        
+        // Geoms will contain at least ways.length entries.
+        var feat_list = new Array(ways.length);
+        
+        for (var i = 0; i < ways.length; i++) {
+            // We know the minimal of this one ahead of time. (Could be -1
+            // due to areas/polygons)
+            var point_list = new Array(ways[i].nodes.length);
+            
+            var poly = this.isWayArea(ways[i]) ? 1 : 0; 
+            for (var j = 0; j < ways[i].nodes.length; j++) {
+               var node = nodes[ways[i].nodes[j]];
+               
+               var point = new OpenLayers.Geometry.Point(node.lon, node.lat);
+               
+               // Since OSM is topological, we stash the node ID internally. 
+               point.osm_id = parseInt(ways[i].nodes[j]);
+               point_list[j] = point;
+               
+               // We don't display nodes if they're used inside other 
+               // elements.
+               node.used = true; 
+            }
+            var geometry = null;
+            if (poly) { 
+                geometry = new OpenLayers.Geometry.Polygon(
+                    new OpenLayers.Geometry.LinearRing(point_list));
+            } else {    
+                geometry = new OpenLayers.Geometry.LineString(point_list);
+            }
+            if (this.internalProjection && this.externalProjection) {
+                geometry.transform(this.externalProjection, 
+                    this.internalProjection);
+            }        
+            var feat = new OpenLayers.Feature.Vector(geometry,
+                ways[i].tags);
+            feat.osm_id = parseInt(ways[i].id);
+            feat.fid = "way." + feat.osm_id;
+            feat_list[i] = feat;
+        } 
+        for (var node_id in nodes) {
+            var node = nodes[node_id];
+            if (!node.used || this.checkTags) {
+                var tags = null;
+                
+                if (this.checkTags) {
+                    var result = this.getTags(node.node, true);
+                    if (node.used && !result[1]) {
+                        continue;
+                    }
+                    tags = result[0];
+                } else { 
+                    tags = this.getTags(node.node);
+                }    
+                
+                var feat = new OpenLayers.Feature.Vector(
+                    new OpenLayers.Geometry.Point(node['lon'], node['lat']),
+                    tags);
+                if (this.internalProjection && this.externalProjection) {
+                    feat.geometry.transform(this.externalProjection, 
+                        this.internalProjection);
+                }        
+                feat.osm_id = parseInt(node_id); 
+                feat.fid = "node." + feat.osm_id;
+                feat_list.push(feat);
+            }   
+            // Memory cleanup
+            node.node = null;
+        }        
+        return feat_list;
+    },
+
+    /**
+     * Method: getNodes
+     * Return the node items from a doc.  
+     *
+     * Parameters:
+     * node - {DOMElement} node to parse tags from
+     */
+    getNodes: function(doc) {
+        var node_list = doc.getElementsByTagName("node");
+        var nodes = {};
+        for (var i = 0; i < node_list.length; i++) {
+            var node = node_list[i];
+            var id = node.getAttribute("id");
+            nodes[id] = {
+                'lat': node.getAttribute("lat"),
+                'lon': node.getAttribute("lon"),
+                'node': node
+            };
+        }
+        return nodes;
+    },
+
+    /**
+     * Method: getWays
+     * Return the way items from a doc.  
+     *
+     * Parameters:
+     * node - {DOMElement} node to parse tags from
+     */
+    getWays: function(doc) {
+        var way_list = doc.getElementsByTagName("way");
+        var return_ways = [];
+        for (var i = 0; i < way_list.length; i++) {
+            var way = way_list[i];
+            var way_object = {
+              id: way.getAttribute("id")
+            };
+            
+            way_object.tags = this.getTags(way);
+            
+            var node_list = way.getElementsByTagName("nd");
+            
+            way_object.nodes = new Array(node_list.length);
+            
+            for (var j = 0; j < node_list.length; j++) {
+                way_object.nodes[j] = node_list[j].getAttribute("ref");
+            }  
+            return_ways.push(way_object);
+        }
+        return return_ways; 
+        
+    },  
+    
+    /**
+     * Method: getTags
+     * Return the tags list attached to a specific DOM element.
+     *
+     * Parameters:
+     * node - {DOMElement} node to parse tags from
+     * interesting_tags - {Boolean} whether the return from this function should
+     *    return a boolean indicating that it has 'interesting tags' -- 
+     *    tags like attribution and source are ignored. (To change the list
+     *    of tags, see interestingTagsExclude)
+     * 
+     * Returns:
+     * tags - {Object} hash of tags
+     * interesting - {Boolean} if interesting_tags is passed, returns
+     *     whether there are any interesting tags on this element.
+     */
+    getTags: function(dom_node, interesting_tags) {
+        var tag_list = dom_node.getElementsByTagName("tag");
+        var tags = {};
+        var interesting = false;
+        for (var j = 0; j < tag_list.length; j++) {
+            var key = tag_list[j].getAttribute("k");
+            tags[key] = tag_list[j].getAttribute("v");
+            if (interesting_tags) {
+                if (!this.interestingTagsExclude[key]) {
+                    interesting = true;
+                }
+            }    
+        }  
+        return interesting_tags ? [tags, interesting] : tags;     
+    },
+
+    /** 
+     * Method: isWayArea
+     * Given a way object from getWays, check whether the tags and geometry
+     * indicate something is an area.
+     *
+     * Returns:
+     * {Boolean}
+     */
+    isWayArea: function(way) { 
+        var poly_shaped = false;
+        var poly_tags = false;
+        
+        if (way.nodes[0] == way.nodes[way.nodes.length - 1]) {
+            poly_shaped = true;
+        }
+        if (this.checkTags) {
+            for(var key in way.tags) {
+                if (this.areaTags[key]) {
+                    poly_tags = true;
+                    break;
+                }
+            }
+        }    
+        return poly_shaped && (this.checkTags ? poly_tags : true);            
+    }, 
+
+    /**
+     * APIMethod: write 
+     * Takes a list of features, returns a serialized OSM format file for use
+     * in tools like JOSM.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)}
+     */
+    write: function(features) { 
+        if (!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        
+        this.osm_id = 1;
+        this.created_nodes = {};
+        var root_node = this.createElementNS(null, "osm");
+        root_node.setAttribute("version", "0.5");
+        root_node.setAttribute("generator", "OpenLayers "+ OpenLayers.VERSION_NUMBER);
+
+        // Loop backwards, because the deserializer puts nodes last, and 
+        // we want them first if possible
+        for(var i = features.length - 1; i >= 0; i--) {
+            var nodes = this.createFeatureNodes(features[i]);
+            for (var j = 0; j < nodes.length; j++) {
+                root_node.appendChild(nodes[j]);
+            }    
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root_node]);
+    },
+
+    /**
+     * Method: createFeatureNodes
+     * Takes a feature, returns a list of nodes from size 0->n.
+     * Will include all pieces of the serialization that are required which
+     * have not already been created. Calls out to createXML based on geometry
+     * type.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    createFeatureNodes: function(feature) {
+        var nodes = [];
+        var className = feature.geometry.CLASS_NAME;
+        var type = className.substring(className.lastIndexOf(".") + 1);
+        type = type.toLowerCase();
+        var builder = this.createXML[type];
+        if (builder) {
+            nodes = builder.apply(this, [feature]);
+        }
+        return nodes;
+    },
+    
+    /**
+     * Method: createXML
+     * Takes a feature, returns a list of nodes from size 0->n.
+     * Will include all pieces of the serialization that are required which
+     * have not already been created.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    createXML: {
+        'point': function(point) {
+            var id = null;
+            var geometry = point.geometry ? point.geometry : point;
+            
+            if (this.internalProjection && this.externalProjection) {
+                geometry = geometry.clone();
+                geometry.transform(this.internalProjection, 
+                                   this.externalProjection);
+            }                       
+            
+            var already_exists = false; // We don't return anything if the node
+                                        // has already been created
+            if (point.osm_id) {
+                id = point.osm_id;
+                if (this.created_nodes[id]) {
+                    already_exists = true;
+                }    
+            } else {
+               id = -this.osm_id;
+               this.osm_id++; 
+            }
+            if (already_exists) {
+                node = this.created_nodes[id];
+            } else {    
+                var node = this.createElementNS(null, "node");
+            }
+            this.created_nodes[id] = node;
+            node.setAttribute("id", id);
+            node.setAttribute("lon", geometry.x); 
+            node.setAttribute("lat", geometry.y);
+            if (point.attributes) {
+                this.serializeTags(point, node);
+            }
+            this.setState(point, node);
+            return already_exists ? [] : [node];
+        }, 
+        linestring: function(feature) {
+            var id;
+            var nodes = [];
+            var geometry = feature.geometry;
+            if (feature.osm_id) {
+                id = feature.osm_id;
+            } else {
+                id = -this.osm_id;
+                this.osm_id++; 
+            }
+            var way = this.createElementNS(null, "way");
+            way.setAttribute("id", id);
+            for (var i = 0; i < geometry.components.length; i++) {
+                var node = this.createXML['point'].apply(this, [geometry.components[i]]);
+                if (node.length) {
+                    node = node[0];
+                    var node_ref = node.getAttribute("id");
+                    nodes.push(node);
+                } else {
+                    node_ref = geometry.components[i].osm_id;
+                    node = this.created_nodes[node_ref];
+                }
+                this.setState(feature, node);
+                var nd_dom = this.createElementNS(null, "nd");
+                nd_dom.setAttribute("ref", node_ref);
+                way.appendChild(nd_dom);
+            }
+            this.serializeTags(feature, way);
+            nodes.push(way);
+            
+            return nodes;
+        },
+        polygon: function(feature) {
+            var attrs = OpenLayers.Util.extend({'area':'yes'}, feature.attributes);
+            var feat = new OpenLayers.Feature.Vector(feature.geometry.components[0], attrs); 
+            feat.osm_id = feature.osm_id;
+            return this.createXML['linestring'].apply(this, [feat]);
+        }
+    },
+
+    /**
+     * Method: serializeTags
+     * Given a feature, serialize the attributes onto the given node.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * node - {DOMNode}
+     */
+    serializeTags: function(feature, node) {
+        for (var key in feature.attributes) {
+            var tag = this.createElementNS(null, "tag");
+            tag.setAttribute("k", key);
+            tag.setAttribute("v", feature.attributes[key]);
+            node.appendChild(tag);
+        }
+    },
+
+    /**
+     * Method: setState 
+     * OpenStreetMap has a convention that 'state' is stored for modification or deletion.
+     * This allows the file to be uploaded via JOSM or the bulk uploader tool.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * node - {DOMNode}
+     */
+    setState: function(feature, node) {
+        if (feature.state) {
+            var state = null;
+            switch(feature.state) {
+                case OpenLayers.State.UPDATE:
+                    state = "modify";
+                case OpenLayers.State.DELETE:
+                    state = "delete";
+            }
+            if (state) {
+                node.setAttribute("action", state);
+            }
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OSM" 
+});     
+/* ======================================================================
+    OpenLayers/Handler.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Events.js
+ */
+
+/**
+ * Class: OpenLayers.Handler
+ * Base class to construct a higher-level handler for event sequences.  All
+ *     handlers have activate and deactivate methods.  In addition, they have
+ *     methods named like browser events.  When a handler is activated, any
+ *     additional methods named like a browser event is registered as a
+ *     listener for the corresponding event.  When a handler is deactivated,
+ *     those same methods are unregistered as event listeners.
+ *
+ * Handlers also typically have a callbacks object with keys named like
+ *     the abstracted events or event sequences that they are in charge of
+ *     handling.  The controls that wrap handlers define the methods that
+ *     correspond to these abstract events - so instead of listening for
+ *     individual browser events, they only listen for the abstract events
+ *     defined by the handler.
+ *     
+ * Handlers are created by controls, which ultimately have the responsibility
+ *     of making changes to the the state of the application.  Handlers
+ *     themselves may make temporary changes, but in general are expected to
+ *     return the application in the same state that they found it.
+ */
+OpenLayers.Handler = OpenLayers.Class({
+
+    /**
+     * Property: id
+     * {String}
+     */
+    id: null,
+        
+    /**
+     * APIProperty: control
+     * {<OpenLayers.Control>}. The control that initialized this handler.  The
+     *     control is assumed to have a valid map property - that map is used
+     *     in the handler's own setMap method.
+     */
+    control: null,
+
+    /**
+     * Property: map
+     * {<OpenLayers.Map>}
+     */
+    map: null,
+
+    /**
+     * APIProperty: keyMask
+     * {Integer} Use bitwise operators and one or more of the OpenLayers.Handler
+     *     constants to construct a keyMask.  The keyMask is used by
+     *     <checkModifiers>.  If the keyMask matches the combination of keys
+     *     down on an event, checkModifiers returns true.
+     *
+     * Example:
+     * (code)
+     *     // handler only responds if the Shift key is down
+     *     handler.keyMask = OpenLayers.Handler.MOD_SHIFT;
+     *
+     *     // handler only responds if Ctrl-Shift is down
+     *     handler.keyMask = OpenLayers.Handler.MOD_SHIFT |
+     *                       OpenLayers.Handler.MOD_CTRL;
+     * (end)
+     */
+    keyMask: null,
+
+    /**
+     * Property: active
+     * {Boolean}
+     */
+    active: false,
+    
+    /**
+     * Property: evt
+     * {Event} This property references the last event handled by the handler.
+     *     Note that this property is not part of the stable API.  Use of the
+     *     evt property should be restricted to controls in the library
+     *     or other applications that are willing to update with changes to
+     *     the OpenLayers code.
+     */
+    evt: null,
+
+    /**
+     * Constructor: OpenLayers.Handler
+     * Construct a handler.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that initialized this
+     *     handler.  The control is assumed to have a valid map property; that
+     *     map is used in the handler's own setMap method.  If a map property
+     *     is present in the options argument it will be used instead.
+     * callbacks - {Object} An object whose properties correspond to abstracted
+     *     events or sequences of browser events.  The values for these
+     *     properties are functions defined by the control that get called by
+     *     the handler.
+     * options - {Object} An optional object whose properties will be set on
+     *     the handler.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Util.extend(this, options);
+        this.control = control;
+        this.callbacks = callbacks;
+
+        var map = this.map || control.map;
+        if (map) {
+            this.setMap(map); 
+        }
+        
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+    },
+    
+    /**
+     * Method: setMap
+     */
+    setMap: function (map) {
+        this.map = map;
+    },
+
+    /**
+     * Method: checkModifiers
+     * Check the keyMask on the handler.  If no <keyMask> is set, this always
+     *     returns true.  If a <keyMask> is set and it matches the combination
+     *     of keys down on an event, this returns true.
+     *
+     * Returns:
+     * {Boolean} The keyMask matches the keys down on an event.
+     */
+    checkModifiers: function (evt) {
+        if(this.keyMask == null) {
+            return true;
+        }
+        /* calculate the keyboard modifier mask for this event */
+        var keyModifiers =
+            (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) |
+            (evt.ctrlKey  ? OpenLayers.Handler.MOD_CTRL  : 0) |
+            (evt.altKey   ? OpenLayers.Handler.MOD_ALT   : 0);
+    
+        /* if it differs from the handler object's key mask,
+           bail out of the event handler */
+        return (keyModifiers == this.keyMask);
+    },
+
+    /**
+     * APIMethod: activate
+     * Turn on the handler.  Returns false if the handler was already active.
+     * 
+     * Returns: 
+     * {Boolean} The handler was activated.
+     */
+    activate: function() {
+        if(this.active) {
+            return false;
+        }
+        // register for event handlers defined on this class.
+        var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
+        for (var i=0, len=events.length; i<len; i++) {
+            if (this[events[i]]) {
+                this.register(events[i], this[events[i]]); 
+            }
+        } 
+        this.active = true;
+        return true;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Turn off the handler.  Returns false if the handler was already inactive.
+     * 
+     * Returns:
+     * {Boolean} The handler was deactivated.
+     */
+    deactivate: function() {
+        if(!this.active) {
+            return false;
+        }
+        // unregister event handlers defined on this class.
+        var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
+        for (var i=0, len=events.length; i<len; i++) {
+            if (this[events[i]]) {
+                this.unregister(events[i], this[events[i]]); 
+            }
+        } 
+        this.active = false;
+        return true;
+    },
+
+    /**
+    * Method: callback
+    * Trigger the control's named callback with the given arguments
+    *
+    * Parameters:
+    * name - {String} The key for the callback that is one of the properties
+    *     of the handler's callbacks object.
+    * args - {Array(*)} An array of arguments (any type) with which to call 
+    *     the callback (defined by the control).
+    */
+    callback: function (name, args) {
+        if (name && this.callbacks[name]) {
+            this.callbacks[name].apply(this.control, args);
+        }
+    },
+
+    /**
+    * Method: register
+    * register an event on the map
+    */
+    register: function (name, method) {
+        // TODO: deal with registerPriority in 3.0
+        this.map.events.registerPriority(name, this, method);
+        this.map.events.registerPriority(name, this, this.setEvent);
+    },
+
+    /**
+    * Method: unregister
+    * unregister an event from the map
+    */
+    unregister: function (name, method) {
+        this.map.events.unregister(name, this, method);   
+        this.map.events.unregister(name, this, this.setEvent);
+    },
+    
+    /**
+     * Method: setEvent
+     * With each registered browser event, the handler sets its own evt
+     *     property.  This property can be accessed by controls if needed
+     *     to get more information about the event that the handler is
+     *     processing.
+     *
+     * This allows modifier keys on the event to be checked (alt, shift,
+     *     and ctrl cannot be checked with the keyboard handler).  For a
+     *     control to determine which modifier keys are associated with the
+     *     event that a handler is currently processing, it should access
+     *     (code)handler.evt.altKey || handler.evt.shiftKey ||
+     *     handler.evt.ctrlKey(end).
+     *
+     * Parameters:
+     * evt - {Event} The browser event.
+     */
+    setEvent: function(evt) {
+        this.evt = evt;
+        return true;
+    },
+
+    /**
+     * Method: destroy
+     * Deconstruct the handler.
+     */
+    destroy: function () {
+        // unregister event listeners
+        this.deactivate();
+        // eliminate circular references
+        this.control = this.map = null;        
+    },
+
+    CLASS_NAME: "OpenLayers.Handler"
+});
+
+/**
+ * Constant: OpenLayers.Handler.MOD_NONE
+ * If set as the <keyMask>, <checkModifiers> returns false if any key is down.
+ */
+OpenLayers.Handler.MOD_NONE  = 0;
+
+/**
+ * Constant: OpenLayers.Handler.MOD_SHIFT
+ * If set as the <keyMask>, <checkModifiers> returns false if Shift is down.
+ */
+OpenLayers.Handler.MOD_SHIFT = 1;
+
+/**
+ * Constant: OpenLayers.Handler.MOD_CTRL
+ * If set as the <keyMask>, <checkModifiers> returns false if Ctrl is down.
+ */
+OpenLayers.Handler.MOD_CTRL  = 2;
+
+/**
+ * Constant: OpenLayers.Handler.MOD_ALT
+ * If set as the <keyMask>, <checkModifiers> returns false if Alt is down.
+ */
+OpenLayers.Handler.MOD_ALT   = 4;
+
+
+/* ======================================================================
+    OpenLayers/Handler/Drag.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Drag
+ * The drag handler is used to deal with sequences of browser events related
+ *     to dragging.  The handler is used by controls that want to know when
+ *     a drag sequence begins, when a drag is happening, and when it has
+ *     finished.
+ *
+ * Controls that use the drag handler typically construct it with callbacks
+ *     for 'down', 'move', and 'done'.  Callbacks for these keys are called
+ *     when the drag begins, with each move, and when the drag is done.  In
+ *     addition, controls can have callbacks keyed to 'up' and 'out' if they
+ *     care to differentiate between the types of events that correspond with
+ *     the end of a drag sequence.  If no drag actually occurs (no mouse move)
+ *     the 'down' and 'up' callbacks will be called, but not the 'done'
+ *     callback.
+ *
+ * Create a new drag handler with the <OpenLayers.Handler.Drag> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
+  
+    /** 
+     * Property: started
+     * {Boolean} When a mousedown or touchstart event is received, we want to
+     * record it, but not set 'dragging' until the mouse moves after starting.
+     */
+    started: false,
+
+    /**
+     * Property: stopDown
+     * {Boolean} Stop propagation of mousedown events from getting to listeners
+     *     on the same element.  Default is true.
+     */
+    stopDown: true,
+
+    /** 
+     * Property: dragging 
+     * {Boolean} 
+     */
+    dragging: false,
+
+    /**
+     * Property: touch
+     * {Boolean} When a touchstart event is fired, touch will be true and all
+     *     mouse related listeners will do nothing.
+     */
+    touch: false,
+
+    /** 
+     * Property: last
+     * {<OpenLayers.Pixel>} The last pixel location of the drag.
+     */
+    last: null,
+
+    /** 
+     * Property: start
+     * {<OpenLayers.Pixel>} The first pixel location of the drag.
+     */
+    start: null,
+
+    /**
+     * Property: lastMoveEvt
+     * {Object} The last mousemove event that occurred. Used to
+     *     position the map correctly when our "delay drag"
+     *     timeout expired.
+     */
+    lastMoveEvt: null,
+
+    /**
+     * Property: oldOnselectstart
+     * {Function}
+     */
+    oldOnselectstart: null,
+    
+    /**
+     * Property: interval
+     * {Integer} In order to increase performance, an interval (in 
+     *     milliseconds) can be set to reduce the number of drag events 
+     *     called. If set, a new drag event will not be set until the 
+     *     interval has passed. 
+     *     Defaults to 0, meaning no interval. 
+     */
+    interval: 0,
+    
+    /**
+     * Property: timeoutId
+     * {String} The id of the timeout used for the mousedown interval.
+     *     This is "private", and should be left alone.
+     */
+    timeoutId: null,
+    
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, the handler will also handle mouse moves when
+     *     the cursor has moved out of the map viewport. Default is false.
+     */
+    documentDrag: false,
+    
+    /**
+     * Property: documentEvents
+     * {Boolean} Are we currently observing document events?
+     */
+    documentEvents: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Drag
+     * Returns OpenLayers.Handler.Drag
+     * 
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that is making use of
+     *     this handler.  If a handler is being used without a control, the
+     *     handlers setMap method must be overridden to deal properly with
+     *     the map.
+     * callbacks - {Object} An object containing a single function to be
+     *     called when the drag operation is finished. The callback should
+     *     expect to recieve a single argument, the pixel location of the event.
+     *     Callbacks for 'move' and 'done' are supported. You can also speficy
+     *     callbacks for 'down', 'up', and 'out' to respond to those events.
+     * options - {Object} 
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+        
+        if (this.documentDrag === true) {
+            var me = this;
+            this._docMove = function(evt) {
+                me.mousemove({
+                    xy: {x: evt.clientX, y: evt.clientY},
+                    element: document
+                });
+            };
+            this._docUp = function(evt) {
+                me.mouseup({xy: {x: evt.clientX, y: evt.clientY}});
+            };
+        }
+    },
+
+    
+    /**
+     * Method: dragstart
+     * This private method is factorized from mousedown and touchstart methods
+     *
+     * Parameters:
+     * evt - {Event} The event
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    dragstart: function (evt) {
+        var propagate = true;
+        this.dragging = false;
+        if (this.checkModifiers(evt) &&
+               (OpenLayers.Event.isLeftClick(evt) ||
+                OpenLayers.Event.isSingleTouch(evt))) {
+            this.started = true;
+            this.start = evt.xy;
+            this.last = evt.xy;
+            OpenLayers.Element.addClass(
+                this.map.viewPortDiv, "olDragDown"
+            );
+            this.down(evt);
+            this.callback("down", [evt.xy]);
+
+            OpenLayers.Event.stop(evt);
+
+            if(!this.oldOnselectstart) {
+                this.oldOnselectstart = document.onselectstart ?
+                    document.onselectstart : OpenLayers.Function.True;
+            }
+            document.onselectstart = OpenLayers.Function.False;
+
+            propagate = !this.stopDown;
+        } else {
+            this.started = false;
+            this.start = null;
+            this.last = null;
+        }
+        return propagate;
+    },
+
+    /**
+     * Method: dragmove
+     * This private method is factorized from mousemove and touchmove methods
+     *
+     * Parameters:
+     * evt - {Event} The event
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    dragmove: function (evt) {
+        this.lastMoveEvt = evt;
+        if (this.started && !this.timeoutId && (evt.xy.x != this.last.x ||
+                                                evt.xy.y != this.last.y)) {
+            if(this.documentDrag === true && this.documentEvents) {
+                if(evt.element === document) {
+                    this.adjustXY(evt);
+                    // do setEvent manually because the documentEvents are not
+                    // registered with the map
+                    this.setEvent(evt);
+                } else {
+                    this.removeDocumentEvents();
+                }
+            }
+            if (this.interval > 0) {
+                this.timeoutId = setTimeout(
+                    OpenLayers.Function.bind(this.removeTimeout, this),
+                    this.interval);
+            }
+            this.dragging = true;
+
+            this.move(evt);
+            this.callback("move", [evt.xy]);
+            if(!this.oldOnselectstart) {
+                this.oldOnselectstart = document.onselectstart;
+                document.onselectstart = OpenLayers.Function.False;
+            }
+            this.last = evt.xy;
+        }
+        return true;
+    },
+
+    /**
+     * Method: dragend
+     * This private method is factorized from mouseup and touchend methods
+     *
+     * Parameters:
+     * evt - {Event} The event
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    dragend: function (evt) {
+        if (this.started) {
+            if(this.documentDrag === true && this.documentEvents) {
+                this.adjustXY(evt);
+                this.removeDocumentEvents();
+            }
+            var dragged = (this.start != this.last);
+            this.started = false;
+            this.dragging = false;
+            OpenLayers.Element.removeClass(
+                this.map.viewPortDiv, "olDragDown"
+            );
+            this.up(evt);
+            this.callback("up", [evt.xy]);
+            if(dragged) {
+                this.callback("done", [evt.xy]);
+            }
+            document.onselectstart = this.oldOnselectstart;
+        }
+        return true;
+    },
+
+    /**
+     * The four methods below (down, move, up, and out) are used by subclasses
+     *     to do their own processing related to these mouse events.
+     */
+
+    /**
+     * Method: down
+     * This method is called during the handling of the mouse down event.
+     *     Subclasses can do their own processing here.
+     *
+     * Parameters:
+     * evt - {Event} The mouse down event
+     */
+    down: function(evt) {
+    },
+
+    /**
+     * Method: move
+     * This method is called during the handling of the mouse move event.
+     *     Subclasses can do their own processing here.
+     *
+     * Parameters:
+     * evt - {Event} The mouse move event
+     *
+     */
+    move: function(evt) {
+    },
+
+    /**
+     * Method: up
+     * This method is called during the handling of the mouse up event.
+     *     Subclasses can do their own processing here.
+     *
+     * Parameters:
+     * evt - {Event} The mouse up event
+     */
+    up: function(evt) {
+    },
+
+    /**
+     * Method: out
+     * This method is called during the handling of the mouse out event.
+     *     Subclasses can do their own processing here.
+     *
+     * Parameters:
+     * evt - {Event} The mouse out event
+     */
+    out: function(evt) {
+    },
+
+    /**
+     * The methods below are part of the magic of event handling.  Because
+     *     they are named like browser events, they are registered as listeners
+     *     for the events they represent.
+     */
+
+    /**
+     * Method: mousedown
+     * Handle mousedown events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    mousedown: function(evt) {
+        return this.dragstart(evt);
+    },
+
+    /**
+     * Method: touchstart
+     * Handle touchstart events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchstart: function(evt) {
+        if (!this.touch) {
+            this.touch = true;
+            // unregister mouse listeners
+            this.map.events.un({
+                mousedown: this.mousedown,
+                mouseup: this.mouseup,
+                mousemove: this.mousemove,
+                click: this.click,
+                scope: this
+            });
+        }
+        return this.dragstart(evt);
+    },
+
+    /**
+     * Method: mousemove
+     * Handle mousemove events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    mousemove: function(evt) {
+        return this.dragmove(evt);
+    },
+
+    /**
+     * Method: touchmove
+     * Handle touchmove events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchmove: function(evt) {
+        return this.dragmove(evt);
+    },
+
+    /**
+     * Method: removeTimeout
+     * Private. Called by mousemove() to remove the drag timeout.
+     */
+    removeTimeout: function() {
+        this.timeoutId = null;
+        // if timeout expires while we're still dragging (mouseup
+        // hasn't occurred) then call mousemove to move to the
+        // correct position
+        if(this.dragging) {
+            this.mousemove(this.lastMoveEvt);
+        }
+    },
+
+    /**
+     * Method: mouseup
+     * Handle mouseup events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    mouseup: function(evt) {
+        return this.dragend(evt);
+    },
+
+    /**
+     * Method: touchend
+     * Handle touchend events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchend: function(evt) {
+        // override evt.xy with last position since touchend does not have
+        // any touch position
+        evt.xy = this.last;
+        return this.dragend(evt);
+    },
+
+    /**
+     * Method: mouseout
+     * Handle mouseout events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    mouseout: function (evt) {
+        if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) {
+            if(this.documentDrag === true) {
+                this.addDocumentEvents();
+            } else {
+                var dragged = (this.start != this.last);
+                this.started = false; 
+                this.dragging = false;
+                OpenLayers.Element.removeClass(
+                    this.map.viewPortDiv, "olDragDown"
+                );
+                this.out(evt);
+                this.callback("out", []);
+                if(dragged) {
+                    this.callback("done", [evt.xy]);
+                }
+                if(document.onselectstart) {
+                    document.onselectstart = this.oldOnselectstart;
+                }
+            }
+        }
+        return true;
+    },
+
+    /**
+     * Method: click
+     * The drag handler captures the click event.  If something else registers
+     *     for clicks on the same element, its listener will not be called 
+     *     after a drag.
+     * 
+     * Parameters: 
+     * evt - {Event} 
+     * 
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    click: function (evt) {
+        // let the click event propagate only if the mouse moved
+        return (this.start == this.last);
+    },
+
+    /**
+     * Method: activate
+     * Activate the handler.
+     * 
+     * Returns:
+     * {Boolean} The handler was successfully activated.
+     */
+    activate: function() {
+        var activated = false;
+        if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            this.dragging = false;
+            activated = true;
+        }
+        return activated;
+    },
+
+    /**
+     * Method: deactivate 
+     * Deactivate the handler.
+     * 
+     * Returns:
+     * {Boolean} The handler was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            this.touch = false;
+            this.started = false;
+            this.dragging = false;
+            this.start = null;
+            this.last = null;
+            deactivated = true;
+            OpenLayers.Element.removeClass(
+                this.map.viewPortDiv, "olDragDown"
+            );
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: adjustXY
+     * Converts event coordinates that are relative to the document body to
+     * ones that are relative to the map viewport. The latter is the default in
+     * OpenLayers.
+     * 
+     * Parameters:
+     * evt - {Object}
+     */
+    adjustXY: function(evt) {
+        var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv);
+        evt.xy.x -= pos[0];
+        evt.xy.y -= pos[1];
+    },
+    
+    /**
+     * Method: addDocumentEvents
+     * Start observing document events when documentDrag is true and the mouse
+     * cursor leaves the map viewport while dragging.
+     */
+    addDocumentEvents: function() {
+        OpenLayers.Element.addClass(document.body, "olDragDown");
+        this.documentEvents = true;
+        OpenLayers.Event.observe(document, "mousemove", this._docMove);
+        OpenLayers.Event.observe(document, "mouseup", this._docUp);
+    },
+    
+    /**
+     * Method: removeDocumentEvents
+     * Stops observing document events when documentDrag is true and the mouse
+     * cursor re-enters the map viewport while dragging.
+     */
+    removeDocumentEvents: function() {
+        OpenLayers.Element.removeClass(document.body, "olDragDown");
+        this.documentEvents = false;
+        OpenLayers.Event.stopObserving(document, "mousemove", this._docMove);
+        OpenLayers.Event.stopObserving(document, "mouseup", this._docUp);
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Drag"
+});
+/* ======================================================================
+    OpenLayers/Handler/Feature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Feature 
+ * Handler to respond to mouse events related to a drawn feature.  Callbacks
+ *     with the following keys will be notified of the following events
+ *     associated with features: click, clickout, over, out, and dblclick.
+ *
+ * This handler stops event propagation for mousedown and mouseup if those
+ *     browser events target features that can be selected.
+ */
+OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
+
+    /**
+     * Property: EVENTMAP
+     * {Object} A object mapping the browser events to objects with callback
+     *     keys for in and out.
+     */
+    EVENTMAP: {
+        'click': {'in': 'click', 'out': 'clickout'},
+        'mousemove': {'in': 'over', 'out': 'out'},
+        'dblclick': {'in': 'dblclick', 'out': null},
+        'mousedown': {'in': null, 'out': null},
+        'mouseup': {'in': null, 'out': null},
+        'touchstart': {'in': 'click', 'out': 'clickout'}
+    },
+
+    /**
+     * Property: feature
+     * {<OpenLayers.Feature.Vector>} The last feature that was hovered.
+     */
+    feature: null,
+
+    /**
+     * Property: lastFeature
+     * {<OpenLayers.Feature.Vector>} The last feature that was handled.
+     */
+    lastFeature: null,
+
+    /**
+     * Property: down
+     * {<OpenLayers.Pixel>} The location of the last mousedown.
+     */
+    down: null,
+
+    /**
+     * Property: up
+     * {<OpenLayers.Pixel>} The location of the last mouseup.
+     */
+    up: null,
+
+    /**
+     * Property: touch
+     * {Boolean} When a touchstart event is fired, touch will be true and all
+     *     mouse related listeners will do nothing.
+     */
+    touch: false,
+    
+    /**
+     * Property: clickTolerance
+     * {Number} The number of pixels the mouse can move between mousedown
+     *     and mouseup for the event to still be considered a click.
+     *     Dragging the map should not trigger the click and clickout callbacks
+     *     unless the map is moved by less than this tolerance. Defaults to 4.
+     */
+    clickTolerance: 4,
+
+    /**
+     * Property: geometryTypes
+     * To restrict dragging to a limited set of geometry types, send a list
+     * of strings corresponding to the geometry class names.
+     * 
+     * @type Array(String)
+     */
+    geometryTypes: null,
+
+    /**
+     * Property: stopClick
+     * {Boolean} If stopClick is set to true, handled clicks do not
+     *      propagate to other click listeners. Otherwise, handled clicks
+     *      do propagate. Unhandled clicks always propagate, whatever the
+     *      value of stopClick. Defaults to true.
+     */
+    stopClick: true,
+
+    /**
+     * Property: stopDown
+     * {Boolean} If stopDown is set to true, handled mousedowns do not
+     *      propagate to other mousedown listeners. Otherwise, handled
+     *      mousedowns do propagate. Unhandled mousedowns always propagate,
+     *      whatever the value of stopDown. Defaults to true.
+     */
+    stopDown: true,
+
+    /**
+     * Property: stopUp
+     * {Boolean} If stopUp is set to true, handled mouseups do not
+     *      propagate to other mouseup listeners. Otherwise, handled mouseups
+     *      do propagate. Unhandled mouseups always propagate, whatever the
+     *      value of stopUp. Defaults to false.
+     */
+    stopUp: false,
+    
+    /**
+     * Constructor: OpenLayers.Handler.Feature
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} 
+     * layer - {<OpenLayers.Layer.Vector>}
+     * callbacks - {Object} An object with a 'over' property whos value is
+     *     a function to be called when the mouse is over a feature. The 
+     *     callback should expect to recieve a single argument, the feature.
+     * options - {Object} 
+     */
+    initialize: function(control, layer, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, [control, callbacks, options]);
+        this.layer = layer;
+    },
+
+    /**
+     * Method: touchstart
+     * Handle touchstart events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchstart: function(evt) {
+        if(!this.touch) {
+            this.touch =  true;
+            this.map.events.un({
+                mousedown: this.mousedown,
+                mouseup: this.mouseup,
+                mousemove: this.mousemove,
+                click: this.click,
+                dblclick: this.dblclick,
+                scope: this
+            });
+        }
+        return OpenLayers.Event.isMultiTouch(evt) ?
+                true : this.mousedown(evt);
+    },
+
+    /**
+     * Method: touchmove
+     * Handle touchmove events. We just prevent the browser default behavior,
+     *    for Android Webkit not to select text when moving the finger after
+     *    selecting a feature.
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    touchmove: function(evt) {
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: mousedown
+     * Handle mouse down.  Stop propagation if a feature is targeted by this
+     *     event (stops map dragging during feature selection).
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    mousedown: function(evt) {
+        this.down = evt.xy;
+        return this.handle(evt) ? !this.stopDown : true;
+    },
+    
+    /**
+     * Method: mouseup
+     * Handle mouse up.  Stop propagation if a feature is targeted by this
+     *     event.
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    mouseup: function(evt) {
+        this.up = evt.xy;
+        return this.handle(evt) ? !this.stopUp : true;
+    },
+
+    /**
+     * Method: click
+     * Handle click.  Call the "click" callback if click on a feature,
+     *     or the "clickout" callback if click outside any feature.
+     * 
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {Boolean}
+     */
+    click: function(evt) {
+        return this.handle(evt) ? !this.stopClick : true;
+    },
+        
+    /**
+     * Method: mousemove
+     * Handle mouse moves.  Call the "over" callback if moving in to a feature,
+     *     or the "out" callback if moving out of a feature.
+     * 
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {Boolean}
+     */
+    mousemove: function(evt) {
+        if (!this.callbacks['over'] && !this.callbacks['out']) {
+            return true;
+        }     
+        this.handle(evt);
+        return true;
+    },
+    
+    /**
+     * Method: dblclick
+     * Handle dblclick.  Call the "dblclick" callback if dblclick on a feature.
+     *
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {Boolean}
+     */
+    dblclick: function(evt) {
+        return !this.handle(evt);
+    },
+
+    /**
+     * Method: geometryTypeMatches
+     * Return true if the geometry type of the passed feature matches
+     *     one of the geometry types in the geometryTypes array.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Vector.Feature>}
+     *
+     * Returns:
+     * {Boolean}
+     */
+    geometryTypeMatches: function(feature) {
+        return this.geometryTypes == null ||
+            OpenLayers.Util.indexOf(this.geometryTypes,
+                                    feature.geometry.CLASS_NAME) > -1;
+    },
+
+    /**
+     * Method: handle
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} The event occurred over a relevant feature.
+     */
+    handle: function(evt) {
+        if(this.feature && !this.feature.layer) {
+            // feature has been destroyed
+            this.feature = null;
+        }
+        var type = evt.type;
+        var handled = false;
+        var previouslyIn = !!(this.feature); // previously in a feature
+        var click = (type == "click" || type == "dblclick" || type == "touchstart");
+        this.feature = this.layer.getFeatureFromEvent(evt);
+        if(this.feature && !this.feature.layer) {
+            // feature has been destroyed
+            this.feature = null;
+        }
+        if(this.lastFeature && !this.lastFeature.layer) {
+            // last feature has been destroyed
+            this.lastFeature = null;
+        }
+        if(this.feature) {
+            if(type === "touchstart") {
+                // stop the event to prevent Android Webkit from
+                // "flashing" the map div
+                OpenLayers.Event.stop(evt);
+            }
+            var inNew = (this.feature != this.lastFeature);
+            if(this.geometryTypeMatches(this.feature)) {
+                // in to a feature
+                if(previouslyIn && inNew) {
+                    // out of last feature and in to another
+                    if(this.lastFeature) {
+                        this.triggerCallback(type, 'out', [this.lastFeature]);
+                    }
+                    this.triggerCallback(type, 'in', [this.feature]);
+                } else if(!previouslyIn || click) {
+                    // in feature for the first time
+                    this.triggerCallback(type, 'in', [this.feature]);
+                }
+                this.lastFeature = this.feature;
+                handled = true;
+            } else {
+                // not in to a feature
+                if(this.lastFeature && (previouslyIn && inNew || click)) {
+                    // out of last feature for the first time
+                    this.triggerCallback(type, 'out', [this.lastFeature]);
+                }
+                // next time the mouse goes in a feature whose geometry type
+                // doesn't match we don't want to call the 'out' callback
+                // again, so let's set this.feature to null so that
+                // previouslyIn will evaluate to false the next time
+                // we enter handle. Yes, a bit hackish...
+                this.feature = null;
+            }
+        } else {
+            if(this.lastFeature && (previouslyIn || click)) {
+                this.triggerCallback(type, 'out', [this.lastFeature]);
+            }
+        }
+        return handled;
+    },
+    
+    /**
+     * Method: triggerCallback
+     * Call the callback keyed in the event map with the supplied arguments.
+     *     For click and clickout, the <clickTolerance> is checked first.
+     *
+     * Parameters:
+     * type - {String}
+     */
+    triggerCallback: function(type, mode, args) {
+        var key = this.EVENTMAP[type][mode];
+        if(key) {
+            if(type == 'click' && this.up && this.down) {
+                // for click/clickout, only trigger callback if tolerance is met
+                var dpx = Math.sqrt(
+                    Math.pow(this.up.x - this.down.x, 2) +
+                    Math.pow(this.up.y - this.down.y, 2)
+                );
+                if(dpx <= this.clickTolerance) {
+                    this.callback(key, args);
+                }
+            } else {
+                this.callback(key, args);
+            }
+        }
+    },
+
+    /**
+     * Method: activate 
+     * Turn on the handler.  Returns false if the handler was already active.
+     *
+     * Returns:
+     * {Boolean}
+     */
+    activate: function() {
+        var activated = false;
+        if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            this.moveLayerToTop();
+            this.map.events.on({
+                "removelayer": this.handleMapEvents,
+                "changelayer": this.handleMapEvents,
+                scope: this
+            });
+            activated = true;
+        }
+        return activated;
+    },
+    
+    /**
+     * Method: deactivate 
+     * Turn off the handler.  Returns false if the handler was already active.
+     *
+     * Returns: 
+     * {Boolean}
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            this.moveLayerBack();
+            this.feature = null;
+            this.lastFeature = null;
+            this.down = null;
+            this.up = null;
+            this.touch = false;
+            this.map.events.un({
+                "removelayer": this.handleMapEvents,
+                "changelayer": this.handleMapEvents,
+                scope: this
+            });
+            deactivated = true;
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method handleMapEvents
+     * 
+     * Parameters:
+     * evt - {Object}
+     */
+    handleMapEvents: function(evt) {
+        if (evt.type == "removelayer" || evt.property == "order") {
+            this.moveLayerToTop();
+        }
+    },
+    
+    /**
+     * Method: moveLayerToTop
+     * Moves the layer for this handler to the top, so mouse events can reach
+     * it.
+     */
+    moveLayerToTop: function() {
+        var index = Math.max(this.map.Z_INDEX_BASE['Feature'] - 1,
+            this.layer.getZIndex()) + 1;
+        this.layer.setZIndex(index);
+        
+    },
+    
+    /**
+     * Method: moveLayerBack
+     * Moves the layer back to the position determined by the map's layers
+     * array.
+     */
+    moveLayerBack: function() {
+        var index = this.layer.getZIndex() - 1;
+        if (index >= this.map.Z_INDEX_BASE['Feature']) {
+            this.layer.setZIndex(index);
+        } else {
+            this.map.setLayerZIndex(this.layer,
+                this.map.getLayerIndex(this.layer));
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Feature"
+});
+/* ======================================================================
+    OpenLayers/Control/DragFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Drag.js
+ * @requires OpenLayers/Handler/Feature.js
+ */
+
+/**
+ * Class: OpenLayers.Control.DragFeature
+ * The DragFeature control moves a feature with a drag of the mouse. Create a
+ * new control with the <OpenLayers.Control.DragFeature> constructor.
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: geometryTypes
+     * {Array(String)} To restrict dragging to a limited set of geometry types,
+     *     send a list of strings corresponding to the geometry class names.
+     */
+    geometryTypes: null,
+    
+    /**
+     * APIProperty: onStart
+     * {Function} Define this function if you want to know when a drag starts.
+     *     The function should expect to receive two arguments: the feature
+     *     that is about to be dragged and the pixel location of the mouse.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that is about to be
+     *     dragged.
+     * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+     */
+    onStart: function(feature, pixel) {},
+
+    /**
+     * APIProperty: onDrag
+     * {Function} Define this function if you want to know about each move of a
+     *     feature. The function should expect to receive two arguments: the
+     *     feature that is being dragged and the pixel location of the mouse.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+     * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+     */
+    onDrag: function(feature, pixel) {},
+
+    /**
+     * APIProperty: onComplete
+     * {Function} Define this function if you want to know when a feature is
+     *     done dragging. The function should expect to receive two arguments:
+     *     the feature that is being dragged and the pixel location of the
+     *     mouse.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+     * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+     */
+    onComplete: function(feature, pixel) {},
+
+    /**
+     * APIProperty: onEnter
+     * {Function} Define this function if you want to know when the mouse
+     *     goes over a feature and thereby makes this feature a candidate
+     *     for dragging.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that is ready
+     *     to be dragged.
+     */
+    onEnter: function(feature) {},
+
+    /**
+     * APIProperty: onLeave
+     * {Function} Define this function if you want to know when the mouse
+     *     goes out of the feature that was dragged.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+     */
+    onLeave: function(feature) {},
+
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, mouse dragging will continue even if the
+     *     mouse cursor leaves the map viewport. Default is false.
+     */
+    documentDrag: false,
+    
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>}
+     */
+    layer: null,
+    
+    /**
+     * Property: feature
+     * {<OpenLayers.Feature.Vector>}
+     */
+    feature: null,
+
+    /**
+     * Property: dragCallbacks
+     * {Object} The functions that are sent to the drag handler for callback.
+     */
+    dragCallbacks: {},
+
+    /**
+     * Property: featureCallbacks
+     * {Object} The functions that are sent to the feature handler for callback.
+     */
+    featureCallbacks: {},
+    
+    /**
+     * Property: lastPixel
+     * {<OpenLayers.Pixel>}
+     */
+    lastPixel: null,
+
+    /**
+     * Constructor: OpenLayers.Control.DragFeature
+     * Create a new control to drag features.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} The layer containing features to be
+     *     dragged.
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+    initialize: function(layer, options) {
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.layer = layer;
+        this.handlers = {
+            drag: new OpenLayers.Handler.Drag(
+                this, OpenLayers.Util.extend({
+                    down: this.downFeature,
+                    move: this.moveFeature,
+                    up: this.upFeature,
+                    out: this.cancel,
+                    done: this.doneDragging
+                }, this.dragCallbacks), {
+                    documentDrag: this.documentDrag
+                }
+            ),
+            feature: new OpenLayers.Handler.Feature(
+                this, this.layer, OpenLayers.Util.extend({
+                    // 'click' and 'clickout' callback are for the mobile
+                    // support: no 'over' or 'out' in touch based browsers.
+                    click: this.clickFeature,
+                    clickout: this.clickoutFeature,
+                    over: this.overFeature,
+                    out: this.outFeature
+                }, this.featureCallbacks),
+                {geometryTypes: this.geometryTypes}
+            )
+        };
+    },
+
+    /**
+     * Method: clickFeature
+     * Called when the feature handler detects a click-in on a feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    clickFeature: function(feature) {
+        if (this.handlers.feature.touch && !this.over && this.overFeature(feature)) {
+            this.handlers.drag.dragstart(this.handlers.feature.evt);
+            // to let the events propagate to the feature handler (click callback)
+            this.handlers.drag.stopDown = false;
+        }
+    },
+
+    /**
+     * Method: clickoutFeature
+     * Called when the feature handler detects a click-out on a feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    clickoutFeature: function(feature) {
+        if (this.handlers.feature.touch && this.over) {
+            this.outFeature(feature);
+            this.handlers.drag.stopDown = true;
+        }
+    },
+
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass
+     */
+    destroy: function() {
+        this.layer = null;
+        OpenLayers.Control.prototype.destroy.apply(this, []);
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the control and the feature handler.
+     * 
+     * Returns:
+     * {Boolean} Successfully activated the control and feature handler.
+     */
+    activate: function() {
+        return (this.handlers.feature.activate() &&
+                OpenLayers.Control.prototype.activate.apply(this, arguments));
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control and all handlers.
+     * 
+     * Returns:
+     * {Boolean} Successfully deactivated the control.
+     */
+    deactivate: function() {
+        // the return from the handlers is unimportant in this case
+        this.handlers.drag.deactivate();
+        this.handlers.feature.deactivate();
+        this.feature = null;
+        this.dragging = false;
+        this.lastPixel = null;
+        OpenLayers.Element.removeClass(
+            this.map.viewPortDiv, this.displayClass + "Over"
+        );
+        return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
+    },
+
+    /**
+     * Method: overFeature
+     * Called when the feature handler detects a mouse-over on a feature.
+     *     This activates the drag handler.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The selected feature.
+     *
+     * Returns:
+     * {Boolean} Successfully activated the drag handler.
+     */
+    overFeature: function(feature) {
+        var activated = false;
+        if(!this.handlers.drag.dragging) {
+            this.feature = feature;
+            this.handlers.drag.activate();
+            activated = true;
+            this.over = true;
+            OpenLayers.Element.addClass(this.map.viewPortDiv, this.displayClass + "Over");
+            this.onEnter(feature);
+        } else {
+            if(this.feature.id == feature.id) {
+                this.over = true;
+            } else {
+                this.over = false;
+            }
+        }
+        return activated;
+    },
+
+    /**
+     * Method: downFeature
+     * Called when the drag handler detects a mouse-down.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+     */
+    downFeature: function(pixel) {
+        this.lastPixel = pixel;
+        this.onStart(this.feature, pixel);
+    },
+
+    /**
+     * Method: moveFeature
+     * Called when the drag handler detects a mouse-move.  Also calls the
+     *     optional onDrag method.
+     * 
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+     */
+    moveFeature: function(pixel) {
+        var res = this.map.getResolution();
+        this.feature.geometry.move(res * (pixel.x - this.lastPixel.x),
+                                   res * (this.lastPixel.y - pixel.y));
+        this.layer.drawFeature(this.feature);
+        this.lastPixel = pixel;
+        this.onDrag(this.feature, pixel);
+    },
+
+    /**
+     * Method: upFeature
+     * Called when the drag handler detects a mouse-up.
+     * 
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+     */
+    upFeature: function(pixel) {
+        if(!this.over) {
+            this.handlers.drag.deactivate();
+        }
+    },
+
+    /**
+     * Method: doneDragging
+     * Called when the drag handler is done dragging.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The last event pixel location.  If this event
+     *     came from a mouseout, this may not be in the map viewport.
+     */
+    doneDragging: function(pixel) {
+        this.onComplete(this.feature, pixel);
+    },
+
+    /**
+     * Method: outFeature
+     * Called when the feature handler detects a mouse-out on a feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature that the mouse left.
+     */
+    outFeature: function(feature) {
+        if(!this.handlers.drag.dragging) {
+            this.over = false;
+            this.handlers.drag.deactivate();
+            OpenLayers.Element.removeClass(
+                this.map.viewPortDiv, this.displayClass + "Over"
+            );
+            this.onLeave(feature);
+            this.feature = null;
+        } else {
+            if(this.feature.id == feature.id) {
+                this.over = false;
+            }
+        }
+    },
+        
+    /**
+     * Method: cancel
+     * Called when the drag handler detects a mouse-out (from the map viewport).
+     */
+    cancel: function() {
+        this.handlers.drag.deactivate();
+        this.over = false;
+    },
+
+    /**
+     * Method: setMap
+     * Set the map property for the control and all handlers.
+     *
+     * Parameters: 
+     * map - {<OpenLayers.Map>} The control's map.
+     */
+    setMap: function(map) {
+        this.handlers.drag.setMap(map);
+        this.handlers.feature.setMap(map);
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.DragFeature"
+});
+/* ======================================================================
+    OpenLayers/StyleMap.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+ 
+/**
+ * Class: OpenLayers.StyleMap
+ */
+OpenLayers.StyleMap = OpenLayers.Class({
+    
+    /**
+     * Property: styles
+     * Hash of {<OpenLayers.Style>}, keyed by names of well known
+     * rendering intents (e.g. "default", "temporary", "select", "delete").
+     */
+    styles: null,
+    
+    /**
+     * Property: extendDefault
+     * {Boolean} if true, every render intent will extend the symbolizers
+     * specified for the "default" intent at rendering time. Otherwise, every
+     * rendering intent will be treated as a completely independent style.
+     */
+    extendDefault: true,
+    
+    /**
+     * Constructor: OpenLayers.StyleMap
+     * 
+     * Parameters:
+     * style   - {Object} Optional. Either a style hash, or a style object, or
+     *           a hash of style objects (style hashes) keyed by rendering
+     *           intent. If just one style hash or style object is passed,
+     *           this will be used for all known render intents (default,
+     *           select, temporary)
+     * options - {Object} optional hash of additional options for this
+     *           instance
+     */
+    initialize: function (style, options) {
+        this.styles = {
+            "default": new OpenLayers.Style(
+                OpenLayers.Feature.Vector.style["default"]),
+            "select": new OpenLayers.Style(
+                OpenLayers.Feature.Vector.style["select"]),
+            "temporary": new OpenLayers.Style(
+                OpenLayers.Feature.Vector.style["temporary"]),
+            "delete": new OpenLayers.Style(
+                OpenLayers.Feature.Vector.style["delete"])
+        };
+        
+        // take whatever the user passed as style parameter and convert it
+        // into parts of stylemap.
+        if(style instanceof OpenLayers.Style) {
+            // user passed a style object
+            this.styles["default"] = style;
+            this.styles["select"] = style;
+            this.styles["temporary"] = style;
+            this.styles["delete"] = style;
+        } else if(typeof style == "object") {
+            for(var key in style) {
+                if(style[key] instanceof OpenLayers.Style) {
+                    // user passed a hash of style objects
+                    this.styles[key] = style[key];
+                } else if(typeof style[key] == "object") {
+                    // user passsed a hash of style hashes
+                    this.styles[key] = new OpenLayers.Style(style[key]);
+                } else {
+                    // user passed a style hash (i.e. symbolizer)
+                    this.styles["default"] = new OpenLayers.Style(style);
+                    this.styles["select"] = new OpenLayers.Style(style);
+                    this.styles["temporary"] = new OpenLayers.Style(style);
+                    this.styles["delete"] = new OpenLayers.Style(style);
+                    break;
+                }
+            }
+        }
+        OpenLayers.Util.extend(this, options);
+    },
+
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        for(var key in this.styles) {
+            this.styles[key].destroy();
+        }
+        this.styles = null;
+    },
+    
+    /**
+     * Method: createSymbolizer
+     * Creates the symbolizer for a feature for a render intent.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature>} The feature to evaluate the rules
+     *           of the intended style against.
+     * intent  - {String} The intent determines the symbolizer that will be
+     *           used to draw the feature. Well known intents are "default"
+     *           (for just drawing the features), "select" (for selected
+     *           features) and "temporary" (for drawing features).
+     * 
+     * Returns:
+     * {Object} symbolizer hash
+     */
+    createSymbolizer: function(feature, intent) {
+        if(!feature) {
+            feature = new OpenLayers.Feature.Vector();
+        }
+        if(!this.styles[intent]) {
+            intent = "default";
+        }
+        feature.renderIntent = intent;
+        var defaultSymbolizer = {};
+        if(this.extendDefault && intent != "default") {
+            defaultSymbolizer = this.styles["default"].createSymbolizer(feature);
+        }
+        return OpenLayers.Util.extend(defaultSymbolizer,
+            this.styles[intent].createSymbolizer(feature));
+    },
+    
+    /**
+     * Method: addUniqueValueRules
+     * Convenience method to create comparison rules for unique values of a
+     * property. The rules will be added to the style object for a specified
+     * rendering intent. This method is a shortcut for creating something like
+     * the "unique value legends" familiar from well known desktop GIS systems
+     * 
+     * Parameters:
+     * renderIntent - {String} rendering intent to add the rules to
+     * property     - {String} values of feature attributes to create the
+     *                rules for
+     * symbolizers  - {Object} Hash of symbolizers, keyed by the desired
+     *                property values 
+     * context      - {Object} An optional object with properties that
+     *                symbolizers' property values should be evaluated
+     *                against. If no context is specified, feature.attributes
+     *                will be used
+     */
+    addUniqueValueRules: function(renderIntent, property, symbolizers, context) {
+        var rules = [];
+        for (var value in symbolizers) {
+            rules.push(new OpenLayers.Rule({
+                symbolizer: symbolizers[value],
+                context: context,
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                    property: property,
+                    value: value
+                })
+            }));
+        }
+        this.styles[renderIntent].addRules(rules);
+    },
+
+    CLASS_NAME: "OpenLayers.StyleMap"
+});
+/* ======================================================================
+    OpenLayers/Layer/Vector.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Renderer.js
+ * @requires OpenLayers/StyleMap.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Vector
+ * Instances of OpenLayers.Layer.Vector are used to render vector data from
+ *     a variety of sources. Create a new vector layer with the
+ *     <OpenLayers.Layer.Vector> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * layer.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * All event objects have at least the following properties:
+     * object - {Object} A reference to layer.events.object.
+     * element - {DOMElement} A reference to layer.events.element.
+     *
+     * Supported map event types (in addition to those from <OpenLayers.Layer>):
+     * beforefeatureadded - Triggered before a feature is added.  Listeners
+     *      will receive an object with a *feature* property referencing the
+     *      feature to be added.  To stop the feature from being added, a
+     *      listener should return false.
+     * beforefeaturesadded - Triggered before an array of features is added.
+     *      Listeners will receive an object with a *features* property
+     *      referencing the feature to be added. To stop the features from
+     *      being added, a listener should return false.
+     * featureadded - Triggered after a feature is added.  The event
+     *      object passed to listeners will have a *feature* property with a
+     *      reference to the added feature.
+     * featuresadded - Triggered after features are added.  The event
+     *      object passed to listeners will have a *features* property with a
+     *      reference to an array of added features.
+     * beforefeatureremoved - Triggered before a feature is removed. Listeners
+     *      will receive an object with a *feature* property referencing the
+     *      feature to be removed.
+     * beforefeaturesremoved - Triggered before multiple features are removed. 
+     *      Listeners will receive an object with a *features* property
+     *      referencing the features to be removed.
+     * featureremoved - Triggerd after a feature is removed. The event
+     *      object passed to listeners will have a *feature* property with a
+     *      reference to the removed feature.
+     * featuresremoved - Triggered after features are removed. The event
+     *      object passed to listeners will have a *features* property with a
+     *      reference to an array of removed features.
+     * beforefeatureselected - Triggered after a feature is selected.  Listeners
+     *      will receive an object with a *feature* property referencing the
+     *      feature to be selected. To stop the feature from being selectd, a
+     *      listener should return false.
+     * featureselected - Triggered after a feature is selected.  Listeners
+     *      will receive an object with a *feature* property referencing the
+     *      selected feature.
+     * featureunselected - Triggered after a feature is unselected.
+     *      Listeners will receive an object with a *feature* property
+     *      referencing the unselected feature.
+     * beforefeaturemodified - Triggered when a feature is selected to 
+     *      be modified.  Listeners will receive an object with a *feature* 
+     *      property referencing the selected feature.
+     * featuremodified - Triggered when a feature has been modified.
+     *      Listeners will receive an object with a *feature* property referencing 
+     *      the modified feature.
+     * afterfeaturemodified - Triggered when a feature is finished being modified.
+     *      Listeners will receive an object with a *feature* property referencing 
+     *      the modified feature.
+     * vertexmodified - Triggered when a vertex within any feature geometry
+     *      has been modified.  Listeners will receive an object with a
+     *      *feature* property referencing the modified feature, a *vertex*
+     *      property referencing the vertex modified (always a point geometry),
+     *      and a *pixel* property referencing the pixel location of the
+     *      modification.
+     * vertexremoved - Triggered when a vertex within any feature geometry
+     *      has been deleted.  Listeners will receive an object with a
+     *      *feature* property referencing the modified feature, a *vertex*
+     *      property referencing the vertex modified (always a point geometry),
+     *      and a *pixel* property referencing the pixel location of the
+     *      removal.
+     * sketchstarted - Triggered when a feature sketch bound for this layer
+     *      is started.  Listeners will receive an object with a *feature*
+     *      property referencing the new sketch feature and a *vertex* property
+     *      referencing the creation point.
+     * sketchmodified - Triggered when a feature sketch bound for this layer
+     *      is modified.  Listeners will receive an object with a *vertex*
+     *      property referencing the modified vertex and a *feature* property
+     *      referencing the sketch feature.
+     * sketchcomplete - Triggered when a feature sketch bound for this layer
+     *      is complete.  Listeners will receive an object with a *feature*
+     *      property referencing the sketch feature.  By returning false, a
+     *      listener can stop the sketch feature from being added to the layer.
+     * refresh - Triggered when something wants a strategy to ask the protocol
+     *      for a new set of features.
+     */
+    EVENT_TYPES: ["beforefeatureadded", "beforefeaturesadded",
+                  "featureadded", "featuresadded", "beforefeatureremoved",
+                  "beforefeaturesremoved", "featureremoved", "featuresremoved",
+                  "beforefeatureselected", "featureselected", "featureunselected", 
+                  "beforefeaturemodified", "featuremodified", "afterfeaturemodified",
+                  "vertexmodified", "vertexremoved", "sketchstarted",
+                  "sketchmodified", "sketchcomplete", "refresh"],
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} The layer is a base layer.  Default is false.  Set this property
+     * in the layer options.
+     */
+    isBaseLayer: false,
+
+    /** 
+     * APIProperty: isFixed
+     * {Boolean} Whether the layer remains in one place while dragging the
+     * map.
+     */
+    isFixed: false,
+
+    /** 
+     * APIProperty: features
+     * {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    features: null,
+    
+    /** 
+     * Property: filter
+     * {<OpenLayers.Filter>} The filter set in this layer,
+     *     a strategy launching read requests can combined
+     *     this filter with its own filter.
+     */
+    filter: null,
+    
+    /** 
+     * Property: selectedFeatures
+     * {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    selectedFeatures: null,
+    
+    /**
+     * Property: unrenderedFeatures
+     * {Object} hash of features, keyed by feature.id, that the renderer
+     *     failed to draw
+     */
+    unrenderedFeatures: null,
+
+    /**
+     * APIProperty: reportError
+     * {Boolean} report friendly error message when loading of renderer
+     * fails.
+     */
+    reportError: true, 
+
+    /** 
+     * APIProperty: style
+     * {Object} Default style for the layer
+     */
+    style: null,
+    
+    /**
+     * Property: styleMap
+     * {<OpenLayers.StyleMap>}
+     */
+    styleMap: null,
+    
+    /**
+     * Property: strategies
+     * {Array(<OpenLayers.Strategy>})} Optional list of strategies for the layer.
+     */
+    strategies: null,
+    
+    /**
+     * Property: protocol
+     * {<OpenLayers.Protocol>} Optional protocol for the layer.
+     */
+    protocol: null,
+    
+    /**
+     * Property: renderers
+     * {Array(String)} List of supported Renderer classes. Add to this list to
+     * add support for additional renderers. This list is ordered:
+     * the first renderer which returns true for the  'supported()'
+     * method will be used, if not defined in the 'renderer' option.
+     */
+    renderers: ['SVG', 'VML', 'Canvas'],
+    
+    /** 
+     * Property: renderer
+     * {<OpenLayers.Renderer>}
+     */
+    renderer: null,
+    
+    /**
+     * APIProperty: rendererOptions
+     * {Object} Options for the renderer. See {<OpenLayers.Renderer>} for
+     *     supported options.
+     */
+    rendererOptions: null,
+    
+    /** 
+     * APIProperty: geometryType
+     * {String} geometryType allows you to limit the types of geometries this
+     * layer supports. This should be set to something like
+     * "OpenLayers.Geometry.Point" to limit types.
+     */
+    geometryType: null,
+
+    /** 
+     * Property: drawn
+     * {Boolean} Whether the Vector Layer features have been drawn yet.
+     */
+    drawn: false,
+
+    /**
+     * Constructor: OpenLayers.Layer.Vector
+     * Create a new vector layer
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * options - {Object} Optional object with non-default properties to set on
+     *           the layer.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Vector>} A new vector layer
+     */
+    initialize: function(name, options) {
+        
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Layer.Vector.prototype.EVENT_TYPES.concat(
+            OpenLayers.Layer.prototype.EVENT_TYPES
+        );
+
+        OpenLayers.Layer.prototype.initialize.apply(this, arguments);
+
+        // allow user-set renderer, otherwise assign one
+        if (!this.renderer || !this.renderer.supported()) {  
+            this.assignRenderer();
+        }
+
+        // if no valid renderer found, display error
+        if (!this.renderer || !this.renderer.supported()) {
+            this.renderer = null;
+            this.displayError();
+        } 
+
+        if (!this.styleMap) {
+            this.styleMap = new OpenLayers.StyleMap();
+        }
+
+        this.features = [];
+        this.selectedFeatures = [];
+        this.unrenderedFeatures = {};
+        
+        // Allow for custom layer behavior
+        if(this.strategies){
+            for(var i=0, len=this.strategies.length; i<len; i++) {
+                this.strategies[i].setLayer(this);
+            }
+        }
+
+    },
+
+    /**
+     * APIMethod: destroy
+     * Destroy this layer
+     */
+    destroy: function() {
+        if (this.strategies) {
+            var strategy, i, len;
+            for(i=0, len=this.strategies.length; i<len; i++) {
+                strategy = this.strategies[i];
+                if(strategy.autoDestroy) {
+                    strategy.destroy();
+                }
+            }
+            this.strategies = null;
+        }
+        if (this.protocol) {
+            if(this.protocol.autoDestroy) {
+                this.protocol.destroy();
+            }
+            this.protocol = null;
+        }
+        this.destroyFeatures();
+        this.features = null;
+        this.selectedFeatures = null;
+        this.unrenderedFeatures = null;
+        if (this.renderer) {
+            this.renderer.destroy();
+        }
+        this.renderer = null;
+        this.geometryType = null;
+        this.drawn = null;
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments);  
+    },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer.
+     * 
+     * Note: Features of the layer are also cloned.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Vector>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Vector(this.name, this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        var features = this.features;
+        var len = features.length;
+        var clonedFeatures = new Array(len);
+        for(var i=0; i<len; ++i) {
+            clonedFeatures[i] = features[i].clone();
+        }
+        obj.features = clonedFeatures;
+
+        return obj;
+    },    
+    
+    /**
+     * Method: refresh
+     * Ask the layer to request features again and redraw them.  Triggers
+     *     the refresh event if the layer is in range and visible.
+     *
+     * Parameters:
+     * obj - {Object} Optional object with properties for any listener of
+     *     the refresh event.
+     */
+    refresh: function(obj) {
+        if(this.calculateInRange() && this.visibility) {
+            this.events.triggerEvent("refresh", obj);
+        }
+    },
+
+    /** 
+     * Method: assignRenderer
+     * Iterates through the available renderer implementations and selects 
+     * and assigns the first one whose "supported()" function returns true.
+     */    
+    assignRenderer: function()  {
+        for (var i=0, len=this.renderers.length; i<len; i++) {
+            var rendererClass = this.renderers[i];
+            var renderer = (typeof rendererClass == "function") ?
+                rendererClass :
+                OpenLayers.Renderer[rendererClass];
+            if (renderer && renderer.prototype.supported()) {
+                this.renderer = new renderer(this.div, this.rendererOptions);
+                break;
+            }  
+        }  
+    },
+
+    /** 
+     * Method: displayError 
+     * Let the user know their browser isn't supported.
+     */
+    displayError: function() {
+        if (this.reportError) {
+            OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported", 
+                                     {'renderers':this.renderers.join("\n")}));
+        }    
+    },
+
+    /** 
+     * Method: setMap
+     * The layer has been added to the map. 
+     * 
+     * If there is no renderer set, the layer can't be used. Remove it.
+     * Otherwise, give the renderer a reference to the map and set its size.
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {        
+        OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+
+        if (!this.renderer) {
+            this.map.removeLayer(this);
+        } else {
+            this.renderer.map = this.map;
+            this.renderer.setSize(this.map.getSize());
+        }
+    },
+
+    /**
+     * Method: afterAdd
+     * Called at the end of the map.addLayer sequence.  At this point, the map
+     *     will have a base layer.  Any autoActivate strategies will be
+     *     activated here.
+     */
+    afterAdd: function() {
+        if(this.strategies) {
+            var strategy, i, len;
+            for(i=0, len=this.strategies.length; i<len; i++) {
+                strategy = this.strategies[i];
+                if(strategy.autoActivate) {
+                    strategy.activate();
+                }
+            }
+        }
+    },
+
+    /**
+     * Method: removeMap
+     * The layer has been removed from the map.
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        this.drawn = false;
+        if(this.strategies) {
+            var strategy, i, len;
+            for(i=0, len=this.strategies.length; i<len; i++) {
+                strategy = this.strategies[i];
+                if(strategy.autoActivate) {
+                    strategy.deactivate();
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: onMapResize
+     * Notify the renderer of the change in size. 
+     * 
+     */
+    onMapResize: function() {
+        OpenLayers.Layer.prototype.onMapResize.apply(this, arguments);
+        this.renderer.setSize(this.map.getSize());
+    },
+
+    /**
+     * Method: moveTo
+     *  Reset the vector layer's div so that it once again is lined up with 
+     *   the map. Notify the renderer of the change of extent, and in the
+     *   case of a change of zoom level (resolution), have the 
+     *   renderer redraw features.
+     * 
+     *  If the layer has not yet been drawn, cycle through the layer's 
+     *   features and draw each one.
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * zoomChanged - {Boolean} 
+     * dragging - {Boolean} 
+     */
+    moveTo: function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+        
+        var ng = (OpenLayers.Renderer.NG && this.renderer instanceof OpenLayers.Renderer.NG);
+        if (ng) {
+            dragging || this.renderer.updateDimensions(zoomChanged);
+        } else {
+            var coordSysUnchanged = true;
+
+            if (!dragging) {
+                this.renderer.root.style.visibility = "hidden";
+            
+                this.div.style.left = -parseInt(this.map.layerContainerDiv.style.left) + "px";
+                this.div.style.top = -parseInt(this.map.layerContainerDiv.style.top) + "px";
+                var extent = this.map.getExtent();
+                coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged);
+            
+                this.renderer.root.style.visibility = "visible";
+
+                // Force a reflow on gecko based browsers to prevent jump/flicker.
+                // This seems to happen on only certain configurations; it was originally
+                // noticed in FF 2.0 and Linux.
+                if (OpenLayers.IS_GECKO === true) {
+                    this.div.scrollLeft = this.div.scrollLeft;
+                }
+            
+                if(!zoomChanged && coordSysUnchanged) {
+                    for(var i in this.unrenderedFeatures) {
+                        var feature = this.unrenderedFeatures[i];
+                        this.drawFeature(feature);
+                    }
+                }
+            }
+        }
+        if (!this.drawn || (!ng && (zoomChanged || !coordSysUnchanged))) {
+            this.drawn = true;
+            var feature;
+            for(var i=0, len=this.features.length; i<len; i++) {
+                this.renderer.locked = (i !== (len - 1));
+                feature = this.features[i];
+                this.drawFeature(feature);
+            }
+        }    
+    },
+    
+    /**
+     * APIMethod: redraw
+     * Redraws the layer.  Returns true if the layer was redrawn, false if not.
+     *
+     * Returns:
+     * {Boolean} The layer was redrawn.
+     */
+    redraw: function() {
+        if (OpenLayers.Renderer.NG && this.renderer instanceof OpenLayers.Renderer.NG) {
+            this.drawn = false;
+        }
+        return OpenLayers.Layer.prototype.redraw.apply(this, arguments);
+    },
+    
+    /** 
+     * APIMethod: display
+     * Hide or show the Layer
+     * 
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(display) {
+        OpenLayers.Layer.prototype.display.apply(this, arguments);
+        // we need to set the display style of the root in case it is attached
+        // to a foreign layer
+        var currentDisplay = this.div.style.display;
+        if(currentDisplay != this.renderer.root.style.display) {
+            this.renderer.root.style.display = currentDisplay;
+        }
+    },
+
+    /**
+     * APIMethod: addFeatures
+     * Add Features to the layer.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} 
+     * options - {Object}
+     */
+    addFeatures: function(features, options) {
+        if (!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        
+        var notify = !options || !options.silent;
+        if(notify) {
+            var event = {features: features};
+            var ret = this.events.triggerEvent("beforefeaturesadded", event);
+            if(ret === false) {
+                return;
+            }
+            features = event.features;
+        }
+        
+        // Track successfully added features for featuresadded event, since
+        // beforefeatureadded can veto single features.
+        var featuresAdded = [];
+        for (var i=0, len=features.length; i<len; i++) {
+            if (i != (features.length - 1)) {
+                this.renderer.locked = true;
+            } else {
+                this.renderer.locked = false;
+            }    
+            var feature = features[i];
+            
+            if (this.geometryType &&
+              !(feature.geometry instanceof this.geometryType)) {
+                var throwStr = OpenLayers.i18n('componentShouldBe',
+                          {'geomType':this.geometryType.prototype.CLASS_NAME});
+                throw throwStr;
+              }
+
+            //give feature reference to its layer
+            feature.layer = this;
+
+            if (!feature.style && this.style) {
+                feature.style = OpenLayers.Util.extend({}, this.style);
+            }
+
+            if (notify) {
+                if(this.events.triggerEvent("beforefeatureadded",
+                                            {feature: feature}) === false) {
+                    continue;
+                }
+                this.preFeatureInsert(feature);
+            }
+
+            featuresAdded.push(feature);
+            this.features.push(feature);
+            this.drawFeature(feature);
+            
+            if (notify) {
+                this.events.triggerEvent("featureadded", {
+                    feature: feature
+                });
+                this.onFeatureInsert(feature);
+            }
+        }
+        
+        if(notify) {
+            this.events.triggerEvent("featuresadded", {features: featuresAdded});
+        }
+    },
+
+
+    /**
+     * APIMethod: removeFeatures
+     * Remove features from the layer.  This erases any drawn features and
+     *     removes them from the layer's control.  The beforefeatureremoved
+     *     and featureremoved events will be triggered for each feature.  The
+     *     featuresremoved event will be triggered after all features have
+     *     been removed.  To supress event triggering, use the silent option.
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} List of features to be
+     *     removed.
+     * options - {Object} Optional properties for changing behavior of the
+     *     removal.
+     *
+     * Valid options:
+     * silent - {Boolean} Supress event triggering.  Default is false.
+     */
+    removeFeatures: function(features, options) {
+        if(!features || features.length === 0) {
+            return;
+        }
+        if (features === this.features) {
+            return this.removeAllFeatures(options);
+        }
+        if (!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        if (features === this.selectedFeatures) {
+            features = features.slice();
+        }
+
+        var notify = !options || !options.silent;
+        
+        if (notify) {
+            this.events.triggerEvent(
+                "beforefeaturesremoved", {features: features}
+            );
+        }
+
+        for (var i = features.length - 1; i >= 0; i--) {
+            // We remain locked so long as we're not at 0
+            // and the 'next' feature has a geometry. We do the geometry check
+            // because if all the features after the current one are 'null', we
+            // won't call eraseGeometry, so we break the 'renderer functions
+            // will always be called with locked=false *last*' rule. The end result
+            // is a possible gratiutious unlocking to save a loop through the rest 
+            // of the list checking the remaining features every time. So long as
+            // null geoms are rare, this is probably okay.    
+            if (i != 0 && features[i-1].geometry) {
+                this.renderer.locked = true;
+            } else {
+                this.renderer.locked = false;
+            }
+    
+            var feature = features[i];
+            delete this.unrenderedFeatures[feature.id];
+
+            if (notify) {
+                this.events.triggerEvent("beforefeatureremoved", {
+                    feature: feature
+                });
+            }
+
+            this.features = OpenLayers.Util.removeItem(this.features, feature);
+            // feature has no layer at this point
+            feature.layer = null;
+
+            if (feature.geometry) {
+                this.renderer.eraseFeatures(feature);
+            }
+                    
+            //in the case that this feature is one of the selected features, 
+            // remove it from that array as well.
+            if (OpenLayers.Util.indexOf(this.selectedFeatures, feature) != -1){
+                OpenLayers.Util.removeItem(this.selectedFeatures, feature);
+            }
+
+            if (notify) {
+                this.events.triggerEvent("featureremoved", {
+                    feature: feature
+                });
+            }
+        }
+
+        if (notify) {
+            this.events.triggerEvent("featuresremoved", {features: features});
+        }
+    },
+    
+    /** 
+     * APIMethod: removeAllFeatures
+     * Remove all features from the layer.
+     *
+     * Parameters:
+     * options - {Object} Optional properties for changing behavior of the
+     *     removal.
+     *
+     * Valid options:
+     * silent - {Boolean} Supress event triggering.  Default is false.
+     */
+    removeAllFeatures: function(options) {
+        var notify = !options || !options.silent;
+        var features = this.features;
+        if (notify) {
+            this.events.triggerEvent(
+                "beforefeaturesremoved", {features: features}
+            );
+        }
+        var feature;
+        for (var i = features.length-1; i >= 0; i--) {
+            feature = features[i];
+            if (notify) {
+                this.events.triggerEvent("beforefeatureremoved", {
+                    feature: feature
+                });
+            }
+            feature.layer = null;
+            if (notify) {
+                this.events.triggerEvent("featureremoved", {
+                    feature: feature
+                });
+            }
+        }
+        this.renderer.clear();
+        this.features = [];
+        this.unrenderedFeatures = {};
+        this.selectedFeatures = [];
+        if (notify) {
+            this.events.triggerEvent("featuresremoved", {features: features});
+        }
+    },
+
+    /**
+     * APIMethod: destroyFeatures
+     * Erase and destroy features on the layer.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} An optional array of
+     *     features to destroy.  If not supplied, all features on the layer
+     *     will be destroyed.
+     * options - {Object}
+     */
+    destroyFeatures: function(features, options) {
+        var all = (features == undefined); // evaluates to true if
+                                           // features is null
+        if(all) {
+            features = this.features;
+        }
+        if(features) {
+            this.removeFeatures(features, options);
+            for(var i=features.length-1; i>=0; i--) {
+                features[i].destroy();
+            }
+        }
+    },
+
+    /**
+     * APIMethod: drawFeature
+     * Draw (or redraw) a feature on the layer.  If the optional style argument
+     * is included, this style will be used.  If no style is included, the
+     * feature's style will be used.  If the feature doesn't have a style,
+     * the layer's style will be used.
+     * 
+     * This function is not designed to be used when adding features to 
+     * the layer (use addFeatures instead). It is meant to be used when
+     * the style of a feature has changed, or in some other way needs to 
+     * visually updated *after* it has already been added to a layer. You
+     * must add the feature to the layer for most layer-related events to 
+     * happen.
+     *
+     * Parameters: 
+     * feature - {<OpenLayers.Feature.Vector>} 
+     * style - {String | Object} Named render intent or full symbolizer object.
+     */
+    drawFeature: function(feature, style) {
+        // don't try to draw the feature with the renderer if the layer is not 
+        // drawn itself
+        if (!this.drawn) {
+            return;
+        }
+        if (typeof style != "object") {
+            if(!style && feature.state === OpenLayers.State.DELETE) {
+                style = "delete";
+            }
+            var renderIntent = style || feature.renderIntent;
+            style = feature.style || this.style;
+            if (!style) {
+                style = this.styleMap.createSymbolizer(feature, renderIntent);
+            }
+        }
+        
+        var drawn = this.renderer.drawFeature(feature, style);
+        //TODO remove the check for null when we get rid of Renderer.SVG
+        if (drawn === false || drawn === null) {
+            this.unrenderedFeatures[feature.id] = feature;
+        } else {
+            delete this.unrenderedFeatures[feature.id];
+        }
+    },
+    
+    /**
+     * Method: eraseFeatures
+     * Erase features from the layer.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    eraseFeatures: function(features) {
+        this.renderer.eraseFeatures(features);
+    },
+
+    /**
+     * Method: getFeatureFromEvent
+     * Given an event, return a feature if the event occurred over one.
+     * Otherwise, return null.
+     *
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature if one was under the event.
+     */
+    getFeatureFromEvent: function(evt) {
+        if (!this.renderer) {
+            OpenLayers.Console.error(OpenLayers.i18n("getFeatureError")); 
+            return null;
+        }
+        var feature = null;
+        var featureId = this.renderer.getFeatureIdFromEvent(evt);
+        if (featureId) {
+            if (typeof featureId === "string") {
+                feature = this.getFeatureById(featureId);
+            } else {
+                feature = featureId;
+            }
+        }
+        return feature;
+    },
+
+    /**
+     * APIMethod: getFeatureBy
+     * Given a property value, return the feature if it exists in the features array
+     *
+     * Parameters:
+     * property - {String}
+     * value - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+     * property value or null if there is no such feature.
+     */
+    getFeatureBy: function(property, value) {
+        //TBD - would it be more efficient to use a hash for this.features?
+        var feature = null;
+        for(var i=0, len=this.features.length; i<len; ++i) {
+            if(this.features[i][property] == value) {
+                feature = this.features[i];
+                break;
+            }
+        }
+        return feature;
+    },
+
+    /**
+     * APIMethod: getFeatureById
+     * Given a feature id, return the feature if it exists in the features array
+     *
+     * Parameters:
+     * featureId - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+     * featureId or null if there is no such feature.
+     */
+    getFeatureById: function(featureId) {
+        return this.getFeatureBy('id', featureId);
+    },
+
+    /**
+     * APIMethod: getFeatureByFid
+     * Given a feature fid, return the feature if it exists in the features array
+     *
+     * Parameters:
+     * featureFid - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+     * featureFid or null if there is no such feature.
+     */
+    getFeatureByFid: function(featureFid) {
+        return this.getFeatureBy('fid', featureFid);
+    },
+    
+    /**
+     * APIMethod: getFeaturesByAttribute
+     * Returns an array of features that have the given attribute key set to the
+     * given value. Comparison of attribute values takes care of datatypes, e.g.
+     * the string '1234' is not equal to the number 1234.
+     *
+     * Parameters:
+     * attrName - {String}
+     * attrValue - {Mixed}
+     *
+     * Returns:
+     * Array(<OpenLayers.Feature.Vector>) An array of features that have the 
+     * passed named attribute set to the given value.
+     */
+    getFeaturesByAttribute: function(attrName, attrValue) {
+        var i,
+            feature,    
+            len = this.features.length,
+            foundFeatures = [];
+        for(i = 0; i < len; i++) {            
+            feature = this.features[i];
+            if(feature && feature.attributes) {
+                if (feature.attributes[attrName] === attrValue) {
+                    foundFeatures.push(feature);
+                }
+            }
+        }
+        return foundFeatures;
+    },
+
+    /**
+     * Unselect the selected features
+     * i.e. clears the featureSelection array
+     * change the style back
+    clearSelection: function() {
+
+       var vectorLayer = this.map.vectorLayer;
+        for (var i = 0; i < this.map.featureSelection.length; i++) {
+            var featureSelection = this.map.featureSelection[i];
+            vectorLayer.drawFeature(featureSelection, vectorLayer.style);
+        }
+        this.map.featureSelection = [];
+    },
+     */
+
+
+    /**
+     * APIMethod: onFeatureInsert
+     * method called after a feature is inserted.
+     * Does nothing by default. Override this if you
+     * need to do something on feature updates.
+     *
+     * Paarameters: 
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    onFeatureInsert: function(feature) {
+    },
+    
+    /**
+     * APIMethod: preFeatureInsert
+     * method called before a feature is inserted.
+     * Does nothing by default. Override this if you
+     * need to do something when features are first added to the
+     * layer, but before they are drawn, such as adjust the style.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    preFeatureInsert: function(feature) {
+    },
+
+    /** 
+     * APIMethod: getDataExtent
+     * Calculates the max extent which includes all of the features.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} or null if the layer has no features with
+     * geometries.
+     */
+    getDataExtent: function () {
+        var maxExtent = null;
+        var features = this.features;
+        if(features && (features.length > 0)) {
+            var geometry = null;
+            for(var i=0, len=features.length; i<len; i++) {
+                geometry = features[i].geometry;
+                if (geometry) {
+                    if (maxExtent === null) {
+                        maxExtent = new OpenLayers.Bounds();
+                    }
+                    maxExtent.extend(geometry.getBounds());
+                }
+            }
+        }
+        return maxExtent;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Vector"
+});
+/* ======================================================================
+    OpenLayers/Layer/Vector/RootContainer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Vector.RootContainer
+ * A special layer type to combine multiple vector layers inside a single
+ *     renderer root container. This class is not supposed to be instantiated
+ *     from user space, it is a helper class for controls that require event
+ *     processing for multiple vector layers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Vector>
+ */
+OpenLayers.Layer.Vector.RootContainer = OpenLayers.Class(OpenLayers.Layer.Vector, {
+    
+    /**
+     * Property: displayInLayerSwitcher
+     * Set to false for this layer type
+     */
+    displayInLayerSwitcher: false,
+    
+    /**
+     * APIProperty: layers
+     * Layers that are attached to this container. Required config option.
+     */
+    layers: null,
+    
+    /**
+     * Constructor: OpenLayers.Layer.Vector.RootContainer
+     * Create a new root container for multiple vector layer. This constructor
+     * is not supposed to be used from user space, it is only to be used by
+     * controls that need feature selection across multiple vector layers.
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * options - {Object} Optional object with non-default properties to set on
+     *           the layer.
+     * 
+     * Required options properties:
+     * layers - {Array(<OpenLayers.Layer.Vector>)} The layers managed by this
+     *     container
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Vector.RootContainer>} A new vector layer root
+     *     container
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
+    },
+    
+    /**
+     * Method: display
+     */
+    display: function() {},
+    
+    /**
+     * Method: getFeatureFromEvent
+     * walk through the layers to find the feature returned by the event
+     * 
+     * Parameters:
+     * evt - {Object} event object with a feature property
+     * 
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    getFeatureFromEvent: function(evt) {
+        var layers = this.layers;
+        var feature;
+        for(var i=0; i<layers.length; i++) {
+            feature = layers[i].getFeatureFromEvent(evt);
+            if(feature) {
+                return feature;
+            }
+        }
+    },
+    
+    /**
+     * Method: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
+        this.collectRoots();
+        map.events.register("changelayer", this, this.handleChangeLayer);
+    },
+    
+    /**
+     * Method: removeMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        map.events.unregister("changelayer", this, this.handleChangeLayer);
+        this.resetRoots();
+        OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
+    },
+    
+    /**
+     * Method: collectRoots
+     * Collects the root nodes of all layers this control is configured with
+     * and moveswien the nodes to this control's layer
+     */
+    collectRoots: function() {
+        var layer;
+        // walk through all map layers, because we want to keep the order
+        for(var i=0; i<this.map.layers.length; ++i) {
+            layer = this.map.layers[i];
+            if(OpenLayers.Util.indexOf(this.layers, layer) != -1) {
+                layer.renderer.moveRoot(this.renderer);
+            }
+        }
+    },
+    
+    /**
+     * Method: resetRoots
+     * Resets the root nodes back into the layers they belong to.
+     */
+    resetRoots: function() {
+        var layer;
+        for(var i=0; i<this.layers.length; ++i) {
+            layer = this.layers[i];
+            if(this.renderer && layer.renderer.getRenderLayerId() == this.id) {
+                this.renderer.moveRoot(layer.renderer);
+            }
+        }
+    },
+    
+    /**
+     * Method: handleChangeLayer
+     * Event handler for the map's changelayer event. We need to rebuild
+     * this container's layer dom if order of one of its layers changes.
+     * This handler is added with the setMap method, and removed with the
+     * removeMap method.
+     * 
+     * Parameters:
+     * evt - {Object}
+     */
+    handleChangeLayer: function(evt) {
+        var layer = evt.layer;
+        if(evt.property == "order" &&
+                        OpenLayers.Util.indexOf(this.layers, layer) != -1) {
+            this.resetRoots();
+            this.collectRoots();
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Vector.RootContainer"
+});
+/* ======================================================================
+    OpenLayers/Control/SelectFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Handler/Feature.js
+ * @requires OpenLayers/Layer/Vector/RootContainer.js
+ */
+
+/**
+ * Class: OpenLayers.Control.SelectFeature
+ * The SelectFeature control selects vector features from a given layer on 
+ * click or hover. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     *  - *beforefeaturehighlighted* Triggered before a feature is highlighted
+     *  - *featurehighlighted* Triggered when a feature is highlighted
+     *  - *featureunhighlighted* Triggered when a feature is unhighlighted
+     */
+    EVENT_TYPES: ["beforefeaturehighlighted", "featurehighlighted", "featureunhighlighted"],
+    
+    /**
+     * Property: multipleKey
+     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+     *     the <multiple> property to true.  Default is null.
+     */
+    multipleKey: null,
+    
+    /**
+     * Property: toggleKey
+     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+     *     the <toggle> property to true.  Default is null.
+     */
+    toggleKey: null,
+    
+    /**
+     * APIProperty: multiple
+     * {Boolean} Allow selection of multiple geometries.  Default is false.
+     */
+    multiple: false, 
+
+    /**
+     * APIProperty: clickout
+     * {Boolean} Unselect features when clicking outside any feature.
+     *     Default is true.
+     */
+    clickout: true,
+
+    /**
+     * APIProperty: toggle
+     * {Boolean} Unselect a selected feature on click.  Default is false.  Only
+     *     has meaning if hover is false.
+     */
+    toggle: false,
+
+    /**
+     * APIProperty: hover
+     * {Boolean} Select on mouse over and deselect on mouse out.  If true, this
+     * ignores clicks and only listens to mouse moves.
+     */
+    hover: false,
+
+    /**
+     * APIProperty: highlightOnly
+     * {Boolean} If true do not actually select features (that is place them in 
+     * the layer's selected features array), just highlight them. This property
+     * has no effect if hover is false. Defaults to false.
+     */
+    highlightOnly: false,
+    
+    /**
+     * APIProperty: box
+     * {Boolean} Allow feature selection by drawing a box.
+     */
+    box: false,
+    
+    /**
+     * Property: onBeforeSelect 
+     * {Function} Optional function to be called before a feature is selected.
+     *     The function should expect to be called with a feature.
+     */
+    onBeforeSelect: function() {},
+    
+    /**
+     * APIProperty: onSelect 
+     * {Function} Optional function to be called when a feature is selected.
+     *     The function should expect to be called with a feature.
+     */
+    onSelect: function() {},
+
+    /**
+     * APIProperty: onUnselect
+     * {Function} Optional function to be called when a feature is unselected.
+     *     The function should expect to be called with a feature.
+     */
+    onUnselect: function() {},
+    
+    /**
+     * Property: scope
+     * {Object} The scope to use with the onBeforeSelect, onSelect, onUnselect
+     *     callbacks. If null the scope will be this control.
+     */
+    scope: null,
+
+    /**
+     * APIProperty: geometryTypes
+     * {Array(String)} To restrict selecting to a limited set of geometry types,
+     *     send a list of strings corresponding to the geometry class names.
+     */
+    geometryTypes: null,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>} The vector layer with a common renderer
+     * root for all layers this control is configured with (if an array of
+     * layers was passed to the constructor), or the vector layer the control
+     * was configured with (if a single layer was passed to the constructor).
+     */
+    layer: null,
+    
+    /**
+     * Property: layers
+     * {Array(<OpenLayers.Layer.Vector>)} The layers this control will work on,
+     * or null if the control was configured with a single layer
+     */
+    layers: null,
+    
+    /**
+     * APIProperty: callbacks
+     * {Object} The functions that are sent to the handlers.feature for callback
+     */
+    callbacks: null,
+    
+    /**
+     * APIProperty: selectStyle 
+     * {Object} Hash of styles
+     */
+    selectStyle: null,
+    
+    /**
+     * Property: renderIntent
+     * {String} key used to retrieve the select style from the layer's
+     * style map.
+     */
+    renderIntent: "select",
+
+    /**
+     * Property: handlers
+     * {Object} Object with references to multiple <OpenLayers.Handler>
+     *     instances.
+     */
+    handlers: null,
+
+    /**
+     * Constructor: OpenLayers.Control.SelectFeature
+     * Create a new control for selecting features.
+     *
+     * Parameters:
+     * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers. The
+     *     layer(s) this control will select features from.
+     * options - {Object} 
+     */
+    initialize: function(layers, options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.SelectFeature.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        if(this.scope === null) {
+            this.scope = this;
+        }
+        this.initLayer(layers);
+        var callbacks = {
+            click: this.clickFeature,
+            clickout: this.clickoutFeature
+        };
+        if (this.hover) {
+            callbacks.over = this.overFeature;
+            callbacks.out = this.outFeature;
+        }
+             
+        this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
+        this.handlers = {
+            feature: new OpenLayers.Handler.Feature(
+                this, this.layer, this.callbacks,
+                {geometryTypes: this.geometryTypes}
+            )
+        };
+
+        if (this.box) {
+            this.handlers.box = new OpenLayers.Handler.Box(
+                this, {done: this.selectBox},
+                {boxDivClassName: "olHandlerBoxSelectFeature"}
+            ); 
+        }
+    },
+
+    /**
+     * Method: initLayer
+     * Assign the layer property. If layers is an array, we need to use
+     *     a RootContainer.
+     *
+     * Parameters:
+     * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers.
+     */
+    initLayer: function(layers) {
+        if(OpenLayers.Util.isArray(layers)) {
+            this.layers = layers;
+            this.layer = new OpenLayers.Layer.Vector.RootContainer(
+                this.id + "_container", {
+                    layers: layers
+                }
+            );
+        } else {
+            this.layer = layers;
+        }
+    },
+    
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        if(this.active && this.layers) {
+            this.map.removeLayer(this.layer);
+        }
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+        if(this.layers) {
+            this.layer.destroy();
+        }
+    },
+
+    /**
+     * Method: activate
+     * Activates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively activated.
+     */
+    activate: function () {
+        if (!this.active) {
+            if(this.layers) {
+                this.map.addLayer(this.layer);
+            }
+            this.handlers.feature.activate();
+            if(this.box && this.handlers.box) {
+                this.handlers.box.activate();
+            }
+        }
+        return OpenLayers.Control.prototype.activate.apply(
+            this, arguments
+        );
+    },
+
+    /**
+     * Method: deactivate
+     * Deactivates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively deactivated.
+     */
+    deactivate: function () {
+        if (this.active) {
+            this.handlers.feature.deactivate();
+            if(this.handlers.box) {
+                this.handlers.box.deactivate();
+            }
+            if(this.layers) {
+                this.map.removeLayer(this.layer);
+            }
+        }
+        return OpenLayers.Control.prototype.deactivate.apply(
+            this, arguments
+        );
+    },
+
+    /**
+     * Method: unselectAll
+     * Unselect all selected features.  To unselect all except for a single
+     *     feature, set the options.except property to the feature.
+     *
+     * Parameters:
+     * options - {Object} Optional configuration object.
+     */
+    unselectAll: function(options) {
+        // we'll want an option to supress notification here
+        var layers = this.layers || [this.layer];
+        var layer, feature;
+        for(var l=0; l<layers.length; ++l) {
+            layer = layers[l];
+            for(var i=layer.selectedFeatures.length-1; i>=0; --i) {
+                feature = layer.selectedFeatures[i];
+                if(!options || options.except != feature) {
+                    this.unselect(feature);
+                }
+            }
+        }
+    },
+
+    /**
+     * Method: clickFeature
+     * Called on click in a feature
+     * Only responds if this.hover is false.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    clickFeature: function(feature) {
+        if(!this.hover) {
+            var selected = (OpenLayers.Util.indexOf(
+                feature.layer.selectedFeatures, feature) > -1);
+            if(selected) {
+                if(this.toggleSelect()) {
+                    this.unselect(feature);
+                } else if(!this.multipleSelect()) {
+                    this.unselectAll({except: feature});
+                }
+            } else {
+                if(!this.multipleSelect()) {
+                    this.unselectAll({except: feature});
+                }
+                this.select(feature);
+            }
+        }
+    },
+
+    /**
+     * Method: multipleSelect
+     * Allow for multiple selected features based on <multiple> property and
+     *     <multipleKey> event modifier.
+     *
+     * Returns:
+     * {Boolean} Allow for multiple selected features.
+     */
+    multipleSelect: function() {
+        return this.multiple || (this.handlers.feature.evt &&
+                                 this.handlers.feature.evt[this.multipleKey]);
+    },
+    
+    /**
+     * Method: toggleSelect
+     * Event should toggle the selected state of a feature based on <toggle>
+     *     property and <toggleKey> event modifier.
+     *
+     * Returns:
+     * {Boolean} Toggle the selected state of a feature.
+     */
+    toggleSelect: function() {
+        return this.toggle || (this.handlers.feature.evt &&
+                               this.handlers.feature.evt[this.toggleKey]);
+    },
+
+    /**
+     * Method: clickoutFeature
+     * Called on click outside a previously clicked (selected) feature.
+     * Only responds if this.hover is false.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Vector.Feature>} 
+     */
+    clickoutFeature: function(feature) {
+        if(!this.hover && this.clickout) {
+            this.unselectAll();
+        }
+    },
+
+    /**
+     * Method: overFeature
+     * Called on over a feature.
+     * Only responds if this.hover is true.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    overFeature: function(feature) {
+        var layer = feature.layer;
+        if(this.hover) {
+            if(this.highlightOnly) {
+                this.highlight(feature);
+            } else if(OpenLayers.Util.indexOf(
+                layer.selectedFeatures, feature) == -1) {
+                this.select(feature);
+            }
+        }
+    },
+
+    /**
+     * Method: outFeature
+     * Called on out of a selected feature.
+     * Only responds if this.hover is true.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    outFeature: function(feature) {
+        if(this.hover) {
+            if(this.highlightOnly) {
+                // we do nothing if we're not the last highlighter of the
+                // feature
+                if(feature._lastHighlighter == this.id) {
+                    // if another select control had highlighted the feature before
+                    // we did it ourself then we use that control to highlight the
+                    // feature as it was before we highlighted it, else we just
+                    // unhighlight it
+                    if(feature._prevHighlighter &&
+                       feature._prevHighlighter != this.id) {
+                        delete feature._lastHighlighter;
+                        var control = this.map.getControl(
+                            feature._prevHighlighter);
+                        if(control) {
+                            control.highlight(feature);
+                        }
+                    } else {
+                        this.unhighlight(feature);
+                    }
+                }
+            } else {
+                this.unselect(feature);
+            }
+        }
+    },
+
+    /**
+     * Method: highlight
+     * Redraw feature with the select style.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    highlight: function(feature) {
+        var layer = feature.layer;
+        var cont = this.events.triggerEvent("beforefeaturehighlighted", {
+            feature : feature
+        });
+        if(cont !== false) {
+            feature._prevHighlighter = feature._lastHighlighter;
+            feature._lastHighlighter = this.id;
+            var style = this.selectStyle || this.renderIntent;
+            layer.drawFeature(feature, style);
+            this.events.triggerEvent("featurehighlighted", {feature : feature});
+        }
+    },
+
+    /**
+     * Method: unhighlight
+     * Redraw feature with the "default" style
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    unhighlight: function(feature) {
+        var layer = feature.layer;
+        // three cases:
+        // 1. there's no other highlighter, in that case _prev is undefined,
+        //    and we just need to undef _last
+        // 2. another control highlighted the feature after we did it, in
+        //    that case _last references this other control, and we just
+        //    need to undef _prev
+        // 3. another control highlighted the feature before we did it, in
+        //    that case _prev references this other control, and we need to
+        //    set _last to _prev and undef _prev
+        if(feature._prevHighlighter == undefined) {
+            delete feature._lastHighlighter;
+        } else if(feature._prevHighlighter == this.id) {
+            delete feature._prevHighlighter;
+        } else {
+            feature._lastHighlighter = feature._prevHighlighter;
+            delete feature._prevHighlighter;
+        }
+        layer.drawFeature(feature, feature.style || feature.layer.style ||
+            "default");
+        this.events.triggerEvent("featureunhighlighted", {feature : feature});
+    },
+    
+    /**
+     * Method: select
+     * Add feature to the layer's selectedFeature array, render the feature as
+     * selected, and call the onSelect function.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    select: function(feature) {
+        var cont = this.onBeforeSelect.call(this.scope, feature);
+        var layer = feature.layer;
+        if(cont !== false) {
+            cont = layer.events.triggerEvent("beforefeatureselected", {
+                feature: feature
+            });
+            if(cont !== false) {
+                layer.selectedFeatures.push(feature);
+                this.highlight(feature);
+                // if the feature handler isn't involved in the feature
+                // selection (because the box handler is used or the
+                // feature is selected programatically) we fake the
+                // feature handler to allow unselecting on click
+                if(!this.handlers.feature.lastFeature) {
+                    this.handlers.feature.lastFeature = layer.selectedFeatures[0];
+                }
+                layer.events.triggerEvent("featureselected", {feature: feature});
+                this.onSelect.call(this.scope, feature);
+            }
+        }
+    },
+
+    /**
+     * Method: unselect
+     * Remove feature from the layer's selectedFeature array, render the feature as
+     * normal, and call the onUnselect function.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    unselect: function(feature) {
+        var layer = feature.layer;
+        // Store feature style for restoration later
+        this.unhighlight(feature);
+        OpenLayers.Util.removeItem(layer.selectedFeatures, feature);
+        layer.events.triggerEvent("featureunselected", {feature: feature});
+        this.onUnselect.call(this.scope, feature);
+    },
+    
+    /**
+     * Method: selectBox
+     * Callback from the handlers.box set up when <box> selection is true
+     *     on.
+     *
+     * Parameters:
+     * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }  
+     */
+    selectBox: function(position) {
+        if (position instanceof OpenLayers.Bounds) {
+            var minXY = this.map.getLonLatFromPixel(
+                new OpenLayers.Pixel(position.left, position.bottom)
+            );
+            var maxXY = this.map.getLonLatFromPixel(
+                new OpenLayers.Pixel(position.right, position.top)
+            );
+            var bounds = new OpenLayers.Bounds(
+                minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
+            );
+            
+            // if multiple is false, first deselect currently selected features
+            if (!this.multipleSelect()) {
+                this.unselectAll();
+            }
+            
+            // because we're using a box, we consider we want multiple selection
+            var prevMultiple = this.multiple;
+            this.multiple = true;
+            var layers = this.layers || [this.layer];
+            var layer;
+            for(var l=0; l<layers.length; ++l) {
+                layer = layers[l];
+                for(var i=0, len = layer.features.length; i<len; ++i) {
+                    var feature = layer.features[i];
+                    // check if the feature is displayed
+                    if (!feature.getVisibility()) {
+                        continue;
+                    }
+
+                    if (this.geometryTypes == null || OpenLayers.Util.indexOf(
+                            this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
+                        if (bounds.toGeometry().intersects(feature.geometry)) {
+                            if (OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1) {
+                                this.select(feature);
+                            }
+                        }
+                    }
+                }
+            }
+            this.multiple = prevMultiple;
+        }
+    },
+
+    /** 
+     * Method: setMap
+     * Set the map property for the control. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        this.handlers.feature.setMap(map);
+        if (this.box) {
+            this.handlers.box.setMap(map);
+        }
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+    
+    /**
+     * APIMethod: setLayer
+     * Attach a new layer to the control, overriding any existing layers.
+     *
+     * Parameters:
+     * layers - Array of {<OpenLayers.Layer.Vector>} or a single
+     *     {<OpenLayers.Layer.Vector>}
+     */
+    setLayer: function(layers) {
+        var isActive = this.active;
+        this.unselectAll();
+        this.deactivate();
+        if(this.layers) {
+            this.layer.destroy();
+            this.layers = null;
+        }
+        this.initLayer(layers);
+        this.handlers.feature.layer = this.layer;
+        if (isActive) {
+            this.activate();
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Control.SelectFeature"
+});
+/* ======================================================================
+    OpenLayers/Handler/Keyboard.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ * @requires OpenLayers/Events.js
+ */
+
+/**
+ * Class: OpenLayers.handler.Keyboard
+ * A handler for keyboard events.  Create a new instance with the
+ *     <OpenLayers.Handler.Keyboard> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler> 
+ */
+OpenLayers.Handler.Keyboard = OpenLayers.Class(OpenLayers.Handler, {
+
+    /* http://www.quirksmode.org/js/keys.html explains key x-browser
+        key handling quirks in pretty nice detail */
+
+    /** 
+     * Constant: KEY_EVENTS
+     * keydown, keypress, keyup
+     */
+    KEY_EVENTS: ["keydown", "keyup"],
+
+    /** 
+    * Property: eventListener
+    * {Function}
+    */
+    eventListener: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Keyboard
+     * Returns a new keyboard handler.
+     * 
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that is making use of
+     *     this handler.  If a handler is being used without a control, the
+     *     handlers setMap method must be overridden to deal properly with
+     *     the map.
+     * callbacks - {Object} An object containing a single function to be
+     *     called when the drag operation is finished. The callback should
+     *     expect to recieve a single argument, the pixel location of the event.
+     *     Callbacks for 'keydown', 'keypress', and 'keyup' are supported.
+     * options - {Object} Optional object whose properties will be set on the
+     *     handler.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+        // cache the bound event listener method so it can be unobserved later
+        this.eventListener = OpenLayers.Function.bindAsEventListener(
+            this.handleKeyEvent, this
+        );
+    },
+    
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        this.deactivate();
+        this.eventListener = null;
+        OpenLayers.Handler.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: activate
+     */
+    activate: function() {
+        if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            for (var i=0, len=this.KEY_EVENTS.length; i<len; i++) {
+                OpenLayers.Event.observe(
+                    document, this.KEY_EVENTS[i], this.eventListener);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    /**
+     * Method: deactivate
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            for (var i=0, len=this.KEY_EVENTS.length; i<len; i++) {
+                OpenLayers.Event.stopObserving(
+                    document, this.KEY_EVENTS[i], this.eventListener);
+            }
+            deactivated = true;
+        }
+        return deactivated;
+    },
+
+    /**
+     * Method: handleKeyEvent 
+     */
+    handleKeyEvent: function (evt) {
+        if (this.checkModifiers(evt)) {
+            this.callback(evt.type, [evt]);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Keyboard"
+});
+/* ======================================================================
+    OpenLayers/Control/ModifyFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/DragFeature.js
+ * @requires OpenLayers/Control/SelectFeature.js
+ * @requires OpenLayers/Handler/Keyboard.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ModifyFeature
+ * Control to modify features.  When activated, a click renders the vertices
+ *     of a feature - these vertices can then be dragged.  By default, the
+ *     delete key will delete the vertex under the mouse.  New features are
+ *     added by dragging "virtual vertices" between vertices.  Create a new
+ *     control with the <OpenLayers.Control.ModifyFeature> constructor.
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: geometryTypes
+     * {Array(String)} To restrict modification to a limited set of geometry
+     *     types, send a list of strings corresponding to the geometry class
+     *     names.
+     */
+    geometryTypes: null,
+
+    /**
+     * APIProperty: clickout
+     * {Boolean} Unselect features when clicking outside any feature.
+     *     Default is true.
+     */
+    clickout: true,
+
+    /**
+     * APIProperty: toggle
+     * {Boolean} Unselect a selected feature on click.
+     *      Default is true.
+     */
+    toggle: true,
+    
+    /**
+     * APIProperty: standalone
+     * {Boolean} Set to true to create a control without SelectFeature
+     *     capabilities. Default is false.  If standalone is true, to modify
+     *     a feature, call the <selectFeature> method with the target feature.
+     *     Note that you must call the <unselectFeature> method to finish
+     *     feature modification in standalone mode (before starting to modify
+     *     another feature).
+     */
+    standalone: false,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>}
+     */
+    layer: null,
+    
+    /**
+     * Property: feature
+     * {<OpenLayers.Feature.Vector>} Feature currently available for modification.
+     */
+    feature: null,
+    
+    /**
+     * Property: vertices
+     * {Array(<OpenLayers.Feature.Vector>)} Verticies currently available
+     *     for dragging.
+     */
+    vertices: null,
+    
+    /**
+     * Property: virtualVertices
+     * {Array(<OpenLayers.Feature.Vector>)} Virtual vertices in the middle
+     *     of each edge.
+     */
+    virtualVertices: null,
+
+    /**
+     * Property: selectControl
+     * {<OpenLayers.Control.SelectFeature>}
+     */
+    selectControl: null,
+    
+    /**
+     * Property: dragControl
+     * {<OpenLayers.Control.DragFeature>}
+     */
+    dragControl: null,
+    
+    /**
+     * Property: handlers
+     * {Object}
+     */
+    handlers: null,
+    
+    /**
+     * APIProperty: deleteCodes
+     * {Array(Integer)} Keycodes for deleting verticies.  Set to null to disable
+     *     vertex deltion by keypress.  If non-null, keypresses with codes
+     *     in this array will delete vertices under the mouse. Default
+     *     is 46 and 68, the 'delete' and lowercase 'd' keys.
+     */
+    deleteCodes: null,
+
+    /**
+     * APIProperty: virtualStyle
+     * {Object} A symbolizer to be used for virtual vertices.
+     */
+    virtualStyle: null,
+    
+    /**
+     * APIProperty: vertexRenderIntent
+     * {String} The renderIntent to use for vertices. If no <virtualStyle> is
+     * provided, this renderIntent will also be used for virtual vertices, with
+     * a fillOpacity and strokeOpacity of 0.3. Default is null, which means
+     * that the layer's default style will be used for vertices.
+     */
+    vertexRenderIntent: null,
+
+    /**
+     * APIProperty: mode
+     * {Integer} Bitfields specifying the modification mode. Defaults to
+     *      OpenLayers.Control.ModifyFeature.RESHAPE. To set the mode to a
+     *      combination of options, use the | operator. For example, to allow
+     *      the control to both resize and rotate features, use the following
+     *      syntax
+     * (code)
+     * control.mode = OpenLayers.Control.ModifyFeature.RESIZE |
+     *                OpenLayers.Control.ModifyFeature.ROTATE;
+     *  (end)
+     */
+    mode: null,
+
+    /**
+     * Property: modified
+     * {Boolean} The currently selected feature has been modified.
+     */
+    modified: false,
+
+    /**
+     * Property: radiusHandle
+     * {<OpenLayers.Feature.Vector>} A handle for rotating/resizing a feature.
+     */
+    radiusHandle: null,
+
+    /**
+     * Property: dragHandle
+     * {<OpenLayers.Feature.Vector>} A handle for dragging a feature.
+     */
+    dragHandle: null,
+
+    /**
+     * APIProperty: onModificationStart 
+     * {Function} *Deprecated*.  Register for "beforefeaturemodified" instead.
+     *     The "beforefeaturemodified" event is triggered on the layer before
+     *     any modification begins.
+     *
+     * Optional function to be called when a feature is selected
+     *     to be modified. The function should expect to be called with a
+     *     feature.  This could be used for example to allow to lock the
+     *     feature on server-side.
+     */
+    onModificationStart: function() {},
+
+    /**
+     * APIProperty: onModification
+     * {Function} *Deprecated*.  Register for "featuremodified" instead.
+     *     The "featuremodified" event is triggered on the layer with each
+     *     feature modification.
+     *
+     * Optional function to be called when a feature has been
+     *     modified.  The function should expect to be called with a feature.
+     */
+    onModification: function() {},
+
+    /**
+     * APIProperty: onModificationEnd
+     * {Function} *Deprecated*.  Register for "afterfeaturemodified" instead.
+     *     The "afterfeaturemodified" event is triggered on the layer after
+     *     a feature has been modified.
+     *
+     * Optional function to be called when a feature is finished 
+     *     being modified.  The function should expect to be called with a
+     *     feature.
+     */
+    onModificationEnd: function() {},
+
+    /**
+     * Constructor: OpenLayers.Control.ModifyFeature
+     * Create a new modify feature control.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} Layer that contains features that
+     *     will be modified.
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+    initialize: function(layer, options) {
+        options = options || {};
+        this.layer = layer;
+        this.vertices = [];
+        this.virtualVertices = [];
+        this.virtualStyle = OpenLayers.Util.extend({},
+            this.layer.style ||
+            this.layer.styleMap.createSymbolizer(null, options.vertexRenderIntent)
+        );
+        this.virtualStyle.fillOpacity = 0.3;
+        this.virtualStyle.strokeOpacity = 0.3;
+        this.deleteCodes = [46, 68];
+        this.mode = OpenLayers.Control.ModifyFeature.RESHAPE;
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        if(!(OpenLayers.Util.isArray(this.deleteCodes))) {
+            this.deleteCodes = [this.deleteCodes];
+        }
+        var control = this;
+
+        // configure the select control
+        var selectOptions = {
+            geometryTypes: this.geometryTypes,
+            clickout: this.clickout,
+            toggle: this.toggle,
+            onBeforeSelect: this.beforeSelectFeature,
+            onSelect: this.selectFeature,
+            onUnselect: this.unselectFeature,
+            scope: this
+        };
+        if(this.standalone === false) {
+            this.selectControl = new OpenLayers.Control.SelectFeature(
+                layer, selectOptions
+            );
+        }
+
+        // configure the drag control
+        var dragOptions = {
+            geometryTypes: ["OpenLayers.Geometry.Point"],
+            snappingOptions: this.snappingOptions,
+            onStart: function(feature, pixel) {
+                control.dragStart.apply(control, [feature, pixel]);
+            },
+            onDrag: function(feature, pixel) {
+                control.dragVertex.apply(control, [feature, pixel]);
+            },
+            onComplete: function(feature) {
+                control.dragComplete.apply(control, [feature]);
+            },
+            featureCallbacks: {
+                over: function(feature) {
+                    /**
+                     * In normal mode, the feature handler is set up to allow
+                     * dragging of all points.  In standalone mode, we only
+                     * want to allow dragging of sketch vertices and virtual
+                     * vertices - or, in the case of a modifiable point, the
+                     * point itself.
+                     */
+                    if(control.standalone !== true || feature._sketch ||
+                       control.feature === feature) {
+                        control.dragControl.overFeature.apply(
+                            control.dragControl, [feature]);
+                    }
+                }
+            }
+        };
+        this.dragControl = new OpenLayers.Control.DragFeature(
+            layer, dragOptions
+        );
+
+        // configure the keyboard handler
+        var keyboardOptions = {
+            keydown: this.handleKeypress
+        };
+        this.handlers = {
+            keyboard: new OpenLayers.Handler.Keyboard(this, keyboardOptions)
+        };
+    },
+
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass.
+     */
+    destroy: function() {
+        this.layer = null;
+        this.standalone || this.selectControl.destroy();
+        this.dragControl.destroy();
+        OpenLayers.Control.prototype.destroy.apply(this, []);
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the control.
+     * 
+     * Returns:
+     * {Boolean} Successfully activated the control.
+     */
+    activate: function() {
+        return ((this.standalone || this.selectControl.activate()) &&
+                this.handlers.keyboard.activate() &&
+                OpenLayers.Control.prototype.activate.apply(this, arguments));
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control.
+     *
+     * Returns: 
+     * {Boolean} Successfully deactivated the control.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        // the return from the controls is unimportant in this case
+        if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.layer.removeFeatures(this.vertices, {silent: true});
+            this.layer.removeFeatures(this.virtualVertices, {silent: true});
+            this.vertices = [];
+            this.dragControl.deactivate();
+            var feature = this.feature;
+            var valid = feature && feature.geometry && feature.layer;
+            if(this.standalone === false) {
+                if(valid) {
+                    this.selectControl.unselect.apply(this.selectControl,
+                                                      [feature]);
+                }
+                this.selectControl.deactivate();
+            } else {
+                if(valid) {
+                    this.unselectFeature(feature);
+                }
+            }
+            this.handlers.keyboard.deactivate();
+            deactivated = true;
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: beforeSelectFeature
+     * Called before a feature is selected.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature about to be selected.
+     */
+    beforeSelectFeature: function(feature) {
+        return this.layer.events.triggerEvent(
+            "beforefeaturemodified", {feature: feature}
+        );
+    },
+
+    /**
+     * APIMethod: selectFeature
+     * Select a feature for modification in standalone mode. In non-standalone
+     * mode, this method is called when the select feature control selects a
+     * feature. Register a listener to the beforefeaturemodified event and
+     * return false to prevent feature modification.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} the selected feature.
+     */
+    selectFeature: function(feature) {
+        if (!this.standalone || this.beforeSelectFeature(feature) !== false) {
+            this.feature = feature;
+            this.modified = false;
+            this.resetVertices();
+            this.dragControl.activate();
+            this.onModificationStart(this.feature);
+        }
+        // keep track of geometry modifications
+        var modified = feature.modified;
+        if (feature.geometry && !(modified && modified.geometry)) {
+            this._originalGeometry = feature.geometry.clone();
+        }
+    },
+
+    /**
+     * Method: unselectFeature
+     * Called when the select feature control unselects a feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The unselected feature.
+     */
+    unselectFeature: function(feature) {
+        this.layer.removeFeatures(this.vertices, {silent: true});
+        this.vertices = [];
+        this.layer.destroyFeatures(this.virtualVertices, {silent: true});
+        this.virtualVertices = [];
+        if(this.dragHandle) {
+            this.layer.destroyFeatures([this.dragHandle], {silent: true});
+            delete this.dragHandle;
+        }
+        if(this.radiusHandle) {
+            this.layer.destroyFeatures([this.radiusHandle], {silent: true});
+            delete this.radiusHandle;
+        }
+        this.feature = null;
+        this.dragControl.deactivate();
+        this.onModificationEnd(feature);
+        this.layer.events.triggerEvent("afterfeaturemodified", {
+            feature: feature,
+            modified: this.modified
+        });
+        this.modified = false;
+    },
+
+    /**
+     * Method: dragStart
+     * Called by the drag feature control with before a feature is dragged.
+     *     This method is used to differentiate between points and vertices
+     *     of higher order geometries.  This respects the <geometryTypes>
+     *     property and forces a select of points when the drag control is
+     *     already active (and stops events from propagating to the select
+     *     control).
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The point or vertex about to be
+     *     dragged.
+     * pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event.
+     */
+    dragStart: function(feature, pixel) {
+        // only change behavior if the feature is not in the vertices array
+        if(feature != this.feature && !feature.geometry.parent &&
+           feature != this.dragHandle && feature != this.radiusHandle) {
+            if(this.standalone === false && this.feature) {
+                // unselect the currently selected feature
+                this.selectControl.clickFeature.apply(this.selectControl,
+                                                      [this.feature]);
+            }
+            // check any constraints on the geometry type
+            if(this.geometryTypes == null ||
+               OpenLayers.Util.indexOf(this.geometryTypes,
+                                       feature.geometry.CLASS_NAME) != -1) {
+                // select the point
+                this.standalone || this.selectControl.clickFeature.apply(
+                                            this.selectControl, [feature]);
+                /**
+                 * TBD: These lines improve workflow by letting the user
+                 *     immediately start dragging after the mouse down.
+                 *     However, it is very ugly to be messing with controls
+                 *     and their handlers in this way.  I'd like a better
+                 *     solution if the workflow change is necessary.
+                 */
+                // prepare the point for dragging
+                this.dragControl.overFeature.apply(this.dragControl,
+                                                   [feature]);
+                this.dragControl.lastPixel = pixel;
+                this.dragControl.handlers.drag.started = true;
+                this.dragControl.handlers.drag.start = pixel;
+                this.dragControl.handlers.drag.last = pixel;
+            }
+        }
+    },
+    
+    /**
+     * Method: dragVertex
+     * Called by the drag feature control with each drag move of a vertex.
+     *
+     * Parameters:
+     * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
+     * pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event.
+     */
+    dragVertex: function(vertex, pixel) {
+        this.modified = true;
+        /**
+         * Five cases:
+         * 1) dragging a simple point
+         * 2) dragging a virtual vertex
+         * 3) dragging a drag handle
+         * 4) dragging a real vertex
+         * 5) dragging a radius handle
+         */
+        if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+            // dragging a simple point
+            if(this.feature != vertex) {
+                this.feature = vertex;
+            }
+            this.layer.events.triggerEvent("vertexmodified", {
+                vertex: vertex.geometry,
+                feature: this.feature,
+                pixel: pixel
+            });
+        } else {
+            if(vertex._index) {
+                // dragging a virtual vertex
+                vertex.geometry.parent.addComponent(vertex.geometry,
+                                                    vertex._index);
+                // move from virtual to real vertex
+                delete vertex._index;
+                OpenLayers.Util.removeItem(this.virtualVertices, vertex);
+                this.vertices.push(vertex);
+            } else if(vertex == this.dragHandle) {
+                // dragging a drag handle
+                this.layer.removeFeatures(this.vertices, {silent: true});
+                this.vertices = [];
+                if(this.radiusHandle) {
+                    this.layer.destroyFeatures([this.radiusHandle], {silent: true});
+                    this.radiusHandle = null;
+                }
+            } else if(vertex !== this.radiusHandle) {
+                // dragging a real vertex
+                this.layer.events.triggerEvent("vertexmodified", {
+                    vertex: vertex.geometry,
+                    feature: this.feature,
+                    pixel: pixel
+                });
+            }
+            // dragging a radius handle - no special treatment
+            if(this.virtualVertices.length > 0) {
+                this.layer.destroyFeatures(this.virtualVertices, {silent: true});
+                this.virtualVertices = [];
+            }
+            this.layer.drawFeature(this.feature, this.standalone ? undefined :
+                                            this.selectControl.renderIntent);
+        }
+        // keep the vertex on top so it gets the mouseout after dragging
+        // this should be removed in favor of an option to draw under or
+        // maintain node z-index
+        this.layer.drawFeature(vertex);
+    },
+    
+    /**
+     * Method: dragComplete
+     * Called by the drag feature control when the feature dragging is complete.
+     *
+     * Parameters:
+     * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
+     */
+    dragComplete: function(vertex) {
+        this.resetVertices();
+        this.setFeatureState();
+        this.onModification(this.feature);
+        this.layer.events.triggerEvent("featuremodified", 
+                                       {feature: this.feature});
+    },
+    
+    /**
+     * Method: setFeatureState
+     * Called when the feature is modified.  If the current state is not
+     *     INSERT or DELETE, the state is set to UPDATE.
+     */
+    setFeatureState: function() {
+        if(this.feature.state != OpenLayers.State.INSERT &&
+           this.feature.state != OpenLayers.State.DELETE) {
+            this.feature.state = OpenLayers.State.UPDATE;
+            if (this.modified && this._originalGeometry) {
+                var feature = this.feature;
+                feature.modified = OpenLayers.Util.extend(feature.modified, {
+                    geometry: this._originalGeometry
+                });
+                delete this._originalGeometry;
+            }
+        }
+    },
+    
+    /**
+     * Method: resetVertices
+     */
+    resetVertices: function() {
+        // if coming from a drag complete we're about to destroy the vertex
+        // that was just dragged. For that reason, the drag feature control
+        // will never detect a mouse-out on that vertex, meaning that the drag
+        // handler won't be deactivated. This can cause errors because the drag
+        // feature control still has a feature to drag but that feature is
+        // destroyed. To prevent this, we call outFeature on the drag feature
+        // control if the control actually has a feature to drag.
+        if(this.dragControl.feature) {
+            this.dragControl.outFeature(this.dragControl.feature);
+        }
+        if(this.vertices.length > 0) {
+            this.layer.removeFeatures(this.vertices, {silent: true});
+            this.vertices = [];
+        }
+        if(this.virtualVertices.length > 0) {
+            this.layer.removeFeatures(this.virtualVertices, {silent: true});
+            this.virtualVertices = [];
+        }
+        if(this.dragHandle) {
+            this.layer.destroyFeatures([this.dragHandle], {silent: true});
+            this.dragHandle = null;
+        }
+        if(this.radiusHandle) {
+            this.layer.destroyFeatures([this.radiusHandle], {silent: true});
+            this.radiusHandle = null;
+        }
+        if(this.feature &&
+           this.feature.geometry.CLASS_NAME != "OpenLayers.Geometry.Point") {
+            if((this.mode & OpenLayers.Control.ModifyFeature.DRAG)) {
+                this.collectDragHandle();
+            }
+            if((this.mode & (OpenLayers.Control.ModifyFeature.ROTATE |
+                             OpenLayers.Control.ModifyFeature.RESIZE))) {
+                this.collectRadiusHandle();
+            }
+            if(this.mode & OpenLayers.Control.ModifyFeature.RESHAPE){
+                // Don't collect vertices when we're resizing
+                if (!(this.mode & OpenLayers.Control.ModifyFeature.RESIZE)){
+                    this.collectVertices();
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: handleKeypress
+     * Called by the feature handler on keypress.  This is used to delete
+     *     vertices. If the <deleteCode> property is set, vertices will
+     *     be deleted when a feature is selected for modification and
+     *     the mouse is over a vertex.
+     *
+     * Parameters:
+     * {Integer} Key code corresponding to the keypress event.
+     */
+    handleKeypress: function(evt) {
+        var code = evt.keyCode;
+        
+        // check for delete key
+        if(this.feature &&
+           OpenLayers.Util.indexOf(this.deleteCodes, code) != -1) {
+            var vertex = this.dragControl.feature;
+            if(vertex &&
+               OpenLayers.Util.indexOf(this.vertices, vertex) != -1 &&
+               !this.dragControl.handlers.drag.dragging &&
+               vertex.geometry.parent) {
+                // remove the vertex
+                vertex.geometry.parent.removeComponent(vertex.geometry);
+                this.layer.events.triggerEvent("vertexremoved", {
+                    vertex: vertex.geometry,
+                    feature: this.feature,
+                    pixel: evt.xy
+                });
+                this.layer.drawFeature(this.feature, this.standalone ?
+                                       undefined :
+                                       this.selectControl.renderIntent);
+                this.modified = true;
+                this.resetVertices();
+                this.setFeatureState();
+                this.onModification(this.feature);
+                this.layer.events.triggerEvent("featuremodified", 
+                                               {feature: this.feature});
+            }
+        }
+    },
+
+    /**
+     * Method: collectVertices
+     * Collect the vertices from the modifiable feature's geometry and push
+     *     them on to the control's vertices array.
+     */
+    collectVertices: function() {
+        this.vertices = [];
+        this.virtualVertices = [];        
+        var control = this;
+        function collectComponentVertices(geometry) {
+            var i, vertex, component, len;
+            if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+                vertex = new OpenLayers.Feature.Vector(geometry);
+                vertex._sketch = true;
+                vertex.renderIntent = control.vertexRenderIntent;
+                control.vertices.push(vertex);
+            } else {
+                var numVert = geometry.components.length;
+                if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+                    numVert -= 1;
+                }
+                for(i=0; i<numVert; ++i) {
+                    component = geometry.components[i];
+                    if(component.CLASS_NAME == "OpenLayers.Geometry.Point") {
+                        vertex = new OpenLayers.Feature.Vector(component);
+                        vertex._sketch = true;
+                        vertex.renderIntent = control.vertexRenderIntent;
+                        control.vertices.push(vertex);
+                    } else {
+                        collectComponentVertices(component);
+                    }
+                }
+                
+                // add virtual vertices in the middle of each edge
+                if(geometry.CLASS_NAME != "OpenLayers.Geometry.MultiPoint") {
+                    for(i=0, len=geometry.components.length; i<len-1; ++i) {
+                        var prevVertex = geometry.components[i];
+                        var nextVertex = geometry.components[i + 1];
+                        if(prevVertex.CLASS_NAME == "OpenLayers.Geometry.Point" &&
+                           nextVertex.CLASS_NAME == "OpenLayers.Geometry.Point") {
+                            var x = (prevVertex.x + nextVertex.x) / 2;
+                            var y = (prevVertex.y + nextVertex.y) / 2;
+                            var point = new OpenLayers.Feature.Vector(
+                                new OpenLayers.Geometry.Point(x, y),
+                                null, control.virtualStyle
+                            );
+                            // set the virtual parent and intended index
+                            point.geometry.parent = geometry;
+                            point._index = i + 1;
+                            point._sketch = true;
+                            control.virtualVertices.push(point);
+                        }
+                    }
+                }
+            }
+        }
+        collectComponentVertices.call(this, this.feature.geometry);
+        this.layer.addFeatures(this.virtualVertices, {silent: true});
+        this.layer.addFeatures(this.vertices, {silent: true});
+    },
+
+    /**
+     * Method: collectDragHandle
+     * Collect the drag handle for the selected geometry.
+     */
+    collectDragHandle: function() {
+        var geometry = this.feature.geometry;
+        var center = geometry.getBounds().getCenterLonLat();
+        var originGeometry = new OpenLayers.Geometry.Point(
+            center.lon, center.lat
+        );
+        var origin = new OpenLayers.Feature.Vector(originGeometry);
+        originGeometry.move = function(x, y) {
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            geometry.move(x, y);
+        };
+        origin._sketch = true;
+        this.dragHandle = origin;
+        this.layer.addFeatures([this.dragHandle], {silent: true});
+    },
+
+    /**
+     * Method: collectRadiusHandle
+     * Collect the radius handle for the selected geometry.
+     */
+    collectRadiusHandle: function() {
+        var geometry = this.feature.geometry;
+        var bounds = geometry.getBounds();
+        var center = bounds.getCenterLonLat();
+        var originGeometry = new OpenLayers.Geometry.Point(
+            center.lon, center.lat
+        );
+        var radiusGeometry = new OpenLayers.Geometry.Point(
+            bounds.right, bounds.bottom
+        );
+        var radius = new OpenLayers.Feature.Vector(radiusGeometry);
+        var resize = (this.mode & OpenLayers.Control.ModifyFeature.RESIZE);
+        var reshape = (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE);
+        var rotate = (this.mode & OpenLayers.Control.ModifyFeature.ROTATE);
+
+        radiusGeometry.move = function(x, y) {
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            var dx1 = this.x - originGeometry.x;
+            var dy1 = this.y - originGeometry.y;
+            var dx0 = dx1 - x;
+            var dy0 = dy1 - y;
+            if(rotate) {
+                var a0 = Math.atan2(dy0, dx0);
+                var a1 = Math.atan2(dy1, dx1);
+                var angle = a1 - a0;
+                angle *= 180 / Math.PI;
+                geometry.rotate(angle, originGeometry);
+            }
+            if(resize) {
+                var scale, ratio;
+                // 'resize' together with 'reshape' implies that the aspect 
+                // ratio of the geometry will not be preserved whilst resizing 
+                if (reshape) {
+                    scale = dy1 / dy0;
+                    ratio = (dx1 / dx0) / scale;
+                } else {
+                    var l0 = Math.sqrt((dx0 * dx0) + (dy0 * dy0));
+                    var l1 = Math.sqrt((dx1 * dx1) + (dy1 * dy1));
+                    scale = l1 / l0;
+                }
+                geometry.resize(scale, originGeometry, ratio);
+            }
+        };
+        radius._sketch = true;
+        this.radiusHandle = radius;
+        this.layer.addFeatures([this.radiusHandle], {silent: true});
+    },
+
+    /**
+     * Method: setMap
+     * Set the map property for the control and all handlers.
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>} The control's map.
+     */
+    setMap: function(map) {
+        this.standalone || this.selectControl.setMap(map);
+        this.dragControl.setMap(map);
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ModifyFeature"
+});
+
+/**
+ * Constant: RESHAPE
+ * {Integer} Constant used to make the control work in reshape mode
+ */
+OpenLayers.Control.ModifyFeature.RESHAPE = 1;
+/**
+ * Constant: RESIZE
+ * {Integer} Constant used to make the control work in resize mode
+ */
+OpenLayers.Control.ModifyFeature.RESIZE = 2;
+/**
+ * Constant: ROTATE
+ * {Integer} Constant used to make the control work in rotate mode
+ */
+OpenLayers.Control.ModifyFeature.ROTATE = 4;
+/**
+ * Constant: DRAG
+ * {Integer} Constant used to make the control work in drag mode
+ */
+OpenLayers.Control.ModifyFeature.DRAG = 8;
+/* ======================================================================
+    OpenLayers/Layer/XYZ.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/** 
+ * Class: OpenLayers.Layer.XYZ
+ * The XYZ class is designed to make it easier for people who have tiles
+ * arranged by a standard XYZ grid. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, {
+    
+    /**
+     * APIProperty: isBaseLayer
+     * Default is true, as this is designed to be a base tile source. 
+     */
+    isBaseLayer: true,
+    
+    /**
+     * APIProperty: sphericalMecator
+     * Whether the tile extents should be set to the defaults for 
+     *    spherical mercator. Useful for things like OpenStreetMap.
+     *    Default is false, except for the OSM subclass.
+     */
+    sphericalMercator: false,
+
+    /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more zoom levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
+     *     setting <serverResolutions> if you only want to expose a subset
+     *     of the server resolutions.
+     */
+    zoomOffset: 0,
+    
+    /**
+     * APIProperty: serverResolutions
+     * {Array} A list of all resolutions available on the server.  Only set this
+     *     property if the map resolutions differs from the server.
+     */
+    serverResolutions: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.XYZ
+     *
+     * Parameters:
+     * name - {String}
+     * url - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, options) {
+        if (options && options.sphericalMercator || this.sphericalMercator) {
+            options = OpenLayers.Util.extend({
+                maxExtent: new OpenLayers.Bounds(
+                    -128 * 156543.03390625,
+                    -128 * 156543.03390625,
+                    128 * 156543.03390625,
+                    128 * 156543.03390625
+                ),
+                maxResolution: 156543.03390625,
+                numZoomLevels: 19,
+                units: "m",
+                projection: "EPSG:900913"
+            }, options);
+        }
+        url = url || this.url;
+        name = name || this.name;
+        var newArguments = [name, url, {}, options];
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },
+    
+    /**
+     * APIMethod: clone
+     * Create a clone of this layer
+     *
+     * Parameters:
+     * obj - {Object} Is this ever used?
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.XYZ>} An exact clone of this OpenLayers.Layer.XYZ
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.XYZ(this.name,
+                                            this.url,
+                                            this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        return obj;
+    },    
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as
+     *          parameters
+     */
+    getURL: function (bounds) {
+        var xyz = this.getXYZ(bounds);
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            var s = '' + xyz.x + xyz.y + xyz.z;
+            url = this.selectUrl(s, url);
+        }
+        
+        return OpenLayers.String.format(url, xyz);
+    },
+    
+    /**
+     * Method: getXYZ
+     * Calculates x, y and z for the given bounds.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {Object} - an object with x, y and z properties.
+     */
+    getXYZ: function(bounds) {
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.maxExtent.left) /
+            (res * this.tileSize.w));
+        var y = Math.round((this.maxExtent.top - bounds.top) /
+            (res * this.tileSize.h));
+        var z = this.serverResolutions != null ?
+            OpenLayers.Util.indexOf(this.serverResolutions, res) :
+            this.map.getZoom() + this.zoomOffset;
+
+        var limit = Math.pow(2, z);
+        if (this.wrapDateLine)
+        {
+           x = ((x % limit) + limit) % limit;
+        }
+
+        return {'x': x, 'y': y, 'z': z};
+    },
+    
+    /* APIMethod: setMap
+     * When the layer is added to a map, then we can fetch our origin 
+     *    (if we don't have one.) 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        if (!this.tileOrigin) { 
+            this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left,
+                                                this.maxExtent.bottom);
+        }                                       
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.XYZ"
+});
+
+
+/**
+ * Class: OpenLayers.Layer.OSM
+ * A class to access OpenStreetMap tiles. By default, uses the OpenStreetMap
+ *    hosted tile.openstreetmap.org 'Mapnik' tileset. If you wish to use
+ *    tiles@home / osmarender layer instead, you can pass a layer like:
+ * 
+ * (code)
+ *     new OpenLayers.Layer.OSM("t@h", 
+ *       "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); 
+ * (end)
+ *
+ * This layer defaults to Spherical Mercator.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.XYZ>
+ */
+OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+     name: "OpenStreetMap",
+     attribution: "Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",
+     sphericalMercator: true,
+     url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png',
+     clone: function(obj) {
+         if (obj == null) {
+             obj = new OpenLayers.Layer.OSM(
+                 this.name, this.url, this.getOptions());
+         }
+         obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+         return obj;
+     },
+     wrapDateLine: true,
+     CLASS_NAME: "OpenLayers.Layer.OSM"
+});
+/* ======================================================================
+    OpenLayers/Layer/Bing.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/XYZ.js
+ * @requires OpenLayers/Layer/SphericalMercator.js
+ */
+
+/** 
+ * Class: OpenLayers.Layer.Bing
+ * Bing layer using direct tile access as provided by Bing Maps REST Services.
+ * See http://msdn.microsoft.com/en-us/library/ff701713.aspx for more
+ * information. Note: Terms of Service compliant use requires the map to be
+ * configured with an <OpenLayers.Control.Attribution> control and the
+ * attribution placed on or near the map.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.XYZ>
+ */
+OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+
+    /**
+     * Property: serverResolutions
+     * {Array} the resolutions provided by the Bing servers.
+     */
+    serverResolutions: [
+        156543.03390625, 78271.516953125, 39135.7584765625,
+        19567.87923828125, 9783.939619140625, 4891.9698095703125,
+        2445.9849047851562, 1222.9924523925781, 611.4962261962891,
+        305.74811309814453, 152.87405654907226, 76.43702827453613,
+        38.218514137268066, 19.109257068634033, 9.554628534317017,
+        4.777314267158508, 2.388657133579254, 1.194328566789627,
+        0.5971642833948135, 0.29858214169740677, 0.14929107084870338,
+        0.07464553542435169
+    ],
+    
+    /**
+     * Property: attributionTemplate
+     * {String}
+     */
+    attributionTemplate: '<span class="olBingAttribution ${type}">' +
+         '<div><a target="_blank" href="http://www.bing.com/maps/">' +
+         '<img src="${logo}" /></a></div>${copyrights}' +
+         '<a style="white-space: nowrap" target="_blank" '+
+         'href="http://www.microsoft.com/maps/product/terms.html">' +
+         'Terms of Use</a></span>',
+
+    /**
+     * Property: metadata
+     * {Object} Metadata for this layer, as returned by the callback script
+     */
+    metadata: null,
+    
+    /**
+     * APIProperty: type
+     * {String} The layer identifier.  Any non-birdseye imageryType
+     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
+     *     used.  Default is "Road".
+     */
+    type: "Road",
+    
+    /**
+     * APIProperty: metadataParams
+     * {Object} Optional url parameters for the Get Imagery Metadata request
+     * as described here: http://msdn.microsoft.com/en-us/library/ff701716.aspx
+     */
+    metadataParams: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.Bing
+     * Create a new Bing layer.
+     *
+     * Example:
+     * (code)
+     * var road = new OpenLayers.Layer.Bing({
+     *     name: "My Bing Aerial Layer",
+     *     type: "Aerial",
+     *     key: "my-api-key-here",
+     * });
+     * (end)
+     *
+     * Parameters:
+     * config - {Object} Configuration properties for the layer.
+     *
+     * Required configuration properties:
+     * key - {String} Bing Maps API key for your application. Get one at
+     *     http://bingmapsportal.com/.
+     * type - {String} The layer identifier.  Any non-birdseye imageryType
+     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
+     *     used.
+     *
+     * Any other documented layer properties can be provided in the config object.
+     */
+    initialize: function(options) {
+        options = OpenLayers.Util.applyDefaults({
+            sphericalMercator: true
+        }, options);
+        var name = options.name || "Bing " + (options.type || this.type);
+        
+        var newArgs = [name, null, options];
+        OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs);
+        this.loadMetadata(); 
+    },
+
+    /**
+     * Method: loadMetadata
+     */
+    loadMetadata: function() {
+        this._callbackId = "_callback_" + this.id.replace(/\./g, "_");
+        // link the processMetadata method to the global scope and bind it
+        // to this instance
+        window[this._callbackId] = OpenLayers.Function.bind(
+            OpenLayers.Layer.Bing.processMetadata, this
+        );
+        var params = OpenLayers.Util.applyDefaults({
+            key: this.key,
+            jsonp: this._callbackId,
+            include: "ImageryProviders"
+        }, this.metadataParams);
+        var url = "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/" +
+            this.type + "?" + OpenLayers.Util.getParameterString(params);
+        var script = document.createElement("script");
+        script.type = "text/javascript";
+        script.src = url;
+        script.id = this._callbackId;
+        document.getElementsByTagName("head")[0].appendChild(script);
+    },
+    
+    /**
+     * Method: initLayer
+     *
+     * Sets layer properties according to the metadata provided by the API
+     */
+    initLayer: function() {
+        var res = this.metadata.resourceSets[0].resources[0];
+        var url = res.imageUrl.replace("{quadkey}", "${quadkey}");
+        this.url = [];
+        for (var i=0; i<res.imageUrlSubdomains.length; ++i) {
+            this.url.push(url.replace("{subdomain}", res.imageUrlSubdomains[i]));
+        };
+        this.addOptions({
+            maxResolution: Math.min(
+                this.serverResolutions[res.zoomMin], this.maxResolution
+            ),
+            zoomOffset: res.zoomMin,
+            numZoomLevels: Math.min(
+                res.zoomMax + 1 - res.zoomMin, this.numZoomLevels
+            )
+        }, true);
+    },
+
+    /**
+     * Method: getURL
+     *
+     * Paramters:
+     * bounds - {<OpenLayers.Bounds>}
+     */
+    getURL: function(bounds) {
+        if (!this.url) {
+            return OpenLayers.Util.getImagesLocation() + "blank.gif";
+        }
+        var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z;
+        var quadDigits = [];
+        for (var i = z; i > 0; --i) {
+            var digit = '0';
+            var mask = 1 << (i - 1);
+            if ((x & mask) != 0) {
+                digit++;
+            }
+            if ((y & mask) != 0) {
+                digit++;
+                digit++;
+            }
+            quadDigits.push(digit);
+        }
+        var quadKey = quadDigits.join("");
+        var url = this.selectUrl('' + x + y + z, this.url);
+
+        return OpenLayers.String.format(url, {'quadkey': quadKey});
+    },
+    
+    /**
+     * Method: updateAttribution
+     * Updates the attribution according to the requirements outlined in
+     * http://gis.638310.n2.nabble.com/Bing-imagery-td5789168.html
+     */
+    updateAttribution: function() {
+        var metadata = this.metadata;
+        if (!metadata || !this.map || !this.map.center) {
+            return;
+        }
+        var res = metadata.resourceSets[0].resources[0];
+        var extent = this.map.getExtent().transform(
+            this.map.getProjectionObject(),
+            new OpenLayers.Projection("EPSG:4326")
+        );
+        var providers = res.imageryProviders, zoom = this.map.getZoom() + 1,
+            copyrights = "", provider, i, ii, j, jj, bbox, coverage;
+        for (i=0,ii=providers.length; i<ii; ++i) {
+            provider = providers[i];
+            for (j=0,jj=provider.coverageAreas.length; j<jj; ++j) {
+                coverage = provider.coverageAreas[j];
+                bbox = OpenLayers.Bounds.fromArray(coverage.bbox);
+                if (extent.intersectsBounds(bbox) &&
+                        zoom <= coverage.zoomMax && zoom >= coverage.zoomMin) {
+                    copyrights += provider.attribution + " ";
+                }
+            }
+        }
+        this.attribution = OpenLayers.String.format(this.attributionTemplate, {
+            type: this.type.toLowerCase(),
+            logo: metadata.brandLogoUri,
+            copyrights: copyrights
+        });
+        this.map && this.map.events.triggerEvent("changelayer", {
+            layer: this,
+            property: "attribution"
+        });
+    },
+    
+    /**
+     * Method: setMap
+     */
+    setMap: function() {
+        OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments);
+        this.updateAttribution();
+        this.map.events.register("moveend", this, this.updateAttribution);
+    },
+    
+    /**
+     * APIMethod: clone
+     * 
+     * Parameters:
+     * obj - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.Bing>} An exact clone of this <OpenLayers.Layer.Bing>
+     */
+    clone: function(obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Bing(this.options);
+        }
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+        // copy/set any non-init, non-simple values here
+        return obj;
+    },
+    
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        this.map &&
+            this.map.events.unregister("moveend", this, this.updateAttribution);
+        OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.Bing"
+});
+
+/**
+ * Function: OpenLayers.Layer.Bing.processMetadata
+ * This function will be bound to an instance, linked to the global scope with
+ * an id, and called by the JSONP script returned by the API.
+ *
+ * Parameters:
+ * metadata - {Object} metadata as returned by the API
+ */
+OpenLayers.Layer.Bing.processMetadata = function(metadata) {
+    this.metadata = metadata;
+    this.initLayer();
+    var script = document.getElementById(this._callbackId);
+    script.parentNode.removeChild(script);
+    window[this._callbackId] = undefined; // cannot delete from window in IE
+    delete this._callbackId;
+};
+/* ======================================================================
+    OpenLayers/Format/SOSGetFeatureOfInterest.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+ 
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetFeatureOfInterest
+ * Read and write SOS GetFeatureOfInterest. This is used to get to
+ * the location of the features (stations). The stations can have 1 or more
+ * sensors.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetFeatureOfInterest = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        sos: "http://www.opengis.net/sos/1.0",
+        gml: "http://www.opengis.net/gml",
+        sa: "http://www.opengis.net/sampling/1.0",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "sos",
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.SOSGetFeatureOfInterest
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Parse a GetFeatureOfInterest response and return an array of features
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} An array of features. 
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+
+        var info = {features: []};
+        this.readNode(data, info);
+       
+        var features = [];
+        for (var i=0, len=info.features.length; i<len; i++) {
+            var container = info.features[i];
+            // reproject features if needed
+            if(this.internalProjection && this.externalProjection &&
+                container.components[0]) {
+                    container.components[0].transform(
+                        this.externalProjection, this.internalProjection
+                    );
+            }             
+            var feature = new OpenLayers.Feature.Vector(
+                container.components[0], container.attributes);
+            features.push(feature);
+        }
+        return features;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "sa": {
+            "SamplingPoint": function(node, obj) {
+                // sampling point can also be without a featureMember if 
+                // there is only 1
+                if (!obj.attributes) {
+                    var feature = {attributes: {}};
+                    obj.features.push(feature);
+                    obj = feature;
+                }
+                obj.attributes.id = this.getAttributeNS(node, 
+                    this.namespaces.gml, "id");
+                this.readChildNodes(node, obj);
+            },
+            "position": function (node, obj) {
+                this.readChildNodes(node, obj);
+            }
+        },
+        "gml": OpenLayers.Util.applyDefaults({
+            "FeatureCollection": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "featureMember": function(node, obj) {
+                var feature = {attributes: {}};
+                obj.features.push(feature);
+                this.readChildNodes(node, feature);
+            },
+            "name": function(node, obj) {
+                obj.attributes.name = this.getChildValue(node);
+            },
+            "pos": function(node, obj) {
+                // we need to parse the srsName to get to the 
+                // externalProjection, that's why we cannot use
+                // GML v3 for this
+                if (!this.externalProjection) {
+                    this.externalProjection = new OpenLayers.Projection(
+                        node.getAttribute("srsName"));
+                }
+             OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(
+                    this, [node, obj]);
+            }
+        }, OpenLayers.Format.GML.v3.prototype.readers.gml)
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "sos": {
+            "GetFeatureOfInterest": function(options) {
+                var node = this.createElementNSPlus("GetFeatureOfInterest", {
+                    attributes: {
+                        version: this.VERSION,
+                        service: 'SOS',
+                        "xsi:schemaLocation": this.schemaLocation
+                    } 
+                }); 
+                for (var i=0, len=options.fois.length; i<len; i++) {
+                    this.writeNode("FeatureOfInterestId", {foi: options.fois[i]}, node);
+                }
+                return node; 
+            },
+            "FeatureOfInterestId": function(options) {
+                var node = this.createElementNSPlus("FeatureOfInterestId", {value: options.foi});
+                return node;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.SOSGetFeatureOfInterest" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/SOSGetObservation.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetObservation
+ * Read and write SOS GetObersation (to get the actual values from a sensor) 
+ *     version 1.0.0
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetObservation = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows",
+        gml: "http://www.opengis.net/gml",
+        sos: "http://www.opengis.net/sos/1.0",
+        ogc: "http://www.opengis.net/ogc",
+        om: "http://www.opengis.net/om/1.0",
+        sa: "http://www.opengis.net/sampling/1.0",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "sos",
+
+    /**
+     * Constructor: OpenLayers.Format.SOSGetObservation
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * Method: read
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} An object containing the measurements
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var info = {measurements: [], observations: []};
+        this.readNode(data, info);
+        return info;
+    },
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} An SOS GetObservation request XML string.
+     */
+    write: function(options) {
+        var node = this.writeNode("sos:GetObservation", options);
+        node.setAttribute("xmlns:om", this.namespaces.om);
+        node.setAttribute("xmlns:ogc", this.namespaces.ogc);
+        this.setAttributeNS(
+            node, this.namespaces.xsi,
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    }, 
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "om": {
+            "ObservationCollection": function(node, obj) {
+                obj.id = this.getAttributeNS(node, this.namespaces.gml, "id");
+                this.readChildNodes(node, obj);
+            },
+            "member": function(node, observationCollection) {
+                this.readChildNodes(node, observationCollection);
+            },
+            "Measurement": function(node, observationCollection) {
+                var measurement = {};
+                observationCollection.measurements.push(measurement);
+                this.readChildNodes(node, measurement);
+            },
+            "Observation": function(node, observationCollection) {
+                var observation = {};
+                observationCollection.observations.push(observation);
+                this.readChildNodes(node, observation);
+            },
+            "samplingTime": function(node, measurement) {
+                var samplingTime = {};
+                measurement.samplingTime = samplingTime;
+                this.readChildNodes(node, samplingTime);
+            },
+            "observedProperty": function(node, measurement) {
+                measurement.observedProperty = 
+                    this.getAttributeNS(node, this.namespaces.xlink, "href");
+                this.readChildNodes(node, measurement);
+            },
+            "procedure": function(node, measurement) {
+                measurement.procedure = 
+                    this.getAttributeNS(node, this.namespaces.xlink, "href");
+                this.readChildNodes(node, measurement);
+            },
+            "featureOfInterest": function(node, observation) {
+                var foi = {features: []};
+                observation.fois = [];
+                observation.fois.push(foi);
+                this.readChildNodes(node, foi);
+                // postprocessing to get actual features
+                var features = [];
+                for (var i=0, len=foi.features.length; i<len; i++) {
+                    var feature = foi.features[i];
+                    features.push(new OpenLayers.Feature.Vector(
+                        feature.components[0], feature.attributes));
+                }
+                foi.features = features;
+            },
+            "result": function(node, measurement) {
+                var result = {};
+                measurement.result = result;
+                if (this.getChildValue(node) !== '') {
+                    result.value = this.getChildValue(node);
+                    result.uom = node.getAttribute("uom");
+                } else {
+                    this.readChildNodes(node, result);
+                }
+            }
+        },
+        "sa": OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.sa,
+        "gml": OpenLayers.Util.applyDefaults({
+            "TimeInstant": function(node, samplingTime) {
+               var timeInstant = {};
+                samplingTime.timeInstant = timeInstant;
+                this.readChildNodes(node, timeInstant);
+            },
+            "timePosition": function(node, timeInstant) {
+                timeInstant.timePosition = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.gml)
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "sos": {
+            "GetObservation": function(options) {
+                var node = this.createElementNSPlus("GetObservation", {
+                    attributes: {
+                        version: this.VERSION,
+                        service: 'SOS'
+                    } 
+                }); 
+                this.writeNode("offering", options, node);
+                if (options.eventTime) {
+                    this.writeNode("eventTime", options, node);
+                }
+                for (var procedure in options.procedures) {
+                    this.writeNode("procedure", options.procedures[procedure], node);
+                }
+                for (var observedProperty in options.observedProperties) {
+                    this.writeNode("observedProperty", options.observedProperties[observedProperty], node);
+                }
+                if (options.foi) {
+                    this.writeNode("featureOfInterest", options.foi, node);
+                }
+                this.writeNode("responseFormat", options, node);
+                if (options.resultModel) {
+                    this.writeNode("resultModel", options, node);
+                }
+                if (options.responseMode) {
+                    this.writeNode("responseMode", options, node);
+                }
+                return node; 
+            },
+            "featureOfInterest": function(foi) {
+                var node = this.createElementNSPlus("featureOfInterest");
+                this.writeNode("ObjectID", foi.objectId, node);
+                return node;
+            },
+            "ObjectID": function(options) {
+                return this.createElementNSPlus("ObjectID",
+                    {value: options});
+            },
+            "responseFormat": function(options) {
+                return this.createElementNSPlus("responseFormat", 
+                    {value: options.responseFormat});
+            },
+            "procedure": function(procedure) {
+                return this.createElementNSPlus("procedure", 
+                    {value: procedure});
+            },
+            "offering": function(options) {
+                return this.createElementNSPlus("offering", {value: 
+                    options.offering});
+            },
+            "observedProperty": function(observedProperty) {
+                return this.createElementNSPlus("observedProperty", 
+                    {value: observedProperty});
+            },
+            "eventTime": function(options) {
+                var node = this.createElementNSPlus("eventTime");
+                if (options.eventTime === 'latest') {
+                    this.writeNode("ogc:TM_Equals", options, node);
+                }
+                return node;
+            },
+            "resultModel": function(options) {
+                return this.createElementNSPlus("resultModel", {value: 
+                    options.resultModel});
+            },
+            "responseMode": function(options) {
+                return this.createElementNSPlus("responseMode", {value: 
+                    options.responseMode});
+            }
+        },
+        "ogc": {
+            "TM_Equals": function(options) {
+                var node = this.createElementNSPlus("ogc:TM_Equals");
+                this.writeNode("ogc:PropertyName", {property: 
+                    "urn:ogc:data:time:iso8601"}, node);
+                if (options.eventTime === 'latest') {
+                    this.writeNode("gml:TimeInstant", {value: 'latest'}, node);
+                }
+                return node;
+            },
+            "PropertyName": function(options) {
+                return this.createElementNSPlus("ogc:PropertyName", 
+                    {value: options.property});
+            }
+        },
+        "gml": {
+            "TimeInstant": function(options) {
+                var node = this.createElementNSPlus("gml:TimeInstant");
+                this.writeNode("gml:timePosition", options, node);
+                return node;
+            },
+            "timePosition": function(options) {
+                var node = this.createElementNSPlus("gml:timePosition", 
+                    {value: options.value});
+                return node;
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.SOSGetObservation" 
+
+});
+/* ======================================================================
+    OpenLayers/Handler/MouseWheel.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.MouseWheel
+ * Handler for wheel up/down events.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.MouseWheel = OpenLayers.Class(OpenLayers.Handler, {
+    /** 
+     * Property: wheelListener 
+     * {function} 
+     */
+    wheelListener: null,
+
+    /** 
+     * Property: mousePosition
+     * {<OpenLayers.Pixel>} mousePosition is necessary because
+     * evt.clientX/Y is buggy in Moz on wheel events, so we cache and use the
+     * value from the last mousemove.
+     */
+    mousePosition: null,
+
+    /**
+     * Property: interval
+     * {Integer} In order to increase server performance, an interval (in 
+     *     milliseconds) can be set to reduce the number of up/down events 
+     *     called. If set, a new up/down event will not be set until the 
+     *     interval has passed. 
+     *     Defaults to 0, meaning no interval. 
+     */
+    interval: 0,
+    
+    /**
+     * Property: delta
+     * {Integer} When interval is set, delta collects the mousewheel z-deltas
+     *     of the events that occur within the interval.
+     *      See also the cumulative option
+     */
+    delta: 0,
+    
+    /**
+     * Property: cumulative
+     * {Boolean} When interval is set: true to collect all the mousewheel 
+     *     z-deltas, false to only record the delta direction (positive or
+     *     negative)
+     */
+    cumulative: true,
+
+    /**
+     * Constructor: OpenLayers.Handler.MouseWheel
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} 
+     * callbacks - {Object} An object containing a single function to be
+     *                          called when the drag operation is finished.
+     *                          The callback should expect to recieve a single
+     *                          argument, the point geometry.
+     * options - {Object} 
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+        this.wheelListener = OpenLayers.Function.bindAsEventListener(
+            this.onWheelEvent, this
+        );
+    },
+
+    /**
+     * Method: destroy
+     */    
+    destroy: function() {
+        OpenLayers.Handler.prototype.destroy.apply(this, arguments);
+        this.wheelListener = null;
+    },
+
+    /**
+     *  Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/
+     */
+
+    /** 
+     * Method: onWheelEvent
+     * Catch the wheel event and handle it xbrowserly
+     * 
+     * Parameters:
+     * e - {Event} 
+     */
+    onWheelEvent: function(e){
+        
+        // make sure we have a map and check keyboard modifiers
+        if (!this.map || !this.checkModifiers(e)) {
+            return;
+        }
+        
+        // Ride up the element's DOM hierarchy to determine if it or any of 
+        //  its ancestors was: 
+        //   * specifically marked as scrollable
+        //   * one of our layer divs
+        //   * the map div
+        //
+        var overScrollableDiv = false;
+        var overLayerDiv = false;
+        var overMapDiv = false;
+        
+        var elem = OpenLayers.Event.element(e);
+        while((elem != null) && !overMapDiv && !overScrollableDiv) {
+
+            if (!overScrollableDiv) {
+                try {
+                    if (elem.currentStyle) {
+                        overflow = elem.currentStyle["overflow"];
+                    } else {
+                        var style = 
+                            document.defaultView.getComputedStyle(elem, null);
+                        var overflow = style.getPropertyValue("overflow");
+                    }
+                    overScrollableDiv = ( overflow && 
+                        (overflow == "auto") || (overflow == "scroll") );
+                } catch(err) {
+                    //sometimes when scrolling in a popup, this causes 
+                    // obscure browser error
+                }
+            }
+
+            if (!overLayerDiv) {
+                for(var i=0, len=this.map.layers.length; i<len; i++) {
+                    // Are we in the layer div? Note that we have two cases
+                    // here: one is to catch EventPane layers, which have a 
+                    // pane above the layer (layer.pane)
+                    if (elem == this.map.layers[i].div 
+                        || elem == this.map.layers[i].pane) { 
+                        overLayerDiv = true;
+                        break;
+                    }
+                }
+            }
+            overMapDiv = (elem == this.map.div);
+
+            elem = elem.parentNode;
+        }
+        
+        // Logic below is the following:
+        //
+        // If we are over a scrollable div or not over the map div:
+        //  * do nothing (let the browser handle scrolling)
+        //
+        //    otherwise 
+        // 
+        //    If we are over the layer div: 
+        //     * zoom/in out
+        //     then
+        //     * kill event (so as not to also scroll the page after zooming)
+        //
+        //       otherwise
+        //
+        //       Kill the event (dont scroll the page if we wheel over the 
+        //        layerswitcher or the pan/zoom control)
+        //
+        if (!overScrollableDiv && overMapDiv) {
+            if (overLayerDiv) {
+                var delta = 0;
+                if (!e) {
+                    e = window.event;
+                }
+                if (e.wheelDelta) {
+                    delta = e.wheelDelta/120; 
+                    if (window.opera && window.opera.version() < 9.2) {
+                        delta = -delta;
+                    }
+                } else if (e.detail) {
+                    delta = -e.detail / 3;
+                }
+                this.delta = this.delta + delta;
+
+                if(this.interval) {
+                    window.clearTimeout(this._timeoutId);
+                    this._timeoutId = window.setTimeout(
+                        OpenLayers.Function.bind(function(){
+                            this.wheelZoom(e);
+                        }, this),
+                        this.interval
+                    );
+                } else {
+                    this.wheelZoom(e);
+                }
+            }
+            OpenLayers.Event.stop(e);
+        }
+    },
+
+    /**
+     * Method: wheelZoom
+     * Given the wheel event, we carry out the appropriate zooming in or out,
+     *     based on the 'wheelDelta' or 'detail' property of the event.
+     * 
+     * Parameters:
+     * e - {Event}
+     */
+    wheelZoom: function(e) {
+        var delta = this.delta;
+        this.delta = 0;
+        
+        if (delta) {
+            // add the mouse position to the event because mozilla has 
+            // a bug with clientX and clientY (see 
+            // https://bugzilla.mozilla.org/show_bug.cgi?id=352179)
+            // getLonLatFromViewPortPx(e) returns wrong values
+            if (this.mousePosition) {
+                e.xy = this.mousePosition;
+            } 
+            if (!e.xy) {
+                // If the mouse hasn't moved over the map yet, then
+                // we don't have a mouse position (in FF), so we just
+                // act as if the mouse was at the center of the map.
+                // Note that we can tell we are in the map -- and 
+                // this.map is ensured to be true above.
+                e.xy = this.map.getPixelFromLonLat(
+                    this.map.getCenter()
+                );
+            }
+            if (delta < 0) {
+                this.callback("down", [e, this.cumulative ? delta : -1]);
+            } else {
+                this.callback("up", [e, this.cumulative ? delta : 1]);
+            }
+        }
+    },
+    
+    /**
+     * Method: mousemove
+     * Update the stored mousePosition on every move.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    mousemove: function (evt) {
+        this.mousePosition = evt.xy;
+    },
+
+    /**
+     * Method: activate 
+     */
+    activate: function (evt) {
+        if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            //register mousewheel events specifically on the window and document
+            var wheelListener = this.wheelListener;
+            OpenLayers.Event.observe(window, "DOMMouseScroll", wheelListener);
+            OpenLayers.Event.observe(window, "mousewheel", wheelListener);
+            OpenLayers.Event.observe(document, "mousewheel", wheelListener);
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    /**
+     * Method: deactivate 
+     */
+    deactivate: function (evt) {
+        if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            // unregister mousewheel events specifically on the window and document
+            var wheelListener = this.wheelListener;
+            OpenLayers.Event.stopObserving(window, "DOMMouseScroll", wheelListener);
+            OpenLayers.Event.stopObserving(window, "mousewheel", wheelListener);
+            OpenLayers.Event.stopObserving(document, "mousewheel", wheelListener);
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.MouseWheel"
+});
+/* ======================================================================
+    OpenLayers/Format/WFST/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFST/v1.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1_0_0
+ * A format for creating WFS v1.0.0 transactions.  Create a new instance with the
+ *     <OpenLayers.Format.WFST.v1_0_0> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.Filter.v1_0_0>
+ *  - <OpenLayers.Format.WFST.v1>
+ */
+OpenLayers.Format.WFST.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.Filter.v1_0_0, OpenLayers.Format.WFST.v1, {
+    
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: "1.0.0",
+
+    /**
+     * APIProperty: srsNameInQuery
+     * {Boolean} If true the reference system is passed in Query requests
+     *     via the "srsName" attribute to the "wfs:Query" element, this
+     *     property defaults to false as it isn't WFS 1.0.0 compliant.
+     */
+    srsNameInQuery: false,
+    
+    /**
+     * Property: schemaLocations
+     * {Object} Properties are namespace aliases, values are schema locations.
+     */
+    schemaLocations: {
+        "wfs": "http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.WFST.v1_0_0
+     * A class for parsing and generating WFS v1.0.0 transactions.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (optional).
+     * featurePrefix - {String} Feature namespace alias (optional - only used
+     *     if featureNS is provided).  Default is 'feature'.
+     * geometryName - {String} Name of geometry attribute.  Default is 'the_geom'.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: readNode
+     * Shorthand for applying one of the named readers given the node
+     *     namespace and local name.  Readers take two args (node, obj) and
+     *     generally extend or modify the second.
+     *
+     * Parameters:
+     * node - {DOMElement} The node to be read (required).
+     * obj - {Object} The object to be modified (optional).
+     * first - {Boolean} Should be set to true for the first node read. This
+     *     is usually the readNode call in the read method. Without this being
+     *     set, auto-configured properties will stick on subsequent reads.
+     *
+     * Returns:
+     * {Object} The input object, modified (or a new one if none was provided).
+     */
+    readNode: function(node, obj, first) {
+        // Not the superclass, only the mixin classes inherit from
+        // Format.GML.v2. We need this because we don't want to get readNode
+        // from the superclass's superclass, which is OpenLayers.Format.XML.
+        return OpenLayers.Format.GML.v2.prototype.readNode.apply(this, [node, obj]);
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wfs": OpenLayers.Util.applyDefaults({
+            "WFS_TransactionResponse": function(node, obj) {
+                obj.insertIds = [];
+                obj.success = false;
+                this.readChildNodes(node, obj);
+            },
+            "InsertResult": function(node, container) {
+                var obj = {fids: []};
+                this.readChildNodes(node, obj);
+                container.insertIds.push(obj.fids[0]);
+            },
+            "TransactionResult": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Status": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "SUCCESS": function(node, obj) {
+                obj.success = true;
+            }
+        }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),
+        "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"],
+        "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"],
+        "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"]
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "wfs": OpenLayers.Util.applyDefaults({
+            "Query": function(options) {
+                options = OpenLayers.Util.extend({
+                    featureNS: this.featureNS,
+                    featurePrefix: this.featurePrefix,
+                    featureType: this.featureType,
+                    srsName: this.srsName,
+                    srsNameInQuery: this.srsNameInQuery
+                }, options);
+                var prefix = options.featurePrefix;
+                var node = this.createElementNSPlus("wfs:Query", {
+                    attributes: {
+                        typeName: (prefix ? prefix + ":" : "") +
+                            options.featureType
+                    }
+                });
+                if(options.srsNameInQuery && options.srsName) {
+                    node.setAttribute("srsName", options.srsName);
+                }
+                if(options.featureNS) {
+                    node.setAttribute("xmlns:" + prefix, options.featureNS);
+                }
+                if(options.propertyNames) {
+                    for(var i=0,len = options.propertyNames.length; i<len; i++) {
+                        this.writeNode(
+                            "ogc:PropertyName", 
+                            {property: options.propertyNames[i]},
+                            node
+                        );
+                    }
+                }
+                if(options.filter) {
+                    this.setFilterProperty(options.filter);
+                    this.writeNode("ogc:Filter", options.filter, node);
+                }
+                return node;
+            }
+        }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),
+        "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"],
+        "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"],
+        "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.writers["ogc"]
+    },
+   
+    CLASS_NAME: "OpenLayers.Format.WFST.v1_0_0" 
+});
+/* ======================================================================
+    OpenLayers/Renderer/Elements.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer.js
+ */
+
+/**
+ * Class: OpenLayers.ElementsIndexer
+ * This class takes care of figuring out which order elements should be
+ *     placed in the DOM based on given indexing methods. 
+ */
+OpenLayers.ElementsIndexer = OpenLayers.Class({
+   
+    /**
+     * Property: maxZIndex
+     * {Integer} This is the largest-most z-index value for a node
+     *     contained within the indexer.
+     */
+    maxZIndex: null,
+    
+    /**
+     * Property: order
+     * {Array<String>} This is an array of node id's stored in the
+     *     order that they should show up on screen. Id's higher up in the
+     *     array (higher array index) represent nodes with higher z-indeces.
+     */
+    order: null, 
+    
+    /**
+     * Property: indices
+     * {Object} This is a hash that maps node ids to their z-index value
+     *     stored in the indexer. This is done to make finding a nodes z-index 
+     *     value O(1).
+     */
+    indices: null,
+    
+    /**
+     * Property: compare
+     * {Function} This is the function used to determine placement of
+     *     of a new node within the indexer. If null, this defaults to to
+     *     the Z_ORDER_DRAWING_ORDER comparison method.
+     */
+    compare: null,
+    
+    /**
+     * APIMethod: initialize
+     * Create a new indexer with 
+     * 
+     * Parameters:
+     * yOrdering - {Boolean} Whether to use y-ordering.
+     */
+    initialize: function(yOrdering) {
+
+        this.compare = yOrdering ? 
+            OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER :
+            OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;
+
+        this.clear();
+    },
+    
+    /**
+     * APIMethod: insert
+     * Insert a new node into the indexer. In order to find the correct 
+     *     positioning for the node to be inserted, this method uses a binary 
+     *     search. This makes inserting O(log(n)). 
+     * 
+     * Parameters:
+     * newNode - {DOMElement} The new node to be inserted.
+     * 
+     * Returns
+     * {DOMElement} the node before which we should insert our newNode, or
+     *     null if newNode can just be appended.
+     */
+    insert: function(newNode) {
+        // If the node is known to the indexer, remove it so we can
+        // recalculate where it should go.
+        if (this.exists(newNode)) {
+            this.remove(newNode);
+        }
+        
+        var nodeId = newNode.id;
+        
+        this.determineZIndex(newNode);       
+
+        var leftIndex = -1;
+        var rightIndex = this.order.length;
+        var middle;
+
+        while (rightIndex - leftIndex > 1) {
+            middle = parseInt((leftIndex + rightIndex) / 2);
+            
+            var placement = this.compare(this, newNode,
+                OpenLayers.Util.getElement(this.order[middle]));
+            
+            if (placement > 0) {
+                leftIndex = middle;
+            } else {
+                rightIndex = middle;
+            } 
+        }
+        
+        this.order.splice(rightIndex, 0, nodeId);
+        this.indices[nodeId] = this.getZIndex(newNode);
+        
+        // If the new node should be before another in the index
+        // order, return the node before which we have to insert the new one;
+        // else, return null to indicate that the new node can be appended.
+        return this.getNextElement(rightIndex);
+    },
+    
+    /**
+     * APIMethod: remove
+     * 
+     * Parameters:
+     * node - {DOMElement} The node to be removed.
+     */
+    remove: function(node) {
+        var nodeId = node.id;
+        var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId);
+        if (arrayIndex >= 0) {
+            // Remove it from the order array, as well as deleting the node
+            // from the indeces hash.
+            this.order.splice(arrayIndex, 1);
+            delete this.indices[nodeId];
+            
+            // Reset the maxium z-index based on the last item in the 
+            // order array.
+            if (this.order.length > 0) {
+                var lastId = this.order[this.order.length - 1];
+                this.maxZIndex = this.indices[lastId];
+            } else {
+                this.maxZIndex = 0;
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: clear
+     */
+    clear: function() {
+        this.order = [];
+        this.indices = {};
+        this.maxZIndex = 0;
+    },
+    
+    /**
+     * APIMethod: exists
+     *
+     * Parameters:
+     * node- {DOMElement} The node to test for existence.
+     *
+     * Returns:
+     * {Boolean} Whether or not the node exists in the indexer?
+     */
+    exists: function(node) {
+        return (this.indices[node.id] != null);
+    },
+
+    /**
+     * APIMethod: getZIndex
+     * Get the z-index value for the current node from the node data itself.
+     * 
+     * Parameters:
+     * node - {DOMElement} The node whose z-index to get.
+     * 
+     * Returns:
+     * {Integer} The z-index value for the specified node (from the node 
+     *     data itself).
+     */
+    getZIndex: function(node) {
+        return node._style.graphicZIndex;  
+    },
+    
+    /**
+     * Method: determineZIndex
+     * Determine the z-index for the current node if there isn't one, 
+     *     and set the maximum value if we've found a new maximum.
+     * 
+     * Parameters:
+     * node - {DOMElement} 
+     */
+    determineZIndex: function(node) {
+        var zIndex = node._style.graphicZIndex;
+        
+        // Everything must have a zIndex. If none is specified,
+        // this means the user *must* (hint: assumption) want this
+        // node to succomb to drawing order. To enforce drawing order
+        // over all indexing methods, we'll create a new z-index that's
+        // greater than any currently in the indexer.
+        if (zIndex == null) {
+            zIndex = this.maxZIndex;
+            node._style.graphicZIndex = zIndex; 
+        } else if (zIndex > this.maxZIndex) {
+            this.maxZIndex = zIndex;
+        }
+    },
+
+    /**
+     * APIMethod: getNextElement
+     * Get the next element in the order stack.
+     * 
+     * Parameters:
+     * index - {Integer} The index of the current node in this.order.
+     * 
+     * Returns:
+     * {DOMElement} the node following the index passed in, or
+     *     null.
+     */
+    getNextElement: function(index) {
+        var nextIndex = index + 1;
+        if (nextIndex < this.order.length) {
+            var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
+            if (nextElement == undefined) {
+                nextElement = this.getNextElement(nextIndex);
+            }
+            return nextElement;
+        } else {
+            return null;
+        } 
+    },
+    
+    CLASS_NAME: "OpenLayers.ElementsIndexer"
+});
+
+/**
+ * Namespace: OpenLayers.ElementsIndexer.IndexingMethods
+ * These are the compare methods for figuring out where a new node should be 
+ *     placed within the indexer. These methods are very similar to general 
+ *     sorting methods in that they return -1, 0, and 1 to specify the 
+ *     direction in which new nodes fall in the ordering.
+ */
+OpenLayers.ElementsIndexer.IndexingMethods = {
+    
+    /**
+     * Method: Z_ORDER
+     * This compare method is used by other comparison methods.
+     *     It can be used individually for ordering, but is not recommended,
+     *     because it doesn't subscribe to drawing order.
+     * 
+     * Parameters:
+     * indexer - {<OpenLayers.ElementsIndexer>}
+     * newNode - {DOMElement}
+     * nextNode - {DOMElement}
+     * 
+     * Returns:
+     * {Integer}
+     */
+    Z_ORDER: function(indexer, newNode, nextNode) {
+        var newZIndex = indexer.getZIndex(newNode);
+
+        var returnVal = 0;
+        if (nextNode) {
+            var nextZIndex = indexer.getZIndex(nextNode);
+            returnVal = newZIndex - nextZIndex; 
+        }
+        
+        return returnVal;
+    },
+
+    /**
+     * APIMethod: Z_ORDER_DRAWING_ORDER
+     * This method orders nodes by their z-index, but does so in a way
+     *     that, if there are other nodes with the same z-index, the newest 
+     *     drawn will be the front most within that z-index. This is the 
+     *     default indexing method.
+     * 
+     * Parameters:
+     * indexer - {<OpenLayers.ElementsIndexer>}
+     * newNode - {DOMElement}
+     * nextNode - {DOMElement}
+     * 
+     * Returns:
+     * {Integer}
+     */
+    Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) {
+        var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
+            indexer, 
+            newNode, 
+            nextNode
+        );
+        
+        // Make Z_ORDER subscribe to drawing order by pushing it above
+        // all of the other nodes with the same z-index.
+        if (nextNode && returnVal == 0) {
+            returnVal = 1;
+        }
+        
+        return returnVal;
+    },
+
+    /**
+     * APIMethod: Z_ORDER_Y_ORDER
+     * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it
+     *     best describes which ordering methods have precedence (though, the 
+     *     name would be too long). This method orders nodes by their z-index, 
+     *     but does so in a way that, if there are other nodes with the same 
+     *     z-index, the nodes with the lower y position will be "closer" than 
+     *     those with a higher y position. If two nodes have the exact same y 
+     *     position, however, then this method will revert to using drawing  
+     *     order to decide placement.
+     * 
+     * Parameters:
+     * indexer - {<OpenLayers.ElementsIndexer>}
+     * newNode - {DOMElement}
+     * nextNode - {DOMElement}
+     * 
+     * Returns:
+     * {Integer}
+     */
+    Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) {
+        var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
+            indexer, 
+            newNode, 
+            nextNode
+        );
+        
+        if (nextNode && returnVal === 0) {            
+            var result = nextNode._boundsBottom - newNode._boundsBottom;
+            returnVal = (result === 0) ? 1 : result;
+        }
+        
+        return returnVal;       
+    }
+};
+
+/**
+ * Class: OpenLayers.Renderer.Elements
+ * This is another virtual class in that it should never be instantiated by 
+ *  itself as a Renderer. It exists because there is *tons* of shared 
+ *  functionality between different vector libraries which use nodes/elements
+ *  as a base for rendering vectors. 
+ * 
+ * The highlevel bits of code that are implemented here are the adding and 
+ *  removing of geometries, which is essentially the same for any 
+ *  element-based renderer. The details of creating each node and drawing the
+ *  paths are of course different, but the machinery is the same. 
+ * 
+ * Inherits:
+ *  - <OpenLayers.Renderer>
+ */
+OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
+
+    /**
+     * Property: rendererRoot
+     * {DOMElement}
+     */
+    rendererRoot: null,
+    
+    /**
+     * Property: root
+     * {DOMElement}
+     */
+    root: null,
+    
+    /**
+     * Property: vectorRoot
+     * {DOMElement}
+     */
+    vectorRoot: null,
+
+    /**
+     * Property: textRoot
+     * {DOMElement}
+     */
+    textRoot: null,
+
+    /**
+     * Property: xmlns
+     * {String}
+     */    
+    xmlns: null,
+    
+    /**
+     * Property: Indexer
+     * {<OpenLayers.ElementIndexer>} An instance of OpenLayers.ElementsIndexer 
+     *     created upon initialization if the zIndexing or yOrdering options
+     *     passed to this renderer's constructor are set to true.
+     */
+    indexer: null, 
+    
+    /**
+     * Constant: BACKGROUND_ID_SUFFIX
+     * {String}
+     */
+    BACKGROUND_ID_SUFFIX: "_background",
+    
+    /**
+     * Constant: LABEL_ID_SUFFIX
+     * {String}
+     */
+    LABEL_ID_SUFFIX: "_label",
+    
+    /**
+     * Constructor: OpenLayers.Renderer.Elements
+     * 
+     * Parameters:
+     * containerID - {String}
+     * options - {Object} options for this renderer. Supported options are:
+     *     * yOrdering - {Boolean} Whether to use y-ordering
+     *     * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored
+     *         if yOrdering is set to true.
+     */
+    initialize: function(containerID, options) {
+        OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
+
+        this.rendererRoot = this.createRenderRoot();
+        this.root = this.createRoot("_root");
+        this.vectorRoot = this.createRoot("_vroot");
+        this.textRoot = this.createRoot("_troot");
+        
+        this.root.appendChild(this.vectorRoot);
+        this.root.appendChild(this.textRoot);
+        
+        this.rendererRoot.appendChild(this.root);
+        this.container.appendChild(this.rendererRoot);
+        
+        if(options && (options.zIndexing || options.yOrdering)) {
+            this.indexer = new OpenLayers.ElementsIndexer(options.yOrdering);
+        }
+    },
+    
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+
+        this.clear(); 
+
+        this.rendererRoot = null;
+        this.root = null;
+        this.xmlns = null;
+
+        OpenLayers.Renderer.prototype.destroy.apply(this, arguments);
+    },
+    
+    /**
+     * Method: clear
+     * Remove all the elements from the root
+     */    
+    clear: function() {
+        var child;
+        var root = this.vectorRoot;
+        if (root) {
+            while (child = root.firstChild) {
+                root.removeChild(child);
+            }
+        }
+        root = this.textRoot;
+        if (root) {
+            while (child = root.firstChild) {
+                root.removeChild(child);
+            }
+        }
+        if (this.indexer) {
+            this.indexer.clear();
+        }
+    },
+
+    /** 
+     * Method: getNodeType
+     * This function is in charge of asking the specific renderer which type
+     *     of node to create for the given geometry and style. All geometries
+     *     in an Elements-based renderer consist of one node and some
+     *     attributes. We have the nodeFactory() function which creates a node
+     *     for us, but it takes a 'type' as input, and that is precisely what
+     *     this function tells us.  
+     *  
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * 
+     * Returns:
+     * {String} The corresponding node type for the specified geometry
+     */
+    getNodeType: function(geometry, style) { },
+
+    /** 
+     * Method: drawGeometry 
+     * Draw the geometry, creating new nodes, setting paths, setting style,
+     *     setting featureId on the node.  This method should only be called
+     *     by the renderer itself.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * featureId - {String}
+     * 
+     * Returns:
+     * {Boolean} true if the geometry has been drawn completely; null if
+     *     incomplete; false otherwise
+     */
+    drawGeometry: function(geometry, style, featureId) {
+        var className = geometry.CLASS_NAME;
+        var rendered = true;
+        if ((className == "OpenLayers.Geometry.Collection") ||
+            (className == "OpenLayers.Geometry.MultiPoint") ||
+            (className == "OpenLayers.Geometry.MultiLineString") ||
+            (className == "OpenLayers.Geometry.MultiPolygon")) {
+            for (var i = 0, len=geometry.components.length; i<len; i++) {
+                rendered = this.drawGeometry(
+                    geometry.components[i], style, featureId) && rendered;
+            }
+            return rendered;
+        };
+
+        rendered = false;
+        var removeBackground = false;
+        if (style.display != "none") {
+            if (style.backgroundGraphic) {
+                this.redrawBackgroundNode(geometry.id, geometry, style,
+                    featureId);
+            } else {
+                removeBackground = true;
+            }
+            rendered = this.redrawNode(geometry.id, geometry, style,
+                featureId);
+        }
+        if (rendered == false) {
+            var node = document.getElementById(geometry.id);
+            if (node) {
+                if (node._style.backgroundGraphic) {
+                    removeBackground = true;
+                }
+                node.parentNode.removeChild(node);
+            }
+        }
+        if (removeBackground) {
+            var node = document.getElementById(
+                geometry.id + this.BACKGROUND_ID_SUFFIX);
+            if (node) {
+                node.parentNode.removeChild(node);
+            }
+        }
+        return rendered;
+    },
+    
+    /**
+     * Method: redrawNode
+     * 
+     * Parameters:
+     * id - {String}
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * featureId - {String}
+     * 
+     * Returns:
+     * {Boolean} true if the complete geometry could be drawn, null if parts of
+     *     the geometry could not be drawn, false otherwise
+     */
+    redrawNode: function(id, geometry, style, featureId) {
+        style = this.applyDefaultSymbolizer(style);
+        // Get the node if it's already on the map.
+        var node = this.nodeFactory(id, this.getNodeType(geometry, style));
+        
+        // Set the data for the node, then draw it.
+        node._featureId = featureId;
+        node._boundsBottom = geometry.getBounds().bottom;
+        node._geometryClass = geometry.CLASS_NAME;
+        node._style = style;
+
+        var drawResult = this.drawGeometryNode(node, geometry, style);
+        if(drawResult === false) {
+            return false;
+        }
+         
+        node = drawResult.node;
+        
+        // Insert the node into the indexer so it can show us where to
+        // place it. Note that this operation is O(log(n)). If there's a
+        // performance problem (when dragging, for instance) this is
+        // likely where it would be.
+        if (this.indexer) {
+            var insert = this.indexer.insert(node);
+            if (insert) {
+                this.vectorRoot.insertBefore(node, insert);
+            } else {
+                this.vectorRoot.appendChild(node);
+            }
+        } else {
+            // if there's no indexer, simply append the node to root,
+            // but only if the node is a new one
+            if (node.parentNode !== this.vectorRoot){ 
+                this.vectorRoot.appendChild(node);
+            }
+        }
+        
+        this.postDraw(node);
+        
+        return drawResult.complete;
+    },
+    
+    /**
+     * Method: redrawBackgroundNode
+     * Redraws the node using special 'background' style properties. Basically
+     *     just calls redrawNode(), but instead of directly using the 
+     *     'externalGraphic', 'graphicXOffset', 'graphicYOffset', and 
+     *     'graphicZIndex' properties directly from the specified 'style' 
+     *     parameter, we create a new style object and set those properties 
+     *     from the corresponding 'background'-prefixed properties from 
+     *     specified 'style' parameter.
+     * 
+     * Parameters:
+     * id - {String}
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * featureId - {String}
+     * 
+     * Returns:
+     * {Boolean} true if the complete geometry could be drawn, null if parts of
+     *     the geometry could not be drawn, false otherwise
+     */
+    redrawBackgroundNode: function(id, geometry, style, featureId) {
+        var backgroundStyle = OpenLayers.Util.extend({}, style);
+        
+        // Set regular style attributes to apply to the background styles.
+        backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic;
+        backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset;
+        backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset;
+        backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex;
+        backgroundStyle.graphicWidth = backgroundStyle.backgroundWidth || backgroundStyle.graphicWidth;
+        backgroundStyle.graphicHeight = backgroundStyle.backgroundHeight || backgroundStyle.graphicHeight;
+        
+        // Erase background styles.
+        backgroundStyle.backgroundGraphic = null;
+        backgroundStyle.backgroundXOffset = null;
+        backgroundStyle.backgroundYOffset = null;
+        backgroundStyle.backgroundGraphicZIndex = null;
+        
+        return this.redrawNode(
+            id + this.BACKGROUND_ID_SUFFIX, 
+            geometry, 
+            backgroundStyle, 
+            null
+        );
+    },
+
+    /**
+     * Method: drawGeometryNode
+     * Given a node, draw a geometry on the specified layer.
+     *     node and geometry are required arguments, style is optional.
+     *     This method is only called by the render itself.
+     *
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * 
+     * Returns:
+     * {Object} a hash with properties "node" (the drawn node) and "complete"
+     *     (null if parts of the geometry could not be drawn, false if nothing
+     *     could be drawn)
+     */
+    drawGeometryNode: function(node, geometry, style) {
+        style = style || node._style;
+
+        var options = {
+            'isFilled': style.fill === undefined ?
+                true :
+                style.fill,
+            'isStroked': style.stroke === undefined ?
+                !!style.strokeWidth :
+                style.stroke
+        };
+        var drawn;
+        switch (geometry.CLASS_NAME) {
+            case "OpenLayers.Geometry.Point":
+                if(style.graphic === false) {
+                    options.isFilled = false;
+                    options.isStroked = false;
+                }
+                drawn = this.drawPoint(node, geometry);
+                break;
+            case "OpenLayers.Geometry.LineString":
+                options.isFilled = false;
+                drawn = this.drawLineString(node, geometry);
+                break;
+            case "OpenLayers.Geometry.LinearRing":
+                drawn = this.drawLinearRing(node, geometry);
+                break;
+            case "OpenLayers.Geometry.Polygon":
+                drawn = this.drawPolygon(node, geometry);
+                break;
+            case "OpenLayers.Geometry.Surface":
+                drawn = this.drawSurface(node, geometry);
+                break;
+            case "OpenLayers.Geometry.Rectangle":
+                drawn = this.drawRectangle(node, geometry);
+                break;
+            default:
+                break;
+        }
+
+        node._options = options; 
+
+        //set style
+        //TBD simplify this
+        if (drawn != false) {
+            return {
+                node: this.setStyle(node, style, options, geometry),
+                complete: drawn
+            };
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: postDraw
+     * Things that have do be done after the geometry node is appended
+     *     to its parent node. To be overridden by subclasses.
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     */
+    postDraw: function(node) {},
+    
+    /**
+     * Method: drawPoint
+     * Virtual function for drawing Point Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the point
+     */ 
+    drawPoint: function(node, geometry) {},
+
+    /**
+     * Method: drawLineString
+     * Virtual function for drawing LineString Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components of
+     *     the linestring, or false if nothing could be drawn
+     */ 
+    drawLineString: function(node, geometry) {},
+
+    /**
+     * Method: drawLinearRing
+     * Virtual function for drawing LinearRing Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the linear ring, or false if nothing could be drawn
+     */ 
+    drawLinearRing: function(node, geometry) {},
+
+    /**
+     * Method: drawPolygon
+     * Virtual function for drawing Polygon Geometry. 
+     *    Should be implemented by subclasses.
+     *    This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the polygon, or false if nothing could be drawn
+     */ 
+    drawPolygon: function(node, geometry) {},
+
+    /**
+     * Method: drawRectangle
+     * Virtual function for drawing Rectangle Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the rectangle
+     */ 
+    drawRectangle: function(node, geometry) {},
+
+    /**
+     * Method: drawCircle
+     * Virtual function for drawing Circle Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the circle
+     */ 
+    drawCircle: function(node, geometry) {},
+
+    /**
+     * Method: drawSurface
+     * Virtual function for drawing Surface Geometry. 
+     *     Should be implemented by subclasses.
+     *     This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the surface
+     */ 
+    drawSurface: function(node, geometry) {},
+
+    /**
+     * Method: removeText
+     * Removes a label
+     * 
+     * Parameters:
+     * featureId - {String}
+     */
+    removeText: function(featureId) {
+        var label = document.getElementById(featureId + this.LABEL_ID_SUFFIX);
+        if (label) {
+            this.textRoot.removeChild(label);
+        }
+    },
+
+    /**
+     * Method: getFeatureIdFromEvent
+     * 
+     * Parameters:
+     * evt - {Object} An <OpenLayers.Event> object
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>} A geometry from an event that 
+     *     happened on a layer.
+     */
+    getFeatureIdFromEvent: function(evt) {
+        var target = evt.target;
+        var useElement = target && target.correspondingUseElement;
+        var node = useElement ? useElement : (target || evt.srcElement);
+        var featureId = node._featureId;
+        return featureId;
+    },
+
+    /** 
+     * Method: eraseGeometry
+     * Erase a geometry from the renderer. In the case of a multi-geometry, 
+     *     we cycle through and recurse on ourselves. Otherwise, we look for a 
+     *     node with the geometry.id, destroy its geometry, and remove it from
+     *     the DOM.
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * featureId - {String}
+     */
+    eraseGeometry: function(geometry, featureId) {
+        if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") ||
+            (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") ||
+            (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") ||
+            (geometry.CLASS_NAME == "OpenLayers.Geometry.Collection")) {
+            for (var i=0, len=geometry.components.length; i<len; i++) {
+                this.eraseGeometry(geometry.components[i], featureId);
+            }
+        } else {    
+            var element = OpenLayers.Util.getElement(geometry.id);
+            if (element && element.parentNode) {
+                if (element.geometry) {
+                    element.geometry.destroy();
+                    element.geometry = null;
+                }
+                element.parentNode.removeChild(element);
+
+                if (this.indexer) {
+                    this.indexer.remove(element);
+                }
+                
+                if (element._style.backgroundGraphic) {
+                    var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX;
+                    var bElem = OpenLayers.Util.getElement(backgroundId);
+                    if (bElem && bElem.parentNode) {
+                        // No need to destroy the geometry since the element and the background
+                        // node share the same geometry.
+                        bElem.parentNode.removeChild(bElem);
+                    }
+                }
+            }
+        }
+    },
+
+    /** 
+     * Method: nodeFactory
+     * Create new node of the specified type, with the (optional) specified id.
+     * 
+     * If node already exists with same ID and a different type, we remove it
+     *     and then call ourselves again to recreate it.
+     * 
+     * Parameters:
+     * id - {String}
+     * type - {String} type Kind of node to draw.
+     * 
+     * Returns:
+     * {DOMElement} A new node of the given type and id.
+     */
+    nodeFactory: function(id, type) {
+        var node = OpenLayers.Util.getElement(id);
+        if (node) {
+            if (!this.nodeTypeCompare(node, type)) {
+                node.parentNode.removeChild(node);
+                node = this.nodeFactory(id, type);
+            }
+        } else {
+            node = this.createNode(type, id);
+        }
+        return node;
+    },
+    
+    /** 
+     * Method: nodeTypeCompare
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * type - {String} Kind of node
+     * 
+     * Returns:
+     * {Boolean} Whether or not the specified node is of the specified type
+     *     This function must be overridden by subclasses.
+     */
+    nodeTypeCompare: function(node, type) {},
+    
+    /** 
+     * Method: createNode
+     * 
+     * Parameters:
+     * type - {String} Kind of node to draw.
+     * id - {String} Id for node.
+     * 
+     * Returns:
+     * {DOMElement} A new node of the given type and id.
+     *     This function must be overridden by subclasses.
+     */
+    createNode: function(type, id) {},
+
+    /**
+     * Method: moveRoot
+     * moves this renderer's root to a different renderer.
+     * 
+     * Parameters:
+     * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
+     */
+    moveRoot: function(renderer) {
+        var root = this.root;
+        if(renderer.root.parentNode == this.rendererRoot) {
+            root = renderer.root;
+        }
+        root.parentNode.removeChild(root);
+        renderer.rendererRoot.appendChild(root);
+    },
+    
+    /**
+     * Method: getRenderLayerId
+     * Gets the layer that this renderer's output appears on. If moveRoot was
+     * used, this will be different from the id of the layer containing the
+     * features rendered by this renderer.
+     * 
+     * Returns:
+     * {String} the id of the output layer.
+     */
+    getRenderLayerId: function() {
+        return this.root.parentNode.parentNode.id;
+    },
+    
+    /**
+     * Method: isComplexSymbol
+     * Determines if a symbol cannot be rendered using drawCircle
+     * 
+     * Parameters:
+     * graphicName - {String}
+     * 
+     * Returns
+     * {Boolean} true if the symbol is complex, false if not
+     */
+    isComplexSymbol: function(graphicName) {
+        return (graphicName != "circle") && !!graphicName;
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer.Elements"
+});
+
+
+/**
+ * Constant: OpenLayers.Renderer.symbol
+ * Coordinate arrays for well known (named) symbols.
+ */
+OpenLayers.Renderer.symbol = {
+    "star": [350,75, 379,161, 469,161, 397,215, 423,301, 350,250, 277,301,
+            303,215, 231,161, 321,161, 350,75],
+    "cross": [4,0, 6,0, 6,4, 10,4, 10,6, 6,6, 6,10, 4,10, 4,6, 0,6, 0,4, 4,4,
+            4,0],
+    "x": [0,0, 25,0, 50,35, 75,0, 100,0, 65,50, 100,100, 75,100, 50,65, 25,100, 0,100, 35,50, 0,0],
+    "square": [0,0, 0,1, 1,1, 1,0, 0,0],
+    "triangle": [0,10, 10,10, 5,0, 0,10]
+};
+/* ======================================================================
+    OpenLayers/Control/ArgParser.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ArgParser
+ * The ArgParser control adds location bar querystring parsing functionality 
+ * to an OpenLayers Map.
+ * When added to a Map control, on a page load/refresh, the Map will 
+ * automatically take the href string and parse it for lon, lat, zoom, and 
+ * layers information. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ArgParser = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Parameter: center
+     * {<OpenLayers.LonLat>}
+     */
+    center: null,
+    
+    /**
+     * Parameter: zoom
+     * {int}
+     */
+    zoom: null,
+
+    /**
+     * Parameter: layers 
+     * {Array(<OpenLayers.Layer>)}
+     */
+    layers: null,
+    
+    /** 
+     * APIProperty: displayProjection
+     * {<OpenLayers.Projection>} Requires proj4js support. 
+     *     Projection used when reading the coordinates from the URL. This will
+     *
+     *     reproject the map coordinates from the URL into the map's
+     *     projection.
+     *
+     *     If you are using this functionality, be aware that any permalink
+     *     which is added to the map will determine the coordinate type which
+     *     is read from the URL, which means you should not add permalinks with
+     *     different displayProjections to the same map. 
+     */
+    displayProjection: null, 
+
+    /**
+     * Constructor: OpenLayers.Control.ArgParser
+     *
+     * Parameters:
+     * options - {Object}
+     */
+
+    /**
+     * Method: getParameters
+     */    
+    getParameters: function(url) {
+        url = url || window.location.href;
+        var parameters = OpenLayers.Util.getParameters(url);
+
+        // If we have an chchor in the url use it to split the url
+        var index = url.indexOf('#');
+        if (index > 0) {
+            // create an url to parce on the getParameters
+            url = '?' + url.substring(index + 1, url.length);
+
+            OpenLayers.Util.extend(parameters,
+                    OpenLayers.Util.getParameters(url));
+        }
+        return parameters;
+    },
+    
+    /**
+     * Method: setMap
+     * Set the map property for the control. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+
+        //make sure we dont already have an arg parser attached
+        for(var i=0, len=this.map.controls.length; i<len; i++) {
+            var control = this.map.controls[i];
+            if ( (control != this) &&
+                 (control.CLASS_NAME == "OpenLayers.Control.ArgParser") ) {
+                
+                // If a second argparser is added to the map, then we 
+                // override the displayProjection to be the one added to the
+                // map. 
+                if (control.displayProjection != this.displayProjection) {
+                    this.displayProjection = control.displayProjection;
+                }    
+                
+                break;
+            }
+        }
+        if (i == this.map.controls.length) {
+
+            var args = this.getParameters();
+            // Be careful to set layer first, to not trigger unnecessary layer loads
+            if (args.layers) {
+                this.layers = args.layers;
+    
+                // when we add a new layer, set its visibility 
+                this.map.events.register('addlayer', this, 
+                                         this.configureLayers);
+                this.configureLayers();
+            }
+            if (args.lat && args.lon) {
+                this.center = new OpenLayers.LonLat(parseFloat(args.lon),
+                                                    parseFloat(args.lat));
+                if (args.zoom) {
+                    this.zoom = parseInt(args.zoom);
+                }
+    
+                // when we add a new baselayer to see when we can set the center
+                this.map.events.register('changebaselayer', this, 
+                                         this.setCenter);
+                this.setCenter();
+            }
+        }
+    },
+   
+    /** 
+     * Method: setCenter
+     * As soon as a baseLayer has been loaded, we center and zoom
+     *   ...and remove the handler.
+     */
+    setCenter: function() {
+        
+        if (this.map.baseLayer) {
+            //dont need to listen for this one anymore
+            this.map.events.unregister('changebaselayer', this, 
+                                       this.setCenter);
+            
+            if (this.displayProjection) {
+                this.center.transform(this.displayProjection, 
+                                      this.map.getProjectionObject()); 
+            }      
+
+            this.map.setCenter(this.center, this.zoom);
+        }
+    },
+
+    /** 
+     * Method: configureLayers
+     * As soon as all the layers are loaded, cycle through them and 
+     *   hide or show them. 
+     */
+    configureLayers: function() {
+
+        if (this.layers.length == this.map.layers.length) { 
+            this.map.events.unregister('addlayer', this, this.configureLayers);
+
+            for(var i=0, len=this.layers.length; i<len; i++) {
+                
+                var layer = this.map.layers[i];
+                var c = this.layers.charAt(i);
+                
+                if (c == "B") {
+                    this.map.setBaseLayer(layer);
+                } else if ( (c == "T") || (c == "F") ) {
+                    layer.setVisibility(c == "T");
+                }
+            }
+        }
+    },     
+
+    CLASS_NAME: "OpenLayers.Control.ArgParser"
+});
+/* ======================================================================
+    OpenLayers/Control/Permalink.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Control/ArgParser.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Permalink
+ * The Permalink control is hyperlink that will return the user to the 
+ * current map view. By default it is drawn in the lower right corner of the
+ * map. The href is updated as the map is zoomed, panned and whilst layers
+ * are switched.
+ * `
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Permalink = OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * APIProperty: argParserClass
+     * {Class} The ArgParser control class (not instance) to use with this
+     *     control.
+     */
+    argParserClass: OpenLayers.Control.ArgParser,
+
+    /** 
+     * Property: element 
+     * {DOMElement}
+     */
+    element: null,
+    
+    /** 
+     * APIProperty: anchor
+     * {Boolean} This option changes 3 things:
+     *     the character '#' is used in place of the character '?',
+     *     the window.href is updated if no element is provided.
+     *     When this option is set to true it's not recommend to provide
+     *     a base without provide an element.
+     */
+    anchor: false,
+
+    /** 
+     * APIProperty: base
+     * {String}
+     */
+    base: '',
+
+    /** 
+     * APIProperty: displayProjection
+     * {<OpenLayers.Projection>} Requires proj4js support.  Projection used
+     *     when creating the coordinates in the link. This will reproject the
+     *     map coordinates into display coordinates. If you are using this
+     *     functionality, the permalink which is last added to the map will
+     *     determine the coordinate type which is read from the URL, which
+     *     means you should not add permalinks with different
+     *     displayProjections to the same map. 
+     */
+    displayProjection: null, 
+
+    /**
+     * Constructor: OpenLayers.Control.Permalink
+     *
+     * Parameters: 
+     * element - {DOMElement} 
+     * base - {String} 
+     * options - {Object} options to the control.
+     *
+     * Or for anchor:
+     * options - {Object} options to the control.
+     */
+    initialize: function(element, base, options) {
+        if (element !== null && typeof element == 'object' && !OpenLayers.Util.isElement(element)) {
+            options = element;
+            this.base = document.location.href;
+            OpenLayers.Control.prototype.initialize.apply(this, [options]);
+            if (this.element != null) {
+                this.element = OpenLayers.Util.getElement(this.element);
+            }
+        }
+        else {
+            OpenLayers.Control.prototype.initialize.apply(this, [options]);
+            this.element = OpenLayers.Util.getElement(element);
+            this.base = base || document.location.href;
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function()  {
+        if (this.element.parentNode == this.div) {
+            this.div.removeChild(this.element);
+        }
+        this.element = null;
+
+        this.map.events.unregister('moveend', this, this.updateLink);
+
+        OpenLayers.Control.prototype.destroy.apply(this, arguments); 
+    },
+
+    /**
+     * Method: setMap
+     * Set the map property for the control. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+
+        //make sure we have an arg parser attached
+        for(var i=0, len=this.map.controls.length; i<len; i++) {
+            var control = this.map.controls[i];
+            if (control.CLASS_NAME == this.argParserClass.CLASS_NAME) {
+                
+                // If a permalink is added to the map, and an ArgParser already
+                // exists, we override the displayProjection to be the one
+                // on the permalink. 
+                if (control.displayProjection != this.displayProjection) {
+                    this.displayProjection = control.displayProjection;
+                }    
+                
+                break;
+            }
+        }
+        if (i == this.map.controls.length) {
+            this.map.addControl(new this.argParserClass(
+                { 'displayProjection': this.displayProjection }));       
+        }
+
+    },
+
+    /**
+     * Method: draw
+     *
+     * Returns:
+     * {DOMElement}
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+          
+        if (!this.element && !this.anchor) {
+            this.element = document.createElement("a");
+            this.element.innerHTML = OpenLayers.i18n("Permalink");
+            this.element.href="";
+            this.div.appendChild(this.element);
+        }
+        this.map.events.on({
+            'moveend': this.updateLink,
+            'changelayer': this.updateLink,
+            'changebaselayer': this.updateLink,
+            scope: this
+        });
+        
+        // Make it so there is at least a link even though the map may not have
+        // moved yet.
+        this.updateLink();
+        
+        return this.div;
+    },
+   
+    /**
+     * Method: updateLink 
+     */
+    updateLink: function() {
+        var separator = this.anchor ? '#' : '?';
+        var href = this.base;
+        if (href.indexOf(separator) != -1) {
+            href = href.substring( 0, href.indexOf(separator) );
+        }
+
+        href += separator + OpenLayers.Util.getParameterString(this.createParams());
+        if (this.anchor && !this.element) {
+            window.location.href = href;
+        }
+        else {
+            this.element.href = href;
+        }
+    }, 
+    
+    /**
+     * APIMethod: createParams
+     * Creates the parameters that need to be encoded into the permalink url.
+     * 
+     * Parameters:
+     * center - {<OpenLayers.LonLat>} center to encode in the permalink.
+     *     Defaults to the current map center.
+     * zoom - {Integer} zoom level to encode in the permalink. Defaults to the
+     *     current map zoom level.
+     * layers - {Array(<OpenLayers.Layer>)} layers to encode in the permalink.
+     *     Defaults to the current map layers.
+     * 
+     * Returns:
+     * {Object} Hash of parameters that will be url-encoded into the
+     * permalink.
+     */
+    createParams: function(center, zoom, layers) {
+        center = center || this.map.getCenter();
+          
+        var params = OpenLayers.Util.getParameters(this.base);
+        
+        // If there's still no center, map is not initialized yet. 
+        // Break out of this function, and simply return the params from the
+        // base link.
+        if (center) { 
+
+            //zoom
+            params.zoom = zoom || this.map.getZoom(); 
+
+            //lon,lat
+            var lat = center.lat;
+            var lon = center.lon;
+            
+            if (this.displayProjection) {
+                var mapPosition = OpenLayers.Projection.transform(
+                  { x: lon, y: lat }, 
+                  this.map.getProjectionObject(), 
+                  this.displayProjection );
+                lon = mapPosition.x;  
+                lat = mapPosition.y;  
+            }       
+            params.lat = Math.round(lat*100000)/100000;
+            params.lon = Math.round(lon*100000)/100000;
+    
+            //layers        
+            layers = layers || this.map.layers;  
+            params.layers = '';
+            for (var i=0, len=layers.length; i<len; i++) {
+                var layer = layers[i];
+    
+                if (layer.isBaseLayer) {
+                    params.layers += (layer == this.map.baseLayer) ? "B" : "0";
+                } else {
+                    params.layers += (layer.getVisibility()) ? "T" : "F";           
+                }
+            }
+        }
+
+        return params;
+    }, 
+
+    CLASS_NAME: "OpenLayers.Control.Permalink"
+});
+/* ======================================================================
+    OpenLayers/Layer/TMS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.TMS
+ * Create a layer for accessing tiles from services that conform with the 
+ *     Tile Map Service Specification 
+ *     (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification).
+ *
+ * Example:
+ * (code)
+ *     var layer = OpenLayers.Layer.TMS(
+ *         "My Layer", // name for display in LayerSwitcher
+ *         "http://tilecache.osgeo.org/wms-c/Basic.py/", // service endpoint
+ *         {layername: "basic", type: "png"} // required properties
+ *     );
+ * (end)
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.TMS = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * APIProperty: serviceVersion
+     * {String} Service version for tile requests.  Default is "1.0.0".
+     */
+    serviceVersion: "1.0.0",
+
+    /**
+     * APIProperty: layername
+     * {String} The identifier for the <TileMap> as advertised by the service.  
+     *     For example, if the service advertises a <TileMap> with 
+     *    'href="http://tms.osgeo.org/1.0.0/vmap0"', the <layername> property 
+     *     would be set to "vmap0".
+     */
+    layername: null,
+
+    /**
+     * APIProperty: type
+     * {String} The format extension corresponding to the requested tile image
+     *     type.  This is advertised in a <TileFormat> element as the 
+     *     "extension" attribute.  For example, if the service advertises a 
+     *     <TileMap> with <TileFormat width="256" height="256" mime-type="image/jpeg" extension="jpg" />,
+     *     the <type> property would be set to "jpg".
+     */
+    type: null,
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} Make this layer a base layer.  Default is true.  Set false to
+     *     use the layer as an overlay.
+     */
+    isBaseLayer: true,
+
+    /**
+     * APIProperty: tileOrigin
+     * {<OpenLayers.LonLat>} Optional origin for aligning the grid of tiles.
+     *     If provided, requests for tiles at all resolutions will be aligned
+     *     with this location (no tiles shall overlap this location).  If
+     *     not provided, the grid of tiles will be aligned with the bottom-left
+     *     corner of the map's <maxExtent>.  Default is ``null``.
+     *
+     * Example:
+     * (code)
+     *     var layer = OpenLayers.Layer.TMS(
+     *         "My Layer",
+     *         "http://tilecache.osgeo.org/wms-c/Basic.py/",
+     *         {
+     *             layername: "basic", 
+     *             type: "png",
+     *             // set if different than the bottom left of map.maxExtent
+     *             tileOrigin: new OpenLayers.LonLat(-180, -90)
+     *         }
+     *     );
+     * (end)
+     */
+    tileOrigin: null,
+
+    /**
+     * APIProperty: serverResolutions
+     * {Array} A list of all resolutions available on the server.  Only set this 
+     *     property if the map resolutions differs from the server.
+     */
+    serverResolutions: null,
+
+    /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more zoom levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
+     *     setting <serverResolutions> if you only want to expose a subset
+     *     of the server resolutions.
+     */
+    zoomOffset: 0,
+    
+    /**
+     * Constructor: OpenLayers.Layer.TMS
+     * 
+     * Parameters:
+     * name - {String} Title to be displayed in a <OpenLayers.Control.LayerSwitcher>
+     * url - {String} Service endpoint (without the version number).  E.g.
+     *     "http://tms.osgeo.org/".
+     * options - {Object} Additional properties to be set on the layer.  The
+     *     <layername> and <type> properties must be set here.
+     */
+    initialize: function(name, url, options) {
+        var newArguments = [];
+        newArguments.push(name, url, {}, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },    
+
+    /**
+     * APIMethod:destroy
+     */
+    destroy: function() {
+        // for now, nothing special to do here. 
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);  
+    },
+
+    
+    /**
+     * APIMethod: clone
+     * Create a complete copy of this layer.
+     *
+     * Parameters:
+     * obj - {Object} Should only be provided by subclasses that call this
+     *     method.
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.TMS>} An exact clone of this <OpenLayers.Layer.TMS>
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.TMS(this.name,
+                                           this.url,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },    
+    
+    /**
+     * Method: getURL
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the 
+     *          passed-in bounds and appropriate tile size specified as 
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+        var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
+        var z = this.serverResolutions != null ?
+            OpenLayers.Util.indexOf(this.serverResolutions, res) :
+            this.map.getZoom() + this.zoomOffset;
+        var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(path, url);
+        }
+        return url + path;
+    },
+
+    /** 
+     * Method: setMap
+     * When the layer is added to a map, then we can fetch our origin 
+     *    (if we don't have one.) 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        if (!this.tileOrigin) { 
+            this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
+                                                this.map.maxExtent.bottom);
+        }                                       
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.TMS"
+});
+/* ======================================================================
+    OpenLayers/Strategy/Fixed.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Fixed
+ * A simple strategy that requests features once and never requests new data.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Fixed = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * APIProperty: preload
+     * {Boolean} Load data before layer made visible. Enabling this may result
+     *   in considerable overhead if your application loads many data layers
+     *   that are not visible by default. Default is false.
+     */
+    preload: false,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Fixed
+     * Create a new Fixed strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+
+    /**
+     * Method: activate
+     * Activate the strategy: load data or add listener to load when visible
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated or false if
+     *      the strategy was already active.
+     */
+    activate: function() {
+        if(OpenLayers.Strategy.prototype.activate.apply(this, arguments)) {
+            this.layer.events.on({
+                "refresh": this.load,
+                scope: this
+            });
+            if(this.layer.visibility == true || this.preload) {
+                this.load();
+            } else {
+                this.layer.events.on({
+                    "visibilitychanged": this.load,
+                    scope: this
+                });
+            }
+            return true;
+        }
+        return false;
+    },
+    
+    /**
+     * Method: deactivate
+     * Deactivate the strategy.  Undo what is done in <activate>.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.layer.events.un({
+                "refresh": this.load,
+                "visibilitychanged": this.load,
+                scope: this
+            });
+        }
+        return deactivated;
+    },
+
+    /**
+     * Method: load
+     * Tells protocol to load data and unhooks the visibilitychanged event
+     *
+     * Parameters:
+     * options - {Object} options to pass to protocol read.
+     */
+    load: function(options) {
+        var layer = this.layer;
+        layer.events.triggerEvent("loadstart");
+        layer.protocol.read(OpenLayers.Util.applyDefaults({
+            callback: OpenLayers.Function.bind(this.merge, this,
+                layer.map.getProjectionObject()),
+            filter: layer.filter
+        }, options));
+        layer.events.un({
+            "visibilitychanged": this.load,
+            scope: this
+        });
+    },
+
+    /**
+     * Method: merge
+     * Add all features to the layer.
+     *
+     * Parameters:
+     * mapProjection - {OpenLayers.Projection} the map projection
+     * resp - {Object} options to pass to protocol read.
+     */
+    merge: function(mapProjection, resp) {
+        var layer = this.layer;
+        layer.destroyFeatures();
+        var features = resp.features;
+        if (features && features.length > 0) {
+            if(!mapProjection.equals(layer.projection)) {
+                var geom;
+                for(var i=0, len=features.length; i<len; ++i) {
+                    geom = features[i].geometry;
+                    if(geom) {
+                        geom.transform(layer.projection, mapProjection);
+                    }
+                }
+            }
+            layer.addFeatures(features);
+        }
+        layer.events.triggerEvent("loadend");
+    },
+
+    CLASS_NAME: "OpenLayers.Strategy.Fixed"
+});
+/* ======================================================================
+    OpenLayers/Control/MouseDefaults.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.MouseDefaults
+ * This class is DEPRECATED in 2.4 and will be removed by 3.0.
+ * If you need this functionality, use <OpenLayers.Control.Navigation> 
+ * instead!!!
+ *
+ * This class is DEPRECATED in 2.4 and will be removed by 3.0.
+ *     If you need this functionality, use Control.Navigation instead!!!
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, {
+
+    /** WARNING WARNING WARNING!!!
+        This class is DEPRECATED in 2.4 and will be removed by 3.0.
+        If you need this functionality, use Control.Navigation instead!!! */
+
+    /** 
+     * Property: performedDrag
+     * {Boolean}
+     */
+    performedDrag: false,
+
+    /** 
+     * Property: wheelObserver 
+     * {Function}
+     */
+    wheelObserver: null,
+
+    /** 
+     * Constructor: OpenLayers.Control.MouseDefaults
+     */
+    initialize: function() {
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: destroy
+     */    
+    destroy: function() {
+        
+        if (this.handler) {
+            this.handler.destroy();
+        }
+        this.handler = null;
+
+        this.map.events.un({
+            "click": this.defaultClick,
+            "dblclick": this.defaultDblClick,
+            "mousedown": this.defaultMouseDown,
+            "mouseup": this.defaultMouseUp,
+            "mousemove": this.defaultMouseMove,
+            "mouseout": this.defaultMouseOut,
+            scope: this
+        });
+
+        //unregister mousewheel events specifically on the window and document
+        OpenLayers.Event.stopObserving(window, "DOMMouseScroll", 
+                                        this.wheelObserver);
+        OpenLayers.Event.stopObserving(window, "mousewheel", 
+                                        this.wheelObserver);
+        OpenLayers.Event.stopObserving(document, "mousewheel", 
+                                        this.wheelObserver);
+        this.wheelObserver = null;
+                      
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);        
+    },
+
+    /**
+     * Method: draw
+     */
+    draw: function() {
+        this.map.events.on({
+            "click": this.defaultClick,
+            "dblclick": this.defaultDblClick,
+            "mousedown": this.defaultMouseDown,
+            "mouseup": this.defaultMouseUp,
+            "mousemove": this.defaultMouseMove,
+            "mouseout": this.defaultMouseOut,
+            scope: this
+        });
+
+        this.registerWheelEvents();
+
+    },
+
+    /**
+     * Method: registerWheelEvents
+     */
+    registerWheelEvents: function() {
+
+        this.wheelObserver = OpenLayers.Function.bindAsEventListener(
+            this.onWheelEvent, this
+        );
+        
+        //register mousewheel events specifically on the window and document
+        OpenLayers.Event.observe(window, "DOMMouseScroll", this.wheelObserver);
+        OpenLayers.Event.observe(window, "mousewheel", this.wheelObserver);
+        OpenLayers.Event.observe(document, "mousewheel", this.wheelObserver);
+    },
+
+    /**
+     * Method: defaultClick
+     * 
+     * Parameters:
+     * evt - {Event} 
+     *
+     * Returns:
+     * {Boolean}
+     */
+    defaultClick: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        var notAfterDrag = !this.performedDrag;
+        this.performedDrag = false;
+        return notAfterDrag;
+    },
+
+    /**
+     * Method: defaultDblClick
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultDblClick: function (evt) {
+        var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); 
+        this.map.setCenter(newCenter, this.map.zoom + 1);
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+
+    /**
+     * Method: defaultMouseDown
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseDown: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        this.mouseDragStart = evt.xy.clone();
+        this.performedDrag  = false;
+        if (evt.shiftKey) {
+            this.map.div.style.cursor = "crosshair";
+            this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
+                                                     this.mouseDragStart,
+                                                     null,
+                                                     null,
+                                                     "absolute",
+                                                     "2px solid red");
+            this.zoomBox.style.backgroundColor = "white";
+            this.zoomBox.style.filter = "alpha(opacity=50)"; // IE
+            this.zoomBox.style.opacity = "0.50";
+            this.zoomBox.style.fontSize = "1px";
+            this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+            this.map.eventsDiv.appendChild(this.zoomBox);
+        }
+        document.onselectstart = OpenLayers.Function.False;
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: defaultMouseMove
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseMove: function (evt) {
+        // record the mouse position, used in onWheelEvent
+        this.mousePosition = evt.xy.clone();
+
+        if (this.mouseDragStart != null) {
+            if (this.zoomBox) {
+                var deltaX = Math.abs(this.mouseDragStart.x - evt.xy.x);
+                var deltaY = Math.abs(this.mouseDragStart.y - evt.xy.y);
+                this.zoomBox.style.width = Math.max(1, deltaX) + "px";
+                this.zoomBox.style.height = Math.max(1, deltaY) + "px";
+                if (evt.xy.x < this.mouseDragStart.x) {
+                    this.zoomBox.style.left = evt.xy.x+"px";
+                }
+                if (evt.xy.y < this.mouseDragStart.y) {
+                    this.zoomBox.style.top = evt.xy.y+"px";
+                }
+            } else {
+                var deltaX = this.mouseDragStart.x - evt.xy.x;
+                var deltaY = this.mouseDragStart.y - evt.xy.y;
+                var size = this.map.getSize();
+                var newXY = new OpenLayers.Pixel(size.w / 2 + deltaX,
+                                                 size.h / 2 + deltaY);
+                var newCenter = this.map.getLonLatFromViewPortPx( newXY ); 
+                this.map.setCenter(newCenter, null, true);
+                this.mouseDragStart = evt.xy.clone();
+                this.map.div.style.cursor = "move";
+            }
+            this.performedDrag = true;
+        }
+    },
+
+    /**
+     * Method: defaultMouseUp
+     * 
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    defaultMouseUp: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        if (this.zoomBox) {
+            this.zoomBoxEnd(evt);    
+        } else {
+            if (this.performedDrag) {
+                this.map.setCenter(this.map.center);
+            }
+        }
+        document.onselectstart=null;
+        this.mouseDragStart = null;
+        this.map.div.style.cursor = "";
+    },
+
+    /**
+     * Method: defaultMouseOut
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseOut: function (evt) {
+        if (this.mouseDragStart != null && 
+            OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) {
+            if (this.zoomBox) {
+                this.removeZoomBox();
+            }
+            this.mouseDragStart = null;
+        }
+    },
+
+
+    /** 
+     * Method: defaultWheelUp
+     * User spun scroll wheel up
+     * 
+     */
+    defaultWheelUp: function(evt) {
+        if (this.map.getZoom() <= this.map.getNumZoomLevels()) {
+            this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),
+                               this.map.getZoom() + 1);
+        }
+    },
+
+    /**
+     * Method: defaultWheelDown
+     * User spun scroll wheel down
+     */
+    defaultWheelDown: function(evt) {
+        if (this.map.getZoom() > 0) {
+            this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),
+                               this.map.getZoom() - 1);
+        }
+    },
+
+    /**
+     * Method: zoomBoxEnd
+     * Zoombox function. 
+     */
+    zoomBoxEnd: function(evt) {
+        if (this.mouseDragStart != null) {
+            if (Math.abs(this.mouseDragStart.x - evt.xy.x) > 5 ||    
+                Math.abs(this.mouseDragStart.y - evt.xy.y) > 5) {   
+                var start = this.map.getLonLatFromViewPortPx( this.mouseDragStart ); 
+                var end = this.map.getLonLatFromViewPortPx( evt.xy );
+                var top = Math.max(start.lat, end.lat);
+                var bottom = Math.min(start.lat, end.lat);
+                var left = Math.min(start.lon, end.lon);
+                var right = Math.max(start.lon, end.lon);
+                var bounds = new OpenLayers.Bounds(left, bottom, right, top);
+                this.map.zoomToExtent(bounds);
+            } else {
+                var end = this.map.getLonLatFromViewPortPx( evt.xy );
+                this.map.setCenter(new OpenLayers.LonLat(
+                  (end.lon),
+                  (end.lat)
+                 ), this.map.getZoom() + 1);
+            }    
+            this.removeZoomBox();
+       }
+    },
+
+    /**
+     * Method: removeZoomBox
+     * Remove the zoombox from the screen and nullify our reference to it.
+     */
+    removeZoomBox: function() {
+        this.map.eventsDiv.removeChild(this.zoomBox);
+        this.zoomBox = null;
+    },
+
+
+/**
+ *  Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/
+ */
+
+
+    /**
+     * Method: onWheelEvent
+     * Catch the wheel event and handle it xbrowserly
+     *
+     * Parameters: 
+     * e - {Event} 
+     */
+    onWheelEvent: function(e){
+    
+        // first determine whether or not the wheeling was inside the map
+        var inMap = false;
+        var elem = OpenLayers.Event.element(e);
+        while(elem != null) {
+            if (this.map && elem == this.map.div) {
+                inMap = true;
+                break;
+            }
+            elem = elem.parentNode;
+        }
+        
+        if (inMap) {
+            
+            var delta = 0;
+            if (!e) {
+                e = window.event;
+            }
+            if (e.wheelDelta) {
+                delta = e.wheelDelta/120; 
+                if (window.opera && window.opera.version() < 9.2) {
+                    delta = -delta;
+                }
+            } else if (e.detail) {
+                delta = -e.detail / 3;
+            }
+            if (delta) {
+                // add the mouse position to the event because mozilla has a bug
+                // with clientX and clientY (see https://bugzilla.mozilla.org/show_bug.cgi?id=352179)
+                // getLonLatFromViewPortPx(e) returns wrong values
+                e.xy = this.mousePosition;
+
+                if (delta < 0) {
+                   this.defaultWheelDown(e);
+                } else {
+                   this.defaultWheelUp(e);
+                }
+            }
+            
+            //only wheel the map, not the window
+            OpenLayers.Event.stop(e);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.MouseDefaults"
+});
+/* ======================================================================
+    OpenLayers/Control/MouseToolbar.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Control/MouseDefaults.js
+ */
+
+/**
+ * Class: OpenLayers.Control.MouseToolbar
+ * This class is DEPRECATED in 2.4 and will be removed by 3.0.
+ * If you need this functionality, use <OpenLayers.Control.NavToolbar>
+ * instead!!! 
+ */
+OpenLayers.Control.MouseToolbar = OpenLayers.Class(
+                                            OpenLayers.Control.MouseDefaults, {
+    
+    /**
+     * Property: mode
+     */ 
+    mode: null,
+    /**
+     * Property: buttons
+     */
+    buttons: null,
+    
+    /**
+     * APIProperty: direction
+     * {String} 'vertical' or 'horizontal'
+     */
+    direction: "vertical",
+    
+    /**
+     * Property: buttonClicked
+     * {String}
+     */
+    buttonClicked: null,
+    
+    /**
+     * Constructor: OpenLayers.Control.MouseToolbar
+     *
+     * Parameters:
+     * position - {<OpenLayers.Pixel>}
+     * direction - {String}
+     */
+    initialize: function(position, direction) {
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+        this.position = new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,
+                                             OpenLayers.Control.MouseToolbar.Y);
+        if (position) {
+            this.position = position;
+        }
+        if (direction) {
+            this.direction = direction; 
+        }
+        this.measureDivs = [];
+    },
+    
+    /**
+     * APIMethod: destroy 
+     */
+    destroy: function() {
+        for( var btnId in this.buttons) {
+            var btn = this.buttons[btnId];
+            btn.map = null;
+            btn.events.destroy();
+        }
+        OpenLayers.Control.MouseDefaults.prototype.destroy.apply(this, 
+                                                                 arguments);
+    },
+    
+    /**
+     * Method: draw
+     */
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments); 
+        OpenLayers.Control.MouseDefaults.prototype.draw.apply(this, arguments);
+        this.buttons = {};
+        var sz = new OpenLayers.Size(28,28);
+        var centered = new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,0);
+        this._addButton("zoombox", "drag-rectangle-off.png", "drag-rectangle-on.png", centered, sz, "Shift->Drag to zoom to area");
+        centered = centered.add((this.direction == "vertical" ? 0 : sz.w), (this.direction == "vertical" ? sz.h : 0));
+        this._addButton("pan", "panning-hand-off.png", "panning-hand-on.png", centered, sz, "Drag the map to pan.");
+        centered = centered.add((this.direction == "vertical" ? 0 : sz.w), (this.direction == "vertical" ? sz.h : 0));
+        this.switchModeTo("pan");
+
+        return this.div;
+    },
+    
+    /**
+     * Method: _addButton
+     */
+    _addButton:function(id, img, activeImg, xy, sz, title) {
+        var imgLocation = OpenLayers.Util.getImagesLocation() + img;
+        var activeImgLocation = OpenLayers.Util.getImagesLocation() + activeImg;
+        // var btn = new ol.AlphaImage("_"+id, imgLocation, xy, sz);
+        var btn = OpenLayers.Util.createAlphaImageDiv(
+                                    "OpenLayers_Control_MouseToolbar_" + id, 
+                                    xy, sz, imgLocation, "absolute");
+
+        //we want to add the outer div
+        this.div.appendChild(btn);
+        btn.imgLocation = imgLocation;
+        btn.activeImgLocation = activeImgLocation;
+        
+        btn.events = new OpenLayers.Events(this, btn, null, true);
+        btn.events.on({
+            "mousedown": this.buttonDown,
+            "mouseup": this.buttonUp,
+            "dblclick": OpenLayers.Event.stop,
+            scope: this
+        });
+        btn.action = id;
+        btn.title = title;
+        btn.alt = title;
+        btn.map = this.map;
+
+        //we want to remember/reference the outer div
+        this.buttons[id] = btn;
+        return btn;
+    },
+
+    /**
+     * Method: buttonDown
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    buttonDown: function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        this.buttonClicked = evt.element.action;
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: buttonUp
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    buttonUp: function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        if (this.buttonClicked != null) {
+            if (this.buttonClicked == evt.element.action) {
+                this.switchModeTo(evt.element.action);
+            }
+            OpenLayers.Event.stop(evt);
+            this.buttonClicked = null;
+        }
+    },
+    
+    /**
+     * Method: defaultDblClick 
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultDblClick: function (evt) {
+        this.switchModeTo("pan");
+        this.performedDrag = false;
+        var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); 
+        this.map.setCenter(newCenter, this.map.zoom + 1);
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+
+    /**
+     * Method: defaultMouseDown
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseDown: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        this.mouseDragStart = evt.xy.clone();
+        this.performedDrag = false;
+        this.startViaKeyboard = false;
+        if (evt.shiftKey && this.mode !="zoombox") {
+            this.switchModeTo("zoombox");
+            this.startViaKeyboard = true;
+        } else if (evt.altKey && this.mode !="measure") {
+            this.switchModeTo("measure");
+        } else if (!this.mode) {
+            this.switchModeTo("pan");
+        }
+        
+        switch (this.mode) {
+            case "zoombox":
+                this.map.div.style.cursor = "crosshair";
+                this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
+                                                         this.mouseDragStart,
+                                                         null,
+                                                         null,
+                                                         "absolute",
+                                                         "2px solid red");
+                this.zoomBox.style.backgroundColor = "white";
+                this.zoomBox.style.filter = "alpha(opacity=50)"; // IE
+                this.zoomBox.style.opacity = "0.50";
+                this.zoomBox.style.fontSize = "1px";
+                this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+                this.map.eventsDiv.appendChild(this.zoomBox);
+                this.performedDrag = true;
+                break;
+            case "measure":
+                var distance = "";
+                if (this.measureStart) {
+                    var measureEnd = this.map.getLonLatFromViewPortPx(this.mouseDragStart);
+                    distance = OpenLayers.Util.distVincenty(this.measureStart, measureEnd);
+                    distance = Math.round(distance * 100) / 100;
+                    distance = distance + "km";
+                    this.measureStartBox = this.measureBox;
+                }    
+                this.measureStart = this.map.getLonLatFromViewPortPx(this.mouseDragStart);;
+                this.measureBox = OpenLayers.Util.createDiv(null,
+                                                         this.mouseDragStart.add(
+                                                           -2-parseInt(this.map.layerContainerDiv.style.left),
+                                                           -2-parseInt(this.map.layerContainerDiv.style.top)),
+                                                         null,
+                                                         null,
+                                                         "absolute");
+                this.measureBox.style.width="4px";
+                this.measureBox.style.height="4px";
+                this.measureBox.style.fontSize = "1px";
+                this.measureBox.style.backgroundColor="red";
+                this.measureBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+                this.map.layerContainerDiv.appendChild(this.measureBox);
+                if (distance) {
+                    this.measureBoxDistance = OpenLayers.Util.createDiv(null,
+                                                         this.mouseDragStart.add(
+                                                           -2-parseInt(this.map.layerContainerDiv.style.left),
+                                                           2-parseInt(this.map.layerContainerDiv.style.top)),
+                                                         null,
+                                                         null,
+                                                         "absolute");
+                    
+                    this.measureBoxDistance.innerHTML = distance;
+                    this.measureBoxDistance.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+                    this.map.layerContainerDiv.appendChild(this.measureBoxDistance);
+                    this.measureDivs.push(this.measureBoxDistance);
+                }
+                this.measureBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+                this.map.layerContainerDiv.appendChild(this.measureBox);
+                this.measureDivs.push(this.measureBox);
+                break;
+            default:
+                this.map.div.style.cursor = "move";
+                break;
+        }
+        document.onselectstart = OpenLayers.Function.False;
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: switchModeTo 
+     *
+     * Parameters:
+     * mode - {String} 
+     */
+    switchModeTo: function(mode) {
+        if (mode != this.mode) {
+            
+
+            if (this.mode && this.buttons[this.mode]) {
+                OpenLayers.Util.modifyAlphaImageDiv(this.buttons[this.mode], null, null, null, this.buttons[this.mode].imgLocation);
+            }
+            if (this.mode == "measure" && mode != "measure") {
+                for(var i=0, len=this.measureDivs.length; i<len; i++) {
+                    if (this.measureDivs[i]) { 
+                        this.map.layerContainerDiv.removeChild(this.measureDivs[i]);
+                    }
+                }
+                this.measureDivs = [];
+                this.measureStart = null;
+            }
+            this.mode = mode;
+            if (this.buttons[mode]) {
+                OpenLayers.Util.modifyAlphaImageDiv(this.buttons[mode], null, null, null, this.buttons[mode].activeImgLocation);
+            }
+            switch (this.mode) {
+                case "zoombox":
+                    this.map.div.style.cursor = "crosshair";
+                    break;
+                default:
+                    this.map.div.style.cursor = "";
+                    break;
+            }
+
+        } 
+    }, 
+
+    /**
+     * Method: leaveMode
+     */
+    leaveMode: function() {
+        this.switchModeTo("pan");
+    },
+    
+    /**
+     * Method: defaultMouseMove
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseMove: function (evt) {
+        if (this.mouseDragStart != null) {
+            switch (this.mode) {
+                case "zoombox": 
+                    var deltaX = Math.abs(this.mouseDragStart.x - evt.xy.x);
+                    var deltaY = Math.abs(this.mouseDragStart.y - evt.xy.y);
+                    this.zoomBox.style.width = Math.max(1, deltaX) + "px";
+                    this.zoomBox.style.height = Math.max(1, deltaY) + "px";
+                    if (evt.xy.x < this.mouseDragStart.x) {
+                        this.zoomBox.style.left = evt.xy.x+"px";
+                    }
+                    if (evt.xy.y < this.mouseDragStart.y) {
+                        this.zoomBox.style.top = evt.xy.y+"px";
+                    }
+                    break;
+                default:
+                    var deltaX = this.mouseDragStart.x - evt.xy.x;
+                    var deltaY = this.mouseDragStart.y - evt.xy.y;
+                    var size = this.map.getSize();
+                    var newXY = new OpenLayers.Pixel(size.w / 2 + deltaX,
+                                                     size.h / 2 + deltaY);
+                    var newCenter = this.map.getLonLatFromViewPortPx( newXY ); 
+                    this.map.setCenter(newCenter, null, true);
+                    this.mouseDragStart = evt.xy.clone();
+            }
+            this.performedDrag = true;
+        }
+    },
+
+    /**
+     * Method: defaultMouseUp
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseUp: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        switch (this.mode) {
+            case "zoombox":
+                this.zoomBoxEnd(evt);
+                if (this.startViaKeyboard) {
+                    this.leaveMode();
+                }
+                break;
+            case "pan":
+                if (this.performedDrag) {
+                    this.map.setCenter(this.map.center);
+                }        
+        }
+        document.onselectstart = null;
+        this.mouseDragStart = null;
+        this.map.div.style.cursor = "default";
+    },
+
+    /**
+     * Method: defaultMouseOut
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultMouseOut: function (evt) {
+        if (this.mouseDragStart != null
+            && OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) {
+            if (this.zoomBox) {
+                this.removeZoomBox();
+                if (this.startViaKeyboard) {
+                    this.leaveMode();
+                }
+            }
+            this.mouseDragStart = null;
+            this.map.div.style.cursor = "default";
+        }
+    },
+
+    /**
+     * Method: defaultClick
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultClick: function (evt) {
+        if (this.performedDrag)  {
+            this.performedDrag = false;
+            return false;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Control.MouseToolbar"
+});
+
+OpenLayers.Control.MouseToolbar.X = 6;
+OpenLayers.Control.MouseToolbar.Y = 300;
+/* ======================================================================
+    OpenLayers/Layer/PointTrack.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Vector.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.PointTrack
+ * Vector layer to display ordered point features as a line, creating one
+ * LineString feature for each pair of two points.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Vector> 
+ */
+OpenLayers.Layer.PointTrack = OpenLayers.Class(OpenLayers.Layer.Vector, {
+  
+    /**
+     * APIProperty:
+     * dataFrom  - {<OpenLayers.Layer.PointTrack.TARGET_NODE>} or
+     *     {<OpenLayers.Layer.PointTrack.SOURCE_NODE>} optional. If the lines
+     *     should get the data/attributes from one of the two points it is
+     *     composed of, which one should it be?
+     */
+    dataFrom: null,
+    
+    /**
+     * APIProperty:
+     * styleFrom  - {<OpenLayers.Layer.PointTrack.TARGET_NODE>} or
+     *     {<OpenLayers.Layer.PointTrack.SOURCE_NODE>} optional. If the lines
+     *     should get the style from one of the two points it is composed of,
+     *     which one should it be?
+     */
+    styleFrom: null,
+    
+    /**
+     * Constructor: OpenLayers.PointTrack
+     * Constructor for a new OpenLayers.PointTrack instance.
+     *
+     * Parameters:
+     * name     - {String} name of the layer
+     * options  - {Object} Optional object with properties to tag onto the
+     *            instance.
+     */    
+    initialize: function(name, options) {
+        OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
+    },
+        
+    /**
+     * APIMethod: addNodes
+     * Adds point features that will be used to create lines from, using point
+     * pairs. The first point of a pair will be the source node, the second
+     * will be the target node.
+     * 
+     * Parameters:
+     * pointFeatures - {Array(<OpenLayers.Feature>)}
+     * options - {Object}
+     * 
+     * Supported options:
+     * silent - {Boolean} true to suppress (before)feature(s)added events
+     */
+    addNodes: function(pointFeatures, options) {
+        if (pointFeatures.length < 2) {
+            OpenLayers.Console.error(
+                    "At least two point features have to be added to create" +
+                    "a line from");
+            return;
+        }
+        
+        var lines = new Array(pointFeatures.length-1);
+        
+        var pointFeature, startPoint, endPoint;
+        for(var i=0, len=pointFeatures.length; i<len; i++) {
+            pointFeature = pointFeatures[i];
+            endPoint = pointFeature.geometry;
+            
+            if (!endPoint) {
+              var lonlat = pointFeature.lonlat;
+              endPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
+            } else if(endPoint.CLASS_NAME != "OpenLayers.Geometry.Point") {
+                OpenLayers.Console.error(
+                        "Only features with point geometries are supported.");
+                return;
+            }
+            
+            if(i > 0) {
+                var attributes = (this.dataFrom != null) ?
+                        (pointFeatures[i+this.dataFrom].data ||
+                                pointFeatures[i+this.dataFrom].attributes) :
+                        null;
+                var style = (this.styleFrom != null) ?
+                        (pointFeatures[i+this.styleFrom].style) :
+                        null;
+                var line = new OpenLayers.Geometry.LineString([startPoint,
+                        endPoint]);
+                        
+                lines[i-1] = new OpenLayers.Feature.Vector(line, attributes,
+                    style);
+            }
+            
+            startPoint = endPoint;
+        }
+
+        this.addFeatures(lines, options);
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.PointTrack"
+});
+
+/**
+ * Constant: OpenLayers.Layer.PointTrack.SOURCE_NODE
+ * {Number} value for <OpenLayers.Layer.PointTrack.dataFrom> and
+ * <OpenLayers.Layer.PointTrack.styleFrom>
+ */
+OpenLayers.Layer.PointTrack.SOURCE_NODE = -1;
+
+/**
+ * Constant: OpenLayers.Layer.PointTrack.TARGET_NODE
+ * {Number} value for <OpenLayers.Layer.PointTrack.dataFrom> and
+ * <OpenLayers.Layer.PointTrack.styleFrom>
+ */
+OpenLayers.Layer.PointTrack.TARGET_NODE = 0;
+
+/**
+ * Constant: OpenLayers.Layer.PointTrack.dataFrom
+ * {Object} with the following keys - *deprecated*
+ * - SOURCE_NODE: take data/attributes from the source node of the line
+ * - TARGET_NODE: take data/attributes from the target node of the line
+ */
+OpenLayers.Layer.PointTrack.dataFrom = {'SOURCE_NODE': -1, 'TARGET_NODE': 0};
+/* ======================================================================
+    OpenLayers/Protocol/WFS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.WFS
+ * Used to create a versioned WFS protocol.  Default version is 1.0.0.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol>} A WFS protocol of the given version.
+ *
+ * Example:
+ * (code)
+ *     var protocol = new OpenLayers.Protocol.WFS({
+ *         version: "1.1.0",
+ *         url:  "http://demo.opengeo.org/geoserver/wfs",
+ *         featureType: "tasmania_roads",
+ *         featureNS: "http://www.openplans.org/topp",
+ *         geometryName: "the_geom"
+ *     });
+ * (end)
+ *
+ * See the protocols for specific WFS versions for more detail.
+ */
+OpenLayers.Protocol.WFS = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Protocol.WFS.DEFAULTS
+    );
+    var cls = OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported WFS version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Function: fromWMSLayer
+ * Convenience function to create a WFS protocol from a WMS layer.  This makes
+ *     the assumption that a WFS requests can be issued at the same URL as
+ *     WMS requests and that a WFS featureType exists with the same name as the
+ *     WMS layer.
+ *     
+ * This function is designed to auto-configure <url>, <featureType>,
+ *     <featurePrefix> and <srsName> for WFS <version> 1.1.0. Note that
+ *     srsName matching with the WMS layer will not work with WFS 1.0.0.
+ * 
+ * Parameters:
+ * layer - {<OpenLayers.Layer.WMS>} WMS layer that has a matching WFS
+ *     FeatureType at the same server url with the same typename.
+ * options - {Object} Default properties to be set on the protocol.
+ *
+ */
+OpenLayers.Protocol.WFS.fromWMSLayer = function(layer, options) {
+    var typeName, featurePrefix;
+    var param = layer.params["LAYERS"];
+    var parts = (OpenLayers.Util.isArray(param) ? param[0] : param).split(":");
+    if(parts.length > 1) {
+        featurePrefix = parts[0];
+    }
+    typeName = parts.pop();
+    var protocolOptions = {
+        url: layer.url,
+        featureType: typeName,
+        featurePrefix: featurePrefix,
+        srsName: layer.projection && layer.projection.getCode() ||
+                 layer.map && layer.map.getProjectionObject().getCode(),
+        version: "1.1.0"
+    };
+    return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(
+        options, protocolOptions
+    ));
+};
+
+/**
+ * Constant: OpenLayers.Protocol.WFS.DEFAULTS
+ */
+OpenLayers.Protocol.WFS.DEFAULTS = {
+    "version": "1.0.0"
+};
+/* ======================================================================
+    OpenLayers/Layer/Markers.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Markers
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer> 
+ */
+OpenLayers.Layer.Markers = OpenLayers.Class(OpenLayers.Layer, {
+    
+    /** 
+     * APIProperty: isBaseLayer 
+     * {Boolean} Markers layer is never a base layer.  
+     */
+    isBaseLayer: false,
+    
+    /** 
+     * APIProperty: markers 
+     * {Array(<OpenLayers.Marker>)} internal marker list 
+     */
+    markers: null,
+
+
+    /** 
+     * Property: drawn 
+     * {Boolean} internal state of drawing. This is a workaround for the fact
+     * that the map does not call moveTo with a zoomChanged when the map is
+     * first starting up. This lets us catch the case where we have *never*
+     * drawn the layer, and draw it even if the zoom hasn't changed.
+     */
+    drawn: false,
+    
+    /**
+     * Constructor: OpenLayers.Layer.Markers 
+     * Create a Markers layer.
+     *
+     * Parameters:
+     * name - {String} 
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.prototype.initialize.apply(this, arguments);
+        this.markers = [];
+    },
+    
+    /**
+     * APIMethod: destroy 
+     */
+    destroy: function() {
+        this.clearMarkers();
+        this.markers = null;
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: setOpacity
+     * Sets the opacity for all the markers.
+     * 
+     * Parameter:
+     * opacity - {Float}
+     */
+    setOpacity: function(opacity) {
+        if (opacity != this.opacity) {
+            this.opacity = opacity;
+            for (var i=0, len=this.markers.length; i<len; i++) {
+                this.markers[i].setOpacity(this.opacity);
+            }
+        }
+    },
+
+    /** 
+     * Method: moveTo
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * zoomChanged - {Boolean} 
+     * dragging - {Boolean} 
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+
+        if (zoomChanged || !this.drawn) {
+            for(var i=0, len=this.markers.length; i<len; i++) {
+                this.drawMarker(this.markers[i]);
+            }
+            this.drawn = true;
+        }
+    },
+
+    /**
+     * APIMethod: addMarker
+     *
+     * Parameters:
+     * marker - {<OpenLayers.Marker>} 
+     */
+    addMarker: function(marker) {
+        this.markers.push(marker);
+
+        if (this.opacity != null) {
+            marker.setOpacity(this.opacity);
+        }
+
+        if (this.map && this.map.getExtent()) {
+            marker.map = this.map;
+            this.drawMarker(marker);
+        }
+    },
+
+    /**
+     * APIMethod: removeMarker
+     *
+     * Parameters:
+     * marker - {<OpenLayers.Marker>} 
+     */
+    removeMarker: function(marker) {
+        if (this.markers && this.markers.length) {
+            OpenLayers.Util.removeItem(this.markers, marker);
+            marker.erase();
+        }
+    },
+
+    /**
+     * Method: clearMarkers
+     * This method removes all markers from a layer. The markers are not
+     * destroyed by this function, but are removed from the list of markers.
+     */
+    clearMarkers: function() {
+        if (this.markers != null) {
+            while(this.markers.length > 0) {
+                this.removeMarker(this.markers[0]);
+            }
+        }
+    },
+
+    /** 
+     * Method: drawMarker
+     * Calculate the pixel location for the marker, create it, and 
+     *    add it to the layer's div
+     *
+     * Parameters:
+     * marker - {<OpenLayers.Marker>} 
+     */
+    drawMarker: function(marker) {
+        var px = this.map.getLayerPxFromLonLat(marker.lonlat);
+        if (px == null) {
+            marker.display(false);
+        } else {
+            if (!marker.isDrawn()) {
+                var markerImg = marker.draw(px);
+                this.div.appendChild(markerImg);
+            } else if(marker.icon) {
+                marker.icon.moveTo(px);
+            }
+        }
+    },
+    
+    /** 
+     * APIMethod: getDataExtent
+     * Calculates the max extent which includes all of the markers.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getDataExtent: function () {
+        var maxExtent = null;
+        
+        if ( this.markers && (this.markers.length > 0)) {
+            var maxExtent = new OpenLayers.Bounds();
+            for(var i=0, len=this.markers.length; i<len; i++) {
+                var marker = this.markers[i];
+                maxExtent.extend(marker.lonlat);
+            }
+        }
+
+        return maxExtent;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Markers"
+});
+/* ======================================================================
+    OpenLayers/Control/Pan.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Pan
+ * The Pan control is a single button to pan the map in one direction. For
+ * a more complete control see <OpenLayers.Control.PanPanel>.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Pan = OpenLayers.Class(OpenLayers.Control, {
+
+    /** 
+     * APIProperty: slideFactor
+     * {Integer} Number of pixels by which we'll pan the map in any direction 
+     *     on clicking the arrow buttons, defaults to 50.  If you want to pan
+     *     by some ratio of the map dimensions, use <slideRatio> instead.
+     */
+    slideFactor: 50,
+
+    /** 
+     * APIProperty: slideRatio
+     * {Number} The fraction of map width/height by which we'll pan the map            
+     *     on clicking the arrow buttons.  Default is null.  If set, will
+     *     override <slideFactor>. E.g. if slideRatio is .5, then Pan Up will
+     *     pan up half the map height. 
+     */
+    slideRatio: null,
+
+    /** 
+     * Property: direction
+     * {String} in {'North', 'South', 'East', 'West'}
+     */
+    direction: null,
+
+    /**
+     * Property: type
+     * {String} The type of <OpenLayers.Control> -- When added to a 
+     *     <Control.Panel>, 'type' is used by the panel to determine how to 
+     *     handle our events.
+     */
+    type: OpenLayers.Control.TYPE_BUTTON,
+
+    /**
+     * Constructor: OpenLayers.Control.Pan 
+     * Control which handles the panning (in any of the cardinal directions)
+     *     of the map by a set px distance. 
+     *
+     * Parameters:
+     * direction - {String} The direction this button should pan.
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(direction, options) {
+    
+        this.direction = direction;
+        this.CLASS_NAME += this.direction;
+        
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: trigger
+     */
+    trigger: function(){
+    
+        var getSlideFactor = OpenLayers.Function.bind(function (dim) {
+            return this.slideRatio ?
+                this.map.getSize()[dim] * this.slideRatio :
+                this.slideFactor;
+        }, this);
+
+        switch (this.direction) {
+            case OpenLayers.Control.Pan.NORTH: 
+                this.map.pan(0, -getSlideFactor("h"));
+                break;
+            case OpenLayers.Control.Pan.SOUTH: 
+                this.map.pan(0, getSlideFactor("h"));
+                break;
+            case OpenLayers.Control.Pan.WEST: 
+                this.map.pan(-getSlideFactor("w"), 0);
+                break;
+            case OpenLayers.Control.Pan.EAST: 
+                this.map.pan(getSlideFactor("w"), 0);
+                break;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Pan"
+});
+
+OpenLayers.Control.Pan.NORTH = "North";
+OpenLayers.Control.Pan.SOUTH = "South";
+OpenLayers.Control.Pan.EAST = "East";
+OpenLayers.Control.Pan.WEST = "West";
+/* ======================================================================
+    OpenLayers/Layer/WMS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMS
+ * Instances of OpenLayers.Layer.WMS are used to display data from OGC Web
+ *     Mapping Services. Create a new WMS layer with the <OpenLayers.Layer.WMS>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.WMS = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Constant: DEFAULT_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs 
+     */
+    DEFAULT_PARAMS: { service: "WMS",
+                      version: "1.1.1",
+                      request: "GetMap",
+                      styles: "",
+                      format: "image/jpeg"
+                     },
+    
+    /**
+     * Property: reproject
+     * *Deprecated*. See http://trac.openlayers.org/wiki/SphericalMercator
+     * for information on the replacement for this functionality. 
+     * {Boolean} Try to reproject this layer if its coordinate reference system
+     *           is different than that of the base layer.  Default is false.  
+     *           Set this in the layer options.  Should be set to false in 
+     *           most cases.
+     */
+    reproject: false,
+ 
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} Default is true for WMS layer
+     */
+    isBaseLayer: true,
+    
+    /**
+     * APIProperty: encodeBBOX
+     * {Boolean} Should the BBOX commas be encoded? The WMS spec says 'no', 
+     * but some services want it that way. Default false.
+     */
+    encodeBBOX: false,
+    
+    /** 
+     * APIProperty: noMagic 
+     * {Boolean} If true, the image format will not be automagicaly switched 
+     *     from image/jpeg to image/png or image/gif when using 
+     *     TRANSPARENT=TRUE. Also isBaseLayer will not changed by the  
+     *     constructor. Default false. 
+     */ 
+    noMagic: false,
+    
+    /**
+     * Property: yx
+     * {Object} Keys in this object are EPSG codes for which the axis order
+     *     is to be reversed (yx instead of xy, LatLon instead of LonLat), with
+     *     true as value. This is only relevant for WMS versions >= 1.3.0.
+     */
+    yx: {'EPSG:4326': true},
+    
+    /**
+     * Constructor: OpenLayers.Layer.WMS
+     * Create a new WMS layer object
+     *
+     * Examples:
+     *
+     * The code below creates a simple WMS layer using the image/jpeg format.
+     * (code)
+     * var wms = new OpenLayers.Layer.WMS("NASA Global Mosaic",
+     *                                    "http://wms.jpl.nasa.gov/wms.cgi", 
+     *                                    {layers: "modis,global_mosaic"});
+     * (end)
+     * Note the 3rd argument (params). Properties added to this object will be
+     * added to the WMS GetMap requests used for this layer's tiles. The only
+     * mandatory parameter is "layers". Other common WMS params include
+     * "transparent", "styles" and "format". Note that the "srs" param will
+     * always be ignored. Instead, it will be derived from the baseLayer's or
+     * map's projection.
+     *
+     * The code below creates a transparent WMS layer with additional options.
+     * (code)
+     * var wms = new OpenLayers.Layer.WMS("NASA Global Mosaic",
+     *                                    "http://wms.jpl.nasa.gov/wms.cgi", 
+     *                                    {
+     *                                        layers: "modis,global_mosaic",
+     *                                        transparent: true
+     *                                    }, {
+     *                                        opacity: 0.5,
+     *                                        singleTile: true
+     *                                    });
+     * (end)
+     * Note that by default, a WMS layer is configured as baseLayer. Setting
+     * the "transparent" param to true will apply some magic (see <noMagic>).
+     * The default image format changes from image/jpeg to image/png, and the
+     * layer is not configured as baseLayer.
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the WMS
+     *                (e.g. http://wms.jpl.nasa.gov/wms.cgi)
+     * params - {Object} An object with key/value pairs representing the
+     *                   GetMap query string parameters and parameter values.
+     * options - {Object} Hashtable of extra options to tag onto the layer.
+     *     These options include all properties listed above, plus the ones
+     *     inherited from superclasses.
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        //uppercase params
+        params = OpenLayers.Util.upperCaseObject(params);
+        if (parseFloat(params.VERSION) >= 1.3 && !params.EXCEPTIONS) {
+            params.EXCEPTIONS = "INIMAGE";
+        } 
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+        OpenLayers.Util.applyDefaults(
+                       this.params, 
+                       OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
+                       );
+
+
+        //layer is transparent        
+        if (!this.noMagic && this.params.TRANSPARENT && 
+            this.params.TRANSPARENT.toString().toLowerCase() == "true") {
+            
+            // unless explicitly set in options, make layer an overlay
+            if ( (options == null) || (!options.isBaseLayer) ) {
+                this.isBaseLayer = false;
+            } 
+            
+            // jpegs can never be transparent, so intelligently switch the 
+            //  format, depending on the browser's capabilities
+            if (this.params.FORMAT == "image/jpeg") {
+                this.params.FORMAT = OpenLayers.Util.alphaHack() ? "image/gif"
+                                                                 : "image/png";
+            }
+        }
+
+    },    
+
+    /**
+     * Method: destroy
+     * Destroy this layer
+     */
+    destroy: function() {
+        // for now, nothing special to do here. 
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);  
+    },
+
+    
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.WMS(this.name,
+                                           this.url,
+                                           this.params,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },    
+    
+    /**
+     * APIMethod: reverseAxisOrder
+     * Returns true if the axis order is reversed for the WMS version and
+     * projection of the layer.
+     * 
+     * Returns:
+     * {Boolean} true if the axis order is reversed, false otherwise.
+     */
+    reverseAxisOrder: function() {
+        return (parseFloat(this.params.VERSION) >= 1.3 && 
+            !!this.yx[this.map.getProjectionObject().getCode()]);
+    },
+    
+    /**
+     * Method: getURL
+     * Return a GetMap query string for this layer
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
+     *                                request.
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as 
+     *          parameters.
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        
+        var imageSize = this.getImageSize();
+        var newParams = {};
+        // WMS 1.3 introduced axis order
+        var reverseAxisOrder = this.reverseAxisOrder();
+        newParams.BBOX = this.encodeBBOX ?
+            bounds.toBBOX(null, reverseAxisOrder) :
+            bounds.toArray(reverseAxisOrder);
+        newParams.WIDTH = imageSize.w;
+        newParams.HEIGHT = imageSize.h;
+        var requestString = this.getFullRequestString(newParams);
+        return requestString;
+    },
+
+    /**
+     * APIMethod: mergeNewParams
+     * Catch changeParams and uppercase the new params to be merged in
+     *     before calling changeParams on the super class.
+     * 
+     *     Once params have been changed, the tiles will be reloaded with
+     *     the new parameters.
+     * 
+     * Parameters:
+     * newParams - {Object} Hashtable of new params to use
+     */
+    mergeNewParams:function(newParams) {
+        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
+        var newArguments = [upperParams];
+        return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this, 
+                                                             newArguments);
+    },
+
+    /** 
+     * APIMethod: getFullRequestString
+     * Combine the layer's url with its params and these newParams. 
+     *   
+     *     Add the SRS parameter from projection -- this is probably
+     *     more eloquently done via a setProjection() method, but this 
+     *     works for now and always.
+     *
+     * Parameters:
+     * newParams - {Object}
+     * altUrl - {String} Use this as the url instead of the layer's url
+     * 
+     * Returns:
+     * {String} 
+     */
+    getFullRequestString:function(newParams, altUrl) {
+        var mapProjection = this.map.getProjectionObject();
+        var projectionCode = this.projection && this.projection.equals(mapProjection) ?
+            this.projection.getCode() :
+            mapProjection.getCode();
+        var value = (projectionCode == "none") ? null : projectionCode;
+        if (parseFloat(this.params.VERSION) >= 1.3) {
+            this.params.CRS = value;
+        } else {
+            this.params.SRS = value;
+        }
+        
+        if (typeof this.params.TRANSPARENT == "boolean") {
+            newParams.TRANSPARENT = this.params.TRANSPARENT ? "TRUE" : "FALSE";
+        }
+
+        return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
+                                                    this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.WMS"
+});
+/* ======================================================================
+    OpenLayers/Layer/WMS/Untiled.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+ 
+/**
+ * @requires OpenLayers/Layer/WMS.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMS.Untiled
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.WMS and 
+ *     pass the option 'singleTile' as true.
+ * 
+ * Inherits from: 
+ *  - <OpenLayers.Layer.WMS>
+ */
+OpenLayers.Layer.WMS.Untiled = OpenLayers.Class(OpenLayers.Layer.WMS, {
+
+    /**
+     * APIProperty: singleTile
+     * {singleTile} Always true for untiled.
+     */
+    singleTile: true,
+
+    /**
+     * Constructor: OpenLayers.Layer.WMS.Untiled
+     *
+     * Parameters:
+     * name - {String} 
+     * url - {String} 
+     * params - {Object} 
+     * options - {Object} 
+     */
+    initialize: function(name, url, params, options) {
+        OpenLayers.Layer.WMS.prototype.initialize.apply(this, arguments);
+        
+        var msg = "The OpenLayers.Layer.WMS.Untiled class is deprecated and " +
+                  "will be removed in 3.0. Instead, you should use the " +
+                  "normal OpenLayers.Layer.WMS class, passing it the option " +
+                  "'singleTile' as true.";
+        OpenLayers.Console.warn(msg);
+    },    
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS.Untiled>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.WMS.Untiled(this.name,
+                                                   this.url,
+                                                   this.params,
+                                                   this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.WMS.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    }, 
+
+    CLASS_NAME: "OpenLayers.Layer.WMS.Untiled"
+});
+/* ======================================================================
+    OpenLayers/Geometry/Surface.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry.js
+ */
+
+OpenLayers.Geometry.Surface = OpenLayers.Class(OpenLayers.Geometry, {
+
+    initialize: function() {
+        OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Geometry.Surface"
+});
+/* ======================================================================
+    OpenLayers/Format/ArcXML/Features.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/ArcXML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.ArcXML.Features
+ * Read/Wite ArcXML features. Create a new instance with the 
+ *     <OpenLayers.Format.ArcXML.Features> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.ArcXML.Features = OpenLayers.Class(OpenLayers.Format.XML, {
+
+    /**
+     * Constructor: OpenLayers.Format.ArcXML.Features
+     * Create a new parser/writer for ArcXML Features.  Create an instance of this class
+     * to get a set of features from an ArcXML response.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {     
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * APIMethod: read
+     * Read data from a string of ArcXML, and return a set of OpenLayers features. 
+     * 
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} A collection of features.
+     */
+    read: function(data) {
+        var axl = new OpenLayers.Format.ArcXML();
+        var parsed = axl.read(data);
+        
+        return parsed.features.feature;
+    }
+});
+/* ======================================================================
+    OpenLayers/Control/Snapping.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Layer/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Snapping
+ * Acts as a snapping agent while editing vector features.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Snapping = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * Supported control event types (in addition to those from <OpenLayers.Control>):
+     * beforesnap - Triggered before a snap occurs.  Listeners receive an
+     *     event object with *point*, *x*, *y*, *distance*, *layer*, and
+     *     *snapType* properties.  The point property will be original point
+     *     geometry considered for snapping. The x and y properties represent
+     *     coordinates the point will receive. The distance is the distance
+     *     of the snap.  The layer is the target layer.  The snapType property
+     *     will be one of "node", "vertex", or "edge". Return false to stop
+     *     snapping from occurring.
+     * snap - Triggered when a snap occurs.  Listeners receive an event with
+     *     *point*, *snapType*, *layer*, and *distance* properties.  The point
+     *     will be the location snapped to.  The snapType will be one of "node",
+     *     "vertex", or "edge".  The layer will be the target layer.  The
+     *     distance will be the distance of the snap in map units.
+     * unsnap - Triggered when a vertex is unsnapped.  Listeners receive an
+     *     event with a *point* property.
+     */
+    EVENT_TYPES: ["beforesnap", "snap", "unsnap"],
+    
+    /**
+     * CONSTANT: DEFAULTS
+     * Default target properties.
+     */
+    DEFAULTS: {
+        tolerance: 10,
+        node: true,
+        edge: true,
+        vertex: true
+    },
+    
+    /**
+     * Property: greedy
+     * {Boolean} Snap to closest feature in first layer with an eligible
+     *     feature.  Default is true.
+     */
+    greedy: true,
+    
+    /**
+     * Property: precedence
+     * {Array} List representing precedence of different snapping types.
+     *     Default is "node", "vertex", "edge".
+     */
+    precedence: ["node", "vertex", "edge"],
+    
+    /**
+     * Property: resolution
+     * {Float} The map resolution for the previously considered snap.
+     */
+    resolution: null,
+    
+    /**
+     * Property: geoToleranceCache
+     * {Object} A cache of geo-tolerances.  Tolerance values (in map units) are
+     *     calculated when the map resolution changes.
+     */
+    geoToleranceCache: null,
+    
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>} The current editable layer.  Set at
+     *     construction or after construction with <setLayer>.
+     */
+    layer: null,
+    
+    /**
+     * Property: feature
+     * {<OpenLayers.Feature.Vector>} The current editable feature.
+     */
+    feature: null,
+    
+    /**
+     * Property: point
+     * {<OpenLayers.Geometry.Point>} The currently snapped vertex.
+     */
+    point: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Snapping
+     * Creates a new snapping control. A control is constructed with an editable
+     *     layer and a set of configuration objects for target layers. While the
+     *     control is active, dragging vertices while drawing new features or
+     *     modifying existing features on the editable layer will engage
+     *     snapping to features on the target layers. Whether a vertex snaps to
+     *     a feature on a target layer depends on the target layer configuration.
+     *
+     * Parameters:
+     * options - {Object} An object containing all configuration properties for
+     *     the control.
+     *
+     * Valid options:
+     * layer - {OpenLayers.Layer.Vector} The editable layer.  Features from this
+     *     layer that are digitized or modified may have vertices snapped to
+     *     features from any of the target layers.
+     * targets - {Array(Object | OpenLayers.Layer.Vector)} A list of objects for
+     *     configuring target layers.  See valid properties of the target
+     *     objects below.  If the items in the targets list are vector layers
+     *     (instead of configuration objects), the defaults from the <defaults>
+     *     property will apply.  The editable layer itself may be a target
+     *     layer - allowing newly created or edited features to be snapped to
+     *     existing features from the same layer.  If no targets are provided
+     *     the layer given in the constructor (as <layer>) will become the
+     *     initial target.
+     * defaults - {Object} An object with default properties to be applied
+     *     to all target objects.
+     * greedy - {Boolean} Snap to closest feature in first target layer that
+     *     applies.  Default is true.  If false, all features in all target
+     *     layers will be checked and the closest feature in all target layers
+     *     will be chosen.  The greedy property determines if the order of the
+     *     target layers is significant.  By default, the order of the target
+     *     layers is significant where layers earlier in the target layer list
+     *     have precedence over layers later in the list.  Within a single
+     *     layer, the closest feature is always chosen for snapping.  This
+     *     property only determines whether the search for a closer feature
+     *     continues after an eligible feature is found in a target layer.
+     *
+     * Valid target properties:
+     * layer - {OpenLayers.Layer.Vector} A target layer.  Features from this
+     *     layer will be eligible to act as snapping target for the editable
+     *     layer.
+     * tolerance - {Float} The distance (in pixels) at which snapping may occur.
+     *     Default is 10.
+     * node - {Boolean} Snap to nodes (first or last point in a geometry) in
+     *     target layer.  Default is true.
+     * nodeTolerance - {Float} Optional distance at which snapping may occur
+     *     for nodes specifically.  If none is provided, <tolerance> will be
+     *     used.
+     * vertex - {Boolean} Snap to vertices in target layer.  Default is true.
+     * vertexTolerance - {Float} Optional distance at which snapping may occur
+     *     for vertices specifically.  If none is provided, <tolerance> will be
+     *     used.
+     * edge - {Boolean} Snap to edges in target layer.  Default is true.
+     * edgeTolerance - {Float} Optional distance at which snapping may occur
+     *     for edges specifically.  If none is provided, <tolerance> will be
+     *     used.
+     * filter - {OpenLayers.Filter} Optional filter to evaluate to determine if
+     *     feature is eligible for snapping.  If filter evaluates to true for a
+     *     target feature a vertex may be snapped to the feature. 
+     * minResolution - {Number} If a minResolution is provided, snapping to this
+     *     target will only be considered if the map resolution is greater than
+     *     or equal to this value (the minResolution is inclusive).  Default is
+     *     no minimum resolution limit.
+     * maxResolution - {Number} If a maxResolution is provided, snapping to this
+     *     target will only be considered if the map resolution is strictly
+     *     less than this value (the maxResolution is exclusive).  Default is
+     *     no maximum resolution limit.
+     */
+    initialize: function(options) {
+        // concatenate events specific to measure with those from the base
+        Array.prototype.push.apply(
+            this.EVENT_TYPES, OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.options = options || {}; // TODO: this could be done by the super
+        
+        // set the editable layer if provided
+        if(this.options.layer) {
+            this.setLayer(this.options.layer);
+        }
+        // configure target layers
+        var defaults = OpenLayers.Util.extend({}, this.options.defaults);
+        this.defaults = OpenLayers.Util.applyDefaults(defaults, this.DEFAULTS);
+        this.setTargets(this.options.targets);
+        if(this.targets.length === 0 && this.layer) {
+            this.addTargetLayer(this.layer);
+        }
+
+        this.geoToleranceCache = {};
+    },
+    
+    /**
+     * APIMethod: setLayer
+     * Set the editable layer.  Call the setLayer method if the editable layer
+     *     changes and the same control should be used on a new editable layer.
+     *     If the control is already active, it will be active after the new
+     *     layer is set.
+     *
+     * Parameters:
+     * layer - {OpenLayers.Layer.Vector}  The new editable layer.
+     */
+    setLayer: function(layer) {
+        if(this.active) {
+            this.deactivate();
+            this.layer = layer;
+            this.activate();
+        } else {
+            this.layer = layer;
+        }
+    },
+    
+    /**
+     * Method: setTargets
+     * Set the targets for the snapping agent.
+     *
+     * Parameters:
+     * targets - {Array} An array of target configs or target layers.
+     */
+    setTargets: function(targets) {
+        this.targets = [];
+        if(targets && targets.length) {
+            var target;
+            for(var i=0, len=targets.length; i<len; ++i) {
+                target = targets[i];
+                if(target instanceof OpenLayers.Layer.Vector) {
+                    this.addTargetLayer(target);
+                } else {
+                    this.addTarget(target);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: addTargetLayer
+     * Add a target layer with the default target config.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} A target layer.
+     */
+    addTargetLayer: function(layer) {
+        this.addTarget({layer: layer});
+    },
+    
+    /**
+     * Method: addTarget
+     * Add a configured target layer.
+     *
+     * Parameters:
+     * target - {Object} A target config.
+     */
+    addTarget: function(target) {
+        target = OpenLayers.Util.applyDefaults(target, this.defaults);
+        target.nodeTolerance = target.nodeTolerance || target.tolerance;
+        target.vertexTolerance = target.vertexTolerance || target.tolerance;
+        target.edgeTolerance = target.edgeTolerance || target.tolerance;
+        this.targets.push(target);
+    },
+    
+    /**
+     * Method: removeTargetLayer
+     * Remove a target layer.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} The target layer to remove.
+     */
+    removeTargetLayer: function(layer) {
+        var target;
+        for(var i=this.targets.length-1; i>=0; --i) {
+            target = this.targets[i];
+            if(target.layer === layer) {
+                this.removeTarget(target);
+            }
+        }
+    },
+    
+    /**
+     * Method: removeTarget
+     * Remove a target.
+     *
+     * Parameters:
+     * target - {Object} A target config.
+     *
+     * Returns:
+     * {Array} The targets array.
+     */
+    removeTarget: function(target) {
+        return OpenLayers.Util.removeItem(this.targets, target);
+    },
+    
+    /**
+     * APIMethod: activate
+     * Activate the control.  Activating the control registers listeners for
+     *     editing related events so that during feature creation and
+     *     modification, moving vertices will trigger snapping.
+     */
+    activate: function() {
+        var activated = OpenLayers.Control.prototype.activate.call(this);
+        if(activated) {
+            if(this.layer && this.layer.events) {
+                this.layer.events.on({
+                    sketchstarted: this.onSketchModified,
+                    sketchmodified: this.onSketchModified,
+                    vertexmodified: this.onVertexModified,
+                    scope: this
+                });
+            }
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control.  Deactivating the control unregisters listeners
+     *     so feature editing may proceed without engaging the snapping agent.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
+        if(deactivated) {
+            if(this.layer && this.layer.events) {
+                this.layer.events.un({
+                    sketchstarted: this.onSketchModified,
+                    sketchmodified: this.onSketchModified,
+                    vertexmodified: this.onVertexModified,
+                    scope: this
+                });
+            }
+        }
+        this.feature = null;
+        this.point = null;
+        return deactivated;
+    },
+    
+    /**
+     * Method: onSketchModified
+     * Registered as a listener for the sketchmodified event on the editable
+     *     layer.
+     *
+     * Parameters:
+     * event - {Object} The sketch modified event.
+     */
+    onSketchModified: function(event) {
+        this.feature = event.feature;
+        this.considerSnapping(event.vertex, event.vertex);
+    },
+    
+    /**
+     * Method: onVertexModified
+     * Registered as a listener for the vertexmodified event on the editable
+     *     layer.
+     *
+     * Parameters:
+     * event - {Object} The vertex modified event.
+     */
+    onVertexModified: function(event) {
+        this.feature = event.feature;
+        var loc = this.layer.map.getLonLatFromViewPortPx(event.pixel);
+        this.considerSnapping(
+            event.vertex, new OpenLayers.Geometry.Point(loc.lon, loc.lat)
+        );
+    },
+
+    /**
+     * Method: considerSnapping
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>} The vertex to be snapped (or
+     *     unsnapped).
+     * loc - {<OpenLayers.Geometry.Point>} The location of the mouse in map
+     *     coords.
+     */
+    considerSnapping: function(point, loc) {
+        var best = {
+            rank: Number.POSITIVE_INFINITY,
+            dist: Number.POSITIVE_INFINITY,
+            x: null, y: null
+        };
+        var snapped = false;
+        var result, target;
+        for(var i=0, len=this.targets.length; i<len; ++i) {
+            target = this.targets[i];
+            result = this.testTarget(target, loc);
+            if(result) {
+                if(this.greedy) {
+                    best = result;
+                    best.target = target; 
+                    snapped = true;
+                    break;
+                } else {
+                    if((result.rank < best.rank) ||
+                       (result.rank === best.rank && result.dist < best.dist)) {
+                        best = result;
+                        best.target = target;
+                        snapped = true;
+                    }
+                }
+            }
+        }
+        if(snapped) {
+            var proceed = this.events.triggerEvent("beforesnap", {
+                point: point, x: best.x, y: best.y, distance: best.dist,
+                layer: best.target.layer, snapType: this.precedence[best.rank]
+            });
+            if(proceed !== false) {
+                point.x = best.x;
+                point.y = best.y;
+                this.point = point;
+                this.events.triggerEvent("snap", {
+                    point: point,
+                    snapType: this.precedence[best.rank],
+                    layer: best.target.layer,
+                    distance: best.dist
+                });
+            } else {
+                snapped = false;
+            }
+        }
+        if(this.point && !snapped) {
+            point.x = loc.x;
+            point.y = loc.y;
+            this.point = null;
+            this.events.triggerEvent("unsnap", {point: point});
+        }
+    },
+    
+    /**
+     * Method: testTarget
+     *
+     * Parameters:
+     * target - {Object} Object with target layer configuration.
+     * loc - {<OpenLayers.Geometry.Point>} The location of the mouse in map
+     *     coords.
+     *
+     * Returns:
+     * {Object} A result object with rank, dist, x, and y properties.
+     *     Returns null if candidate is not eligible for snapping.
+     */
+    testTarget: function(target, loc) {
+        var resolution = this.layer.map.getResolution();
+        if ("minResolution" in target) {
+            if (resolution < target.minResolution) {
+                return null;
+            }
+        }
+        if ("maxResolution" in target) {
+            if (resolution >= target.maxResolution) {
+                return null;
+            }
+        }
+        var tolerance = {
+            node: this.getGeoTolerance(target.nodeTolerance, resolution),
+            vertex: this.getGeoTolerance(target.vertexTolerance, resolution),
+            edge: this.getGeoTolerance(target.edgeTolerance, resolution)
+        };
+        // this could be cached if we don't support setting tolerance values directly
+        var maxTolerance = Math.max(
+            tolerance.node, tolerance.vertex, tolerance.edge
+        );
+        var result = {
+            rank: Number.POSITIVE_INFINITY, dist: Number.POSITIVE_INFINITY
+        };
+        var eligible = false;
+        var features = target.layer.features;
+        var feature, type, vertices, vertex, closest, dist, found;
+        var numTypes = this.precedence.length;
+        var ll = new OpenLayers.LonLat(loc.x, loc.y);
+        for(var i=0, len=features.length; i<len; ++i) {
+            feature = features[i];
+            if(feature !== this.feature && !feature._sketch &&
+               feature.state !== OpenLayers.State.DELETE &&
+               (!target.filter || target.filter.evaluate(feature.attributes))) {
+                if(feature.atPoint(ll, maxTolerance, maxTolerance)) {
+                    for(var j=0, stop=Math.min(result.rank+1, numTypes); j<stop; ++j) {
+                        type = this.precedence[j];
+                        if(target[type]) {
+                            if(type === "edge") {
+                                closest = feature.geometry.distanceTo(loc, {details: true});
+                                dist = closest.distance;
+                                if(dist <= tolerance[type] && dist < result.dist) {
+                                    result = {
+                                        rank: j, dist: dist,
+                                        x: closest.x0, y: closest.y0 // closest coords on feature
+                                    };
+                                    eligible = true;
+                                    // don't look for lower precedence types for this feature
+                                    break;
+                                }
+                            } else {
+                                // look for nodes or vertices
+                                vertices = feature.geometry.getVertices(type === "node");
+                                found = false;
+                                for(var k=0, klen=vertices.length; k<klen; ++k) {
+                                    vertex = vertices[k];
+                                    dist = vertex.distanceTo(loc);
+                                    if(dist <= tolerance[type] &&
+                                       (j < result.rank || (j === result.rank && dist < result.dist))) {
+                                        result = {
+                                            rank: j, dist: dist,
+                                            x: vertex.x, y: vertex.y
+                                        };
+                                        eligible = true;
+                                        found = true;
+                                    }
+                                }
+                                if(found) {
+                                    // don't look for lower precedence types for this feature
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return eligible ? result : null;
+    },
+    
+    /**
+     * Method: getGeoTolerance
+     * Calculate a tolerance in map units given a tolerance in pixels.  This
+     *     takes advantage of the <geoToleranceCache> when the map resolution
+     *     has not changed.
+     *     
+     * Parameters:
+     * tolerance - {Number} A tolerance value in pixels.
+     * resolution - {Number} Map resolution.
+     *
+     * Returns:
+     * {Number} A tolerance value in map units.
+     */
+    getGeoTolerance: function(tolerance, resolution) {
+        if(resolution !== this.resolution) {
+            this.resolution = resolution;
+            this.geoToleranceCache = {};
+        }
+        var geoTolerance = this.geoToleranceCache[tolerance];
+        if(geoTolerance === undefined) {
+            geoTolerance = tolerance * resolution;
+            this.geoToleranceCache[tolerance] = geoTolerance;
+        }
+        return geoTolerance;
+    },
+    
+    /**
+     * Method: destroy
+     * Clean up the control.
+     */
+    destroy: function() {
+        if(this.active) {
+            this.deactivate(); // TODO: this should be handled by the super
+        }
+        delete this.layer;
+        delete this.targets;
+        OpenLayers.Control.prototype.destroy.call(this);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Snapping"
+});
+/* ======================================================================
+    OpenLayers/Format/CSWGetDomain.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetDomain
+ * Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetDomain format of the given version.
+ */
+OpenLayers.Format.CSWGetDomain = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Format.CSWGetDomain.DEFAULTS
+    );
+    var cls = OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported CSWGetDomain version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: DEFAULTS
+ * {Object} Default properties for the CSWGetDomain format.
+ */
+OpenLayers.Format.CSWGetDomain.DEFAULTS = {
+    "version": "2.0.2"
+};
+/* ======================================================================
+    OpenLayers/Format/CSWGetDomain/v2_0_2.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetDomain.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetDomain.v2_0_2
+ *     A format for creating CSWGetDomain v2.0.2 transactions. 
+ *     Create a new instance with the
+ *     <OpenLayers.Format.CSWGetDomain.v2_0_2> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetDomain.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance",
+        csw: "http://www.opengis.net/cat/csw/2.0.2"
+    },
+
+    /**
+     * Property: defaultPrefix
+     * {String} The default prefix (used by Format.XML).
+     */
+    defaultPrefix: "csw",
+    
+    /**
+     * Property: version
+     * {String} CSW version number.
+     */
+    version: "2.0.2",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/cat/csw/2.0.2
+     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+     */
+    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+    /**
+     * APIProperty: PropertyName
+     * {String} Value of the csw:PropertyName element, used when
+     *     writing a GetDomain document.
+     */
+    PropertyName: null,
+
+    /**
+     * APIProperty: ParameterName
+     * {String} Value of the csw:ParameterName element, used when
+     *     writing a GetDomain document.
+     */
+    ParameterName: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.CSWGetDomain.v2_0_2
+     * A class for parsing and generating CSWGetDomain v2.0.2 transactions.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * - PropertyName
+     * - ParameterName
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Parse the response from a GetDomain request.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var obj = {};
+        this.readNode(data, obj);
+        return obj;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "csw": {
+            "GetDomainResponse": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "DomainValues": function(node, obj) {
+                if (!(OpenLayers.Util.isArray(obj.DomainValues))) {
+                    obj.DomainValues = [];
+                }
+                var attrs = node.attributes;
+                var domainValue = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    domainValue[attrs[i].name] = attrs[i].nodeValue;
+                }
+                this.readChildNodes(node, domainValue);
+                obj.DomainValues.push(domainValue);
+            },
+            "PropertyName": function(node, obj) {
+                obj.PropertyName = this.getChildValue(node);
+            },
+            "ParameterName": function(node, obj) {
+                obj.ParameterName = this.getChildValue(node);
+            },
+            "ListOfValues": function(node, obj) {
+                if (!(OpenLayers.Util.isArray(obj.ListOfValues))) {
+                    obj.ListOfValues = [];
+                }
+                this.readChildNodes(node, obj.ListOfValues);
+            },
+            "Value": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.push({Value: value});
+            },
+            "ConceptualScheme": function(node, obj) {
+                obj.ConceptualScheme = {};
+                this.readChildNodes(node, obj.ConceptualScheme);
+            },
+            "Name": function(node, obj) {
+                obj.Name = this.getChildValue(node);
+            },
+            "Document": function(node, obj) {
+                obj.Document = this.getChildValue(node);
+            },
+            "Authority": function(node, obj) {
+                obj.Authority = this.getChildValue(node);
+            },
+            "RangeOfValues": function(node, obj) {
+                obj.RangeOfValues = {};
+                this.readChildNodes(node, obj.RangeOfValues);
+            },
+            "MinValue": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.MinValue = value;
+            },
+            "MaxValue": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.MaxValue = value;
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: write
+     * Given an configuration js object, write a CSWGetDomain request. 
+     *
+     * Parameters:
+     * options - {Object} A object mapping the request.
+     *
+     * Returns:
+     * {String} A serialized CSWGetDomain request.
+     */
+    write: function(options) {
+        var node = this.writeNode("csw:GetDomain", options);
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "csw": {
+            "GetDomain": function(options) {
+                var node = this.createElementNSPlus("csw:GetDomain", {
+                    attributes: {
+                        service: "CSW",
+                        version: this.version
+                    }
+                });
+                if (options.PropertyName || this.PropertyName) {
+                    this.writeNode(
+                        "csw:PropertyName",
+                        options.PropertyName || this.PropertyName,
+                        node
+                    );
+                } else if (options.ParameterName || this.ParameterName) {
+                    this.writeNode(
+                        "csw:ParameterName",
+                        options.ParameterName || this.ParameterName,
+                        node
+                    );
+                }
+                this.readChildNodes(node, options);
+                return node;
+            },
+            "PropertyName": function(value) {
+                var node = this.createElementNSPlus("csw:PropertyName", {
+                    value: value
+                });
+                return node;
+            },
+            "ParameterName": function(value) {
+                var node = this.createElementNSPlus("csw:ParameterName", {
+                    value: value
+                });
+                return node;
+            }
+        }
+    },
+   
+    CLASS_NAME: "OpenLayers.Format.CSWGetDomain.v2_0_2" 
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities
+ * Read WMS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.1.1".
+     */
+    defaultVersion: "1.1.1",
+    
+    /**
+     * APIProperty: profile
+     * {String} If provided, use a custom profile.
+     *
+     * Currently supported profiles:
+     * - WMSC - parses vendor specific capabilities for WMS-C.
+     */
+    profile: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities
+     * Create a new parser for WMS capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities.v1
+ * Abstract class not to be instantiated directly. Creates
+ * the common parts for both WMS 1.1.X and WMS 1.3.X.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMSCapabilities.v1 = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        wms: "http://www.opengis.net/wms",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "wms",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities.v1
+     * Create an instance of one of the subclasses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var raw = data;
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        if (capabilities.service === undefined) {
+            // an exception must have occurred, so parse it
+            var parser = new OpenLayers.Format.OGCExceptionReport();
+            capabilities.error = parser.read(raw);
+        } else {
+            // postprocess the layer list
+            this.postProcessLayers(capabilities);
+        }
+        return capabilities;
+    },
+
+    /**
+     * Method: postProcessLayers
+     * Post process the layers, so that the nested layer structure is converted
+     * to a flat layer list with only named layers.
+     *
+     * Parameters:
+     * capabilities - {Object} The object (structure) returned by the parser with
+     *     all the info from the GetCapabilities response.
+     */
+    postProcessLayers: function(capabilities) {
+        if (capabilities.capability) {
+            capabilities.capability.layers = [];
+            var layers = capabilities.capability.nestedLayers;
+            for (var i=0, len = layers.length; i<len; ++i) {
+                var layer = layers[i];
+                this.processLayer(capabilities.capability, layer);
+            }
+        }
+    },
+
+    /**
+     * Method: processLayer
+     * Recursive submethod of postProcessLayers. This function will among
+     * others deal with property inheritance.
+     *
+     * Parameters:
+     * capability - {Object} The capability part of the capabilities object
+     * layer - {Object} The layer that needs processing
+     * parentLayer - {Object} The parent layer of the respective layer
+    */
+    processLayer: function(capability, layer, parentLayer) {
+        if (layer.formats === undefined) {
+            layer.formats = capability.request.getmap.formats;
+        }
+
+        var i, len;
+
+        // deal with property inheritance
+        if(parentLayer) {
+            // add style
+            layer.styles = layer.styles.concat(parentLayer.styles);
+            var attributes = ["queryable",
+                              "cascaded",
+                              "fixedWidth",
+                              "fixedHeight",
+                              "opaque",
+                              "noSubsets",
+                              "llbbox",
+                              "minScale",
+                              "maxScale",
+                              "attribution"];
+
+            var complexAttr = ["srs",
+                               "bbox",
+                               "dimensions",
+                               "authorityURLs"];
+            
+            var key;
+
+            for (i=0, len=attributes.length; i<len; i++) {
+                key = attributes[i];
+                if (key in parentLayer) {
+                    // only take parent value if not present (null or undefined)
+                    if (layer[key] == null) {
+                        layer[key] = parentLayer[key];
+                    }
+                    // if attribute isn't present, and we haven't
+                    // inherited anything from a parent layer
+                    // set to default value
+                    if (layer[key] == null) {
+                        var intAttr = ["cascaded", "fixedWidth", "fixedHeight"];
+                        var boolAttr = ["queryable", "opaque", "noSubsets"];
+                        if (OpenLayers.Util.indexOf(intAttr, key) != -1) {
+                            layer[key] = 0;
+                        }
+                        if (OpenLayers.Util.indexOf(boolAttr, key) != -1) {
+                            layer[key] = false;
+                        }
+                    }
+                }
+            }
+
+            for (i=0, len=complexAttr.length; i<len; i++) {
+                key = complexAttr[i];
+                layer[key] = OpenLayers.Util.applyDefaults(
+                    layer[key], parentLayer[key]);
+            }
+        }
+
+        // process sublayers
+        for (i=0, len=layer.nestedLayers.length; i<len; i++) {
+            var childLayer = layer.nestedLayers[i];
+            this.processLayer(capability, childLayer, layer);
+        }
+        
+        if (layer.name) {
+            capability.layers.push(layer);
+        }
+    
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": {
+            "Service": function(node, obj) {
+                obj.service = {};
+                this.readChildNodes(node, obj.service);
+            },
+            "Name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+            },
+            "Abstract": function(node, obj) {
+                obj["abstract"] = this.getChildValue(node);
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = {};
+                bbox.bbox = [
+                    parseFloat(node.getAttribute("minx")),
+                    parseFloat(node.getAttribute("miny")),
+                    parseFloat(node.getAttribute("maxx")),
+                    parseFloat(node.getAttribute("maxy"))
+                ];
+                var res = {
+                    x: parseFloat(node.getAttribute("resx")),
+                    y: parseFloat(node.getAttribute("resy"))
+                };
+
+                if (! (isNaN(res.x) && isNaN(res.y))) {
+                    bbox.res = res;
+                }
+                // return the bbox so that descendant classes can set the
+                // CRS and SRS and add it to the obj
+                return bbox;
+            },
+            "OnlineResource": function(node, obj) {
+                obj.href = this.getAttributeNS(node, this.namespaces.xlink, 
+                    "href");
+            },
+            "ContactInformation": function(node, obj) {
+                obj.contactInformation = {};
+                this.readChildNodes(node, obj.contactInformation);
+            },
+            "ContactPersonPrimary": function(node, obj) {
+                obj.personPrimary = {};
+                this.readChildNodes(node, obj.personPrimary);
+            },
+            "ContactPerson": function(node, obj) {
+                obj.person = this.getChildValue(node);
+            },
+            "ContactOrganization": function(node, obj) {
+                obj.organization = this.getChildValue(node);
+            },
+            "ContactPosition": function(node, obj) {
+                obj.position = this.getChildValue(node);
+            },
+            "ContactAddress": function(node, obj) {
+                obj.contactAddress = {};
+                this.readChildNodes(node, obj.contactAddress);
+            },
+            "AddressType": function(node, obj) {
+                obj.type = this.getChildValue(node);
+            },
+            "Address": function(node, obj) {
+                obj.address = this.getChildValue(node);
+            },
+            "City": function(node, obj) {
+                obj.city = this.getChildValue(node);
+            },
+            "StateOrProvince": function(node, obj) {
+                obj.stateOrProvince = this.getChildValue(node);
+            },
+            "PostCode": function(node, obj) {
+                obj.postcode = this.getChildValue(node);
+            },
+            "Country": function(node, obj) {
+                obj.country = this.getChildValue(node);
+            },
+            "ContactVoiceTelephone": function(node, obj) {
+                obj.phone = this.getChildValue(node);
+            },
+            "ContactFacsimileTelephone": function(node, obj) {
+                obj.fax = this.getChildValue(node);
+            },
+            "ContactElectronicMailAddress": function(node, obj) {
+                obj.email = this.getChildValue(node);
+            },
+            "Fees": function(node, obj) {
+                var fees = this.getChildValue(node);
+                if (fees && fees.toLowerCase() != "none") {
+                    obj.fees = fees;
+                }
+            },
+            "AccessConstraints": function(node, obj) {
+                var constraints = this.getChildValue(node);
+                if (constraints && constraints.toLowerCase() != "none") {
+                    obj.accessConstraints = constraints;
+                }
+            },
+            "Capability": function(node, obj) {
+                obj.capability = {nestedLayers: []};
+                this.readChildNodes(node, obj.capability);
+            },
+            "Request": function(node, obj) {
+                obj.request = {};
+                this.readChildNodes(node, obj.request);
+            },
+            "GetCapabilities": function(node, obj) {
+                obj.getcapabilities = {formats: []};
+                this.readChildNodes(node, obj.getcapabilities);
+            },
+            "Format": function(node, obj) {
+                if (OpenLayers.Util.isArray(obj.formats)) {
+                    obj.formats.push(this.getChildValue(node));
+                } else {
+                    obj.format = this.getChildValue(node);
+                }
+            },
+            "DCPType": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "HTTP": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Get": function(node, obj) {
+                obj.get = {};
+                this.readChildNodes(node, obj.get);
+                // backwards compatibility
+                if (!obj.href) {
+                    obj.href = obj.get.href;
+                }
+            },
+            "Post": function(node, obj) {
+                obj.post = {};
+                this.readChildNodes(node, obj.post);
+                // backwards compatibility
+                if (!obj.href) {
+                    obj.href = obj.get.href;
+                }
+            },
+            "GetMap": function(node, obj) {
+                obj.getmap = {formats: []};
+                this.readChildNodes(node, obj.getmap);
+            },
+            "GetFeatureInfo": function(node, obj) {
+                obj.getfeatureinfo = {formats: []};
+                this.readChildNodes(node, obj.getfeatureinfo);
+            },
+            "Exception": function(node, obj) {
+                obj.exception = {formats: []};
+                this.readChildNodes(node, obj.exception);
+            },
+            "Layer": function(node, obj) {
+                var attrNode = node.getAttributeNode("queryable");
+                var queryable = (attrNode && attrNode.specified) ? 
+                    node.getAttribute("queryable") : null;
+                attrNode = node.getAttributeNode("cascaded");
+                var cascaded = (attrNode && attrNode.specified) ?
+                    node.getAttribute("cascaded") : null;
+                attrNode = node.getAttributeNode("opaque");
+                var opaque = (attrNode && attrNode.specified) ?
+                    node.getAttribute('opaque') : null;
+                var noSubsets = node.getAttribute('noSubsets');
+                var fixedWidth = node.getAttribute('fixedWidth');
+                var fixedHeight = node.getAttribute('fixedHeight');
+                var layer = {nestedLayers: [], styles: [], srs: {}, 
+                    metadataURLs: [], bbox: {}, dimensions: {},
+                    authorityURLs: {}, identifiers: {}, keywords: [],
+                    queryable: (queryable && queryable !== "") ? 
+                        ( queryable === "1" || queryable === "true" ) : null,
+                    cascaded: (cascaded !== null) ? parseInt(cascaded) : null,
+                    opaque: opaque ? 
+                        (opaque === "1" || opaque === "true" ) : null,
+                    noSubsets: (noSubsets !== null) ? 
+                        ( noSubsets === "1" || noSubsets === "true" ) : null,
+                    fixedWidth: (fixedWidth != null) ? 
+                        parseInt(fixedWidth) : null,
+                    fixedHeight: (fixedHeight != null) ? 
+                        parseInt(fixedHeight) : null
+                };
+                obj.nestedLayers.push(layer);
+                this.readChildNodes(node, layer);
+                if(layer.name) {
+                    var parts = layer.name.split(":");
+                    if(parts.length > 0) {
+                        layer.prefix = parts[0];
+                    }
+                }
+            },
+            "Attribution": function(node, obj) {
+                obj.attribution = {};
+                this.readChildNodes(node, obj.attribution);
+            },
+            "LogoURL": function(node, obj) {
+                obj.logo = {
+                    width: node.getAttribute("width"),
+                    height: node.getAttribute("height")
+                };
+                this.readChildNodes(node, obj.logo);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                obj.styles.push(style);
+                this.readChildNodes(node, style);
+            },
+            "LegendURL": function(node, obj) {
+                var legend = {
+                    width: node.getAttribute("width"),
+                    height: node.getAttribute("height")
+                };
+                obj.legend = legend;
+                this.readChildNodes(node, legend);
+            },
+            "MetadataURL": function(node, obj) {
+                var metadataURL = {type: node.getAttribute("type")};
+                obj.metadataURLs.push(metadataURL);
+                this.readChildNodes(node, metadataURL);
+            },
+            "DataURL": function(node, obj) {
+                obj.dataURL = {};
+                this.readChildNodes(node, obj.dataURL);
+            },
+            "FeatureListURL": function(node, obj) {
+                obj.featureListURL = {};
+                this.readChildNodes(node, obj.featureListURL);
+            },
+            "AuthorityURL": function(node, obj) {
+                var name = node.getAttribute("name");
+                var authority = {};
+                this.readChildNodes(node, authority);
+                obj.authorityURLs[name] = authority.href;
+            },
+            "Identifier": function(node, obj) {
+                var authority = node.getAttribute("authority");
+                obj.identifiers[authority] = this.getChildValue(node);
+            },
+            "KeywordList": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "SRS": function(node, obj) {
+                obj.srs[this.getChildValue(node)] = true;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities.v1_1
+ * Abstract class not to be instantiated directly.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1, {
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "WMT_MS_Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Keyword": function(node, obj) {
+                if (obj.keywords) {
+                    obj.keywords.push(this.getChildValue(node));
+                }
+            },
+            "DescribeLayer": function(node, obj) {
+                obj.describelayer = {formats: []};
+                this.readChildNodes(node, obj.describelayer);
+            },
+            "GetLegendGraphic": function(node, obj) {
+                obj.getlegendgraphic = {formats: []};
+                this.readChildNodes(node, obj.getlegendgraphic);
+            },
+            "GetStyles": function(node, obj) {
+                obj.getstyles = {formats: []};
+                this.readChildNodes(node, obj.getstyles);
+            },
+            "PutStyles": function(node, obj) {
+                obj.putstyles = {formats: []};
+                this.readChildNodes(node, obj.putstyles);
+            },
+            "UserDefinedSymbolization": function(node, obj) {
+                var userSymbols = {
+                    supportSLD: parseInt(node.getAttribute("SupportSLD")) == 1,
+                    userLayer: parseInt(node.getAttribute("UserLayer")) == 1,
+                    userStyle: parseInt(node.getAttribute("UserStyle")) == 1,
+                    remoteWFS: parseInt(node.getAttribute("RemoteWFS")) == 1
+                };
+                obj.userSymbols = userSymbols;
+            },
+            "LatLonBoundingBox": function(node, obj) {
+                obj.llbbox = [
+                    parseFloat(node.getAttribute("minx")),
+                    parseFloat(node.getAttribute("miny")),
+                    parseFloat(node.getAttribute("maxx")),
+                    parseFloat(node.getAttribute("maxy"))
+                ];
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+                bbox.srs  = node.getAttribute("SRS");
+                obj.bbox[bbox.srs] = bbox;
+            },
+            "ScaleHint": function(node, obj) {
+                var min = node.getAttribute("min");
+                var max = node.getAttribute("max");
+                var rad2 = Math.pow(2, 0.5);
+                var ipm = OpenLayers.INCHES_PER_UNIT["m"];
+                obj.maxScale = parseFloat(
+                    ((min / rad2) * ipm * 
+                        OpenLayers.DOTS_PER_INCH).toPrecision(13)
+                );
+                obj.minScale = parseFloat(
+                    ((max / rad2) * ipm * 
+                        OpenLayers.DOTS_PER_INCH).toPrecision(13)
+                );
+            },
+            "Dimension": function(node, obj) {
+                var name = node.getAttribute("name").toLowerCase();
+                var dim = {
+                    name: name,
+                    units: node.getAttribute("units"),
+                    unitsymbol: node.getAttribute("unitSymbol")
+                };
+                obj.dimensions[dim.name] = dim;
+            },
+            "Extent": function(node, obj) {
+                var name = node.getAttribute("name").toLowerCase();
+                if (name in obj["dimensions"]) {
+                    var extent = obj.dimensions[name];
+                    extent.nearestVal = 
+                        node.getAttribute("nearestValue") === "1";
+                    extent.multipleVal = 
+                        node.getAttribute("multipleValues") === "1";
+                    extent.current = node.getAttribute("current") === "1";
+                    extent["default"] = node.getAttribute("default") || "";
+                    var values = this.getChildValue(node);
+                    extent.values = values.split(",");
+                }
+                }
+        }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_0
+ * Read WMS Capabilities version 1.1.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1_1, {
+    
+    /**
+     * Property: version
+     * {String} The specific parser version.
+     */
+    version: "1.1.0",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_0
+     * Create a new parser for WMS capabilities version 1.1.0.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "SRS": function(node, obj) {
+                var srs = this.getChildValue(node);
+                var values = srs.split(/ +/);
+                for (var i=0, len=values.length; i<len; i++) {
+                    obj.srs[values[i]] = true;
+                }
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Protocol/WFS/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol/WFS.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.WFS.v1
+ * Abstract class for for v1.0.0 and v1.1.0 protocol.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+OpenLayers.Protocol.WFS.v1 = OpenLayers.Class(OpenLayers.Protocol, {
+    
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: null,
+    
+    /**
+     * Property: srsName
+     * {String} Name of spatial reference system.  Default is "EPSG:4326".
+     */
+    srsName: "EPSG:4326",
+    
+    /**
+     * Property: featureType
+     * {String} Local feature typeName.
+     */
+    featureType: null,
+    
+    /**
+     * Property: featureNS
+     * {String} Feature namespace.
+     */
+    featureNS: null,
+    
+    /**
+     * Property: geometryName
+     * {String} Name of the geometry attribute for features.  Default is
+     *     "the_geom" for WFS <version> 1.0, and null for higher versions.
+     */
+    geometryName: "the_geom",
+    
+    /**
+     * Property: schema
+     * {String} Optional schema location that will be included in the
+     *     schemaLocation attribute value.  Note that the feature type schema
+     *     is required for a strict XML validator (on transactions with an
+     *     insert for example), but is *not* required by the WFS specification
+     *     (since the server is supposed to know about feature type schemas).
+     */
+    schema: null,
+
+    /**
+     * Property: featurePrefix
+     * {String} Namespace alias for feature type.  Default is "feature".
+     */
+    featurePrefix: "feature",
+    
+    /**
+     * Property: formatOptions
+     * {Object} Optional options for the format.  If a format is not provided,
+     *     this property can be used to extend the default format options.
+     */
+    formatOptions: null,
+
+    /** 
+     * Property: readFormat 
+     * {<OpenLayers.Format>} For WFS requests it is possible to get a  
+     *     different output format than GML. In that case, we cannot parse  
+     *     the response with the default format (WFST) and we need a different 
+     *     format for reading. 
+     */ 
+    readFormat: null,
+    
+    /**
+     * Property: readOptions
+     * {Object} Optional object to pass to format's read.
+     */
+    readOptions: null,
+    
+    /**
+     * Constructor: OpenLayers.Protocol.WFS
+     * A class for giving layers WFS protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * url - {String} URL to send requests to (required).
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (required, but can be autodetected
+     *     during the first query if GML is used as readFormat and
+     *     featurePrefix is provided and matches the prefix used by the server
+     *     for this featureType).
+     * featurePrefix - {String} Feature namespace alias (optional - only used
+     *     for writing if featureNS is provided).  Default is 'feature'.
+     * geometryName - {String} Name of geometry attribute.  The default is
+     *     'the_geom' for WFS <version> 1.0, and null for higher versions. If
+     *     null, it will be set to the name of the first geometry found in the
+     *     first read operation.
+     * multi - {Boolean} If set to true, geometries will be casted to Multi
+     *     geometries before they are written in a transaction. No casting will
+     *     be done when reading features.
+     */
+    initialize: function(options) {
+        OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
+        if(!options.format) {
+            this.format = OpenLayers.Format.WFST(OpenLayers.Util.extend({
+                version: this.version,
+                featureType: this.featureType,
+                featureNS: this.featureNS,
+                featurePrefix: this.featurePrefix,
+                geometryName: this.geometryName,
+                srsName: this.srsName,
+                schema: this.schema
+            }, this.formatOptions));
+        }
+        if (!options.geometryName && parseFloat(this.format.version) > 1.0) {
+            this.setGeometryName(null);
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        if(this.options && !this.options.format) {
+            this.format.destroy();
+        }
+        this.format = null;
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: read
+     * Construct a request for reading new features.  Since WFS splits the
+     *     basic CRUD operations into GetFeature requests (for read) and
+     *     Transactions (for all others), this method does not make use of the
+     *     format's read method (that is only about reading transaction
+     *     responses).
+     *
+     * Parameters:
+     * options - {Object} Options for the read operation, in addition to the
+     *     options set on the instance (options set here will take precedence).
+     *
+     * To use a configured protocol to get e.g. a WFS hit count, applications
+     * could do the following:
+     *
+     * (code)
+     * protocol.read({
+     *     readOptions: {output: "object"},
+     *     resultType: "hits",
+     *     maxFeatures: null,
+     *     callback: function(resp) {
+     *         // process resp.numberOfFeatures here
+     *     }
+     * });
+     * (end)
+     *
+     * To use a configured protocol to use WFS paging (if supported by the
+     * server), applications could do the following:
+     *
+     * (code)
+     * protocol.read({
+     *     startIndex: 0,
+     *     count: 50
+     * });
+     * (end)
+     *
+     * To limit the attributes returned by the GetFeature request, applications
+     * can use the propertyNames option to specify the properties to include in
+     * the response:
+     *
+     * (code)
+     * protocol.read({
+     *     propertyNames: ["DURATION", "INTENSITY"]
+     * });
+     * (end)
+     */
+    read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options || {});
+        var response = new OpenLayers.Protocol.Response({requestType: "read"});
+        
+        var data = OpenLayers.Format.XML.prototype.write.apply(
+            this.format, [this.format.writeNode("wfs:GetFeature", options)]
+        );
+
+        response.priv = OpenLayers.Request.POST({
+            url: options.url,
+            callback: this.createCallback(this.handleRead, response, options),
+            params: options.params,
+            headers: options.headers,
+            data: data
+        });
+
+        return response;
+    },
+
+    /**
+     * APIMethod: setFeatureType
+     * Change the feature type on the fly.
+     *
+     * Parameters:
+     * featureType - {String} Local (without prefix) feature typeName.
+     */
+    setFeatureType: function(featureType) {
+        this.featureType = featureType;
+        this.format.featureType = featureType;
+    },
+ 
+    /**
+     * APIMethod: setGeometryName
+     * Sets the geometryName option after instantiation.
+     *
+     * Parameters:
+     * geometryName - {String} Name of geometry attribute.
+     */
+    setGeometryName: function(geometryName) {
+        this.geometryName = geometryName;
+        this.format.geometryName = geometryName;
+    },
+    
+    /**
+     * Method: handleRead
+     * Deal with response from the read request.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass
+     *     to the user callback.
+     * options - {Object} The user options passed to the read call.
+     */
+    handleRead: function(response, options) {
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options);
+
+        if(options.callback) {
+            var request = response.priv;
+            if(request.status >= 200 && request.status < 300) {
+                // success
+                var result = this.parseResponse(request, options.readOptions);
+                if (result && result.success !== false) { 
+                    if (options.readOptions && options.readOptions.output == "object") {
+                        OpenLayers.Util.extend(response, result);
+                    } else {
+                        response.features = result;
+                    }
+                    response.code = OpenLayers.Protocol.Response.SUCCESS;
+                } else {
+                    // failure (service exception)
+                    response.code = OpenLayers.Protocol.Response.FAILURE;
+                    response.error = result;
+                }
+            } else {
+                // failure
+                response.code = OpenLayers.Protocol.Response.FAILURE;
+            }
+            options.callback.call(options.scope, response);
+        }
+    },
+
+    /**
+     * Method: parseResponse
+     * Read HTTP response body and return features
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     * options - {Object} Optional object to pass to format's read
+     *
+     * Returns:
+     * {Object} or {Array({<OpenLayers.Feature.Vector>})} or
+     *     {<OpenLayers.Feature.Vector>} 
+     * An object with a features property, an array of features or a single 
+     * feature.
+     */
+    parseResponse: function(request, options) {
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        if(!doc || doc.length <= 0) {
+            return null;
+        }
+        var result = (this.readFormat !== null) ? this.readFormat.read(doc) : 
+            this.format.read(doc, options);
+        if (!this.featureNS) {
+            var format = this.readFormat || this.format;
+            this.featureNS = format.featureNS;
+            // no need to auto-configure again on subsequent reads
+            format.autoConfig = false;
+            if (!this.geometryName) {
+                this.setGeometryName(format.geometryName);
+            }
+        }
+        return result;
+    },
+
+    /**
+     * Method: commit
+     * Given a list of feature, assemble a batch request for update, create,
+     *     and delete transactions.  A commit call on the prototype amounts
+     *     to writing a WFS transaction - so the write method on the format
+     *     is used.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)}
+     * options - {Object}
+     *
+     * Valid options properties:
+     * nativeElements - {Array({Object})} Array of objects with information for writing
+     * out <Native> elements, these objects have vendorId, safeToIgnore and
+     * value properties. The <Native> element is intended to allow access to 
+     * vendor specific capabilities of any particular web feature server or 
+     * datastore.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} A response object with a features
+     *     property containing any insertIds and a priv property referencing
+     *     the XMLHttpRequest object.
+     */
+    commit: function(features, options) {
+
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options);
+        
+        var response = new OpenLayers.Protocol.Response({
+            requestType: "commit",
+            reqFeatures: features
+        });
+        response.priv = OpenLayers.Request.POST({
+            url: options.url,
+            headers: options.headers,
+            data: this.format.write(features, options),
+            callback: this.createCallback(this.handleCommit, response, options)
+        });
+        
+        return response;
+    },
+    
+    /**
+     * Method: handleCommit
+     * Called when the commit request returns.
+     * 
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass
+     *     to the user callback.
+     * options - {Object} The user options passed to the commit call.
+     */
+    handleCommit: function(response, options) {
+        if(options.callback) {
+            var request = response.priv;
+
+            // ensure that we have an xml doc
+            var data = request.responseXML;
+            if(!data || !data.documentElement) {
+                data = request.responseText;
+            }
+            
+            var obj = this.format.read(data) || {};
+            
+            response.insertIds = obj.insertIds || [];
+            if (obj.success) {
+                response.code = OpenLayers.Protocol.Response.SUCCESS;
+            } else {
+                response.code = OpenLayers.Protocol.Response.FAILURE;
+                response.error = obj;
+            }
+            options.callback.call(options.scope, response);
+        }
+    },
+    
+    /**
+     * Method: filterDelete
+     * Send a request that deletes all features by their filter.
+     * 
+     * Parameters:
+     * filter - {OpenLayers.Filter} filter
+     */
+    filterDelete: function(filter, options) {
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options);    
+        
+        var response = new OpenLayers.Protocol.Response({
+            requestType: "commit"
+        });    
+        
+        var root = this.format.createElementNSPlus("wfs:Transaction", {
+            attributes: {
+                service: "WFS",
+                version: this.version
+            }
+        });
+        
+        var deleteNode = this.format.createElementNSPlus("wfs:Delete", {
+            attributes: {
+                typeName: (options.featureNS ? this.featurePrefix + ":" : "") +
+                    options.featureType
+            }
+        });       
+        
+        if(options.featureNS) {
+            deleteNode.setAttribute("xmlns:" + this.featurePrefix, options.featureNS);
+        }
+        var filterNode = this.format.writeNode("ogc:Filter", filter);
+        
+        deleteNode.appendChild(filterNode);
+        
+        root.appendChild(deleteNode);
+        
+        var data = OpenLayers.Format.XML.prototype.write.apply(
+            this.format, [root]
+        );
+        
+        return OpenLayers.Request.POST({
+            url: this.url,
+            callback : options.callback || function(){},
+            data: data
+        });   
+        
+    },
+
+    /**
+     * Method: abort
+     * Abort an ongoing request, the response object passed to
+     * this method must come from this protocol (as a result
+     * of a read, or commit operation).
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>}
+     */
+    abort: function(response) {
+        if (response) {
+            response.priv.abort();
+        }
+    },
+  
+    CLASS_NAME: "OpenLayers.Protocol.WFS.v1" 
+});
+/* ======================================================================
+    OpenLayers/Handler/Point.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Handler.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Point
+ * Handler to draw a point on the map. Point is displayed on activation,
+ *     moves on mouse move, and is finished on mouse up. The handler triggers
+ *     callbacks for 'done', 'cancel', and 'modify'. The modify callback is
+ *     called with each change in the sketch and will receive the latest point
+ *     drawn.  Create a new instance with the <OpenLayers.Handler.Point>
+ *     constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.Point = OpenLayers.Class(OpenLayers.Handler, {
+    
+    /**
+     * Property: point
+     * {<OpenLayers.Feature.Vector>} The currently drawn point
+     */
+    point: null,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>} The temporary drawing layer
+     */
+    layer: null,
+    
+    /**
+     * APIProperty: multi
+     * {Boolean} Cast features to multi-part geometries before passing to the
+     *     layer.  Default is false.
+     */
+    multi: false,
+    
+    /**
+     * Property: mouseDown
+     * {Boolean} The mouse is down
+     */
+    mouseDown: false,
+
+    /**
+     * Property: stoppedDown
+     * {Boolean} Indicate whether the last mousedown stopped the event
+     * propagation.
+     */
+    stoppedDown: null,
+
+    /**
+     * Property: lastDown
+     * {<OpenLayers.Pixel>} Location of the last mouse down
+     */
+    lastDown: null,
+
+    /**
+     * Property: lastUp
+     * {<OpenLayers.Pixel>}
+     */
+    lastUp: null,
+
+    /**
+     * APIProperty: persist
+     * {Boolean} Leave the feature rendered until destroyFeature is called.
+     *     Default is false.  If set to true, the feature remains rendered until
+     *     destroyFeature is called, typically by deactivating the handler or
+     *     starting another drawing.
+     */
+    persist: false,
+
+    /**
+     * APIProperty: stopDown
+     * {Boolean} Stop event propagation on mousedown. Must be false to
+     *     allow "pan while drawing". Defaults to false.
+     */
+    stopDown: false,
+
+    /**
+     * APIPropery: stopUp
+     * {Boolean} Stop event propagation on mouse. Must be false to
+     *     allow "pan while dragging". Defaults to fase.
+     */
+    stopUp: false,
+
+    /**
+     * Property: layerOptions
+     * {Object} Any optional properties to be set on the sketch layer.
+     */
+    layerOptions: null,
+    
+    /**
+     * APIProperty: pixelTolerance
+     * {Number} Maximum number of pixels between down and up (mousedown
+     *     and mouseup, or touchstart and touchend) for the handler to
+     *     add a new point. If set to an integer value, if the
+     *     displacement between down and up is great to this value
+     *     no point will be added. Default value is 5.
+     */
+    pixelTolerance: 5,
+
+    /**
+     * Property: touch
+     * {Boolean} Indcates the support of touch events.
+     */
+    touch: false,
+
+    /**
+     * Property: lastTouchPx
+     * {<OpenLayers.Pixel>} The last pixel used to know the distance between
+     * two touches (for double touch).
+     */
+    lastTouchPx: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Point
+     * Create a new point handler.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} An optional object with properties to be set on the
+     *           handler
+     *
+     * Named callbacks:
+     * create - Called when a sketch is first created.  Callback called with
+     *     the creation point geometry and sketch feature.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the point geometry.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
+     */
+    initialize: function(control, callbacks, options) {
+        if(!(options && options.layerOptions && options.layerOptions.styleMap)) {
+            this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        }
+
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+    },
+    
+    /**
+     * APIMethod: activate
+     * turn on the handler
+     */
+    activate: function() {
+        if(!OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            return false;
+        }
+        // create temporary vector layer for rendering geometry sketch
+        // TBD: this could be moved to initialize/destroy - setting visibility here
+        var options = OpenLayers.Util.extend({
+            displayInLayerSwitcher: false,
+            // indicate that the temp vector layer will never be out of range
+            // without this, resolution properties must be specified at the
+            // map-level for this temporary layer to init its resolutions
+            // correctly
+            calculateInRange: OpenLayers.Function.True
+        }, this.layerOptions);
+        this.layer = new OpenLayers.Layer.Vector(this.CLASS_NAME, options);
+        this.map.addLayer(this.layer);
+        return true;
+    },
+    
+    /**
+     * Method: createFeature
+     * Add temporary features
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
+     */
+    createFeature: function(pixel) {
+        var lonlat = this.map.getLonLatFromPixel(pixel);
+        var geometry = new OpenLayers.Geometry.Point(
+            lonlat.lon, lonlat.lat
+        );
+        this.point = new OpenLayers.Feature.Vector(geometry);
+        this.callback("create", [this.point.geometry, this.point]);
+        this.point.geometry.clearBounds();
+        this.layer.addFeatures([this.point], {silent: true});
+    },
+
+    /**
+     * APIMethod: deactivate
+     * turn off the handler
+     */
+    deactivate: function() {
+        if(!OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            return false;
+        }
+        this.cancel();
+        // If a layer's map property is set to null, it means that that layer
+        // isn't added to the map. Since we ourself added the layer to the map
+        // in activate(), we can assume that if this.layer.map is null it means
+        // that the layer has been destroyed (as a result of map.destroy() for
+        // example.
+        if (this.layer.map != null) {
+            this.destroyFeature(true);
+            this.layer.destroy(false);
+        }
+        this.layer = null;
+        this.touch = false;
+        return true;
+    },
+    
+    /**
+     * Method: destroyFeature
+     * Destroy the temporary geometries
+     *
+     * Parameters:
+     * force - {Boolean} Destroy even if persist is true.
+     */
+    destroyFeature: function(force) {
+        if(this.layer && (force || !this.persist)) {
+            this.layer.destroyFeatures();
+        }
+        this.point = null;
+    },
+
+    /**
+     * Method: destroyPersistedFeature
+     * Destroy the persisted feature.
+     */
+    destroyPersistedFeature: function() {
+        var layer = this.layer;
+        if(layer && layer.features.length > 1) {
+            this.layer.features[0].destroy();
+        }
+    },
+
+    /**
+     * Method: finalize
+     * Finish the geometry and call the "done" callback.
+     *
+     * Parameters:
+     * cancel - {Boolean} Call cancel instead of done callback.  Default
+     *          is false.
+     */
+    finalize: function(cancel) {
+        var key = cancel ? "cancel" : "done";
+        this.mouseDown = false;
+        this.lastDown = null;
+        this.lastUp = null;
+        this.lastTouchPx = null;
+        this.callback(key, [this.geometryClone()]);
+        this.destroyFeature(cancel);
+    },
+
+    /**
+     * APIMethod: cancel
+     * Finish the geometry and call the "cancel" callback.
+     */
+    cancel: function() {
+        this.finalize(true);
+    },
+
+    /**
+     * Method: click
+     * Handle clicks.  Clicks are stopped from propagating to other listeners
+     *     on map.events or other dom elements.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    click: function(evt) {
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+
+    /**
+     * Method: dblclick
+     * Handle double-clicks.  Double-clicks are stopped from propagating to other
+     *     listeners on map.events or other dom elements.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    dblclick: function(evt) {
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+    
+    /**
+     * Method: modifyFeature
+     * Modify the existing geometry given a pixel location.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
+     */
+    modifyFeature: function(pixel) {
+        if(!this.point) {
+            this.createFeature(pixel);
+        }
+        var lonlat = this.map.getLonLatFromPixel(pixel);
+        this.point.geometry.x = lonlat.lon;
+        this.point.geometry.y = lonlat.lat;
+        this.callback("modify", [this.point.geometry, this.point, false]);
+        this.point.geometry.clearBounds();
+        this.drawFeature();
+    },
+
+    /**
+     * Method: drawFeature
+     * Render features on the temporary layer.
+     */
+    drawFeature: function() {
+        this.layer.drawFeature(this.point, this.style);
+    },
+    
+    /**
+     * Method: getGeometry
+     * Return the sketch geometry.  If <multi> is true, this will return
+     *     a multi-part geometry.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Point>}
+     */
+    getGeometry: function() {
+        var geometry = this.point && this.point.geometry;
+        if(geometry && this.multi) {
+            geometry = new OpenLayers.Geometry.MultiPoint([geometry]);
+        }
+        return geometry;
+    },
+
+    /**
+     * Method: geometryClone
+     * Return a clone of the relevant geometry.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>}
+     */
+    geometryClone: function() {
+        var geom = this.getGeometry();
+        return geom && geom.clone();
+    },
+
+    /**
+     * Method: mousedown
+     * Handle mousedown.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    mousedown: function(evt) {
+        return this.down(evt);
+    },
+
+    /**
+     * Method: touchstart
+     * Handle touchstart.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    touchstart: function(evt) {
+        if (!this.touch) {
+            this.touch = true;
+            // unregister mouse listeners
+            this.map.events.un({
+                mousedown: this.mousedown,
+                mouseup: this.mouseup,
+                mousemove: this.mousemove,
+                click: this.click,
+                dblclick: this.dblclick,
+                scope: this
+            });
+        }
+        this.lastTouchPx = evt.xy;
+        return this.down(evt);
+    },
+
+    /**
+     * Method: mousemove
+     * Handle mousemove.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    mousemove: function(evt) {
+        return this.move(evt);
+    },
+
+    /**
+     * Method: touchmove
+     * Handle touchmove.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    touchmove: function(evt) {
+        this.lastTouchPx = evt.xy;
+        return this.move(evt);
+    },
+
+    /**
+     * Method: mouseup
+     * Handle mouseup.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    mouseup: function(evt) {
+        return this.up(evt);
+    },
+
+    /**
+     * Method: touchend
+     * Handle touchend.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    touchend: function(evt) {
+        evt.xy = this.lastTouchPx;
+        return this.up(evt);
+    },
+  
+    /**
+     * Method: down
+     * Handle mousedown and touchstart.  Adjust the geometry and redraw.
+     * Return determines whether to propagate the event on the map.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    down: function(evt) {
+        this.mouseDown = true;
+        this.lastDown = evt.xy;
+        if(!this.touch) { // no point displayed until up on touch devices
+            this.modifyFeature(evt.xy);
+        }
+        this.stoppedDown = this.stopDown;
+        return !this.stopDown;
+    },
+
+    /**
+     * Method: move
+     * Handle mousemove and touchmove.  Adjust the geometry and redraw.
+     * Return determines whether to propagate the event on the map.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    move: function (evt) {
+        if(!this.touch // no point displayed until up on touch devices
+           && (!this.mouseDown || this.stoppedDown)) {
+            this.modifyFeature(evt.xy);
+        }
+        return true;
+    },
+
+    /**
+     * Method: up
+     * Handle mouseup and touchend.  Send the latest point in the geometry to the control.
+     * Return determines whether to propagate the event on the map.
+     *
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    up: function (evt) {
+        this.mouseDown = false;
+        this.stoppedDown = this.stopDown;
+
+        // check keyboard modifiers
+        if(!this.checkModifiers(evt)) {
+            return true;
+        }
+        // ignore double-clicks
+        if (this.lastUp && this.lastUp.equals(evt.xy)) {
+            return true;
+        }
+        if (this.lastDown && this.passesTolerance(this.lastDown, evt.xy,
+                                                  this.pixelTolerance)) {
+            if (this.touch) {
+                this.modifyFeature(evt.xy);
+            }
+            if(this.persist) {
+                this.destroyPersistedFeature();
+            }
+            this.lastUp = evt.xy;
+            this.finalize();
+            return !this.stopUp;
+        } else {
+            return true;
+        }
+    },
+
+    /**
+     * Method: mouseout
+     * Handle mouse out.  For better user experience reset mouseDown
+     * and stoppedDown when the mouse leaves the map viewport.
+     *
+     * Parameters:
+     * evt - {Event} The browser event
+     */
+    mouseout: function(evt) {
+        if(OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) {
+            this.stoppedDown = this.stopDown;
+            this.mouseDown = false;
+        }
+    },
+
+    /**
+     * Method: passesTolerance
+     * Determine whether the event is within the optional pixel tolerance.
+     *
+     * Returns:
+     * {Boolean} The event is within the pixel tolerance (if specified).
+     */
+    passesTolerance: function(pixel1, pixel2, tolerance) {
+        var passes = true;
+
+        if (tolerance != null && pixel1 && pixel2) {
+            var dist = pixel1.distanceTo(pixel2);
+            if (dist > tolerance) {
+                passes = false;
+            }
+        }
+        return passes;
+    },
+    
+    CLASS_NAME: "OpenLayers.Handler.Point"
+});
+/* ======================================================================
+    OpenLayers/Handler/Path.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Handler/Point.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Path
+ * Handler to draw a path on the map.  Path is displayed on mouse down,
+ * moves on mouse move, and is finished on mouse up.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Handler.Point>
+ */
+OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
+    
+    /**
+     * Property: line
+     * {<OpenLayers.Feature.Vector>}
+     */
+    line: null,
+
+    /**
+     * APIProperty: maxVertices
+     * {Number} The maximum number of vertices which can be drawn by this
+     * handler. When the number of vertices reaches maxVertices, the
+     * geometry is automatically finalized. This property doesn't
+     * apply if freehand is set. Default is null.
+     */
+    maxVertices: null,
+
+    /**
+     * Property: doubleTouchTolerance
+     * {Number} Maximum number of pixels between two touches for
+     *     the gesture to be considered a "finalize feature" action.
+     *     Default is 20.
+     */
+    doubleTouchTolerance: 20,
+
+    /**
+     * Property: freehand
+     * {Boolean} In freehand mode, the handler starts the path on mouse down,
+     * adds a point for every mouse move, and finishes the path on mouse up.
+     * Outside of freehand mode, a point is added to the path on every mouse
+     * click and double-click finishes the path.
+     */
+    freehand: false,
+    
+    /**
+     * Property: freehandToggle
+     * {String} If set, freehandToggle is checked on mouse events and will set
+     * the freehand mode to the opposite of this.freehand.  To disallow
+     * toggling between freehand and non-freehand mode, set freehandToggle to
+     * null.  Acceptable toggle values are 'shiftKey', 'ctrlKey', and 'altKey'.
+     */
+    freehandToggle: 'shiftKey',
+
+    /**
+     * Property: timerId
+     * {Integer} The timer used to test the double touch.
+     */
+    timerId: null,
+
+    /**
+     * Property: redoStack
+     * {Array} Stack containing points removed with <undo>.
+     */
+    redoStack: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Path
+     * Create a new path hander
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} An optional object with properties to be set on the
+     *           handler
+     *
+     * Named callbacks:
+     * create - Called when a sketch is first created.  Callback called with
+     *     the creation point geometry and sketch feature.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * point - Called as each point is added.  Receives the new point geometry.
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the linestring geometry.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
+    },
+        
+    /**
+     * Method: createFeature
+     * Add temporary geometries
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
+     *     feature.
+     */
+    createFeature: function(pixel) {
+        var lonlat = this.map.getLonLatFromPixel(pixel);
+        var geometry = new OpenLayers.Geometry.Point(
+            lonlat.lon, lonlat.lat
+        );
+        this.point = new OpenLayers.Feature.Vector(geometry);
+        this.line = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LineString([this.point.geometry])
+        );
+        this.callback("create", [this.point.geometry, this.getSketch()]);
+        this.point.geometry.clearBounds();
+        this.layer.addFeatures([this.line, this.point], {silent: true});
+    },
+        
+    /**
+     * Method: destroyFeature
+     * Destroy temporary geometries
+     *
+     * Parameters:
+     * force - {Boolean} Destroy even if persist is true.
+     */
+    destroyFeature: function(force) {
+        OpenLayers.Handler.Point.prototype.destroyFeature.call(
+            this, force);
+        this.line = null;
+    },
+
+    /**
+     * Method: destroyPersistedFeature
+     * Destroy the persisted feature.
+     */
+    destroyPersistedFeature: function() {
+        var layer = this.layer;
+        if(layer && layer.features.length > 2) {
+            this.layer.features[0].destroy();
+        }
+    },
+
+    /**
+     * Method: removePoint
+     * Destroy the temporary point.
+     */
+    removePoint: function() {
+        if(this.point) {
+            this.layer.removeFeatures([this.point]);
+        }
+    },
+    
+    /**
+     * Method: addPoint
+     * Add point to geometry.  Send the point index to override
+     * the behavior of LinearRing that disregards adding duplicate points.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The pixel location for the new point.
+     */
+    addPoint: function(pixel) {
+        this.layer.removeFeatures([this.point]);
+        var lonlat = this.control.map.getLonLatFromPixel(pixel);
+        this.point = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
+        );
+        this.line.geometry.addComponent(
+            this.point.geometry, this.line.geometry.components.length
+        );
+        this.layer.addFeatures([this.point]);
+        this.callback("point", [this.point.geometry, this.getGeometry()]);
+        this.callback("modify", [this.point.geometry, this.getSketch()]);
+        this.drawFeature();
+        delete this.redoStack;
+    },
+    
+    /**
+     * Method: insertXY
+     * Insert a point in the current sketch given x & y coordinates.  The new
+     *     point is inserted immediately before the most recently drawn point.
+     *
+     * Parameters:
+     * x - {Number} The x-coordinate of the point.
+     * y - {Number} The y-coordinate of the point.
+     */
+    insertXY: function(x, y) {
+        this.line.geometry.addComponent(
+            new OpenLayers.Geometry.Point(x, y), 
+            this.getCurrentPointIndex()
+        );
+        this.drawFeature();
+        delete this.redoStack;
+    },
+
+    /**
+     * Method: insertDeltaXY
+     * Insert a point given offsets from the previously inserted point.
+     *
+     * Parameters:
+     * dx - {Number} The x-coordinate offset of the point.
+     * dy - {Number} The y-coordinate offset of the point.
+     */
+    insertDeltaXY: function(dx, dy) {
+        var previousIndex = this.getCurrentPointIndex() - 1;
+        var p0 = this.line.geometry.components[previousIndex];
+        if (p0 && !isNaN(p0.x) && !isNaN(p0.y)) {
+            this.insertXY(p0.x + dx, p0.y + dy);
+        }
+    },
+
+    /**
+     * Method: insertDirectionLength
+     * Insert a point in the current sketch given a direction and a length.
+     *
+     * Parameters:
+     * direction - {Number} Degrees clockwise from the positive x-axis.
+     * length - {Number} Distance from the previously drawn point.
+     */
+    insertDirectionLength: function(direction, length) {
+        direction *= Math.PI / 180;
+        var dx = length * Math.cos(direction);
+        var dy = length * Math.sin(direction);
+        this.insertDeltaXY(dx, dy);
+    },
+
+    /**
+     * Method: insertDeflectionLength
+     * Insert a point in the current sketch given a deflection and a length.
+     *     The deflection should be degrees clockwise from the previously 
+     *     digitized segment.
+     *
+     * Parameters:
+     * deflection - {Number} Degrees clockwise from the previous segment.
+     * length - {Number} Distance from the previously drawn point.
+     */
+    insertDeflectionLength: function(deflection, length) {
+        var previousIndex = this.getCurrentPointIndex() - 1;
+        if (previousIndex > 0) {
+            var p1 = this.line.geometry.components[previousIndex];
+            var p0 = this.line.geometry.components[previousIndex-1];
+            var theta = Math.atan2(p1.y - p0.y, p1.x - p0.x);
+            this.insertDirectionLength(
+                (theta * 180 / Math.PI) + deflection, length
+            );
+        }
+    },
+
+    /**
+     * Method: getCurrentPointIndex
+     * 
+     * Returns:
+     * {Number} The index of the most recently drawn point.
+     */
+    getCurrentPointIndex: function() {
+        return this.line.geometry.components.length - 1;
+    },
+    
+    
+    /**
+     * Method: undo
+     * Remove the most recently added point in the sketch geometry.
+     *
+     * Returns: 
+     * {Boolean} A point was removed.
+     */
+    undo: function() {
+        var geometry = this.line.geometry;
+        var components = geometry.components;
+        var index = this.getCurrentPointIndex() - 1;
+        var target = components[index];
+        var undone = geometry.removeComponent(target);
+        if (undone) {
+            if (!this.redoStack) {
+                this.redoStack = [];
+            }
+            this.redoStack.push(target);
+            this.drawFeature();
+        }
+        return undone;
+    },
+    
+    /**
+     * Method: redo
+     * Reinsert the most recently removed point resulting from an <undo> call.
+     *     The undo stack is deleted whenever a point is added by other means.
+     *
+     * Returns: 
+     * {Boolean} A point was added.
+     */
+    redo: function() {
+        var target = this.redoStack && this.redoStack.pop();
+        if (target) {
+            this.line.geometry.addComponent(target, this.getCurrentPointIndex());
+            this.drawFeature();
+        }
+        return !!target;
+    },
+    
+    /**
+     * Method: freehandMode
+     * Determine whether to behave in freehand mode or not.
+     *
+     * Returns:
+     * {Boolean}
+     */
+    freehandMode: function(evt) {
+        return (this.freehandToggle && evt[this.freehandToggle]) ?
+                    !this.freehand : this.freehand;
+    },
+
+    /**
+     * Method: modifyFeature
+     * Modify the existing geometry given the new point
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The updated pixel location for the latest
+     *     point.
+     * drawing - {Boolean} Indicate if we're currently drawing.
+     */
+    modifyFeature: function(pixel, drawing) {
+        if(!this.line) {
+            this.createFeature(pixel);
+        }
+        var lonlat = this.control.map.getLonLatFromPixel(pixel);
+        this.point.geometry.x = lonlat.lon;
+        this.point.geometry.y = lonlat.lat;
+        this.callback("modify", [this.point.geometry, this.getSketch(), drawing]);
+        this.point.geometry.clearBounds();
+        this.drawFeature();
+    },
+
+    /**
+     * Method: drawFeature
+     * Render geometries on the temporary layer.
+     */
+    drawFeature: function() {
+        this.layer.drawFeature(this.line, this.style);
+        this.layer.drawFeature(this.point, this.style);
+    },
+
+    /**
+     * Method: getSketch
+     * Return the sketch feature.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    getSketch: function() {
+        return this.line;
+    },
+
+    /**
+     * Method: getGeometry
+     * Return the sketch geometry.  If <multi> is true, this will return
+     *     a multi-part geometry.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.LineString>}
+     */
+    getGeometry: function() {
+        var geometry = this.line && this.line.geometry;
+        if(geometry && this.multi) {
+            geometry = new OpenLayers.Geometry.MultiLineString([geometry]);
+        }
+        return geometry;
+    },
+
+    /**
+     * method: touchstart
+     * handle touchstart.
+     *
+     * parameters:
+     * evt - {event} the browser event
+     *
+     * returns:
+     * {boolean} allow event propagation
+     */
+    touchstart: function(evt) {
+        if (this.timerId &&
+            this.passesTolerance(this.lastTouchPx, evt.xy,
+                                 this.doubleTouchTolerance)) {
+            // double-tap, finalize the geometry
+            this.finishGeometry();
+            window.clearTimeout(this.timerId);
+            this.timerId = null;
+            return false;
+        } else {
+            if (this.timerId) {
+                window.clearTimeout(this.timerId);
+                this.timerId = null;
+            }
+            this.timerId = window.setTimeout(
+                OpenLayers.Function.bind(function() {
+                    this.timerId = null;
+                }, this), 300);
+            return OpenLayers.Handler.Point.prototype.touchstart.call(this, evt);
+        }
+    },
+
+    /**
+     * Method: down
+     * Handle mousedown and touchstart.  Add a new point to the geometry and
+     * render it. Return determines whether to propagate the event on the map.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    down: function(evt) {
+        var stopDown = this.stopDown;
+        if(this.freehandMode(evt)) {
+            stopDown = true;
+        }
+        if (!this.touch && (!this.lastDown ||
+                            !this.passesTolerance(this.lastDown, evt.xy,
+                                                  this.pixelTolerance))) {
+            this.modifyFeature(evt.xy, !!this.lastUp);
+        }
+        this.mouseDown = true;
+        this.lastDown = evt.xy;
+        this.stoppedDown = stopDown;
+        return !stopDown;
+    },
+
+    /**
+     * Method: move
+     * Handle mousemove and touchmove.  Adjust the geometry and redraw.
+     * Return determines whether to propagate the event on the map.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    move: function (evt) {
+        if(this.stoppedDown && this.freehandMode(evt)) {
+            if(this.persist) {
+                this.destroyPersistedFeature();
+            }
+            this.addPoint(evt.xy);
+            return false;
+        }
+        if (!this.touch && (!this.mouseDown || this.stoppedDown)) {
+            this.modifyFeature(evt.xy, !!this.lastUp);
+        }
+        return true;
+    },
+    
+    /**
+     * Method: up
+     * Handle mouseup and touchend.  Send the latest point in the geometry to
+     * the control. Return determines whether to propagate the event on the map.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    up: function (evt) {
+        if (this.mouseDown && (!this.lastUp || !this.lastUp.equals(evt.xy))) {
+            if(this.stoppedDown && this.freehandMode(evt)) {
+                if (this.persist) {
+                    this.destroyPersistedFeature();
+                }
+                this.removePoint();
+                this.finalize();
+            } else {
+                if (this.passesTolerance(this.lastDown, evt.xy,
+                                         this.pixelTolerance)) {
+                    if (this.touch) {
+                        this.modifyFeature(evt.xy);
+                    }
+                    if(this.lastUp == null && this.persist) {
+                        this.destroyPersistedFeature();
+                    }
+                    this.addPoint(evt.xy);
+                    this.lastUp = evt.xy;
+                    if(this.line.geometry.components.length === this.maxVertices + 1) {
+                        this.finishGeometry();
+                    }
+                }
+            }
+        }
+        this.stoppedDown = this.stopDown;
+        this.mouseDown = false;
+        return !this.stopUp;
+    },
+
+    /**
+     * APIMethod: finishGeometry
+     * Finish the geometry and send it back to the control.
+     */
+    finishGeometry: function() {
+        var index = this.line.geometry.components.length - 1;
+        this.line.geometry.removeComponent(this.line.geometry.components[index]);
+        this.removePoint();
+        this.finalize();
+    },
+  
+    /**
+     * Method: dblclick 
+     * Handle double-clicks.
+     * 
+     * Parameters:
+     * evt - {Event} The browser event
+     *
+     * Returns: 
+     * {Boolean} Allow event propagation
+     */
+    dblclick: function(evt) {
+        if(!this.freehandMode(evt)) {
+            this.finishGeometry();
+        }
+        return false;
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Path"
+});
+/* ======================================================================
+    OpenLayers/Layer/GML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Vector.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.GML
+ * Create a vector layer by parsing a GML file. The GML file is
+ *     passed in as a parameter.
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.Vector
+ *     with Protocol.HTTP and Strategy.Fixed. Provide the protocol with a 
+ *     format parameter to get the parser you want for your data.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Vector>
+ */
+OpenLayers.Layer.GML = OpenLayers.Class(OpenLayers.Layer.Vector, {
+    
+    /**
+      * Property: loaded
+      * {Boolean} Flag for whether the GML data has been loaded yet.
+      */
+    loaded: false,
+
+    /**
+      * APIProperty: format
+      * {<OpenLayers.Format>} The format you want the data to be parsed with.
+      */
+    format: null,
+
+    /**
+     * APIProperty: formatOptions
+     * {Object} Hash of options which should be passed to the format when it is
+     * created. Must be passed in the constructor.
+     */
+    formatOptions: null, 
+    
+    /**
+     * Constructor: OpenLayers.Layer.GML
+     * Load and parse a single file on the web, according to the format
+     * provided via the 'format' option, defaulting to GML. 
+     *
+     * Parameters:
+     * name - {String} 
+     * url - {String} URL of a GML file.
+     * options - {Object} Hashtable of extra options to tag onto the layer.
+     */
+     initialize: function(name, url, options) {
+        var newArguments = [];
+        newArguments.push(name, options);
+        OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments);
+        this.url = url;
+    },
+
+    /**
+     * APIMethod: setVisibility
+     * Set the visibility flag for the layer and hide/show&redraw accordingly. 
+     * Fire event unless otherwise specified
+     * GML will be loaded if the layer is being made visible for the first
+     * time.
+     *  
+     * Parameters:
+     * visible - {Boolean} Whether or not to display the layer 
+     *                          (if in range)
+     * noEvent - {Boolean} 
+     */
+    setVisibility: function(visibility, noEvent) {
+        OpenLayers.Layer.Vector.prototype.setVisibility.apply(this, arguments);
+        if(this.visibility && !this.loaded){
+            // Load the GML
+            this.loadGML();
+        }
+    },
+
+    /**
+     * Method: moveTo
+     * If layer is visible and GML has not been loaded, load GML, then load GML
+     * and call OpenLayers.Layer.Vector.moveTo() to redraw at the new location.
+     * 
+     * Parameters:
+     * bounds - {Object} 
+     * zoomChanged - {Object} 
+     * minor - {Object} 
+     */
+    moveTo:function(bounds, zoomChanged, minor) {
+        OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments);
+        // Wait until initialisation is complete before loading GML
+        // otherwise we can get a race condition where the root HTML DOM is
+        // loaded after the GML is paited.
+        // See http://trac.openlayers.org/ticket/404
+        if(this.visibility && !this.loaded){
+            this.loadGML();
+        }
+    },
+
+    /**
+     * Method: loadGML
+     */
+    loadGML: function() {
+        if (!this.loaded) {
+            this.events.triggerEvent("loadstart");
+            OpenLayers.Request.GET({
+                url: this.url,
+                success: this.requestSuccess,
+                failure: this.requestFailure,
+                scope: this
+            });
+            this.loaded = true;
+        }    
+    },    
+    
+    /**
+     * Method: setUrl
+     * Change the URL and reload the GML
+     *
+     * Parameters:
+     * url - {String} URL of a GML file.
+     */
+    setUrl:function(url) {
+        this.url = url;
+        this.destroyFeatures();
+        this.loaded = false;
+        this.loadGML();
+    },
+    
+    /**
+     * Method: requestSuccess
+     * Process GML after it has been loaded.
+     * Called by initialize() and loadUrl() after the GML has been loaded.
+     *
+     * Parameters:
+     * request - {String} 
+     */
+    requestSuccess:function(request) {
+        var doc = request.responseXML;
+        
+        if (!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        
+        var options = {};
+        
+        OpenLayers.Util.extend(options, this.formatOptions);
+        if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+            options.externalProjection = this.projection;
+            options.internalProjection = this.map.getProjectionObject();
+        }    
+        
+        var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
+        this.addFeatures(gml.read(doc));
+        this.events.triggerEvent("loadend");
+    },
+    
+    /**
+     * Method: requestFailure
+     * Process a failed loading of GML.
+     * Called by initialize() and loadUrl() if there was a problem loading GML.
+     *
+     * Parameters:
+     * request - {String} 
+     */
+    requestFailure: function(request) {
+        OpenLayers.Console.userError(OpenLayers.i18n("errorLoadingGML", {'url':this.url}));
+        this.events.triggerEvent("loadend");
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.GML"
+});
+/* ======================================================================
+    OpenLayers/Control/PanPanel.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/Panel.js
+ * @requires OpenLayers/Control/Pan.js
+ */
+
+/**
+ * Class: OpenLayers.Control.PanPanel
+ * The PanPanel is visible control for panning the map North, South, East or
+ * West in small steps. By default it is drawn in the top left corner of the
+ * map.
+ *
+ * Note: 
+ * If you wish to use this class with the default images and you want 
+ *       it to look nice in ie6, you should add the following, conditionally
+ *       added css stylesheet to your HTML file:
+ * 
+ * (code)
+ * <!--[if lte IE 6]>
+ *   <link rel="stylesheet" href="../theme/default/ie6-style.css" type="text/css" />
+ * <![endif]-->
+ * (end)
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control.Panel> 
+ */
+OpenLayers.Control.PanPanel = OpenLayers.Class(OpenLayers.Control.Panel, {
+
+    /** 
+     * APIProperty: slideFactor
+     * {Integer} Number of pixels by which we'll pan the map in any direction 
+     *     on clicking the arrow buttons, defaults to 50.  If you want to pan
+     *     by some ratio of the map dimensions, use <slideRatio> instead.
+     */
+    slideFactor: 50,
+
+    /** 
+     * APIProperty: slideRatio
+     * {Number} The fraction of map width/height by which we'll pan the map            
+     *     on clicking the arrow buttons.  Default is null.  If set, will
+     *     override <slideFactor>. E.g. if slideRatio is .5, then Pan Up will
+     *     pan up half the map height. 
+     */
+    slideRatio: null,
+
+    /**
+     * Constructor: OpenLayers.Control.PanPanel 
+     * Add the four directional pan buttons.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
+        var options = {
+            slideFactor: this.slideFactor,
+            slideRatio: this.slideRatio
+        };
+        this.addControls([
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH, options),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH, options),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST, options),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST, options)
+        ]);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.PanPanel"
+});
+/* ======================================================================
+    OpenLayers/Control/Attribution.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Attribution
+ * The attribution control adds attribution from layers to the map display. 
+ * It uses 'attribution' property of each layer.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Attribution = 
+  OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * APIProperty: seperator
+     * {String} String used to seperate layers.
+     */
+    separator: ", ",
+    
+    /**
+     * Constructor: OpenLayers.Control.Attribution 
+     * 
+     * Parameters:
+     * options - {Object} Options for control.
+     */
+
+    /** 
+     * Method: destroy
+     * Destroy control.
+     */
+    destroy: function() {
+        this.map.events.un({
+            "removelayer": this.updateAttribution,
+            "addlayer": this.updateAttribution,
+            "changelayer": this.updateAttribution,
+            "changebaselayer": this.updateAttribution,
+            scope: this
+        });
+        
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },    
+    
+    /**
+     * Method: draw
+     * Initialize control.
+     * 
+     * Returns: 
+     * {DOMElement} A reference to the DIV DOMElement containing the control
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        
+        this.map.events.on({
+            'changebaselayer': this.updateAttribution,
+            'changelayer': this.updateAttribution,
+            'addlayer': this.updateAttribution,
+            'removelayer': this.updateAttribution,
+            scope: this
+        });
+        this.updateAttribution();
+        
+        return this.div;    
+    },
+
+    /**
+     * Method: updateAttribution
+     * Update attribution string.
+     */
+    updateAttribution: function() {
+        var attributions = [];
+        if (this.map && this.map.layers) {
+            for(var i=0, len=this.map.layers.length; i<len; i++) {
+                var layer = this.map.layers[i];
+                if (layer.attribution && layer.getVisibility()) {
+                    // add attribution only if attribution text is unique
+                    if (OpenLayers.Util.indexOf(
+                                    attributions, layer.attribution) === -1) {
+                        attributions.push( layer.attribution );
+                    }
+                }
+            } 
+            this.div.innerHTML = attributions.join(this.separator);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Attribution"
+});
+/* ======================================================================
+    OpenLayers/Renderer/NG.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer/Elements.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer.NG
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Renderer.Elements>
+ */
+OpenLayers.Renderer.NG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
+    
+    /**
+     * Constant: labelNodeType
+     * {String} The node type for text label containers. To be defined by
+     * subclasses.
+     */
+    labelNodeType: null,
+    
+    /**
+     * Constructor: OpenLayers.Renderer.NG
+     * 
+     * Parameters:
+     * containerID - {String}
+     * options - {Object} options for this renderer. Supported options are:
+     *     * yOrdering - {Boolean} Whether to use y-ordering
+     *     * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored
+     *         if yOrdering is set to true.
+     */
+
+    /**
+     * Method: updateDimensions
+     * To be extended by subclasses - here we set positioning related styles
+     * on HTML elements, subclasses have to do the same for renderer specific
+     * elements (e.g. viewBox, width and height of the rendererRoot)
+     *
+     * Parameters:
+     * zoomChanged - {Boolean} Has the zoom changed? If so, subclasses may have
+     *     to update feature styles/dimensions.
+     */
+    updateDimensions: function(zoomChanged) {
+        var mapExtent = this.map.getExtent();
+        var renderExtent = mapExtent.scale(3);
+        this.setExtent(renderExtent, true);
+        var res = this.getResolution();
+        var div = this.rendererRoot.parentNode;
+        var layerLeft = parseFloat(div.parentNode.style.left);
+        var layerTop = parseFloat(div.parentNode.style.top);
+        div.style.left = ((renderExtent.left - mapExtent.left) / res - layerLeft) + "px";
+        div.style.top = ((mapExtent.top - renderExtent.top) / res - layerTop) + "px";
+    },
+    
+    /**
+     * Method: resize
+     */
+    setSize: function() {
+        this.map.getExtent() && this.updateDimensions();
+    },
+
+    /**
+     * Method: drawFeature
+     * Draw the feature.  The optional style argument can be used
+     * to override the feature's own style.  This method should only
+     * be called from layer.drawFeature().
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     * style - {<Object>}
+     * 
+     * Returns:
+     * {Boolean} true if the feature has been drawn completely, false if not,
+     *     undefined if the feature had no geometry
+     */
+    drawFeature: function(feature, style) {
+        if(style == null) {
+            style = feature.style;
+        }
+        if (feature.geometry) {
+            var rendered = this.drawGeometry(feature.geometry, style, feature.id);
+            if(rendered !== false && style.label) {
+                var location = feature.geometry.getCentroid(); 
+                this.drawText(feature.id, style, location);
+            } else {
+                this.removeText(feature.id);
+            }
+            return rendered;
+        }
+    },
+    
+    /**
+     * Method: drawText
+     * Function for drawing text labels.
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * featureId - {String|DOMElement}
+     * style - {Object}
+     * location - {<OpenLayers.Geometry.Point>}, will be modified inline
+     *
+     * Returns:
+     * {DOMElement} container holding the text label (to be populated by
+     * subclasses)
+     */
+    drawText: function(featureId, style, location) {
+        var label;
+        if (typeof featureId !== "string") {
+            label = featureId;
+        } else {
+            label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, this.labelNodeType);
+            label._featureId = featureId;
+        }
+        label._style = style;
+        label._x = location.x;
+        label._y = location.y;
+        if(style.labelXOffset || style.labelYOffset) {
+            var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset;
+            var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset;
+            var res = this.getResolution();
+            location.move(xOffset*res, yOffset*res);
+        }
+
+        if(label.parentNode !== this.textRoot) {
+            this.textRoot.appendChild(label);
+        }   
+
+        return label;
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer.NG"
+});
+/* ======================================================================
+    OpenLayers/Renderer/SVG2.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer/NG.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer.SVG2
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Renderer.NG>
+ */
+OpenLayers.Renderer.SVG2 = OpenLayers.Class(OpenLayers.Renderer.NG, {
+
+    /** 
+     * Property: xmlns
+     * {String}
+     */
+    xmlns: "http://www.w3.org/2000/svg",
+    
+    /**
+     * Property: xlinkns
+     * {String}
+     */
+    xlinkns: "http://www.w3.org/1999/xlink",
+
+    /**
+     * Property: symbolMetrics
+     * {Object} Cache for symbol metrics according to their svg coordinate
+     *     space. This is an object keyed by the symbol's id, and values are
+     *     an object with size, x and y properties.
+     */
+    symbolMetrics: null,
+    
+    /**
+     * Constant: labelNodeType
+     * {String} The node type for text label containers.
+     */
+    labelNodeType: "g",
+
+    /**
+     * Constructor: OpenLayers.Renderer.SVG2
+     * 
+     * Parameters:
+     * containerID - {String}
+     */
+    initialize: function(containerID) {
+        if (!this.supported()) { 
+            return; 
+        }
+        OpenLayers.Renderer.Elements.prototype.initialize.apply(this, 
+                                                                arguments);
+        
+        this.symbolMetrics = {};
+    },
+
+    /**
+     * APIMethod: supported
+     * 
+     * Returns:
+     * {Boolean} Whether or not the browser supports the SVG renderer
+     */
+    supported: function() {
+        var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
+        return (document.implementation && 
+           (document.implementation.hasFeature("org.w3c.svg", "1.0") || 
+            document.implementation.hasFeature(svgFeature + "SVG", "1.1") || 
+            document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
+    },    
+
+    /**
+     * Method: updateDimensions
+     *
+     * Parameters:
+     * zoomChanged - {Boolean}
+     */
+    updateDimensions: function(zoomChanged) {
+        OpenLayers.Renderer.NG.prototype.updateDimensions.apply(this, arguments);
+        
+        var res = this.getResolution();
+        
+        var width = this.extent.getWidth();
+        var height = this.extent.getHeight();
+        
+        var extentString = [
+            this.extent.left,
+            -this.extent.top,
+            width,
+            height
+        ].join(" ");
+        this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
+        this.rendererRoot.setAttributeNS(null, "width", width / res);
+        this.rendererRoot.setAttributeNS(null, "height", height / res);
+
+        if (zoomChanged === true) {
+            // update styles for the new resolution
+            var i, len;
+            var nodes = this.vectorRoot.childNodes;
+            for (i=0, len=nodes.length; i<len; ++i) {
+                this.setStyle(nodes[i]);
+            }
+            var textNodes = this.textRoot.childNodes;
+            var label;
+            for (i=0, len=textNodes.length; i<len; ++i) {
+                label = textNodes[i];
+                this.drawText(label, label._style,
+                    new OpenLayers.Geometry.Point(label._x, label._y)
+                );
+            }
+        }
+    },
+    
+    /** 
+     * Method: getNodeType
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * 
+     * Returns:
+     * {String} The corresponding node type for the specified geometry
+     */
+    getNodeType: function(geometry, style) {
+        var nodeType = null;
+        switch (geometry.CLASS_NAME) {
+            case "OpenLayers.Geometry.Point":
+                if (style.externalGraphic) {
+                    nodeType = "image";
+                } else if (this.isComplexSymbol(style.graphicName)) {
+                    nodeType = "svg";
+                } else {
+                    nodeType = "circle";
+                }
+                break;
+            case "OpenLayers.Geometry.Rectangle":
+                nodeType = "rect";
+                break;
+            case "OpenLayers.Geometry.LineString":
+                nodeType = "polyline";
+                break;
+            case "OpenLayers.Geometry.LinearRing":
+                nodeType = "polygon";
+                break;
+            case "OpenLayers.Geometry.Polygon":
+            case "OpenLayers.Geometry.Curve":
+            case "OpenLayers.Geometry.Surface":
+                nodeType = "path";
+                break;
+            default:
+                break;
+        }
+        return nodeType;
+    },
+
+    /** 
+     * Method: setStyle
+     * Use to set all the style attributes to a SVG node.
+     * 
+     * Takes care to adjust stroke width and point radius to be
+     * resolution-relative
+     *
+     * Parameters:
+     * node - {SVGDomElement} An SVG element to decorate
+     * style - {Object}
+     * options - {Object} Currently supported options include 
+     *                              'isFilled' {Boolean} and
+     *                              'isStroked' {Boolean}
+     */
+    setStyle: function(node, style, options) {
+        style = style  || node._style;
+        options = options || node._options;
+        var resolution = this.getResolution();
+        var r = node._radius;
+        var widthFactor = resolution;
+        if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
+            node.style.visibility = "";
+            if (style.graphic === false) {
+                node.style.visibility = "hidden";
+            } else if (style.externalGraphic) {
+                
+                if (style.graphicTitle) {
+                    node.setAttributeNS(null, "title", style.graphicTitle);
+                    //Standards-conformant SVG 
+                    var label = this.nodeFactory(null, "title"); 
+                    label.textContent = style.graphicTitle; 
+                    node.appendChild(label); 
+                }
+                if (style.graphicWidth && style.graphicHeight) {
+                    node.setAttributeNS(null, "preserveAspectRatio", "none");
+                }
+                var width = style.graphicWidth || style.graphicHeight;
+                var height = style.graphicHeight || style.graphicWidth;
+                width = width ? width : style.pointRadius*2;
+                height = height ? height : style.pointRadius*2;
+                width *= resolution;
+                height *= resolution;
+                
+                var xOffset = (style.graphicXOffset != undefined) ?
+                    style.graphicXOffset * resolution : -(0.5 * width);
+                var yOffset = (style.graphicYOffset != undefined) ?
+                    style.graphicYOffset * resolution : -(0.5 * height);
+
+                var opacity = style.graphicOpacity || style.fillOpacity;
+                
+                node.setAttributeNS(null, "x", node._x + xOffset);
+                node.setAttributeNS(null, "y", node._y + yOffset);
+                node.setAttributeNS(null, "width", width);
+                node.setAttributeNS(null, "height", height);
+                node.setAttributeNS(this.xlinkns, "href", style.externalGraphic);
+                node.setAttributeNS(null, "style", "opacity: "+opacity);
+                node.onclick = OpenLayers.Renderer.SVG2.preventDefault;
+            } else if (this.isComplexSymbol(style.graphicName)) {
+                // the symbol viewBox is three times as large as the symbol
+                var offset = style.pointRadius * 3 * resolution;
+                var size = offset * 2;
+                var src = this.importSymbol(style.graphicName);
+                widthFactor = this.symbolMetrics[src.id].size * 3 / size * resolution;
+                
+                // remove the node from the dom before we modify it. This
+                // prevents various rendering issues in Safari and FF
+                var parent = node.parentNode;
+                var nextSibling = node.nextSibling;
+                if(parent) {
+                    parent.removeChild(node);
+                }
+                
+                // The more appropriate way to implement this would be use/defs, 
+                // but due to various issues in several browsers, it is safer to 
+                // copy the symbols instead of referencing them.  
+                // See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985  
+                // and this email thread 
+                // http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html 
+                node.firstChild && node.removeChild(node.firstChild); 
+                node.appendChild(src.firstChild.cloneNode(true)); 
+                node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox")); 
+
+                node.setAttributeNS(null, "width", size);
+                node.setAttributeNS(null, "height", size);
+                node.setAttributeNS(null, "x", node._x - offset);
+                node.setAttributeNS(null, "y", node._y - offset);
+                
+                // now that the node has all its new properties, insert it
+                // back into the dom where it was
+                if(nextSibling) {
+                    parent.insertBefore(node, nextSibling);
+                } else if(parent) {
+                    parent.appendChild(node);
+                }
+            } else {
+                node.setAttributeNS(null, "r", style.pointRadius * resolution);
+            }
+
+            var rotation = style.rotation;
+            if (rotation !== undefined || node._rotation !== undefined) {
+                node._rotation = rotation;
+                rotation |= 0;
+                if (node.nodeName !== "svg") { 
+                    node.setAttributeNS(null, "transform", 
+                        ["rotate(", rotation, node._x, node._y, ")"].join(" ")
+                    ); 
+                } else {
+                    var metrics = this.symbolMetrics[src.id]; 
+                    node.firstChild.setAttributeNS(null, "transform",
+                        ["rotate(", rotation, metrics.x, metrics.y, ")"].join(" ")
+                    );
+                }
+            }
+        }
+        
+        if (options.isFilled) {
+            node.setAttributeNS(null, "fill", style.fillColor);
+            node.setAttributeNS(null, "fill-opacity", style.fillOpacity);
+        } else {
+            node.setAttributeNS(null, "fill", "none");
+        }
+
+        if (options.isStroked) {
+            node.setAttributeNS(null, "stroke", style.strokeColor);
+            node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
+            node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
+            node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
+            // Hard-coded linejoin for now, to make it look the same as in VML.
+            // There is no strokeLinejoin property yet for symbolizers.
+            node.setAttributeNS(null, "stroke-linejoin", "round");
+            style.strokeDashstyle && node.setAttributeNS(null,
+                "stroke-dasharray", this.dashStyle(style, widthFactor));
+        } else {
+            node.setAttributeNS(null, "stroke", "none");
+        }
+        
+        if (style.pointerEvents) {
+            node.setAttributeNS(null, "pointer-events", style.pointerEvents);
+        }
+                
+        if (style.cursor != null) {
+            node.setAttributeNS(null, "cursor", style.cursor);
+        }
+        
+        return node;
+    },
+
+    /** 
+     * Method: dashStyle
+     * 
+     * Parameters:
+     * style - {Object}
+     * widthFactor - {Number}
+     * 
+     * Returns:
+     * {String} A SVG compliant 'stroke-dasharray' value
+     */
+    dashStyle: function(style, widthFactor) {
+        var w = style.strokeWidth * widthFactor;
+        var str = style.strokeDashstyle;
+        switch (str) {
+            case 'solid':
+                return 'none';
+            case 'dot':
+                return [widthFactor, 4 * w].join();
+            case 'dash':
+                return [4 * w, 4 * w].join();
+            case 'dashdot':
+                return [4 * w, 4 * w, widthFactor, 4 * w].join();
+            case 'longdash':
+                return [8 * w, 4 * w].join();
+            case 'longdashdot':
+                return [8 * w, 4 * w, widthFactor, 4 * w].join();
+            default:
+                var parts = OpenLayers.String.trim(str).split(/\s+/g);
+                for (var i=0, ii=parts.length; i<ii; i++) {
+                    parts[i] = parts[i] * widthFactor;
+                }
+                return parts.join();            
+        }
+    },
+    
+    /** 
+     * Method: createNode
+     * 
+     * Parameters:
+     * type - {String} Kind of node to draw
+     * id - {String} Id for node
+     * 
+     * Returns:
+     * {DOMElement} A new node of the given type and id
+     */
+    createNode: function(type, id) {
+        var node = document.createElementNS(this.xmlns, type);
+        if (id) {
+            node.setAttributeNS(null, "id", id);
+        }
+        return node;    
+    },
+    
+    /** 
+     * Method: nodeTypeCompare
+     * 
+     * Parameters:
+     * node - {SVGDomElement} An SVG element
+     * type - {String} Kind of node
+     * 
+     * Returns:
+     * {Boolean} Whether or not the specified node is of the specified type
+     */
+    nodeTypeCompare: function(node, type) {
+        return (type == node.nodeName);
+    },
+   
+    /**
+     * Method: createRenderRoot
+     * 
+     * Returns:
+     * {DOMElement} The specific render engine's root element
+     */
+    createRenderRoot: function() {
+        return this.nodeFactory(this.container.id + "_svgRoot", "svg");
+    },
+
+    /**
+     * Method: createRoot
+     * 
+     * Parameter:
+     * suffix - {String} suffix to append to the id
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    createRoot: function(suffix) {
+        return this.nodeFactory(this.container.id + suffix, "g");
+    },
+
+    /**
+     * Method: createDefs
+     *
+     * Returns:
+     * {DOMElement} The element to which we'll add the symbol definitions
+     */
+    createDefs: function() {
+        var defs = this.nodeFactory(this.container.id + "_defs", "defs");
+        this.rendererRoot.appendChild(defs);
+        return defs;
+    },
+
+    /**************************************
+     *                                    *
+     *     GEOMETRY DRAWING FUNCTIONS     *
+     *                                    *
+     **************************************/
+
+    /**
+     * Method: drawPoint
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the point
+     */ 
+    drawPoint: function(node, geometry) {
+        return this.drawCircle(node, geometry, 1);
+    },
+
+    /**
+     * Method: drawCircle
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * radius - {Float}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the circle
+     */
+    drawCircle: function(node, geometry, radius) {
+        var x = geometry.x;
+        var y = -geometry.y;
+        node.setAttributeNS(null, "cx", x);
+        node.setAttributeNS(null, "cy", y);
+        node._x = x;
+        node._y = y;
+        node._radius = radius;
+        return node;
+    },
+    
+    /**
+     * Method: drawLineString
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components of
+     *     the linestring, or false if nothing could be drawn
+     */ 
+    drawLineString: function(node, geometry) {
+        var path = this.getComponentsString(geometry.components);
+        node.setAttributeNS(null, "points", path);
+        return node;
+    },
+    
+    /**
+     * Method: drawLinearRing
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the linear ring, or false if nothing could be drawn
+     */ 
+    drawLinearRing: function(node, geometry) {
+        var path = this.getComponentsString(geometry.components);
+        node.setAttributeNS(null, "points", path);
+        return node;
+    },
+    
+    /**
+     * Method: drawPolygon
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the polygon, or false if nothing could be drawn
+     */ 
+    drawPolygon: function(node, geometry) {
+        var d = [];
+        var draw = true;
+        var complete = true;
+        var linearRingResult, path;
+        for (var j=0, len=geometry.components.length; j<len; j++) {
+            d.push("M");
+            path = this.getComponentsString(
+                geometry.components[j].components, " ");
+            d.push(path);
+        }
+        d.push("z");
+        node.setAttributeNS(null, "d", d.join(" "));
+        node.setAttributeNS(null, "fill-rule", "evenodd");
+        return node;
+    },
+    
+    /**
+     * Method: drawRectangle
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the rectangle
+     */ 
+    drawRectangle: function(node, geometry) {
+        node.setAttributeNS(null, "x", geometry.x);
+        node.setAttributeNS(null, "y", -geometry.y);
+        node.setAttributeNS(null, "width", geometry.width);
+        node.setAttributeNS(null, "height", geometry.height);
+        return node;
+    },
+    
+    /**
+     * Method: drawSurface
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the surface
+     */ 
+    drawSurface: function(node, geometry) {
+
+        // create the svg path string representation
+        var d = [];
+        var draw = true;
+        for (var i=0, len=geometry.components.length; i<len; i++) {
+            if ((i%3) == 0 && (i/3) == 0) {
+                var component = this.getShortString(geometry.components[i]);
+                d.push("M", component);
+            } else if ((i%3) == 1) {
+                var component = this.getShortString(geometry.components[i]);
+                d.push("C", component);
+            } else {
+                var component = this.getShortString(geometry.components[i]);
+                d.push(component);
+            }
+        }
+        d.push("Z");
+        node.setAttributeNS(null, "d", d.join(" "));
+        return node;
+    },
+    
+    /**
+     * Method: drawText
+     * Function for drawing text labels.
+     * This method is only called by the renderer itself.
+     *
+     * Parameters:
+     * featureId - {String|DOMElement}
+     * style - {Object}
+     * location - {<OpenLayers.Geometry.Point>}, will be modified inline
+     *
+     * Returns:
+     * {DOMElement} container holding the text label
+     */
+    drawText: function(featureId, style, location) {
+        var g = OpenLayers.Renderer.NG.prototype.drawText.apply(this, arguments);
+        var text = g.firstChild ||
+            this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_text", "text");
+
+        var res = this.getResolution();
+        text.setAttributeNS(null, "x", location.x / res);
+        text.setAttributeNS(null, "y", - location.y / res);
+        g.setAttributeNS(null, "transform", "scale(" + res + ")");
+
+        if (style.fontColor) {
+            text.setAttributeNS(null, "fill", style.fontColor);
+        }
+        if (style.fontOpacity) {
+            text.setAttributeNS(null, "opacity", style.fontOpacity);
+        }
+        if (style.fontFamily) {
+            text.setAttributeNS(null, "font-family", style.fontFamily);
+        }
+        if (style.fontSize) {
+            text.setAttributeNS(null, "font-size", style.fontSize);
+        }
+        if (style.fontWeight) {
+            text.setAttributeNS(null, "font-weight", style.fontWeight);
+        }
+        if (style.fontStyle) {
+            text.setAttributeNS(null, "font-style", style.fontStyle);
+        }
+        if (style.labelSelect === true) {
+            text.setAttributeNS(null, "pointer-events", "visible");
+            text._featureId = featureId;
+        } else {
+            text.setAttributeNS(null, "pointer-events", "none");
+        }
+        var align = style.labelAlign || "cm";
+        text.setAttributeNS(null, "text-anchor",
+            OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]] || "middle");
+
+        if (OpenLayers.IS_GECKO === true) {
+            text.setAttributeNS(null, "dominant-baseline",
+                OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]] || "central");
+        }
+
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
+        while (text.childNodes.length > numRows) {
+            text.removeChild(text.lastChild);
+        }
+        for (var i = 0; i < numRows; i++) {
+            var tspan = text.childNodes[i] ||
+                this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan");
+            if (style.labelSelect === true) {
+                tspan._featureId = featureId;
+            }
+            if (OpenLayers.IS_GECKO === false) {
+                tspan.setAttributeNS(null, "baseline-shift",
+                    OpenLayers.Renderer.SVG2.LABEL_VSHIFT[align[1]] || "-35%");
+            }
+            tspan.setAttribute("x", location.x / res);
+            if (i == 0) {
+                var vfactor = OpenLayers.Renderer.SVG2.LABEL_VFACTOR[align[1]];
+                if (vfactor == null) {
+                    vfactor = -.5;
+                }
+                tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em");
+            } else {
+                tspan.setAttribute("dy", "1em");
+            }
+            tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i];
+            if (!tspan.parentNode) {
+                text.appendChild(tspan);
+            }
+        }
+
+        if (!text.parentNode) {
+            g.appendChild(text);
+        }
+
+        return g;
+    },
+    
+    /** 
+     * Method: getComponentString
+     * 
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry.Point>)} Array of points
+     * separator - {String} character between coordinate pairs. Defaults to ","
+     * 
+     * Returns:
+     * {Object} hash with properties "path" (the string created from the
+     *     components and "complete" (false if the renderer was unable to
+     *     draw all components)
+     */
+    getComponentsString: function(components, separator) {
+        var len = components.length;
+        var strings = new Array(len);
+        for (var i=0; i<len; i++) {
+            strings[i] = this.getShortString(components[i]);
+        }
+
+        return strings.join(separator || ",");
+    },
+    
+    /** 
+     * Method: getShortString
+     * 
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     * 
+     * Returns:
+     * {String} or false if point is outside the valid range
+     */
+    getShortString: function(point) {
+        return point.x + "," + (-point.y);
+    },
+    
+    /**
+     * Method: importSymbol
+     * add a new symbol definition from the rendererer's symbol hash
+     * 
+     * Parameters:
+     * graphicName - {String} name of the symbol to import
+     * 
+     * Returns:
+     * {DOMElement} - the imported symbol
+     */      
+    importSymbol: function (graphicName)  {
+        if (!this.defs) {
+            // create svg defs tag
+            this.defs = this.createDefs();
+        }
+        var id = this.container.id + "-" + graphicName;
+        
+        // check if symbol already exists in the defs
+        var existing = document.getElementById(id);
+        if (existing != null) {
+            return existing;
+        }
+        
+        var symbol = OpenLayers.Renderer.symbol[graphicName];
+        if (!symbol) {
+            throw new Error(graphicName + ' is not a valid symbol name');
+        }
+
+        var symbolNode = this.nodeFactory(id, "symbol");
+        var node = this.nodeFactory(null, "polygon");
+        symbolNode.appendChild(node);
+        var symbolExtent = new OpenLayers.Bounds(
+                                    Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
+
+        var points = [];
+        var x,y;
+        for (var i=0, len=symbol.length; i<len; i=i+2) {
+            x = symbol[i];
+            y = symbol[i+1];
+            symbolExtent.left = Math.min(symbolExtent.left, x);
+            symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
+            symbolExtent.right = Math.max(symbolExtent.right, x);
+            symbolExtent.top = Math.max(symbolExtent.top, y);
+            points.push(x, ",", y);
+        }
+        
+        node.setAttributeNS(null, "points", points.join(" "));
+        
+        var width = symbolExtent.getWidth();
+        var height = symbolExtent.getHeight();
+        // create a viewBox three times as large as the symbol itself,
+        // to allow for strokeWidth being displayed correctly at the corners.
+        var viewBox = [symbolExtent.left - width,
+                        symbolExtent.bottom - height, width * 3, height * 3];
+        symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" "));
+        this.symbolMetrics[id] = {
+            size: Math.max(width, height),
+            x: symbolExtent.getCenterLonLat().lon,
+            y: symbolExtent.getCenterLonLat().lat
+        };
+        
+        this.defs.appendChild(symbolNode);
+        return symbolNode;
+    },
+    
+    /**
+     * Method: getFeatureIdFromEvent
+     * 
+     * Parameters:
+     * evt - {Object} An <OpenLayers.Event> object
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>} A geometry from an event that 
+     *     happened on a layer.
+     */
+    getFeatureIdFromEvent: function(evt) {
+        var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
+        if(!featureId) {
+            var target = evt.target;
+            featureId = target.parentNode && target != this.rendererRoot &&
+                target.parentNode._featureId;
+        }
+        return featureId;
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer.SVG2"
+});
+
+/**
+ * Constant: OpenLayers.Renderer.SVG2.LABEL_ALIGN
+ * {Object}
+ */
+OpenLayers.Renderer.SVG2.LABEL_ALIGN = {
+    "l": "start",
+    "r": "end",
+    "b": "bottom",
+    "t": "hanging"
+};
+
+/**
+ * Constant: OpenLayers.Renderer.SVG2.LABEL_VSHIFT
+ * {Object}
+ */
+OpenLayers.Renderer.SVG2.LABEL_VSHIFT = {
+    // according to
+    // http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html
+    // a baseline-shift of -70% shifts the text exactly from the
+    // bottom to the top of the baseline, so -35% moves the text to
+    // the center of the baseline.
+    "t": "-70%",
+    "b": "0"    
+};
+
+/**
+ * Constant: OpenLayers.Renderer.SVG2.LABEL_VFACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.SVG2.LABEL_VFACTOR = {
+    "t": 0,
+    "b": -1
+};
+
+/** 
+ * Function: OpenLayers.Renderer.SVG2.preventDefault 
+ * Used to prevent default events (especially opening images in a new tab on 
+ * ctrl-click) from being executed for externalGraphic and graphicName symbols 
+ */ 
+OpenLayers.Renderer.SVG2.preventDefault = function(e) { 
+    e.preventDefault && e.preventDefault(); 
+};
+/* ======================================================================
+    OpenLayers/Kinetic.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+OpenLayers.Kinetic = OpenLayers.Class({
+
+    /**
+     * Property: threshold
+     * In most cases changing the threshold isn't needed.
+     * In px/ms, default to 0.
+     */
+    threshold: 0,
+
+    /**
+     * Property: interval
+     * {Integer} Interval in milliseconds between 2 steps in the "kinetic
+     *     dragging". Defaults to 10 milliseconds.
+     */
+    interval: 10,
+
+    /**
+     * Property: deceleration
+     * {Float} the deseleration in px/ms², default to 0.0035.
+     */
+    deceleration: 0.0035,
+
+    /**
+     * Property: nbPoints
+     * {Integer} the number of points we use to calculate the kinetic
+     * initial values.
+     */
+    nbPoints: 100,
+
+    /**
+     * Property: delay
+     * {Float} time to consider to calculate the kinetic initial values.
+     * In ms, default to 200.
+     */
+    delay: 200,
+
+    /**
+     * Property: points
+     * List of points use to calculate the kinetic initial values.
+     */
+    points: undefined,
+
+    /**
+     * Property: timerId
+     * ID of the timer.
+     */
+    timerId: undefined,
+
+    /**
+     * Constructor: OpenLayers.Kinetic
+     *
+     * Parameters:
+     * options - {Object}
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+    },
+
+    /**
+     * Method: begin
+     * Begins the dragging.
+     */
+    begin: function() {
+        clearInterval(this.timerId);
+        this.timerId = undefined;
+        this.points = [];
+    },
+
+    /**
+     * Method: update
+     * Updates during the dragging.
+     *
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The new position.
+     */
+    update: function(xy) {
+        this.points.unshift({xy: xy, tick: new Date().getTime()});
+        if (this.points.length > this.nbPoints) {
+            this.points.pop();
+        }
+    },
+
+    /**
+     * Method: end
+     * Ends the dragging, start the kinetic.
+     *
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The last position.
+     *
+     * Returns:
+     * {Object} An object with two properties: "speed", and "theta". The
+     *     "speed" and "theta" values are to be passed to the move 
+     *     function when starting the animation.
+     */
+    end: function(xy) {
+        var last, now = new Date().getTime();
+        for (var i = 0, l = this.points.length, point; i < l; i++) {
+            point = this.points[i];
+            if (now - point.tick > this.delay) {
+                break;
+            }
+            last = point;
+        }
+        if (!last) {
+            return;
+        }
+        var time = new Date().getTime() - last.tick;
+        var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) +
+                             Math.pow(xy.y - last.xy.y, 2));
+        var speed = dist / time;
+        if (speed == 0 || speed < this.threshold) {
+            return;
+        }
+        var theta = Math.asin((xy.y - last.xy.y) / dist);
+        if (last.xy.x <= xy.x) {
+            theta = Math.PI - theta;
+        }
+        return {speed: speed, theta: theta};
+    },
+
+    /**
+     * Method: move
+     * Launch the kinetic move pan.
+     *
+     * Parameters:
+     * info - {Object} An object with two properties, "speed", and "theta".
+     *     These values are those returned from the "end" call.
+     * callback - {Function} Function called on every step of the animation,
+     *     receives x, y (values to pan), end (is the last point).
+     */
+    move: function(info, callback) {
+        var v0 = info.speed;
+        var fx = Math.cos(info.theta);
+        var fy = -Math.sin(info.theta);
+
+        var time = 0;
+        var initialTime = new Date().getTime();
+
+        var lastX = 0;
+        var lastY = 0;
+
+        var timerCallback = function() {
+            if (this.timerId == null) {
+                return;
+            }
+
+            time += this.interval;
+            var realTime = new Date().getTime() - initialTime;
+            var t = (time + realTime) / 2.0;
+
+            var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t;
+            var x = p * fx;
+            var y = p * fy;
+
+            var args = {};
+            args.end = false;
+            var v = -this.deceleration * t + v0;
+
+            if (v <= 0) {
+                clearInterval(this.timerId);
+                this.timerId = null;
+                args.end = true;
+            }
+
+            args.x = x - lastX;
+            args.y = y - lastY;
+            lastX = x;
+            lastY = y;
+            callback(args.x, args.y, args.end);
+        };
+
+        this.timerId = window.setInterval(
+            OpenLayers.Function.bind(timerCallback, this),
+            this.interval);
+    },
+
+    CLASS_NAME: "OpenLayers.Kinetic"
+});
+/* ======================================================================
+    OpenLayers/Ajax.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+OpenLayers.ProxyHost = "";
+//OpenLayers.ProxyHost = "examples/proxy.cgi?url=";
+
+/**
+ * Ajax reader for OpenLayers
+ *
+ *  @uri url to do remote XML http get
+ *  @param {String} 'get' format params (x=y&a=b...)
+ *  @who object to handle callbacks for this request
+ *  @complete  the function to be called on success 
+ *  @failure  the function to be called on failure
+ *  
+ *   example usage from a caller:
+ *  
+ *     caps: function(request) {
+ *      -blah-  
+ *     },
+ *  
+ *     OpenLayers.loadURL(url,params,this,caps);
+ *
+ * Notice the above example does not provide an error handler; a default empty
+ * handler is provided which merely logs the error if a failure handler is not 
+ * supplied
+ *
+ */
+
+
+/**
+ * Function: OpenLayers.nullHandler
+ * @param {} request
+ */
+OpenLayers.nullHandler = function(request) {
+    OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText}));
+};
+
+/** 
+ * APIFunction: OpenLayers.loadURL
+ * Background load a document.
+ * *Deprecated*.  Use <OpenLayers.Request.GET> method instead.
+ *
+ * Parameters:
+ * uri - {String} URI of source doc
+ * params - {String} or {Object} GET params. Either a string in the form
+ *     "?hello=world&foo=bar" (do not forget the leading question mark)
+ *     or an object in the form {'hello': 'world', 'foo': 'bar}
+ * caller - {Object} object which gets callbacks
+ * onComplete - {Function} Optional callback for success.  The callback
+ *     will be called with this set to caller and will receive the request
+ *     object as an argument.  Note that if you do not specify an onComplete
+ *     function, <OpenLayers.nullHandler> will be called (which pops up a 
+ *     user friendly error message dialog).
+ * onFailure - {Function} Optional callback for failure.  In the event of
+ *     a failure, the callback will be called with this set to caller and will
+ *     receive the request object as an argument.  Note that if you do not
+ *     specify an onComplete function, <OpenLayers.nullHandler> will be called
+ *     (which pops up a user friendly error message dialog).
+ *
+ * Returns:
+ * {<OpenLayers.Request.XMLHttpRequest>}  The request object. To abort loading,
+ *     call request.abort().
+ */
+OpenLayers.loadURL = function(uri, params, caller,
+                                  onComplete, onFailure) {
+    
+    if(typeof params == 'string') {
+        params = OpenLayers.Util.getParameters(params);
+    }
+    var success = (onComplete) ? onComplete : OpenLayers.nullHandler;
+    var failure = (onFailure) ? onFailure : OpenLayers.nullHandler;
+    
+    return OpenLayers.Request.GET({
+        url: uri, params: params,
+        success: success, failure: failure, scope: caller
+    });
+};
+
+/** 
+ * Function: OpenLayers.parseXMLString
+ * Parse XML into a doc structure
+ * 
+ * Parameters:
+ * text - {String} 
+ * 
+ * Returns:
+ * {?} Parsed AJAX Responsev
+ */
+OpenLayers.parseXMLString = function(text) {
+
+    //MS sucks, if the server is bad it dies
+    var index = text.indexOf('<');
+    if (index > 0) {
+        text = text.substring(index);
+    }
+
+    var ajaxResponse = OpenLayers.Util.Try(
+        function() {
+            var xmldom = new ActiveXObject('Microsoft.XMLDOM');
+            xmldom.loadXML(text);
+            return xmldom;
+        },
+        function() {
+            return new DOMParser().parseFromString(text, 'text/xml');
+        },
+        function() {
+            var req = new XMLHttpRequest();
+            req.open("GET", "data:" + "text/xml" +
+                     ";charset=utf-8," + encodeURIComponent(text), false);
+            if (req.overrideMimeType) {
+                req.overrideMimeType("text/xml");
+            }
+            req.send(null);
+            return req.responseXML;
+        }
+    );
+
+    return ajaxResponse;
+};
+
+
+/**
+ * Namespace: OpenLayers.Ajax
+ */
+OpenLayers.Ajax = {
+
+    /**
+     * Method: emptyFunction
+     */
+    emptyFunction: function () {},
+
+    /**
+     * Method: getTransport
+     * 
+     * Returns: 
+     * {Object} Transport mechanism for whichever browser we're in, or false if
+     *          none available.
+     */
+    getTransport: function() {
+        return OpenLayers.Util.Try(
+            function() {return new XMLHttpRequest();},
+            function() {return new ActiveXObject('Msxml2.XMLHTTP');},
+            function() {return new ActiveXObject('Microsoft.XMLHTTP');}
+        ) || false;
+    },
+
+    /**
+     * Property: activeRequestCount
+     * {Integer}
+     */
+    activeRequestCount: 0
+};
+
+/**
+ * Namespace: OpenLayers.Ajax.Responders
+ * {Object}
+ */
+OpenLayers.Ajax.Responders = {
+  
+    /**
+     * Property: responders
+     * {Array}
+     */
+    responders: [],
+
+    /**
+     * Method: register
+     *  
+     * Parameters:
+     * responderToAdd - {?}
+     */
+    register: function(responderToAdd) {
+        for (var i = 0; i < this.responders.length; i++){
+            if (responderToAdd == this.responders[i]){
+                return;
+            }
+        }
+        this.responders.push(responderToAdd);
+    },
+
+    /**
+     * Method: unregister
+     *  
+     * Parameters:
+     * responderToRemove - {?}
+     */
+    unregister: function(responderToRemove) {
+        OpenLayers.Util.removeItem(this.reponders, responderToRemove);
+    },
+
+    /**
+     * Method: dispatch
+     * 
+     * Parameters:
+     * callback - {?}
+     * request - {?}
+     * transport - {?}
+     */
+    dispatch: function(callback, request, transport) {
+        var responder;
+        for (var i = 0; i < this.responders.length; i++) {
+            responder = this.responders[i];
+     
+            if (responder[callback] && 
+                typeof responder[callback] == 'function') {
+                try {
+                    responder[callback].apply(responder, 
+                                              [request, transport]);
+                } catch (e) {}
+            }
+        }
+    }
+};
+
+OpenLayers.Ajax.Responders.register({
+    /** 
+     * Function: onCreate
+     */
+    onCreate: function() {
+        OpenLayers.Ajax.activeRequestCount++;
+    },
+
+    /**
+     * Function: onComplete
+     */
+     onComplete: function() {
+         OpenLayers.Ajax.activeRequestCount--;
+     }
+});
+
+/**
+ * Class: OpenLayers.Ajax.Base
+ */
+OpenLayers.Ajax.Base = OpenLayers.Class({
+      
+    /**
+     * Constructor: OpenLayers.Ajax.Base
+     * 
+     * Parameters: 
+     * options - {Object}
+     */
+    initialize: function(options) {
+        this.options = {
+            method:       'post',
+            asynchronous: true,
+            contentType:  'application/xml',
+            parameters:   ''
+        };
+        OpenLayers.Util.extend(this.options, options || {});
+        
+        this.options.method = this.options.method.toLowerCase();
+        
+        if (typeof this.options.parameters == 'string') {
+            this.options.parameters = 
+                OpenLayers.Util.getParameters(this.options.parameters);
+        }
+    }
+});
+
+/**
+ * Class: OpenLayers.Ajax.Request
+ * *Deprecated*.  Use <OpenLayers.Request> method instead.
+ *
+ * Inherit:
+ *  - <OpenLayers.Ajax.Base>
+ */
+OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
+
+    /**
+     * Property: _complete
+     *
+     * {Boolean}
+     */
+    _complete: false,
+      
+    /**
+     * Constructor: OpenLayers.Ajax.Request
+     * 
+     * Parameters: 
+     * url - {String}
+     * options - {Object}
+     */
+    initialize: function(url, options) {
+        OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]);
+        
+        if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(url, "http")) {
+            url = OpenLayers.ProxyHost + encodeURIComponent(url);
+        }
+        
+        this.transport = OpenLayers.Ajax.getTransport();
+        this.request(url);
+    },
+
+    /**
+     * Method: request
+     * 
+     * Parameters:
+     * url - {String}
+     */
+    request: function(url) {
+        this.url = url;
+        this.method = this.options.method;
+        var params = OpenLayers.Util.extend({}, this.options.parameters);
+        
+        if (this.method != 'get' && this.method != 'post') {
+            // simulate other verbs over post
+            params['_method'] = this.method;
+            this.method = 'post';
+        }
+
+        this.parameters = params;        
+        
+        if (params = OpenLayers.Util.getParameterString(params)) {
+            // when GET, append parameters to URL
+            if (this.method == 'get') {
+                this.url += ((this.url.indexOf('?') > -1) ? '&' : '?') + params;
+            } else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+                params += '&_=';
+            }
+        }
+        try {
+            var response = new OpenLayers.Ajax.Response(this);
+            if (this.options.onCreate) {
+                this.options.onCreate(response);
+            }
+            
+            OpenLayers.Ajax.Responders.dispatch('onCreate', 
+                                                this, 
+                                                response);
+    
+            this.transport.open(this.method.toUpperCase(), 
+                                this.url,
+                                this.options.asynchronous);
+    
+            if (this.options.asynchronous) {
+                window.setTimeout(
+                    OpenLayers.Function.bind(this.respondToReadyState, this, 1),
+                    10);
+            }
+            
+            this.transport.onreadystatechange = 
+                OpenLayers.Function.bind(this.onStateChange, this);    
+            this.setRequestHeaders();
+    
+            this.body =  this.method == 'post' ?
+                (this.options.postBody || params) : null;
+            this.transport.send(this.body);
+    
+            // Force Firefox to handle ready state 4 for synchronous requests
+            if (!this.options.asynchronous && 
+                this.transport.overrideMimeType) {
+                this.onStateChange();
+            }
+        } catch (e) {
+            this.dispatchException(e);
+        }
+    },
+
+    /**
+     * Method: onStateChange
+     */
+    onStateChange: function() {
+        var readyState = this.transport.readyState;
+        if (readyState > 1 && !((readyState == 4) && this._complete)) {
+            this.respondToReadyState(this.transport.readyState);
+        }
+    },
+     
+    /**
+     * Method: setRequestHeaders
+     */
+    setRequestHeaders: function() {
+        var headers = {
+            'X-Requested-With': 'XMLHttpRequest',
+            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*',
+            'OpenLayers': true
+        };
+
+        if (this.method == 'post') {
+            headers['Content-type'] = this.options.contentType +
+                (this.options.encoding ? '; charset=' + this.options.encoding : '');
+    
+            /* Force "Connection: close" for older Mozilla browsers to work
+             * around a bug where XMLHttpRequest sends an incorrect
+             * Content-length header. See Mozilla Bugzilla #246651.
+             */
+            if (this.transport.overrideMimeType &&
+                (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) {
+                headers['Connection'] = 'close';
+            }
+        }
+        // user-defined headers
+        if (typeof this.options.requestHeaders == 'object') {    
+            var extras = this.options.requestHeaders;
+            
+            if (typeof extras.push == 'function') {
+                for (var i = 0, length = extras.length; i < length; i += 2) {
+                    headers[extras[i]] = extras[i+1];
+                }
+            } else {
+                for (var i in extras) {
+                    headers[i] = extras[i];
+                }
+            }
+        }
+        
+        for (var name in headers) {
+            this.transport.setRequestHeader(name, headers[name]);
+        }
+    },
+    
+    /**
+     * Method: success
+     *
+     * Returns:
+     * {Boolean} - 
+     */
+    success: function() {
+        var status = this.getStatus();
+        return !status || (status >=200 && status < 300);
+    },
+    
+    /**
+     * Method: getStatus
+     *
+     * Returns:
+     * {Integer} - Status
+     */
+    getStatus: function() {
+        try {
+            return this.transport.status || 0;
+        } catch (e) {
+            return 0;
+        }
+    },
+
+    /**
+     * Method: respondToReadyState
+     *
+     * Parameters:
+     * readyState - {?}
+     */
+    respondToReadyState: function(readyState) {
+        var state = OpenLayers.Ajax.Request.Events[readyState];
+        var response = new OpenLayers.Ajax.Response(this);
+    
+        if (state == 'Complete') {
+            try {
+                this._complete = true;
+                (this.options['on' + response.status] ||
+                    this.options['on' + (this.success() ? 'Success' : 'Failure')] ||
+                    OpenLayers.Ajax.emptyFunction)(response);
+            } catch (e) {
+                this.dispatchException(e);
+            }
+    
+            var contentType = response.getHeader('Content-type');
+        }
+    
+        try {
+            (this.options['on' + state] || 
+             OpenLayers.Ajax.emptyFunction)(response);
+             OpenLayers.Ajax.Responders.dispatch('on' + state, 
+                                                 this, 
+                                                 response);
+        } catch (e) {
+            this.dispatchException(e);
+        }
+    
+        if (state == 'Complete') {
+            // avoid memory leak in MSIE: clean up
+            this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction;
+        }
+    },
+    
+    /**
+     * Method: getHeader
+     * 
+     * Parameters:
+     * name - {String} Header name
+     *
+     * Returns:
+     * {?} - response header for the given name
+     */
+    getHeader: function(name) {
+        try {
+            return this.transport.getResponseHeader(name);
+        } catch (e) {
+            return null;
+        }
+    },
+
+    /**
+     * Method: dispatchException
+     * If the optional onException function is set, execute it
+     * and then dispatch the call to any other listener registered
+     * for onException.
+     * 
+     * If no optional onException function is set, we suspect that
+     * the user may have also not used
+     * OpenLayers.Ajax.Responders.register to register a listener
+     * for the onException call.  To make sure that something
+     * gets done with this exception, only dispatch the call if there
+     * are listeners.
+     *
+     * If you explicitly want to swallow exceptions, set
+     * request.options.onException to an empty function (function(){})
+     * or register an empty function with <OpenLayers.Ajax.Responders>
+     * for onException.
+     * 
+     * Parameters:
+     * exception - {?}
+     */
+    dispatchException: function(exception) {
+        var handler = this.options.onException;
+        if(handler) {
+            // call options.onException and alert any other listeners
+            handler(this, exception);
+            OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
+        } else {
+            // check if there are any other listeners
+            var listener = false;
+            var responders = OpenLayers.Ajax.Responders.responders;
+            for (var i = 0; i < responders.length; i++) {
+                if(responders[i].onException) {
+                    listener = true;
+                    break;
+                }
+            }
+            if(listener) {
+                // call all listeners
+                OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
+            } else {
+                // let the exception through
+                throw exception;
+            }
+        }
+    }
+});
+
+/** 
+ * Property: Events
+ * {Array(String)}
+ */
+OpenLayers.Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+/**
+ * Class: OpenLayers.Ajax.Response
+ */
+OpenLayers.Ajax.Response = OpenLayers.Class({
+
+    /**
+     * Property: status
+     *
+     * {Integer}
+     */
+    status: 0,
+    
+
+    /**
+     * Property: statusText
+     *
+     * {String}
+     */
+    statusText: '',
+      
+    /**
+     * Constructor: OpenLayers.Ajax.Response
+     * 
+     * Parameters: 
+     * request - {Object}
+     */
+    initialize: function(request) {
+        this.request = request;
+        var transport = this.transport = request.transport,
+            readyState = this.readyState = transport.readyState;
+        
+        if ((readyState > 2 &&
+            !(!!(window.attachEvent && !window.opera))) ||
+            readyState == 4) {
+            this.status       = this.getStatus();
+            this.statusText   = this.getStatusText();
+            this.responseText = transport.responseText == null ?
+                '' : String(transport.responseText);
+        }
+        
+        if(readyState == 4) {
+            var xml = transport.responseXML;
+            this.responseXML  = xml === undefined ? null : xml;
+        }
+    },
+    
+    /**
+     * Method: getStatus
+     */
+    getStatus: OpenLayers.Ajax.Request.prototype.getStatus,
+    
+    /**
+     * Method: getStatustext
+     *
+     * Returns:
+     * {String} - statusText
+     */
+    getStatusText: function() {
+        try {
+            return this.transport.statusText || '';
+        } catch (e) {
+            return '';
+        }
+    },
+    
+    /**
+     * Method: getHeader
+     */
+    getHeader: OpenLayers.Ajax.Request.prototype.getHeader,
+    
+    /** 
+     * Method: getResponseHeader
+     *
+     * Returns:
+     * {?} - response header for given name
+     */
+    getResponseHeader: function(name) {
+        return this.transport.getResponseHeader(name);
+    }
+});
+
+
+/**
+ * Function: getElementsByTagNameNS
+ * 
+ * Parameters:
+ * parentnode - {?}
+ * nsuri - {?}
+ * nsprefix - {?}
+ * tagname - {?}
+ * 
+ * Returns:
+ * {?}
+ */
+OpenLayers.Ajax.getElementsByTagNameNS  = function(parentnode, nsuri, 
+                                                   nsprefix, tagname) {
+    var elem = null;
+    if (parentnode.getElementsByTagNameNS) {
+        elem = parentnode.getElementsByTagNameNS(nsuri, tagname);
+    } else {
+        elem = parentnode.getElementsByTagName(nsprefix + ':' + tagname);
+    }
+    return elem;
+};
+
+
+/**
+ * Function: serializeXMLToString
+ * Wrapper function around XMLSerializer, which doesn't exist/work in
+ *     IE/Safari. We need to come up with a way to serialize in those browser:
+ *     for now, these browsers will just fail. #535, #536
+ *
+ * Parameters: 
+ * xmldom {XMLNode} xml dom to serialize
+ * 
+ * Returns:
+ * {?}
+ */
+OpenLayers.Ajax.serializeXMLToString = function(xmldom) {
+    var serializer = new XMLSerializer();
+    var data = serializer.serializeToString(xmldom);
+    return data;
+};
+/* ======================================================================
+    OpenLayers/Layer/GeoRSS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Markers.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.GeoRSS
+ * Add GeoRSS Point features to your map. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Markers>
+ *  - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.GeoRSS = OpenLayers.Class(OpenLayers.Layer.Markers, {
+
+    /** 
+     * Property: location 
+     * {String} store url of text file 
+     */
+    location: null,
+
+    /** 
+     * Property: features 
+     * {Array(<OpenLayers.Feature>)} 
+     */
+    features: null,
+    
+    /**
+     * APIProperty: formatOptions
+     * {Object} Hash of options which should be passed to the format when it is
+     * created. Must be passed in the constructor.
+     */
+    formatOptions: null, 
+
+    /** 
+     * Property: selectedFeature 
+     * {<OpenLayers.Feature>} 
+     */
+    selectedFeature: null,
+
+    /** 
+     * APIProperty: icon 
+     * {<OpenLayers.Icon>}. This determines the Icon to be used on the map
+     * for this GeoRSS layer.
+     */
+    icon: null,
+
+    /**
+     * APIProperty: popupSize
+     * {<OpenLayers.Size>} This determines the size of GeoRSS popups. If 
+     * not provided, defaults to 250px by 120px. 
+     */
+    popupSize: null, 
+    
+    /** 
+     * APIProperty: useFeedTitle 
+     * {Boolean} Set layer.name to the first <title> element in the feed. Default is true. 
+     */
+    useFeedTitle: true,
+    
+    /**
+    * Constructor: OpenLayers.Layer.GeoRSS
+    * Create a GeoRSS Layer.
+    *
+    * Parameters:
+    * name - {String} 
+    * location - {String} 
+    * options - {Object}
+    */
+    initialize: function(name, location, options) {
+        OpenLayers.Layer.Markers.prototype.initialize.apply(this, [name, options]);
+        this.location = location;
+        this.features = [];
+    },
+
+    /**
+     * Method: destroy 
+     */
+    destroy: function() {
+        // Warning: Layer.Markers.destroy() must be called prior to calling
+        // clearFeatures() here, otherwise we leak memory. Indeed, if
+        // Layer.Markers.destroy() is called after clearFeatures(), it won't be
+        // able to remove the marker image elements from the layer's div since
+        // the markers will have been destroyed by clearFeatures().
+        OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
+        this.clearFeatures();
+        this.features = null;
+    },
+
+    /**
+     * Method: loadRSS
+     * Start the load of the RSS data. Don't do this when we first add the layer,
+     * since we may not be visible at any point, and it would therefore be a waste.
+     */
+    loadRSS: function() {
+        if (!this.loaded) {
+            this.events.triggerEvent("loadstart");
+            OpenLayers.Request.GET({
+                url: this.location,
+                success: this.parseData,
+                scope: this
+            });
+            this.loaded = true;
+        }    
+    },    
+    
+    /**
+     * Method: moveTo
+     * If layer is visible and RSS has not been loaded, load RSS. 
+     * 
+     * Parameters:
+     * bounds - {Object} 
+     * zoomChanged - {Object} 
+     * minor - {Object} 
+     */
+    moveTo:function(bounds, zoomChanged, minor) {
+        OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
+        if(this.visibility && !this.loaded){
+            this.loadRSS();
+        }
+    },
+        
+    /**
+     * Method: parseData
+     * Parse the data returned from the Events call.
+     *
+     * Parameters:
+     * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>} 
+     */
+    parseData: function(ajaxRequest) {
+        var doc = ajaxRequest.responseXML;
+        if (!doc || !doc.documentElement) {
+            doc = OpenLayers.Format.XML.prototype.read(ajaxRequest.responseText);
+        }
+        
+        if (this.useFeedTitle) {
+            var name = null;
+            try {
+                name = doc.getElementsByTagNameNS('*', 'title')[0].firstChild.nodeValue;
+            }
+            catch (e) {
+                name = doc.getElementsByTagName('title')[0].firstChild.nodeValue;
+            }
+            if (name) {
+                this.setName(name);
+            }    
+        }
+       
+        var options = {};
+        
+        OpenLayers.Util.extend(options, this.formatOptions);
+        
+        if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+            options.externalProjection = this.projection;
+            options.internalProjection = this.map.getProjectionObject();
+        }    
+        
+        var format = new OpenLayers.Format.GeoRSS(options);
+        var features = format.read(doc);
+        
+        for (var i=0, len=features.length; i<len; i++) {
+            var data = {};
+            var feature = features[i];
+            
+            // we don't support features with no geometry in the GeoRSS
+            // layer at this time. 
+            if (!feature.geometry) {
+                continue;
+            }    
+            
+            var title = feature.attributes.title ? 
+                         feature.attributes.title : "Untitled";
+            
+            var description = feature.attributes.description ? 
+                         feature.attributes.description : "No description.";
+            
+            var link = feature.attributes.link ? feature.attributes.link : "";
+
+            var location = feature.geometry.getBounds().getCenterLonLat();
+            
+            
+            data.icon = this.icon == null ? 
+                                     OpenLayers.Marker.defaultIcon() : 
+                                     this.icon.clone();
+            
+            data.popupSize = this.popupSize ? 
+                             this.popupSize.clone() :
+                             new OpenLayers.Size(250, 120);
+            
+            if (title || description) {
+                // we have supplemental data, store them.
+                data.title = title;
+                data.description = description;
+            
+                var contentHTML = '<div class="olLayerGeoRSSClose">[x]</div>'; 
+                contentHTML += '<div class="olLayerGeoRSSTitle">';
+                if (link) {
+                    contentHTML += '<a class="link" href="'+link+'" target="_blank">';
+                }
+                contentHTML += title;
+                if (link) {
+                    contentHTML += '</a>';
+                }
+                contentHTML += '</div>';
+                contentHTML += '<div style="" class="olLayerGeoRSSDescription">';
+                contentHTML += description;
+                contentHTML += '</div>';
+                data['popupContentHTML'] = contentHTML;                
+            }
+            var feature = new OpenLayers.Feature(this, location, data);
+            this.features.push(feature);
+            var marker = feature.createMarker();
+            marker.events.register('click', feature, this.markerClick);
+            this.addMarker(marker);
+        }
+        this.events.triggerEvent("loadend");
+    },
+    
+    /**
+     * Method: markerClick
+     *
+     * Parameters:
+     * evt - {Event} 
+     */
+    markerClick: function(evt) {
+        var sameMarkerClicked = (this == this.layer.selectedFeature);
+        this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
+        for(var i=0, len=this.layer.map.popups.length; i<len; i++) {
+            this.layer.map.removePopup(this.layer.map.popups[i]);
+        }
+        if (!sameMarkerClicked) {
+            var popup = this.createPopup();
+            OpenLayers.Event.observe(popup.div, "click",
+                OpenLayers.Function.bind(function() { 
+                    for(var i=0, len=this.layer.map.popups.length; i<len; i++) { 
+                        this.layer.map.removePopup(this.layer.map.popups[i]); 
+                    }
+                }, this)
+            );
+            this.layer.map.addPopup(popup); 
+        }
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: clearFeatures
+     * Destroy all features in this layer.
+     */
+    clearFeatures: function() {
+        if (this.features != null) {
+            while(this.features.length > 0) {
+                var feature = this.features[0];
+                OpenLayers.Util.removeItem(this.features, feature);
+                feature.destroy();
+            }
+        }        
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.GeoRSS"
+});
+/* ======================================================================
+    OpenLayers/Format/SOSCapabilities.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+ 
+/**
+ * Class: OpenLayers.Format.SOSCapabilities
+ * Read SOS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.SOSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * Constructor: OpenLayers.Format.SOSCapabilities
+     * Create a new parser for SOS Capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return information about
+     * the service (offering and observedProperty mostly).
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Info about the SOS
+     */
+    
+    CLASS_NAME: "OpenLayers.Format.SOSCapabilities" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/KaMap.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.KaMap
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.KaMap = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /** 
+     * APIProperty: isBaseLayer
+     * {Boolean} KaMap Layer is always a base layer 
+     */    
+    isBaseLayer: true,
+
+    /**
+     * APIProperty: units
+     * {?}
+     */    
+    units: null,
+
+    /**
+     * APIProperty: resolution
+     * {Float}
+     */
+    resolution: OpenLayers.DOTS_PER_INCH,
+    
+    /**
+     * Constant: DEFAULT_PARAMS
+     * {Object} parameters set by default. The default parameters set 
+     * the format via the 'i' parameter to 'jpeg'.    
+     */
+    DEFAULT_PARAMS: {
+        i: 'jpeg',
+        map: ''
+    },
+        
+    /**
+     * Constructor: OpenLayers.Layer.KaMap
+     * 
+     * Parameters:
+     * name - {String}
+     * url - {String}
+     * params - {Object} Parameters to be sent to the HTTP server in the
+     *    query string for the tile. The format can be set via the 'i'
+     *    parameter (defaults to jpg) , and the map should be set via 
+     *    the 'map' parameter. It has been reported that ka-Map may behave
+     *    inconsistently if your format parameter does not match the format
+     *    parameter configured in your config.php. (See ticket #327 for more
+     *    information.)
+     * options - {Object} Additional options for the layer. Any of the 
+     *     APIProperties listed on this layer, and any layer types it
+     *     extends, can be overridden through the options parameter. 
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+        this.params = OpenLayers.Util.applyDefaults(
+            this.params, this.DEFAULT_PARAMS
+        );
+    },
+
+    /**
+     * Method: getURL
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * 
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the 
+     *          passed-in bounds and appropriate tile size specified as 
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var mapRes = this.map.getResolution();
+        var scale = Math.round((this.map.getScale() * 10000)) / 10000;
+        var pX = Math.round(bounds.left / mapRes);
+        var pY = -Math.round(bounds.top / mapRes);
+        return this.getFullRequestString(
+                      { t: pY, 
+                        l: pX,
+                        s: scale
+                      });
+    },
+
+    /** 
+     * Method: calculateGridLayout
+     * ka-Map uses the center point of the map as an origin for 
+     * its tiles. Override calculateGridLayout to center tiles 
+     * correctly for this case.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * origin - {<OpenLayers.LonLat>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, origin, resolution) {
+        var tilelon = resolution*this.tileSize.w;
+        var tilelat = resolution*this.tileSize.h;
+        
+        var offsetlon = bounds.left;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = tilecol * tilelon;
+        
+        var offsetlat = bounds.top;  
+        var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = -(tilerowremain+1) * this.tileSize.h;
+        var tileoffsetlat = tilerow * tilelat;
+        
+        return { 
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+    },    
+
+    /**
+     * APIMethod: clone
+     * 
+     * Parameters: 
+     * obj - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.Kamap>} An exact clone of this OpenLayers.Layer.KaMap
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.KaMap(this.name,
+                                            this.url,
+                                            this.params,
+                                            this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        if (this.tileSize != null) {
+            obj.tileSize = this.tileSize.clone();
+        }
+        
+        // we do not want to copy reference to grid, so we make a new array
+        obj.grid = [];
+
+        return obj;
+    },    
+    
+    /**
+     * APIMethod: getTileBounds
+     * Returns The tile bounds for a layer given a pixel location.
+     *
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>} The location in the viewport.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} Bounds of the tile at the given pixel location.
+     */
+    getTileBounds: function(viewPortPx) {
+        var resolution = this.getResolution();
+        var tileMapWidth = resolution * this.tileSize.w;
+        var tileMapHeight = resolution * this.tileSize.h;
+        var mapPoint = this.getLonLatFromViewPortPx(viewPortPx);
+        var tileLeft = tileMapWidth * Math.floor(mapPoint.lon / tileMapWidth);
+        var tileBottom = tileMapHeight * Math.floor(mapPoint.lat / tileMapHeight);
+        return new OpenLayers.Bounds(tileLeft, tileBottom,
+                                     tileLeft + tileMapWidth,
+                                     tileBottom + tileMapHeight);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.KaMap"
+});
+/* ======================================================================
+    OpenLayers/Format/WMC.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/Context.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC
+ * Read and write Web Map Context documents.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMC = OpenLayers.Class(OpenLayers.Format.Context, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.1.0".
+     */
+    defaultVersion: "1.1.0",
+
+    /**
+     * Constructor: OpenLayers.Format.WMC
+     * Create a new parser for Web Map Context documents.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    
+    /**
+     * Method: layerToContext
+     * Create a layer context object given a wms layer object.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Layer.WMS>} The layer.
+     *
+     * Returns:
+     * {Object} A layer context object.
+     */
+    layerToContext: function(layer) {
+        var parser = this.getParser();
+        var layerContext = {
+            queryable: layer.queryable,
+            visibility: layer.visibility,
+            name: layer.params["LAYERS"],
+            title: layer.name,
+            "abstract": layer.metadata["abstract"],
+            dataURL: layer.metadata.dataURL,
+            metadataURL: layer.metadataURL,
+            server: {
+            version: layer.params["VERSION"],
+                url: layer.url
+            },
+            maxExtent: layer.maxExtent,
+            transparent: layer.params["TRANSPARENT"],
+            numZoomLevels: layer.numZoomLevels,
+            units: layer.units,
+            isBaseLayer: layer.isBaseLayer,
+            opacity: layer.opacity,
+            displayInLayerSwitcher: layer.displayInLayerSwitcher,
+            singleTile: layer.singleTile,
+            tileSize: (layer.singleTile || !layer.tileSize) ? 
+                undefined : {width: layer.tileSize.w, height: layer.tileSize.h},
+            minScale : (layer.options.resolutions ||
+                        layer.options.scales || 
+                        layer.options.maxResolution || 
+                        layer.options.minScale) ? 
+                        layer.minScale : undefined,
+            maxScale : (layer.options.resolutions ||
+                        layer.options.scales || 
+                        layer.options.minResolution || 
+                        layer.options.maxScale) ? 
+                        layer.maxScale : undefined,
+            formats: [],
+            styles: [],
+            srs: layer.srs,
+            dimensions: layer.dimensions
+        };
+
+
+        if (layer.metadata.servertitle) {
+            layerContext.server.title = layer.metadata.servertitle;
+        }
+
+        if (layer.metadata.formats && layer.metadata.formats.length > 0) {
+            for (var i=0, len=layer.metadata.formats.length; i<len; i++) {
+                var format = layer.metadata.formats[i];
+                layerContext.formats.push({
+                    value: format.value,
+                    current: (format.value == layer.params["FORMAT"])
+                });
+            }
+        } else {
+            layerContext.formats.push({
+                value: layer.params["FORMAT"],
+                current: true
+            });
+        }
+
+        if (layer.metadata.styles && layer.metadata.styles.length > 0) {
+            for (var i=0, len=layer.metadata.styles.length; i<len; i++) {
+                var style = layer.metadata.styles[i];
+                if ((style.href == layer.params["SLD"]) ||
+                    (style.body == layer.params["SLD_BODY"]) ||
+                    (style.name == layer.params["STYLES"])) {
+                    style.current = true;
+                } else {
+                    style.current = false;
+                }
+                layerContext.styles.push(style);
+            }
+        } else {
+            layerContext.styles.push({
+                href: layer.params["SLD"],
+                body: layer.params["SLD_BODY"],
+                name: layer.params["STYLES"] || parser.defaultStyleName,
+                title: parser.defaultStyleTitle,
+                current: true
+            });
+        }
+
+        return layerContext;
+    },
+    
+    /**
+     * Method: toContext
+     * Create a context object free from layer given a map or a
+     * context object.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Map> | Object} The map or context.
+     *
+     * Returns:
+     * {Object} A context object.
+     */
+    toContext: function(obj) {
+        var context = {};
+        var layers = obj.layers;
+        if (obj.CLASS_NAME == "OpenLayers.Map") {
+            var metadata = obj.metadata || {};
+            context.size = obj.getSize();
+            context.bounds = obj.getExtent();
+            context.projection = obj.projection;
+            context.title = obj.title;
+            context.keywords = metadata.keywords;
+            context["abstract"] = metadata["abstract"];
+            context.logo = metadata.logo;
+            context.descriptionURL = metadata.descriptionURL;
+            context.contactInformation = metadata.contactInformation;
+            context.maxExtent = obj.maxExtent;
+        } else {
+            // copy all obj properties except the "layers" property
+            OpenLayers.Util.applyDefaults(context, obj);
+            if (context.layers != undefined) {
+                delete(context.layers);
+            }
+        }
+
+        if (context.layersContext == undefined) {
+            context.layersContext = [];
+        }
+
+        // let's convert layers into layersContext object (if any)
+        if (layers != undefined && OpenLayers.Util.isArray(layers)) {
+            for (var i=0, len=layers.length; i<len; i++) {
+                var layer = layers[i];
+                if (layer instanceof OpenLayers.Layer.WMS) {
+                    context.layersContext.push(this.layerToContext(layer));
+                }
+            }
+        }
+        return context;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMC" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMC/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC.js
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1
+ * Superclass for WMC version 1 parsers.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMC.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ol: "http://openlayers.org/context",
+        wmc: "http://www.opengis.net/context",
+        sld: "http://www.opengis.net/sld",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+    
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: "",
+
+    /**
+     * Method: getNamespacePrefix
+     * Get the namespace prefix for a given uri from the <namespaces> object.
+     *
+     * Returns:
+     * {String} A namespace prefix or null if none found.
+     */
+    getNamespacePrefix: function(uri) {
+        var prefix = null;
+        if(uri == null) {
+            prefix = this.namespaces[this.defaultPrefix];
+        } else {
+            for(prefix in this.namespaces) {
+                if(this.namespaces[prefix] == uri) {
+                    break;
+                }
+            }
+        }
+        return prefix;
+    },
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "wmc",
+
+    /**
+     * Property: rootPrefix
+     * {String} Prefix on the root node that maps to the context namespace URI.
+     */
+    rootPrefix: null,
+    
+    /**
+     * Property: defaultStyleName
+     * {String} Style name used if layer has no style param.  Default is "".
+     */
+    defaultStyleName: "",
+    
+    /**
+     * Property: defaultStyleTitle
+     * {String} Default style title.  Default is "Default".
+     */
+    defaultStyleTitle: "Default",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMC.v1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.WMC> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Method: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        this.rootPrefix = root.prefix;
+        var context = {
+            version: root.getAttribute("version")
+        };
+        this.runChildNodes(context, root);
+        return context;
+    },
+    
+    /**
+     * Method: runChildNodes
+     */
+    runChildNodes: function(obj, node) {
+        var children = node.childNodes;
+        var childNode, processor, prefix, local;
+        for(var i=0, len=children.length; i<len; ++i) {
+            childNode = children[i];
+            if(childNode.nodeType == 1) {
+                prefix = this.getNamespacePrefix(childNode.namespaceURI);
+                local = childNode.nodeName.split(":").pop();
+                processor = this["read_" + prefix + "_" + local];
+                if(processor) {
+                    processor.apply(this, [obj, childNode]);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: read_wmc_General
+     */
+    read_wmc_General: function(context, node) {
+        this.runChildNodes(context, node);
+    },
+    
+    /**
+     * Method: read_wmc_BoundingBox
+     */
+    read_wmc_BoundingBox: function(context, node) {
+        context.projection = node.getAttribute("SRS");
+        context.bounds = new OpenLayers.Bounds(
+            parseFloat(node.getAttribute("minx")),
+            parseFloat(node.getAttribute("miny")),
+            parseFloat(node.getAttribute("maxx")),
+            parseFloat(node.getAttribute("maxy"))
+        );
+    },
+    
+    /**
+     * Method: read_wmc_LayerList
+     */
+    read_wmc_LayerList: function(context, node) {
+        // layersContext is an array containing info for each layer
+        context.layersContext = [];
+        this.runChildNodes(context, node);
+    },
+    
+    /**
+     * Method: read_wmc_Layer
+     */
+    read_wmc_Layer: function(context, node) {
+        var layerContext = {
+            visibility: (node.getAttribute("hidden") != "1"),
+            queryable: (node.getAttribute("queryable") == "1"),
+            formats: [],
+             styles: [],
+             metadata: {}
+        };
+
+        this.runChildNodes(layerContext, node);
+        // set properties common to multiple objects on layer options/params
+        context.layersContext.push(layerContext);
+    },
+    
+    /**
+     * Method: read_wmc_Extension
+     */
+    read_wmc_Extension: function(obj, node) {
+        this.runChildNodes(obj, node);
+    },
+
+    /**
+     * Method: read_ol_units
+     */
+    read_ol_units: function(layerContext, node) {
+        layerContext.units = this.getChildValue(node);
+    },
+    
+    /**
+     * Method: read_ol_maxExtent
+     */
+    read_ol_maxExtent: function(obj, node) {
+        var bounds = new OpenLayers.Bounds(
+            node.getAttribute("minx"), node.getAttribute("miny"),
+            node.getAttribute("maxx"), node.getAttribute("maxy")
+        );
+        obj.maxExtent = bounds;
+    },
+    
+    /**
+     * Method: read_ol_transparent
+     */
+    read_ol_transparent: function(layerContext, node) {
+        layerContext.transparent = this.getChildValue(node);
+    },
+
+    /**
+     * Method: read_ol_numZoomLevels
+     */
+    read_ol_numZoomLevels: function(layerContext, node) {
+        layerContext.numZoomLevels = parseInt(this.getChildValue(node));
+    },
+
+    /**
+     * Method: read_ol_opacity
+     */
+    read_ol_opacity: function(layerContext, node) {
+        layerContext.opacity = parseFloat(this.getChildValue(node));
+    },
+
+    /**
+     * Method: read_ol_singleTile
+     */
+    read_ol_singleTile: function(layerContext, node) {
+        layerContext.singleTile = (this.getChildValue(node) == "true");
+    },
+
+    /**
+     * Method: read_ol_tileSize
+     */
+    read_ol_tileSize: function(layerContext, node) {
+        var obj = {"width": node.getAttribute("width"), "height": node.getAttribute("height")};
+        layerContext.tileSize = obj;
+    },
+    
+    /**
+     * Method: read_ol_isBaseLayer
+     */
+    read_ol_isBaseLayer: function(layerContext, node) {
+        layerContext.isBaseLayer = (this.getChildValue(node) == "true");
+    },
+
+    /**
+     * Method: read_ol_displayInLayerSwitcher
+     */
+    read_ol_displayInLayerSwitcher: function(layerContext, node) {
+        layerContext.displayInLayerSwitcher = (this.getChildValue(node) == "true");
+    },
+
+    /**
+     * Method: read_wmc_Server
+     */
+    read_wmc_Server: function(layerContext, node) {
+        layerContext.version = node.getAttribute("version");
+         layerContext.url = this.getOnlineResource_href(node);
+         layerContext.metadata.servertitle = node.getAttribute("title");
+    },
+
+    /**
+     * Method: read_wmc_FormatList
+     */
+    read_wmc_FormatList: function(layerContext, node) {
+        this.runChildNodes(layerContext, node);
+    },
+
+    /**
+     * Method: read_wmc_Format
+     */
+    read_wmc_Format: function(layerContext, node) {
+        var format = {
+            value: this.getChildValue(node)
+        };
+        if(node.getAttribute("current") == "1") {
+            format.current = true;
+        }
+        layerContext.formats.push(format);
+    },
+    
+    /**
+     * Method: read_wmc_StyleList
+     */
+    read_wmc_StyleList: function(layerContext, node) {
+        this.runChildNodes(layerContext, node);
+    },
+
+    /**
+     * Method: read_wmc_Style
+     */
+    read_wmc_Style: function(layerContext, node) {
+        var style = {};
+        this.runChildNodes(style, node);
+        if(node.getAttribute("current") == "1") {
+            style.current = true;
+        }
+        layerContext.styles.push(style);
+    },
+    
+    /**
+     * Method: read_wmc_SLD
+     */
+    read_wmc_SLD: function(style, node) {
+        this.runChildNodes(style, node);
+        // style either comes back with an href or a body property
+    },
+    
+    /**
+     * Method: read_sld_StyledLayerDescriptor
+     */
+    read_sld_StyledLayerDescriptor: function(sld, node) {
+        var xml = OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+        sld.body = xml;
+    },
+
+    /**
+      * Method: read_sld_FeatureTypeStyle
+      */
+     read_sld_FeatureTypeStyle: function(sld, node) {
+         var xml = OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+         sld.body = xml;
+     },
+
+     /**
+     * Method: read_wmc_OnlineResource
+     */
+    read_wmc_OnlineResource: function(obj, node) {
+        obj.href = this.getAttributeNS(
+            node, this.namespaces.xlink, "href"
+        );
+    },
+    
+    /**
+     * Method: read_wmc_Name
+     */
+    read_wmc_Name: function(obj, node) {
+        var name = this.getChildValue(node);
+        if(name) {
+            obj.name = name;
+        }
+    },
+
+    /**
+     * Method: read_wmc_Title
+     */
+    read_wmc_Title: function(obj, node) {
+        var title = this.getChildValue(node);
+        if(title) {
+            obj.title = title;
+        }
+    },
+
+    /**
+     * Method: read_wmc_MetadataURL
+     */
+    read_wmc_MetadataURL: function(layerContext, node) {
+         layerContext.metadataURL = this.getOnlineResource_href(node);
+     },
+
+     /**
+      * Method: read_wmc_KeywordList
+      */
+     read_wmc_KeywordList: function(context, node) {
+         context.keywords = [];
+         this.runChildNodes(context.keywords, node);
+    },
+
+    /**
+      * Method: read_wmc_Keyword
+      */
+     read_wmc_Keyword: function(keywords, node) {
+         keywords.push(this.getChildValue(node));
+     },
+
+     /**
+     * Method: read_wmc_Abstract
+     */
+    read_wmc_Abstract: function(obj, node) {
+        var abst = this.getChildValue(node);
+        if(abst) {
+            obj["abstract"] = abst;
+        }
+    },
+    
+    /**
+      * Method: read_wmc_LogoURL
+      */
+     read_wmc_LogoURL: function(context, node) {
+         context.logo = {
+             width:  node.getAttribute("width"),
+             height: node.getAttribute("height"),
+             format: node.getAttribute("format"),
+             href:   this.getOnlineResource_href(node)
+         };
+     },
+
+     /**
+      * Method: read_wmc_DescriptionURL
+      */
+     read_wmc_DescriptionURL: function(context, node) {
+         context.descriptionURL = this.getOnlineResource_href(node);
+     },
+
+     /**
+      * Method: read_wmc_ContactInformation
+     */
+     read_wmc_ContactInformation: function(obj, node) {
+         var contact = {};
+         this.runChildNodes(contact, node);
+         obj.contactInformation = contact;
+     },
+
+     /**
+      * Method: read_wmc_ContactPersonPrimary
+      */
+     read_wmc_ContactPersonPrimary: function(contact, node) {
+         var personPrimary = {};
+         this.runChildNodes(personPrimary, node);
+         contact.personPrimary = personPrimary;
+     },
+
+     /**
+      * Method: read_wmc_ContactPerson
+      */
+     read_wmc_ContactPerson: function(primaryPerson, node) {
+         var person = this.getChildValue(node);
+         if (person) {
+             primaryPerson.person = person;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactOrganization
+      */
+     read_wmc_ContactOrganization: function(primaryPerson, node) {
+         var organization = this.getChildValue(node);
+         if (organization) {
+             primaryPerson.organization = organization;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactPosition
+      */
+     read_wmc_ContactPosition: function(contact, node) {
+         var position = this.getChildValue(node);
+         if (position) {
+             contact.position = position;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactAddress
+      */
+     read_wmc_ContactAddress: function(contact, node) {
+         var contactAddress = {};
+         this.runChildNodes(contactAddress, node);
+         contact.contactAddress = contactAddress;
+     },
+
+     /**
+      * Method: read_wmc_AddressType
+      */
+     read_wmc_AddressType: function(contactAddress, node) {
+         var type = this.getChildValue(node);
+         if (type) {
+             contactAddress.type = type;
+         }
+     },
+
+     /**
+      * Method: read_wmc_Address
+      */
+     read_wmc_Address: function(contactAddress, node) {
+         var address = this.getChildValue(node);
+         if (address) {
+             contactAddress.address = address;
+         }
+     },
+
+     /**
+      * Method: read_wmc_City
+      */
+     read_wmc_City: function(contactAddress, node) {
+         var city = this.getChildValue(node);
+         if (city) {
+             contactAddress.city = city;
+         }
+     },
+
+     /**
+      * Method: read_wmc_StateOrProvince
+      */
+     read_wmc_StateOrProvince: function(contactAddress, node) {
+         var stateOrProvince = this.getChildValue(node);
+         if (stateOrProvince) {
+             contactAddress.stateOrProvince = stateOrProvince;
+         }
+     },
+
+     /**
+      * Method: read_wmc_PostCode
+      */
+     read_wmc_PostCode: function(contactAddress, node) {
+         var postcode = this.getChildValue(node);
+         if (postcode) {
+             contactAddress.postcode = postcode;
+         }
+     },
+
+     /**
+      * Method: read_wmc_Country
+      */
+     read_wmc_Country: function(contactAddress, node) {
+         var country = this.getChildValue(node);
+         if (country) {
+             contactAddress.country = country;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactVoiceTelephone
+      */
+     read_wmc_ContactVoiceTelephone: function(contact, node) {
+         var phone = this.getChildValue(node);
+         if (phone) {
+             contact.phone = phone;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactFacsimileTelephone
+      */
+     read_wmc_ContactFacsimileTelephone: function(contact, node) {
+         var fax = this.getChildValue(node);
+         if (fax) {
+             contact.fax = fax;
+         }
+     },
+
+     /**
+      * Method: read_wmc_ContactElectronicMailAddress
+      */
+     read_wmc_ContactElectronicMailAddress: function(contact, node) {
+         var email = this.getChildValue(node);
+         if (email) {
+             contact.email = email;
+         }
+     },
+
+     /**
+      * Method: read_wmc_DataURL
+      */
+     read_wmc_DataURL: function(layerContext, node) {
+         layerContext.dataURL = this.getOnlineResource_href(node);
+     },
+
+     /**
+     * Method: read_wmc_LegendURL
+     */
+    read_wmc_LegendURL: function(style, node) {
+        var legend = {
+            width: node.getAttribute('width'),
+             height: node.getAttribute('height'),
+             format: node.getAttribute('format'),
+             href:   this.getOnlineResource_href(node)
+        };
+        style.legend = legend;
+    },
+    
+    /**
+      * Method: read_wmc_DimensionList
+      */
+     read_wmc_DimensionList: function(layerContext, node) {
+         layerContext.dimensions = {};
+         this.runChildNodes(layerContext.dimensions, node);
+     },
+     /**
+      * Method: read_wmc_Dimension
+      */
+     read_wmc_Dimension: function(dimensions, node) {
+         var name = node.getAttribute("name").toLowerCase();
+
+         var dim = {
+             name:           name,
+             units:          node.getAttribute("units")          ||  "",
+             unitSymbol:     node.getAttribute("unitSymbol")     ||  "",
+             userValue:      node.getAttribute("userValue")      ||  "",
+             nearestValue:   node.getAttribute("nearestValue")   === "1",
+             multipleValues: node.getAttribute("multipleValues") === "1",
+             current:        node.getAttribute("current")        === "1",
+             "default":      node.getAttribute("default")        ||  ""
+         };
+         var values = this.getChildValue(node);
+         dim.values = values.split(",");
+
+         dimensions[dim.name] = dim;
+     },
+
+     /**
+     * Method: write
+     *
+     * Parameters:
+     * context - {Object} An object representing the map context.
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} A WMC document string.
+     */
+    write: function(context, options) {
+        var root = this.createElementDefaultNS("ViewContext");
+        this.setAttributes(root, {
+            version: this.VERSION,
+            id: (options && typeof options.id == "string") ?
+                    options.id :
+                    OpenLayers.Util.createUniqueID("OpenLayers_Context_")
+        });
+        
+        // add schemaLocation attribute
+        this.setAttributeNS(
+            root, this.namespaces.xsi,
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        
+        // required General element
+        root.appendChild(this.write_wmc_General(context));
+
+        // required LayerList element
+        root.appendChild(this.write_wmc_LayerList(context));
+
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    },
+    
+    /**
+     * Method: createElementDefaultNS
+     * Shorthand for createElementNS with namespace from <defaultPrefix>.
+     *     Can optionally be used to set attributes and a text child value.
+     *
+     * Parameters:
+     * name - {String} The qualified node name.
+     * childValue - {String} Optional value for text child node.
+     * attributes - {Object} Optional object representing attributes.
+     *
+     * Returns:
+     * {Element} An element node.
+     */
+    createElementDefaultNS: function(name, childValue, attributes) {
+        var node = this.createElementNS(
+            this.namespaces[this.defaultPrefix],
+            name
+        );
+        if(childValue) {
+            node.appendChild(this.createTextNode(childValue));
+        }
+        if(attributes) {
+            this.setAttributes(node, attributes);
+        }
+        return node;
+    },
+    
+    /**
+     * Method: setAttributes
+     * Set multiple attributes given key value pairs from an object.
+     *
+     * Parameters:
+     * node - {Element} An element node.
+     * obj - {Object} An object whose properties represent attribute names and
+     *     values represent attribute values.
+     */
+    setAttributes: function(node, obj) {
+        var value;
+        for(var name in obj) {
+            value = obj[name].toString();
+            if(value.match(/[A-Z]/)) {
+                // safari lowercases attributes with setAttribute
+                this.setAttributeNS(node, null, name, value);
+            } else {
+                node.setAttribute(name, value);
+            }
+        }
+    },
+
+    /**
+     * Method: write_wmc_General
+     * Create a General node given an context object.
+     *
+     * Parameters:
+     * context - {Object} Context object.
+     *
+     * Returns:
+     * {Element} A WMC General element node.
+     */
+    write_wmc_General: function(context) {
+        var node = this.createElementDefaultNS("General");
+
+        // optional Window element
+        if(context.size) {
+            node.appendChild(this.createElementDefaultNS(
+                "Window", null,
+                {
+                    width: context.size.w,
+                    height: context.size.h
+                }
+            ));
+        }
+        
+        // required BoundingBox element
+        var bounds = context.bounds;
+        node.appendChild(this.createElementDefaultNS(
+            "BoundingBox", null,
+            {
+                minx: bounds.left.toPrecision(18),
+                miny: bounds.bottom.toPrecision(18),
+                maxx: bounds.right.toPrecision(18),
+                maxy: bounds.top.toPrecision(18),
+                SRS: context.projection
+            }
+        ));
+
+        // required Title element
+        node.appendChild(this.createElementDefaultNS(
+            "Title", context.title
+        ));
+        
+         // optional KeywordList element
+         if (context.keywords) {
+             node.appendChild(this.write_wmc_KeywordList(context.keywords));
+         }
+
+         // optional Abstract element
+         if (context["abstract"]) {
+             node.appendChild(this.createElementDefaultNS(
+                 "Abstract", context["abstract"]
+             ));
+         }
+
+         // Optional LogoURL element
+         if (context.logo) {
+             node.appendChild(this.write_wmc_URLType("LogoURL", context.logo.href, context.logo));
+         }
+
+         // Optional DescriptionURL element
+         if (context.descriptionURL) {
+             node.appendChild(this.write_wmc_URLType("DescriptionURL", context.descriptionURL));
+         }
+
+         // Optional ContactInformation element
+         if (context.contactInformation) {
+             node.appendChild(this.write_wmc_ContactInformation(context.contactInformation));
+         }
+
+        // OpenLayers specific map properties
+        node.appendChild(this.write_ol_MapExtension(context));
+        
+        return node;
+    },
+    
+    /**
+      * Method: write_wmc_KeywordList
+      */
+     write_wmc_KeywordList: function(keywords) {
+         var node = this.createElementDefaultNS("KeywordList");
+
+         for (var i=0, len=keywords.length; i<len; i++) {
+             node.appendChild(this.createElementDefaultNS(
+                 "Keyword", keywords[i]
+             ));
+         }
+         return node;
+     },
+     /**
+      * Method: write_wmc_ContactInformation
+      */
+     write_wmc_ContactInformation: function(contact) {
+         var node = this.createElementDefaultNS("ContactInformation");
+
+         if (contact.personPrimary) {
+             node.appendChild(this.write_wmc_ContactPersonPrimary(contact.personPrimary));
+         }
+         if (contact.position) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactPosition", contact.position
+             ));
+         }
+         if (contact.contactAddress) {
+             node.appendChild(this.write_wmc_ContactAddress(contact.contactAddress));
+         }
+         if (contact.phone) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactVoiceTelephone", contact.phone
+             ));
+         }
+         if (contact.fax) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactFacsimileTelephone", contact.fax
+             ));
+         }
+         if (contact.email) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactElectronicMailAddress", contact.email
+             ));
+         }
+         return node;
+     },
+
+     /**
+      * Method: write_wmc_ContactPersonPrimary
+      */
+     write_wmc_ContactPersonPrimary: function(personPrimary) {
+         var node = this.createElementDefaultNS("ContactPersonPrimary");
+         if (personPrimary.person) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactPerson", personPrimary.person
+             ));
+         }
+         if (personPrimary.organization) {
+             node.appendChild(this.createElementDefaultNS(
+                 "ContactOrganization", personPrimary.organization
+             ));
+         }
+         return node;
+     },
+
+     /**
+      * Method: write_wmc_ContactAddress
+      */
+     write_wmc_ContactAddress: function(contactAddress) {
+         var node = this.createElementDefaultNS("ContactAddress");
+         if (contactAddress.type) {
+             node.appendChild(this.createElementDefaultNS(
+                 "AddressType", contactAddress.type
+             ));
+         }
+         if (contactAddress.address) {
+             node.appendChild(this.createElementDefaultNS(
+                 "Address", contactAddress.address
+             ));
+         }
+         if (contactAddress.city) {
+             node.appendChild(this.createElementDefaultNS(
+                 "City", contactAddress.city
+             ));
+         }
+         if (contactAddress.stateOrProvince) {
+             node.appendChild(this.createElementDefaultNS(
+                 "StateOrProvince", contactAddress.stateOrProvince
+             ));
+         }
+         if (contactAddress.postcode) {
+             node.appendChild(this.createElementDefaultNS(
+                 "PostCode", contactAddress.postcode
+             ));
+         }
+         if (contactAddress.country) {
+             node.appendChild(this.createElementDefaultNS(
+                 "Country", contactAddress.country
+             ));
+         }
+         return node;
+     },
+
+     /**
+     * Method: write_ol_MapExtension
+     */
+    write_ol_MapExtension: function(context) {
+        var node = this.createElementDefaultNS("Extension");
+        
+        var bounds = context.maxExtent;
+        if(bounds) {
+            var maxExtent = this.createElementNS(
+                this.namespaces.ol, "ol:maxExtent"
+            );
+            this.setAttributes(maxExtent, {
+                minx: bounds.left.toPrecision(18),
+                miny: bounds.bottom.toPrecision(18),
+                maxx: bounds.right.toPrecision(18),
+                maxy: bounds.top.toPrecision(18)
+            });
+            node.appendChild(maxExtent);
+        }
+        
+        return node;
+    },
+    
+    /**
+     * Method: write_wmc_LayerList
+     * Create a LayerList node given an context object.
+     *
+     * Parameters:
+     * context - {Object} Context object.
+     *
+     * Returns:
+     * {Element} A WMC LayerList element node.
+     */
+    write_wmc_LayerList: function(context) {
+        var list = this.createElementDefaultNS("LayerList");
+        
+        for(var i=0, len=context.layersContext.length; i<len; ++i) {
+            list.appendChild(this.write_wmc_Layer(context.layersContext[i]));
+        }
+        
+        return list;
+    },
+
+    /**
+     * Method: write_wmc_Layer
+     * Create a Layer node given a layer context object.
+     *
+     * Parameters:
+     * context - {Object} A layer context object.}
+     *
+     * Returns:
+     * {Element} A WMC Layer element node.
+     */
+    write_wmc_Layer: function(context) {
+        var node = this.createElementDefaultNS(
+            "Layer", null, {
+                queryable: context.queryable ? "1" : "0",
+                hidden: context.visibility ? "0" : "1"
+            }
+        );
+        
+        // required Server element
+        node.appendChild(this.write_wmc_Server(context));
+
+        // required Name element
+        node.appendChild(this.createElementDefaultNS(
+            "Name", context.name
+        ));
+        
+        // required Title element
+        node.appendChild(this.createElementDefaultNS(
+            "Title", context.title
+        ));
+
+         // optional Abstract element
+         if (context["abstract"]) {
+             node.appendChild(this.createElementDefaultNS(
+                 "Abstract", context["abstract"]
+             ));
+         }
+
+         // optional DataURL element
+         if (context.dataURL) {
+             node.appendChild(this.write_wmc_URLType("DataURL", context.dataURL));
+         }
+
+        // optional MetadataURL element
+        if (context.metadataURL) {
+             node.appendChild(this.write_wmc_URLType("MetadataURL", context.metadataURL));
+        }
+        
+        return node;
+    },
+    
+    /**
+     * Method: write_wmc_LayerExtension
+     * Add OpenLayers specific layer parameters to an Extension element.
+     *
+     * Parameters:
+     * context - {Object} A layer context object.
+     *
+     * Returns:
+     * {Element} A WMC Extension element (for a layer).
+     */
+    write_wmc_LayerExtension: function(context) {
+        var node = this.createElementDefaultNS("Extension");
+        
+        var bounds = context.maxExtent;
+        var maxExtent = this.createElementNS(
+            this.namespaces.ol, "ol:maxExtent"
+        );
+        this.setAttributes(maxExtent, {
+            minx: bounds.left.toPrecision(18),
+            miny: bounds.bottom.toPrecision(18),
+            maxx: bounds.right.toPrecision(18),
+            maxy: bounds.top.toPrecision(18)
+        });
+        node.appendChild(maxExtent);
+        
+        if (context.tileSize && !context.singleTile) {
+            var size = this.createElementNS(
+                this.namespaces.ol, "ol:tileSize"
+            );
+            this.setAttributes(size, context.tileSize);
+            node.appendChild(size);
+        }
+        
+        var properties = [
+            "transparent", "numZoomLevels", "units", "isBaseLayer",
+            "opacity", "displayInLayerSwitcher", "singleTile"
+        ];
+        var child;
+        for(var i=0, len=properties.length; i<len; ++i) {
+            child = this.createOLPropertyNode(context, properties[i]);
+            if(child) {
+                node.appendChild(child);
+            }
+        }
+
+        return node;
+    },
+    
+    /**
+     * Method: createOLPropertyNode
+     * Create a node representing an OpenLayers property.  If the property is
+     *     null or undefined, null will be returned.
+     *
+     * Parameters:
+     * object - {Object} An object.
+     * prop - {String} A property.
+     *
+     * Returns:
+     * {Element} A property node.
+     */
+    createOLPropertyNode: function(obj, prop) {
+        var node = null;
+        if(obj[prop] != null) {
+            node = this.createElementNS(this.namespaces.ol, "ol:" + prop);
+            node.appendChild(this.createTextNode(obj[prop].toString()));
+        }
+        return node;
+    },
+
+    /**
+     * Method: write_wmc_Server
+     * Create a Server node given a layer context object.
+     *
+     * Parameters:
+     * context - {Object} Layer context object.
+     *
+     * Returns:
+     * {Element} A WMC Server element node.
+     */
+    write_wmc_Server: function(context) {
+         var server = context.server;
+        var node = this.createElementDefaultNS("Server");
+         var attributes = {
+            service: "OGC:WMS",
+             version: server.version
+         };
+         if (server.title) {
+             attributes.title = server.title
+         }
+         this.setAttributes(node, attributes);
+        
+        // required OnlineResource element
+         node.appendChild(this.write_wmc_OnlineResource(server.url));
+        
+        return node;
+    },
+
+    /**
+      * Method: write_wmc_URLType
+      * Create a LogoURL/DescriptionURL/MetadataURL/DataURL/LegendURL node given a object and elementName.
+     *
+     * Parameters:
+      * elName - {String} Name of element (LogoURL/DescriptionURL/MetadataURL/LegendURL)
+      * url - {String} URL string value
+      * attr - {Object} Optional attributes (width, height, format)
+     * Returns:
+      * {Element} A WMC element node.
+     */
+     write_wmc_URLType: function(elName, url, attr) {
+         var node = this.createElementDefaultNS(elName);
+         node.appendChild(this.write_wmc_OnlineResource(url));
+         if (attr) {
+             var optionalAttributes = ["width", "height", "format"];
+             for (var i=0; i<optionalAttributes.length; i++) {
+                 if (optionalAttributes[i] in attr) {
+                     node.setAttribute(optionalAttributes[i], attr[optionalAttributes[i]]);
+                 }
+             }
+         }
+         return node;
+     },
+
+     /**
+      * Method: write_wmc_DimensionList
+      */
+     write_wmc_DimensionList: function(context) {
+         var node = this.createElementDefaultNS("DimensionList");
+         var required_attributes = {
+             name: true,
+             units: true,
+             unitSymbol: true,
+             userValue: true
+         };
+         for (var dim in context.dimensions) {
+             var attributes = {};
+             var dimension = context.dimensions[dim];
+             for (var name in dimension) {
+                 if (typeof dimension[name] == "boolean") {
+                     attributes[name] = Number(dimension[name]);
+                 } else {
+                     attributes[name] = dimension[name];
+                 }
+             }
+             var values = "";
+             if (attributes.values) {
+                 values = attributes.values.join(",");
+                 delete attributes.values;
+             }
+
+             node.appendChild(this.createElementDefaultNS(
+                 "Dimension", values, attributes
+             ));
+         }
+        return node;
+    },
+
+    /**
+     * Method: write_wmc_FormatList
+     * Create a FormatList node given a layer context.
+     *
+     * Parameters:
+     * context - {Object} Layer context object.
+     *
+     * Returns:
+     * {Element} A WMC FormatList element node.
+     */
+    write_wmc_FormatList: function(context) {
+        var node = this.createElementDefaultNS("FormatList");
+        for (var i=0, len=context.formats.length; i<len; i++) {
+            var format = context.formats[i];
+            node.appendChild(this.createElementDefaultNS(
+                "Format",
+                format.value,
+                (format.current && format.current == true) ?
+                    {current: "1"} : null
+            ));
+        }
+
+        return node;
+    },
+
+    /**
+     * Method: write_wmc_StyleList
+     * Create a StyleList node given a layer context.
+     *
+     * Parameters:
+     * context - {Object} Layer context object.
+     *
+     * Returns:
+     * {Element} A WMC StyleList element node.
+     */
+    write_wmc_StyleList: function(layer) {
+        var node = this.createElementDefaultNS("StyleList");
+
+        var styles = layer.styles;
+        if (styles && OpenLayers.Util.isArray(styles)) {
+            var sld;
+            for (var i=0, len=styles.length; i<len; i++) {
+                var s = styles[i];
+                // three style types to consider
+                // [1] linked SLD
+                // [2] inline SLD
+                // [3] named style
+                // running child nodes always gets name, optionally gets href or body
+                var style = this.createElementDefaultNS(
+                    "Style",
+                    null,
+                    (s.current && s.current == true) ?
+                    {current: "1"} : null
+                );
+                if(s.href) { // [1]
+                    sld = this.createElementDefaultNS("SLD");
+                     // Name is optional.
+                     if (s.name) {
+                    sld.appendChild(this.createElementDefaultNS("Name", s.name));
+                     }
+                    // Title is optional.
+                    if (s.title) {
+                        sld.appendChild(this.createElementDefaultNS("Title", s.title));
+                    }
+                     // LegendURL is optional
+                     if (s.legend) {
+                         sld.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+                     }
+
+                     var link = this.write_wmc_OnlineResource(s.href);
+                     sld.appendChild(link);
+                    style.appendChild(sld);
+                } else if(s.body) { // [2]
+                    sld = this.createElementDefaultNS("SLD");
+                     // Name is optional.
+                     if (s.name) {
+                         sld.appendChild(this.createElementDefaultNS("Name", s.name));
+                     }
+                     // Title is optional.
+                     if (s.title) {
+                         sld.appendChild(this.createElementDefaultNS("Title", s.title));
+                     }
+                     // LegendURL is optional
+                     if (s.legend) {
+                         sld.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+                     }
+
+                    // read in body as xml doc - assume proper namespace declarations
+                    var doc = OpenLayers.Format.XML.prototype.read.apply(this, [s.body]);
+                    // append to StyledLayerDescriptor node
+                    var imported = doc.documentElement;
+                    if(sld.ownerDocument && sld.ownerDocument.importNode) {
+                        imported = sld.ownerDocument.importNode(imported, true);
+                    }
+                    sld.appendChild(imported);
+                    style.appendChild(sld);            
+                } else { // [3]
+                    // both Name and Title are required.
+                    style.appendChild(this.createElementDefaultNS("Name", s.name));
+                    style.appendChild(this.createElementDefaultNS("Title", s.title));
+                    // Abstract is optional
+                    if (s['abstract']) { // abstract is a js keyword
+                        style.appendChild(this.createElementDefaultNS(
+                            "Abstract", s['abstract']
+                        ));
+                    }
+                     // LegendURL is optional
+                     if (s.legend) {
+                         style.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+                }
+                 }
+                node.appendChild(style);
+            }
+        }
+
+        return node;
+    },
+
+    /**
+     * Method: write_wmc_OnlineResource
+     * Create an OnlineResource node given a URL.
+     *
+     * Parameters:
+     * href - {String} URL for the resource.
+     *
+     * Returns:
+     * {Element} A WMC OnlineResource element node.
+     */
+    write_wmc_OnlineResource: function(href) {
+        var node = this.createElementDefaultNS("OnlineResource");
+        this.setAttributeNS(node, this.namespaces.xlink, "xlink:type", "simple");
+        this.setAttributeNS(node, this.namespaces.xlink, "xlink:href", href);
+        return node;
+    },
+
+     /**
+      * Method: getOnlineResource_href
+      */
+     getOnlineResource_href: function(node) {
+         var object = {};
+         var links = node.getElementsByTagName("OnlineResource");
+         if(links.length > 0) {
+             this.read_wmc_OnlineResource(object, links[0]);
+         }
+         return object.href;
+     },
+
+
+    CLASS_NAME: "OpenLayers.Format.WMC.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMC/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1_1_0
+ * Read and write WMC version 1.1.0.
+ *
+ * Differences between 1.1.0 and 1.0.0:
+ *     - 1.1.0 Layers have optional sld:MinScaleDenominator and
+ *       sld:MaxScaleDenominator
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMC.v1>
+ */
+OpenLayers.Format.WMC.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.WMC.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.1.0
+     */
+    VERSION: "1.1.0",
+
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/context
+     *     http://schemas.opengis.net/context/1.1.0/context.xsd
+     */
+    schemaLocation: "http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.WMC.v1_1_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.WMC> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMC.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Method: read_sld_MinScaleDenominator
+     * Read a sld:MinScaleDenominator node.
+     *
+     * Parameters:
+     * layerContext - {Object} An object representing a layer.
+     * node - {Element} An element node.
+     */
+    read_sld_MinScaleDenominator: function(layerContext, node) {
+        var minScaleDenominator = parseFloat(this.getChildValue(node));
+        if (minScaleDenominator > 0) {
+            layerContext.maxScale = minScaleDenominator;
+        }
+    },
+
+    /**
+     * Method: read_sld_MaxScaleDenominator
+     * Read a sld:MaxScaleDenominator node.
+     *
+     * Parameters:
+     * layerContext - {Object} An object representing a layer.
+     * node - {Element} An element node.
+     */
+    read_sld_MaxScaleDenominator: function(layerContext, node) {
+        layerContext.minScale = parseFloat(this.getChildValue(node));
+    },
+
+    /**
+     * Method: read_wmc_SRS
+     */
+    read_wmc_SRS: function(layerContext, node) {
+        if (! ("srs" in layerContext)) {
+            layerContext.srs = {};
+        }
+        layerContext.srs[this.getChildValue(node)] = true;
+    },
+
+    /**
+     * Method: write_wmc_Layer
+     * Create a Layer node given a layer context object. This method adds
+     *     elements specific to version 1.1.0.
+     *
+     * Parameters:
+     * context - {Object} A layer context object.}
+     *
+     * Returns:
+     * {Element} A WMC Layer element node.
+     */
+    write_wmc_Layer: function(context) {
+        var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
+            this, [context]
+        );
+        
+        // min/max scale denominator elements go before the 4th element in v1
+        if(context.maxScale) {
+            var minSD = this.createElementNS(
+                this.namespaces.sld, "sld:MinScaleDenominator"
+            );
+            minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));
+            node.appendChild(minSD);
+        }
+        
+        if(context.minScale) {
+            var maxSD = this.createElementNS(
+                this.namespaces.sld, "sld:MaxScaleDenominator"
+            );
+            maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));
+            node.appendChild(maxSD);
+        }
+
+        // optional SRS element(s)
+        if (context.srs) {
+            for(var name in context.srs) {
+                node.appendChild(this.createElementDefaultNS("SRS", name));
+            }
+        }
+
+        // optional FormatList element
+        node.appendChild(this.write_wmc_FormatList(context));
+
+        // optional StyleList element
+        node.appendChild(this.write_wmc_StyleList(context));
+        
+        // optional DimensionList element
+        if (context.dimensions) {
+            node.appendChild(this.write_wmc_DimensionList(context));
+        }
+
+        // OpenLayers specific properties go in an Extension element
+        node.appendChild(this.write_wmc_LayerExtension(context));
+        
+        return node;
+        
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMC.v1_1_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/XLS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS
+ * Read/Wite XLS (OpenLS). Create a new instance with the <OpenLayers.Format.XLS>
+ *     constructor. Currently only implemented for Location Utility Services, more
+ *     specifically only for Geocoding. No support for Reverse Geocoding as yet.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.XLS = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.1.0".
+     */
+    defaultVersion: "1.1.0",
+ 
+    /**
+     * APIProperty: stringifyOutput
+     * {Boolean} If true, write will return a string otherwise a DOMElement.
+     * Default is true.
+     */
+    stringifyOutput: true,
+    
+    /**
+     * Constructor: OpenLayers.Format.XLS
+     * Create a new parser for XLS.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: write
+     * Write out an XLS request.
+     *
+     * Parameters:
+     * request - {Object} An object representing the LUS request.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} An XLS document string.
+     */
+    
+    /**
+     * APIMethod: read
+     * Read an XLS doc and return an object representing the result.
+     *
+     * Parameters:
+     * data - {String | DOMElement} Data to read.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the GeocodeResponse.
+     */
+
+    CLASS_NAME: "OpenLayers.Format.XLS" 
+});
+/* ======================================================================
+    OpenLayers/Format/XLS/v1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XLS.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS.v1
+ * Superclass for XLS version 1 parsers. Only supports GeocodeRequest for now.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.XLS.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xls: "http://www.opengis.net/xls",
+        gml: "http://www.opengis.net/gml",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */
+    xy: true,
+    
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "xls",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location for a particular minor version.
+     */
+    schemaLocation: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.XLS.v1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.XLS> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * Method: read
+     *
+     * Parameters:
+     * data - {DOMElement} An XLS document element.
+     * options - {Object} Options for the reader.
+     *
+     * Returns:
+     * {Object} An object representing the XLSResponse.
+     */
+    read: function(data, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        var xls = {};
+        this.readChildNodes(data, xls);
+        return xls;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "xls": {
+            "XLS": function(node, xls) {
+                xls.version = node.getAttribute("version");
+                this.readChildNodes(node, xls);
+            },
+            "Response": function(node, xls) {
+               this.readChildNodes(node, xls);
+            },
+            "GeocodeResponse": function(node, xls) {
+               xls.responseLists = [];
+               this.readChildNodes(node, xls);
+            },
+            "GeocodeResponseList": function(node, xls) {
+                var responseList = {
+                    features: [], 
+                    numberOfGeocodedAddresses: 
+                        parseInt(node.getAttribute("numberOfGeocodedAddresses"))
+                };
+                xls.responseLists.push(responseList);
+                this.readChildNodes(node, responseList);
+            },
+            "GeocodedAddress": function(node, responseList) {
+                var feature = new OpenLayers.Feature.Vector();
+                responseList.features.push(feature);
+                this.readChildNodes(node, feature);
+                // post-process geometry
+                feature.geometry = feature.components[0];
+            },
+            "GeocodeMatchCode": function(node, feature) {
+                feature.attributes.matchCode = {
+                    accuracy: parseFloat(node.getAttribute("accuracy")),
+                    matchType: node.getAttribute("matchType")
+                };
+            },
+            "Address": function(node, feature) {
+                var address = {
+                    countryCode: node.getAttribute("countryCode"),
+                    addressee: node.getAttribute("addressee"),
+                    street: [],
+                    place: []
+                };
+                feature.attributes.address = address;
+                this.readChildNodes(node, address);
+            },
+            "freeFormAddress": function(node, address) {
+                address.freeFormAddress = this.getChildValue(node);
+            },
+            "StreetAddress": function(node, address) {
+                this.readChildNodes(node, address);
+            },
+            "Building": function(node, address) {
+                address.building = {
+                    'number': node.getAttribute("number"),
+                    subdivision: node.getAttribute("subdivision"),
+                    buildingName: node.getAttribute("buildingName")
+                };
+            },
+            "Street": function(node, address) {
+                // only support the built-in primitive type for now
+                address.street.push(this.getChildValue(node));
+            },
+            "Place": function(node, address) {
+                // type is one of CountrySubdivision, 
+                // CountrySecondarySubdivision, Municipality or
+                // MunicipalitySubdivision
+                address.place[node.getAttribute("type")] = 
+                    this.getChildValue(node);
+            },
+            "PostalCode": function(node, address) {
+                address.postalCode = this.getChildValue(node);
+            }
+        },
+        "gml": OpenLayers.Format.GML.v3.prototype.readers.gml
+    },
+    
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * request - {Object} An object representing the geocode request.
+     *
+     * Returns:
+     * {DOMElement} The root of an XLS document.
+     */
+    write: function(request) {
+        return this.writers.xls.XLS.apply(this, [request]);
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "xls": {
+            "XLS": function(request) {
+                var root = this.createElementNSPlus(
+                    "xls:XLS",
+                    {attributes: {
+                        "version": this.VERSION,
+                        "xsi:schemaLocation": this.schemaLocation
+                    }}
+                );
+                this.writeNode("RequestHeader", request.header, root);
+                this.writeNode("Request", request, root);
+                return root;
+            },
+            "RequestHeader": function(header) {
+                return this.createElementNSPlus("xls:RequestHeader");
+            },
+            "Request": function(request) {
+                var node = this.createElementNSPlus("xls:Request", {
+                    attributes: {
+                        methodName: "GeocodeRequest",
+                        requestID: request.requestID || "",
+                        version: this.VERSION
+                    }
+                });
+                this.writeNode("GeocodeRequest", request.addresses, node);
+                return node;
+            },
+            "GeocodeRequest": function(addresses) {
+                var node = this.createElementNSPlus("xls:GeocodeRequest");
+                for (var i=0, len=addresses.length; i<len; i++) {
+                    this.writeNode("Address", addresses[i], node);
+                }
+                return node;
+            },
+            "Address": function(address) {
+                var node = this.createElementNSPlus("xls:Address", {
+                    attributes: {
+                        countryCode: address.countryCode
+                    }
+                });
+                if (address.freeFormAddress) {
+                    this.writeNode("freeFormAddess", address.freeFormAddress, node);
+                } else {
+                    if (address.street) {
+                        this.writeNode("StreetAddress", address, node);
+                    }
+                    if (address.municipality) {
+                        this.writeNode("Municipality", address.municipality, node);
+                    }
+                    if (address.countrySubdivision) {
+                        this.writeNode("CountrySubdivision", address.countrySubdivision, node);
+                    }
+                    if (address.postalCode) {
+                        this.writeNode("PostalCode", address.postalCode, node);
+                    }
+                }
+                return node;
+            },
+            "freeFormAddress": function(freeFormAddress) {
+                return this.createElementNSPlus("freeFormAddress", 
+                    {value: freeFormAddress});
+            },
+            "StreetAddress": function(address) {
+                var node = this.createElementNSPlus("xls:StreetAddress");
+                if (address.building) {
+                    this.writeNode(node, "Building", address.building);
+                }
+                var street = address.street;
+                if (!(OpenLayers.Util.isArray(street))) {
+                    street = [street];
+                }
+                for (var i=0, len=street.length; i < len; i++) {
+                    this.writeNode("Street", street[i], node);
+                }
+                return node;
+            },
+            "Building": function(building) {
+                return this.createElementNSPlus("xls:Building", {
+                    attributes: {
+                        "number": building["number"],
+                        "subdivision": building.subdivision,
+                        "buildingName": building.buildingName
+                    }
+                });
+            },
+            "Street": function(street) {
+                return this.createElementNSPlus("xls:Street", {value: street});
+            },
+            "Municipality": function(municipality) {
+                return this.createElementNSPlus("xls:Place", {
+                    attributes: {
+                        type: "Municipality"
+                    },
+                    value: municipality
+                });
+            },
+            "CountrySubdivision": function(countrySubdivision) {
+                return this.createElementNSPlus("xls:Place", {
+                    attributes: {
+                        type: "CountrySubdivision"
+                    },
+                    value: countrySubdivision
+                });
+            },
+            "PostalCode": function(postalCode) {
+                return this.createElementNSPlus("xls:PostalCode", {
+                    value: postalCode
+                });
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.XLS.v1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/XLS/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XLS/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS.v1_1_0
+ * Read / write XLS version 1.1.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XLS.v1>
+ */
+OpenLayers.Format.XLS.v1_1_0 = OpenLayers.Class(
+    OpenLayers.Format.XLS.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.1
+     */
+    VERSION: "1.1",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/xls
+     *   http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd
+     */
+    schemaLocation: "http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.XLS.v1_1_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.XLS> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XLS.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    CLASS_NAME: "OpenLayers.Format.XLS.v1_1_0"
+
+});
+
+// Support non standard implementation
+OpenLayers.Format.XLS.v1_1 = OpenLayers.Format.XLS.v1_1_0;
+/* ======================================================================
+    OpenLayers/Renderer/SVG.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer/Elements.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer.SVG
+ * 
+ * Inherits:
+ *  - <OpenLayers.Renderer.Elements>
+ */
+OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
+
+    /** 
+     * Property: xmlns
+     * {String}
+     */
+    xmlns: "http://www.w3.org/2000/svg",
+    
+    /**
+     * Property: xlinkns
+     * {String}
+     */
+    xlinkns: "http://www.w3.org/1999/xlink",
+
+    /**
+     * Constant: MAX_PIXEL
+     * {Integer} Firefox has a limitation where values larger or smaller than  
+     *           about 15000 in an SVG document lock the browser up. This 
+     *           works around it.
+     */
+    MAX_PIXEL: 15000,
+
+    /**
+     * Property: translationParameters
+     * {Object} Hash with "x" and "y" properties
+     */
+    translationParameters: null,
+    
+    /**
+     * Property: symbolMetrics
+     * {Object} Cache for symbol metrics according to their svg coordinate
+     *     space. This is an object keyed by the symbol's id, and values are
+     *     an array of [width, centerX, centerY].
+     */
+    symbolMetrics: null,
+    
+    /**
+     * Constructor: OpenLayers.Renderer.SVG
+     * 
+     * Parameters:
+     * containerID - {String}
+     */
+    initialize: function(containerID) {
+        if (!this.supported()) { 
+            return; 
+        }
+        OpenLayers.Renderer.Elements.prototype.initialize.apply(this, 
+                                                                arguments);
+        this.translationParameters = {x: 0, y: 0};
+        
+        this.symbolMetrics = {};
+    },
+
+    /**
+     * APIMethod: supported
+     * 
+     * Returns:
+     * {Boolean} Whether or not the browser supports the SVG renderer
+     */
+    supported: function() {
+        var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
+        return (document.implementation && 
+           (document.implementation.hasFeature("org.w3c.svg", "1.0") || 
+            document.implementation.hasFeature(svgFeature + "SVG", "1.1") || 
+            document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
+    },    
+
+    /**
+     * Method: inValidRange
+     * See #669 for more information
+     *
+     * Parameters:
+     * x      - {Integer}
+     * y      - {Integer}
+     * xyOnly - {Boolean} whether or not to just check for x and y, which means
+     *     to not take the current translation parameters into account if true.
+     * 
+     * Returns:
+     * {Boolean} Whether or not the 'x' and 'y' coordinates are in the  
+     *           valid range.
+     */ 
+    inValidRange: function(x, y, xyOnly) {
+        var left = x + (xyOnly ? 0 : this.translationParameters.x);
+        var top = y + (xyOnly ? 0 : this.translationParameters.y);
+        return (left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL &&
+                top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL);
+    },
+
+    /**
+     * Method: setExtent
+     * 
+     * Parameters:
+     * extent - {<OpenLayers.Bounds>}
+     * resolutionChanged - {Boolean}
+     * 
+     * Returns:
+     * {Boolean} true to notify the layer that the new extent does not exceed
+     *     the coordinate range, and the features will not need to be redrawn.
+     *     False otherwise.
+     */
+    setExtent: function(extent, resolutionChanged) {
+        OpenLayers.Renderer.Elements.prototype.setExtent.apply(this, 
+                                                               arguments);
+        
+        var resolution = this.getResolution();
+        var left = -extent.left / resolution;
+        var top = extent.top / resolution;
+
+        // If the resolution has changed, start over changing the corner, because
+        // the features will redraw.
+        if (resolutionChanged) {
+            this.left = left;
+            this.top = top;
+            // Set the viewbox
+            var extentString = "0 0 " + this.size.w + " " + this.size.h;
+
+            this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
+            this.translate(0, 0);
+            return true;
+        } else {
+            var inRange = this.translate(left - this.left, top - this.top);
+            if (!inRange) {
+                // recenter the coordinate system
+                this.setExtent(extent, true);
+            }
+            return inRange;
+        }
+    },
+    
+    /**
+     * Method: translate
+     * Transforms the SVG coordinate system
+     * 
+     * Parameters:
+     * x - {Float}
+     * y - {Float}
+     * 
+     * Returns:
+     * {Boolean} true if the translation parameters are in the valid coordinates
+     *     range, false otherwise.
+     */
+    translate: function(x, y) {
+        if (!this.inValidRange(x, y, true)) {
+            return false;
+        } else {
+            var transformString = "";
+            if (x || y) {
+                transformString = "translate(" + x + "," + y + ")";
+            }
+            this.root.setAttributeNS(null, "transform", transformString);
+            this.translationParameters = {x: x, y: y};
+            return true;
+        }
+    },
+
+    /**
+     * Method: setSize
+     * Sets the size of the drawing surface.
+     * 
+     * Parameters:
+     * size - {<OpenLayers.Size>} The size of the drawing surface
+     */
+    setSize: function(size) {
+        OpenLayers.Renderer.prototype.setSize.apply(this, arguments);
+        
+        this.rendererRoot.setAttributeNS(null, "width", this.size.w);
+        this.rendererRoot.setAttributeNS(null, "height", this.size.h);
+    },
+
+    /** 
+     * Method: getNodeType 
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     * 
+     * Returns:
+     * {String} The corresponding node type for the specified geometry
+     */
+    getNodeType: function(geometry, style) {
+        var nodeType = null;
+        switch (geometry.CLASS_NAME) {
+            case "OpenLayers.Geometry.Point":
+                if (style.externalGraphic) {
+                    nodeType = "image";
+                } else if (this.isComplexSymbol(style.graphicName)) {
+                    nodeType = "svg";
+                } else {
+                    nodeType = "circle";
+                }
+                break;
+            case "OpenLayers.Geometry.Rectangle":
+                nodeType = "rect";
+                break;
+            case "OpenLayers.Geometry.LineString":
+                nodeType = "polyline";
+                break;
+            case "OpenLayers.Geometry.LinearRing":
+                nodeType = "polygon";
+                break;
+            case "OpenLayers.Geometry.Polygon":
+            case "OpenLayers.Geometry.Curve":
+            case "OpenLayers.Geometry.Surface":
+                nodeType = "path";
+                break;
+            default:
+                break;
+        }
+        return nodeType;
+    },
+
+    /** 
+     * Method: setStyle
+     * Use to set all the style attributes to a SVG node.
+     * 
+     * Takes care to adjust stroke width and point radius to be
+     * resolution-relative
+     *
+     * Parameters:
+     * node - {SVGDomElement} An SVG element to decorate
+     * style - {Object}
+     * options - {Object} Currently supported options include 
+     *                              'isFilled' {Boolean} and
+     *                              'isStroked' {Boolean}
+     */
+    setStyle: function(node, style, options) {
+        style = style  || node._style;
+        options = options || node._options;
+        var r = parseFloat(node.getAttributeNS(null, "r"));
+        var widthFactor = 1;
+        var pos;
+        if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
+            node.style.visibility = "";
+            if (style.graphic === false) {
+                node.style.visibility = "hidden";
+            } else if (style.externalGraphic) {
+                pos = this.getPosition(node);
+                
+                if (style.graphicTitle) {
+                    node.setAttributeNS(null, "title", style.graphicTitle);
+                    //Standards-conformant SVG
+                    var label = this.nodeFactory(null, "title");
+                    label.textContent = style.graphicTitle;
+                    node.appendChild(label);
+                }
+                if (style.graphicWidth && style.graphicHeight) {
+                  node.setAttributeNS(null, "preserveAspectRatio", "none");
+                }
+                var width = style.graphicWidth || style.graphicHeight;
+                var height = style.graphicHeight || style.graphicWidth;
+                width = width ? width : style.pointRadius*2;
+                height = height ? height : style.pointRadius*2;
+                var xOffset = (style.graphicXOffset != undefined) ?
+                    style.graphicXOffset : -(0.5 * width);
+                var yOffset = (style.graphicYOffset != undefined) ?
+                    style.graphicYOffset : -(0.5 * height);
+
+                var opacity = style.graphicOpacity || style.fillOpacity;
+                
+                node.setAttributeNS(null, "x", (pos.x + xOffset).toFixed());
+                node.setAttributeNS(null, "y", (pos.y + yOffset).toFixed());
+                node.setAttributeNS(null, "width", width);
+                node.setAttributeNS(null, "height", height);
+                node.setAttributeNS(this.xlinkns, "href", style.externalGraphic);
+                node.setAttributeNS(null, "style", "opacity: "+opacity);
+                node.onclick = OpenLayers.Renderer.SVG.preventDefault;
+            } else if (this.isComplexSymbol(style.graphicName)) {
+                // the symbol viewBox is three times as large as the symbol
+                var offset = style.pointRadius * 3;
+                var size = offset * 2;
+                var src = this.importSymbol(style.graphicName);
+                pos = this.getPosition(node);
+                widthFactor = this.symbolMetrics[src.id][0] * 3 / size;
+                
+                // remove the node from the dom before we modify it. This
+                // prevents various rendering issues in Safari and FF
+                var parent = node.parentNode;
+                var nextSibling = node.nextSibling;
+                if(parent) {
+                    parent.removeChild(node);
+                }
+                
+                // The more appropriate way to implement this would be use/defs,
+                // but due to various issues in several browsers, it is safer to
+                // copy the symbols instead of referencing them. 
+                // See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985 
+                // and this email thread
+                // http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html
+                node.firstChild && node.removeChild(node.firstChild);
+                node.appendChild(src.firstChild.cloneNode(true));
+                node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox"));
+                
+                node.setAttributeNS(null, "width", size);
+                node.setAttributeNS(null, "height", size);
+                node.setAttributeNS(null, "x", pos.x - offset);
+                node.setAttributeNS(null, "y", pos.y - offset);
+                
+                // now that the node has all its new properties, insert it
+                // back into the dom where it was
+                if(nextSibling) {
+                    parent.insertBefore(node, nextSibling);
+                } else if(parent) {
+                    parent.appendChild(node);
+                }
+            } else {
+                node.setAttributeNS(null, "r", style.pointRadius);
+            }
+
+            var rotation = style.rotation;
+            
+            if ((rotation !== undefined || node._rotation !== undefined) && pos) {
+                node._rotation = rotation;
+                rotation |= 0;
+                if (node.nodeName !== "svg") { 
+                    node.setAttributeNS(null, "transform", 
+                        "rotate(" + rotation + " " + pos.x + " " + 
+                        pos.y + ")"); 
+                } else {
+                    var metrics = this.symbolMetrics[src.id];
+                    node.firstChild.setAttributeNS(null, "transform", "rotate(" 
+                        + rotation + " " 
+                        + metrics[1] + " "
+                        + metrics[2] + ")");
+                }
+            }
+        }
+        
+        if (options.isFilled) {
+            node.setAttributeNS(null, "fill", style.fillColor);
+            node.setAttributeNS(null, "fill-opacity", style.fillOpacity);
+        } else {
+            node.setAttributeNS(null, "fill", "none");
+        }
+
+        if (options.isStroked) {
+            node.setAttributeNS(null, "stroke", style.strokeColor);
+            node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
+            node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
+            node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
+            // Hard-coded linejoin for now, to make it look the same as in VML.
+            // There is no strokeLinejoin property yet for symbolizers.
+            node.setAttributeNS(null, "stroke-linejoin", "round");
+            style.strokeDashstyle && node.setAttributeNS(null,
+                "stroke-dasharray", this.dashStyle(style, widthFactor));
+        } else {
+            node.setAttributeNS(null, "stroke", "none");
+        }
+        
+        if (style.pointerEvents) {
+            node.setAttributeNS(null, "pointer-events", style.pointerEvents);
+        }
+                
+        if (style.cursor != null) {
+            node.setAttributeNS(null, "cursor", style.cursor);
+        }
+        
+        return node;
+    },
+
+    /** 
+     * Method: dashStyle
+     * 
+     * Parameters:
+     * style - {Object}
+     * widthFactor - {Number}
+     * 
+     * Returns:
+     * {String} A SVG compliant 'stroke-dasharray' value
+     */
+    dashStyle: function(style, widthFactor) {
+        var w = style.strokeWidth * widthFactor;
+        var str = style.strokeDashstyle;
+        switch (str) {
+            case 'solid':
+                return 'none';
+            case 'dot':
+                return [1, 4 * w].join();
+            case 'dash':
+                return [4 * w, 4 * w].join();
+            case 'dashdot':
+                return [4 * w, 4 * w, 1, 4 * w].join();
+            case 'longdash':
+                return [8 * w, 4 * w].join();
+            case 'longdashdot':
+                return [8 * w, 4 * w, 1, 4 * w].join();
+            default:
+                return OpenLayers.String.trim(str).replace(/\s+/g, ",");
+        }
+    },
+    
+    /** 
+     * Method: createNode
+     * 
+     * Parameters:
+     * type - {String} Kind of node to draw
+     * id - {String} Id for node
+     * 
+     * Returns:
+     * {DOMElement} A new node of the given type and id
+     */
+    createNode: function(type, id) {
+        var node = document.createElementNS(this.xmlns, type);
+        if (id) {
+            node.setAttributeNS(null, "id", id);
+        }
+        return node;    
+    },
+    
+    /** 
+     * Method: nodeTypeCompare
+     * 
+     * Parameters:
+     * node - {SVGDomElement} An SVG element
+     * type - {String} Kind of node
+     * 
+     * Returns:
+     * {Boolean} Whether or not the specified node is of the specified type
+     */
+    nodeTypeCompare: function(node, type) {
+        return (type == node.nodeName);
+    },
+   
+    /**
+     * Method: createRenderRoot
+     * 
+     * Returns:
+     * {DOMElement} The specific render engine's root element
+     */
+    createRenderRoot: function() {
+        return this.nodeFactory(this.container.id + "_svgRoot", "svg");
+    },
+
+    /**
+     * Method: createRoot
+     * 
+     * Parameter:
+     * suffix - {String} suffix to append to the id
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    createRoot: function(suffix) {
+        return this.nodeFactory(this.container.id + suffix, "g");
+    },
+
+    /**
+     * Method: createDefs
+     *
+     * Returns:
+     * {DOMElement} The element to which we'll add the symbol definitions
+     */
+    createDefs: function() {
+        var defs = this.nodeFactory(this.container.id + "_defs", "defs");
+        this.rendererRoot.appendChild(defs);
+        return defs;
+    },
+
+    /**************************************
+     *                                    *
+     *     GEOMETRY DRAWING FUNCTIONS     *
+     *                                    *
+     **************************************/
+
+    /**
+     * Method: drawPoint
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the point
+     */ 
+    drawPoint: function(node, geometry) {
+        return this.drawCircle(node, geometry, 1);
+    },
+
+    /**
+     * Method: drawCircle
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * radius - {Float}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the circle
+     */
+    drawCircle: function(node, geometry, radius) {
+        var resolution = this.getResolution();
+        var x = (geometry.x / resolution + this.left);
+        var y = (this.top - geometry.y / resolution);
+
+        if (this.inValidRange(x, y)) { 
+            node.setAttributeNS(null, "cx", x);
+            node.setAttributeNS(null, "cy", y);
+            node.setAttributeNS(null, "r", radius);
+            return node;
+        } else {
+            return false;
+        }    
+            
+    },
+    
+    /**
+     * Method: drawLineString
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components of
+     *     the linestring, or false if nothing could be drawn
+     */ 
+    drawLineString: function(node, geometry) {
+        var componentsResult = this.getComponentsString(geometry.components);
+        if (componentsResult.path) {
+            node.setAttributeNS(null, "points", componentsResult.path);
+            return (componentsResult.complete ? node : null);  
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: drawLinearRing
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the linear ring, or false if nothing could be drawn
+     */ 
+    drawLinearRing: function(node, geometry) {
+        var componentsResult = this.getComponentsString(geometry.components);
+        if (componentsResult.path) {
+            node.setAttributeNS(null, "points", componentsResult.path);
+            return (componentsResult.complete ? node : null);  
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: drawPolygon
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or null if the renderer could not draw all components
+     *     of the polygon, or false if nothing could be drawn
+     */ 
+    drawPolygon: function(node, geometry) {
+        var d = "";
+        var draw = true;
+        var complete = true;
+        var linearRingResult, path;
+        for (var j=0, len=geometry.components.length; j<len; j++) {
+            d += " M";
+            linearRingResult = this.getComponentsString(
+                geometry.components[j].components, " ");
+            path = linearRingResult.path;
+            if (path) {
+                d += " " + path;
+                complete = linearRingResult.complete && complete;
+            } else {
+                draw = false;
+            }
+        }
+        d += " z";
+        if (draw) {
+            node.setAttributeNS(null, "d", d);
+            node.setAttributeNS(null, "fill-rule", "evenodd");
+            return complete ? node : null;
+        } else {
+            return false;
+        }    
+    },
+    
+    /**
+     * Method: drawRectangle
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the rectangle
+     */ 
+    drawRectangle: function(node, geometry) {
+        var resolution = this.getResolution();
+        var x = (geometry.x / resolution + this.left);
+        var y = (this.top - geometry.y / resolution);
+
+        if (this.inValidRange(x, y)) { 
+            node.setAttributeNS(null, "x", x);
+            node.setAttributeNS(null, "y", y);
+            node.setAttributeNS(null, "width", geometry.width / resolution);
+            node.setAttributeNS(null, "height", geometry.height / resolution);
+            return node;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: drawSurface
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the renderer could not draw the surface
+     */ 
+    drawSurface: function(node, geometry) {
+
+        // create the svg path string representation
+        var d = null;
+        var draw = true;
+        for (var i=0, len=geometry.components.length; i<len; i++) {
+            if ((i%3) == 0 && (i/3) == 0) {
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d = "M " + component;
+            } else if ((i%3) == 1) {
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " C " + component;
+            } else {
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " " + component;
+            }
+        }
+        d += " Z";
+        if (draw) {
+            node.setAttributeNS(null, "d", d);
+            return node;
+        } else {
+            return false;
+        }    
+    },
+    
+    /**
+     * Method: drawText
+     * This method is only called by the renderer itself.
+     *
+     * Parameters:
+     * featureId - {String}
+     * style -
+     * location - {<OpenLayers.Geometry.Point>}
+     */
+    drawText: function(featureId, style, location) {
+        var resolution = this.getResolution();
+
+        var x = (location.x / resolution + this.left);
+        var y = (location.y / resolution - this.top);
+
+        var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "text");
+
+        label.setAttributeNS(null, "x", x);
+        label.setAttributeNS(null, "y", -y);
+
+        if (style.fontColor) {
+            label.setAttributeNS(null, "fill", style.fontColor);
+        }
+        if (style.fontOpacity) {
+            label.setAttributeNS(null, "opacity", style.fontOpacity);
+        }
+        if (style.fontFamily) {
+            label.setAttributeNS(null, "font-family", style.fontFamily);
+        }
+        if (style.fontSize) {
+            label.setAttributeNS(null, "font-size", style.fontSize);
+        }
+        if (style.fontWeight) {
+            label.setAttributeNS(null, "font-weight", style.fontWeight);
+        }
+        if (style.fontStyle) {
+            label.setAttributeNS(null, "font-style", style.fontStyle);
+        }
+        if (style.labelSelect === true) {
+            label.setAttributeNS(null, "pointer-events", "visible");
+            label._featureId = featureId;
+        } else {
+            label.setAttributeNS(null, "pointer-events", "none");
+        }
+        var align = style.labelAlign || "cm";
+        label.setAttributeNS(null, "text-anchor",
+            OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]] || "middle");
+
+        if (OpenLayers.IS_GECKO === true) {
+            label.setAttributeNS(null, "dominant-baseline",
+                OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]] || "central");
+        }
+
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
+        while (label.childNodes.length > numRows) {
+            label.removeChild(label.lastChild);
+        }
+        for (var i = 0; i < numRows; i++) {
+            var tspan = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan");
+            if (style.labelSelect === true) {
+                tspan._featureId = featureId;
+                tspan._geometry = location;
+                tspan._geometryClass = location.CLASS_NAME;
+            }
+            if (OpenLayers.IS_GECKO === false) {
+                tspan.setAttributeNS(null, "baseline-shift",
+                    OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]] || "-35%");
+            }
+            tspan.setAttribute("x", x);
+            if (i == 0) {
+                var vfactor = OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]];
+                if (vfactor == null) {
+                     vfactor = -.5;
+                }
+                tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em");
+            } else {
+                tspan.setAttribute("dy", "1em");
+            }
+            tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i];
+            if (!tspan.parentNode) {
+                label.appendChild(tspan);
+            }
+        }
+
+        if (!label.parentNode) {
+            this.textRoot.appendChild(label);
+        }
+    },
+    
+    /** 
+     * Method: getComponentString
+     * 
+     * Parameters:
+     * components - {Array(<OpenLayers.Geometry.Point>)} Array of points
+     * separator - {String} character between coordinate pairs. Defaults to ","
+     * 
+     * Returns:
+     * {Object} hash with properties "path" (the string created from the
+     *     components and "complete" (false if the renderer was unable to
+     *     draw all components)
+     */
+    getComponentsString: function(components, separator) {
+        var renderCmp = [];
+        var complete = true;
+        var len = components.length;
+        var strings = [];
+        var str, component;
+        for(var i=0; i<len; i++) {
+            component = components[i];
+            renderCmp.push(component);
+            str = this.getShortString(component);
+            if (str) {
+                strings.push(str);
+            } else {
+                // The current component is outside the valid range. Let's
+                // see if the previous or next component is inside the range.
+                // If so, add the coordinate of the intersection with the
+                // valid range bounds.
+                if (i > 0) {
+                    if (this.getShortString(components[i - 1])) {
+                        strings.push(this.clipLine(components[i],
+                            components[i-1]));
+                    }
+                }
+                if (i < len - 1) {
+                    if (this.getShortString(components[i + 1])) {
+                        strings.push(this.clipLine(components[i],
+                            components[i+1]));
+                    }
+                }
+                complete = false;
+            }
+        }
+
+        return {
+            path: strings.join(separator || ","),
+            complete: complete
+        };
+    },
+    
+    /**
+     * Method: clipLine
+     * Given two points (one inside the valid range, and one outside),
+     * clips the line betweeen the two points so that the new points are both
+     * inside the valid range.
+     * 
+     * Parameters:
+     * badComponent - {<OpenLayers.Geometry.Point>} original geometry of the
+     *     invalid point
+     * goodComponent - {<OpenLayers.Geometry.Point>} original geometry of the
+     *     valid point
+     * Returns
+     * {String} the SVG coordinate pair of the clipped point (like
+     *     getShortString), or an empty string if both passed componets are at
+     *     the same point.
+     */
+    clipLine: function(badComponent, goodComponent) {
+        if (goodComponent.equals(badComponent)) {
+            return "";
+        }
+        var resolution = this.getResolution();
+        var maxX = this.MAX_PIXEL - this.translationParameters.x;
+        var maxY = this.MAX_PIXEL - this.translationParameters.y;
+        var x1 = goodComponent.x / resolution + this.left;
+        var y1 = this.top - goodComponent.y / resolution;
+        var x2 = badComponent.x / resolution + this.left;
+        var y2 = this.top - badComponent.y / resolution;
+        var k;
+        if (x2 < -maxX || x2 > maxX) {
+            k = (y2 - y1) / (x2 - x1);
+            x2 = x2 < 0 ? -maxX : maxX;
+            y2 = y1 + (x2 - x1) * k;
+        }
+        if (y2 < -maxY || y2 > maxY) {
+            k = (x2 - x1) / (y2 - y1);
+            y2 = y2 < 0 ? -maxY : maxY;
+            x2 = x1 + (y2 - y1) * k;
+        }
+        return x2 + "," + y2;
+    },
+
+    /** 
+     * Method: getShortString
+     * 
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     * 
+     * Returns:
+     * {String} or false if point is outside the valid range
+     */
+    getShortString: function(point) {
+        var resolution = this.getResolution();
+        var x = (point.x / resolution + this.left);
+        var y = (this.top - point.y / resolution);
+
+        if (this.inValidRange(x, y)) { 
+            return x + "," + y;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: getPosition
+     * Finds the position of an svg node.
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * 
+     * Returns:
+     * {Object} hash with x and y properties, representing the coordinates
+     *     within the svg coordinate system
+     */
+    getPosition: function(node) {
+        return({
+            x: parseFloat(node.getAttributeNS(null, "cx")),
+            y: parseFloat(node.getAttributeNS(null, "cy"))
+        });
+    },
+
+    /**
+     * Method: importSymbol
+     * add a new symbol definition from the rendererer's symbol hash
+     * 
+     * Parameters:
+     * graphicName - {String} name of the symbol to import
+     * 
+     * Returns:
+     * {DOMElement} - the imported symbol
+     */      
+    importSymbol: function (graphicName)  {
+        if (!this.defs) {
+            // create svg defs tag
+            this.defs = this.createDefs();
+        }
+        var id = this.container.id + "-" + graphicName;
+        
+        // check if symbol already exists in the defs
+        var existing = document.getElementById(id)
+        if (existing != null) {
+            return existing;
+        }
+        
+        var symbol = OpenLayers.Renderer.symbol[graphicName];
+        if (!symbol) {
+            throw new Error(graphicName + ' is not a valid symbol name');
+        }
+
+        var symbolNode = this.nodeFactory(id, "symbol");
+        var node = this.nodeFactory(null, "polygon");
+        symbolNode.appendChild(node);
+        var symbolExtent = new OpenLayers.Bounds(
+                                    Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
+
+        var points = [];
+        var x,y;
+        for (var i=0; i<symbol.length; i=i+2) {
+            x = symbol[i];
+            y = symbol[i+1];
+            symbolExtent.left = Math.min(symbolExtent.left, x);
+            symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
+            symbolExtent.right = Math.max(symbolExtent.right, x);
+            symbolExtent.top = Math.max(symbolExtent.top, y);
+            points.push(x, ",", y);
+        }
+        
+        node.setAttributeNS(null, "points", points.join(" "));
+        
+        var width = symbolExtent.getWidth();
+        var height = symbolExtent.getHeight();
+        // create a viewBox three times as large as the symbol itself,
+        // to allow for strokeWidth being displayed correctly at the corners.
+        var viewBox = [symbolExtent.left - width,
+                        symbolExtent.bottom - height, width * 3, height * 3];
+        symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" "));
+        this.symbolMetrics[id] = [
+            Math.max(width, height),
+            symbolExtent.getCenterLonLat().lon,
+            symbolExtent.getCenterLonLat().lat
+        ];
+        
+        this.defs.appendChild(symbolNode);
+        return symbolNode;
+    },
+    
+    /**
+     * Method: getFeatureIdFromEvent
+     * 
+     * Parameters:
+     * evt - {Object} An <OpenLayers.Event> object
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>} A geometry from an event that 
+     *     happened on a layer.
+     */
+    getFeatureIdFromEvent: function(evt) {
+        var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
+        if(!featureId) {
+            var target = evt.target;
+            featureId = target.parentNode && target != this.rendererRoot &&
+                target.parentNode._featureId;
+        }
+        return featureId;
+    },
+
+    CLASS_NAME: "OpenLayers.Renderer.SVG"
+});
+
+/**
+ * Constant: OpenLayers.Renderer.SVG.LABEL_ALIGN
+ * {Object}
+ */
+OpenLayers.Renderer.SVG.LABEL_ALIGN = {
+    "l": "start",
+    "r": "end",
+    "b": "bottom",
+    "t": "hanging"
+};
+
+/**
+ * Constant: OpenLayers.Renderer.SVG.LABEL_VSHIFT
+ * {Object}
+ */
+OpenLayers.Renderer.SVG.LABEL_VSHIFT = {
+    // according to
+    // http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html
+    // a baseline-shift of -70% shifts the text exactly from the
+    // bottom to the top of the baseline, so -35% moves the text to
+    // the center of the baseline.
+    "t": "-70%",
+    "b": "0"    
+};
+
+/**
+ * Constant: OpenLayers.Renderer.SVG.LABEL_VFACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.SVG.LABEL_VFACTOR = {
+    "t": 0,
+    "b": -1
+};
+
+/**
+ * Function: OpenLayers.Renderer.SVG.preventDefault
+ * Used to prevent default events (especially opening images in a new tab on
+ * ctrl-click) from being executed for externalGraphic symbols
+ */
+OpenLayers.Renderer.SVG.preventDefault = function(e) {
+    e.preventDefault && e.preventDefault();
+};
+/* ======================================================================
+    OpenLayers/Format/WMSDescribeLayer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSDescribeLayer
+ * Read SLD WMS DescribeLayer response
+ * DescribeLayer is meant to couple WMS to WFS and WCS
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMSDescribeLayer = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.1.1".
+     */
+    defaultVersion: "1.1.1",
+   
+    /**
+     * Method: getVersion
+     * Returns the version to use. Subclasses can override this function
+     * if a different version detection is needed.
+     *
+     * Parameters:
+     * root - {DOMElement}
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} The version to use.
+     */
+    getVersion: function(root, options) {
+        var version = OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(
+            this, arguments);
+        // these are identical to us, but some WMS use 1.1.1 and some use 1.1.0
+        if (version == "1.1.1" || version == "1.1.0") {
+            version = "1.1";
+        }
+        return version;
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.WMSDescribeLayer
+     * Create a new parser for WMS DescribeLayer responses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read DescribeLayer data from a string, and return the response. 
+     * The OGC currently defines 2 formats which are allowed for output,
+     * so we need to parse these 2 types
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} Array of {<LayerDescription>} objects which have:
+     * - {String} owsType: WFS/WCS
+     * - {String} owsURL: the online resource
+     * - {String} typeName: the name of the typename on the service
+     */
+    
+    CLASS_NAME: "OpenLayers.Format.WMSDescribeLayer" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSDescribeLayer/v1_1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSDescribeLayer.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSDescribeLayer.v1_1
+ * Read SLD WMS DescribeLayer response for WMS 1.1.X
+ * WMS 1.1.X is tightly coupled to SLD 1.0.0
+ *
+ * Example DescribeLayer request: 
+ * http://demo.opengeo.org/geoserver/wms?request=DescribeLayer&version=1.1.1&layers=topp:states
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSDescribeLayer>
+ */
+OpenLayers.Format.WMSDescribeLayer.v1_1 = OpenLayers.Class(
+    OpenLayers.Format.WMSDescribeLayer, {
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSDescribeLayer
+     * Create a new parser for WMS DescribeLayer responses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this, 
+            [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read DescribeLayer data from a string, and return the response. 
+     * The OGC defines 2 formats which are allowed for output,
+     * so we need to parse these 2 types for version 1.1.X
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} Array of {<LayerDescription>} objects which have:
+     * - {String} owsType: WFS/WCS
+     * - {String} owsURL: the online resource
+     * - {String} typeName: the name of the typename on the service
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var children = root.childNodes; 
+        var describelayer = [];
+        var childNode, nodeName;
+        for(var i=0; i<children.length; ++i) { 
+            childNode = children[i];
+            nodeName = childNode.nodeName; 
+            if (nodeName == 'LayerDescription') {
+                var layerName = childNode.getAttribute('name');
+                var owsType = '';
+                var owsURL = '';
+                var typeName = '';
+                // check for owsType and owsURL attributes
+                if (childNode.getAttribute('owsType')) {
+                  owsType = childNode.getAttribute('owsType');
+                  owsURL = childNode.getAttribute('owsURL');
+                } else {
+                    // look for wfs or wcs attribute
+                    if (childNode.getAttribute('wfs') != '') {
+                        owsType = 'WFS';
+                        owsURL = childNode.getAttribute('wfs');
+                    } else if (childNode.getAttribute('wcs') != '') {
+                        owsType = 'WCS';
+                        owsURL = childNode.getAttribute('wcs');
+                    }
+                }
+                // look for Query child
+                var query = childNode.getElementsByTagName('Query');
+                if(query.length > 0) {
+                    typeName = query[0].getAttribute('typeName');
+                    if (!typeName) {
+                        // because of Ionic bug
+                        typeName = query[0].getAttribute('typename');
+                    }
+                }
+                describelayer.push({layerName: layerName, owsType: owsType, 
+                    owsURL: owsURL, typeName: typeName}); 
+            }
+        }
+        return describelayer;
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WMSDescribeLayer.v1_1" 
+
+});
+/* ======================================================================
+    OpenLayers/Popup.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+
+/**
+ * Class: OpenLayers.Popup
+ * A popup is a small div that can opened and closed on the map.
+ * Typically opened in response to clicking on a marker.  
+ * See <OpenLayers.Marker>.  Popup's don't require their own
+ * layer and are added the the map using the <OpenLayers.Map.addPopup>
+ * method.
+ *
+ * Example:
+ * (code)
+ * popup = new OpenLayers.Popup("chicken", 
+ *                    new OpenLayers.LonLat(5,40),
+ *                    new OpenLayers.Size(200,200),
+ *                    "example popup",
+ *                    true);
+ *       
+ * map.addPopup(popup);
+ * (end)
+ */
+OpenLayers.Popup = OpenLayers.Class({
+
+    /** 
+     * Property: events  
+     * {<OpenLayers.Events>} custom event manager 
+     */
+    events: null,
+    
+    /** Property: id
+     * {String} the unique identifier assigned to this popup.
+     */
+    id: "",
+
+    /** 
+     * Property: lonlat 
+     * {<OpenLayers.LonLat>} the position of this popup on the map
+     */
+    lonlat: null,
+
+    /** 
+     * Property: div 
+     * {DOMElement} the div that contains this popup.
+     */
+    div: null,
+
+    /** 
+     * Property: contentSize 
+     * {<OpenLayers.Size>} the width and height of the content.
+     */
+    contentSize: null,    
+
+    /** 
+     * Property: size 
+     * {<OpenLayers.Size>} the width and height of the popup.
+     */
+    size: null,    
+
+    /** 
+     * Property: contentHTML 
+     * {String} An HTML string for this popup to display.
+     */
+    contentHTML: null,
+    
+    /** 
+     * Property: backgroundColor 
+     * {String} the background color used by the popup.
+     */
+    backgroundColor: "",
+    
+    /** 
+     * Property: opacity 
+     * {float} the opacity of this popup (between 0.0 and 1.0)
+     */
+    opacity: "",
+
+    /** 
+     * Property: border 
+     * {String} the border size of the popup.  (eg 2px)
+     */
+    border: "",
+    
+    /** 
+     * Property: contentDiv 
+     * {DOMElement} a reference to the element that holds the content of
+     *              the div.
+     */
+    contentDiv: null,
+    
+    /** 
+     * Property: groupDiv 
+     * {DOMElement} First and only child of 'div'. The group Div contains the
+     *     'contentDiv' and the 'closeDiv'.
+     */
+    groupDiv: null,
+
+    /** 
+     * Property: closeDiv
+     * {DOMElement} the optional closer image
+     */
+    closeDiv: null,
+
+    /** 
+     * APIProperty: autoSize
+     * {Boolean} Resize the popup to auto-fit the contents.
+     *     Default is false.
+     */
+    autoSize: false,
+
+    /**
+     * APIProperty: minSize
+     * {<OpenLayers.Size>} Minimum size allowed for the popup's contents.
+     */
+    minSize: null,
+
+    /**
+     * APIProperty: maxSize
+     * {<OpenLayers.Size>} Maximum size allowed for the popup's contents.
+     */
+    maxSize: null,
+
+    /** 
+     * Property: displayClass
+     * {String} The CSS class of the popup.
+     */
+    displayClass: "olPopup",
+
+    /** 
+     * Property: contentDisplayClass
+     * {String} The CSS class of the popup content div.
+     */
+    contentDisplayClass: "olPopupContent",
+
+    /** 
+     * Property: padding 
+     * {int or <OpenLayers.Bounds>} An extra opportunity to specify internal 
+     *     padding of the content div inside the popup. This was originally
+     *     confused with the css padding as specified in style.css's 
+     *     'olPopupContent' class. We would like to get rid of this altogether,
+     *     except that it does come in handy for the framed and anchoredbubble
+     *     popups, who need to maintain yet another barrier between their 
+     *     content and the outer border of the popup itself. 
+     * 
+     *     Note that in order to not break API, we must continue to support 
+     *     this property being set as an integer. Really, though, we'd like to 
+     *     have this specified as a Bounds object so that user can specify
+     *     distinct left, top, right, bottom paddings. With the 3.0 release
+     *     we can make this only a bounds.
+     */
+    padding: 0,
+
+    /** 
+     * Property: disableFirefoxOverflowHack
+     * {Boolean} The hack for overflow in Firefox causes all elements 
+     *     to be re-drawn, which causes Flash elements to be 
+     *     re-initialized, which is troublesome.
+     *     With this property the hack can be disabled.
+     */
+    disableFirefoxOverflowHack: false,
+
+    /**
+     * Method: fixPadding
+     * To be removed in 3.0, this function merely helps us to deal with the 
+     *     case where the user may have set an integer value for padding, 
+     *     instead of an <OpenLayers.Bounds> object.
+     */
+    fixPadding: function() {
+        if (typeof this.padding == "number") {
+            this.padding = new OpenLayers.Bounds(
+                this.padding, this.padding, this.padding, this.padding
+            );
+        }
+    },
+
+    /**
+     * APIProperty: panMapIfOutOfView
+     * {Boolean} When drawn, pan map such that the entire popup is visible in
+     *     the current viewport (if necessary).
+     *     Default is false.
+     */
+    panMapIfOutOfView: false,
+    
+    /**
+     * APIProperty: keepInMap 
+     * {Boolean} If panMapIfOutOfView is false, and this property is true, 
+     *     contrain the popup such that it always fits in the available map
+     *     space. By default, this is not set on the base class. If you are
+     *     creating popups that are near map edges and not allowing pannning,
+     *     and especially if you have a popup which has a
+     *     fixedRelativePosition, setting this to false may be a smart thing to
+     *     do. Subclasses may want to override this setting.
+     *   
+     *     Default is false.
+     */
+    keepInMap: false,
+
+    /**
+     * APIProperty: closeOnMove
+     * {Boolean} When map pans, close the popup.
+     *     Default is false.
+     */
+    closeOnMove: false,
+    
+    /** 
+     * Property: map 
+     * {<OpenLayers.Map>} this gets set in Map.js when the popup is added to the map
+     */
+    map: null,
+
+    /** 
+    * Constructor: OpenLayers.Popup
+    * Create a popup.
+    * 
+    * Parameters: 
+    * id - {String} a unqiue identifier for this popup.  If null is passed
+    *               an identifier will be automatically generated. 
+    * lonlat - {<OpenLayers.LonLat>}  The position on the map the popup will
+    *                                 be shown.
+    * contentSize - {<OpenLayers.Size>} The size of the content.
+    * contentHTML - {String}          An HTML string to display inside the   
+    *                                 popup.
+    * closeBox - {Boolean}            Whether to display a close box inside
+    *                                 the popup.
+    * closeBoxCallback - {Function}   Function to be called on closeBox click.
+    */
+    initialize:function(id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback) {
+        if (id == null) {
+            id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+        }
+
+        this.id = id;
+        this.lonlat = lonlat;
+
+        this.contentSize = (contentSize != null) ? contentSize 
+                                  : new OpenLayers.Size(
+                                                   OpenLayers.Popup.WIDTH,
+                                                   OpenLayers.Popup.HEIGHT);
+        if (contentHTML != null) { 
+             this.contentHTML = contentHTML;
+        }
+        this.backgroundColor = OpenLayers.Popup.COLOR;
+        this.opacity = OpenLayers.Popup.OPACITY;
+        this.border = OpenLayers.Popup.BORDER;
+
+        this.div = OpenLayers.Util.createDiv(this.id, null, null, 
+                                             null, null, null, "hidden");
+        this.div.className = this.displayClass;
+        
+        var groupDivId = this.id + "_GroupDiv";
+        this.groupDiv = OpenLayers.Util.createDiv(groupDivId, null, null, 
+                                                    null, "relative", null,
+                                                    "hidden");
+
+        var id = this.div.id + "_contentDiv";
+        this.contentDiv = OpenLayers.Util.createDiv(id, null, this.contentSize.clone(), 
+                                                    null, "relative");
+        this.contentDiv.className = this.contentDisplayClass;
+        this.groupDiv.appendChild(this.contentDiv);
+        this.div.appendChild(this.groupDiv);
+
+        if (closeBox) {
+            this.addCloseBox(closeBoxCallback);
+        } 
+
+        this.registerEvents();
+    },
+
+    /** 
+     * Method: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+
+        this.id = null;
+        this.lonlat = null;
+        this.size = null;
+        this.contentHTML = null;
+        
+        this.backgroundColor = null;
+        this.opacity = null;
+        this.border = null;
+        
+        if (this.closeOnMove && this.map) {
+            this.map.events.unregister("movestart", this, this.hide);
+        }
+
+        this.events.destroy();
+        this.events = null;
+        
+        if (this.closeDiv) {
+            OpenLayers.Event.stopObservingElement(this.closeDiv); 
+            this.groupDiv.removeChild(this.closeDiv);
+        }
+        this.closeDiv = null;
+        
+        this.div.removeChild(this.groupDiv);
+        this.groupDiv = null;
+
+        if (this.map != null) {
+            this.map.removePopup(this);
+        }
+        this.map = null;
+        this.div = null;
+        
+        this.autoSize = null;
+        this.minSize = null;
+        this.maxSize = null;
+        this.padding = null;
+        this.panMapIfOutOfView = null;
+    },
+
+    /** 
+    * Method: draw
+    * Constructs the elements that make up the popup.
+    *
+    * Parameters:
+    * px - {<OpenLayers.Pixel>} the position the popup in pixels.
+    * 
+    * Returns:
+    * {DOMElement} Reference to a div that contains the drawn popup
+    */
+    draw: function(px) {
+        if (px == null) {
+            if ((this.lonlat != null) && (this.map != null)) {
+                px = this.map.getLayerPxFromLonLat(this.lonlat);
+            }
+        }
+
+        // this assumes that this.map already exists, which is okay because 
+        // this.draw is only called once the popup has been added to the map.
+        if (this.closeOnMove) {
+            this.map.events.register("movestart", this, this.hide);
+        }
+        
+        //listen to movestart, moveend to disable overflow (FF bug)
+        if (!this.disableFirefoxOverflowHack && OpenLayers.BROWSER_NAME == 'firefox') {
+            this.map.events.register("movestart", this, function() {
+                var style = document.defaultView.getComputedStyle(
+                    this.contentDiv, null
+                );
+                var currentOverflow = style.getPropertyValue("overflow");
+                if (currentOverflow != "hidden") {
+                    this.contentDiv._oldOverflow = currentOverflow;
+                    this.contentDiv.style.overflow = "hidden";
+                }
+            });
+            this.map.events.register("moveend", this, function() {
+                var oldOverflow = this.contentDiv._oldOverflow;
+                if (oldOverflow) {
+                    this.contentDiv.style.overflow = oldOverflow;
+                    this.contentDiv._oldOverflow = null;
+                }
+            });
+        }
+
+        this.moveTo(px);
+        if (!this.autoSize && !this.size) {
+            this.setSize(this.contentSize);
+        }
+        this.setBackgroundColor();
+        this.setOpacity();
+        this.setBorder();
+        this.setContentHTML();
+        
+        if (this.panMapIfOutOfView) {
+            this.panIntoView();
+        }    
+
+        return this.div;
+    },
+
+    /** 
+     * Method: updatePosition
+     * if the popup has a lonlat and its map members set, 
+     * then have it move itself to its proper position
+     */
+    updatePosition: function() {
+        if ((this.lonlat) && (this.map)) {
+            var px = this.map.getLayerPxFromLonLat(this.lonlat);
+            if (px) {
+                this.moveTo(px);           
+            }    
+        }
+    },
+
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} the top and left position of the popup div. 
+     */
+    moveTo: function(px) {
+        if ((px != null) && (this.div != null)) {
+            this.div.style.left = px.x + "px";
+            this.div.style.top = px.y + "px";
+        }
+    },
+
+    /**
+     * Method: visible
+     *
+     * Returns:      
+     * {Boolean} Boolean indicating whether or not the popup is visible
+     */
+    visible: function() {
+        return OpenLayers.Element.visible(this.div);
+    },
+
+    /**
+     * Method: toggle
+     * Toggles visibility of the popup.
+     */
+    toggle: function() {
+        if (this.visible()) {
+            this.hide();
+        } else {
+            this.show();
+        }
+    },
+
+    /**
+     * Method: show
+     * Makes the popup visible.
+     */
+    show: function() {
+        this.div.style.display = '';
+
+        if (this.panMapIfOutOfView) {
+            this.panIntoView();
+        }    
+    },
+
+    /**
+     * Method: hide
+     * Makes the popup invisible.
+     */
+    hide: function() {
+        this.div.style.display = 'none';
+    },
+
+    /**
+     * Method: setSize
+     * Used to adjust the size of the popup. 
+     *
+     * Parameters:
+     * contentSize - {<OpenLayers.Size>} the new size for the popup's 
+     *     contents div (in pixels).
+     */
+    setSize:function(contentSize) { 
+        this.size = contentSize.clone(); 
+        
+        // if our contentDiv has a css 'padding' set on it by a stylesheet, we 
+        //  must add that to the desired "size". 
+        var contentDivPadding = this.getContentDivPadding();
+        var wPadding = contentDivPadding.left + contentDivPadding.right;
+        var hPadding = contentDivPadding.top + contentDivPadding.bottom;
+
+        // take into account the popup's 'padding' property
+        this.fixPadding();
+        wPadding += this.padding.left + this.padding.right;
+        hPadding += this.padding.top + this.padding.bottom;
+
+        // make extra space for the close div
+        if (this.closeDiv) {
+            var closeDivWidth = parseInt(this.closeDiv.style.width);
+            wPadding += closeDivWidth + contentDivPadding.right;
+        }
+
+        //increase size of the main popup div to take into account the 
+        // users's desired padding and close div.        
+        this.size.w += wPadding;
+        this.size.h += hPadding;
+
+        //now if our browser is IE, we need to actually make the contents 
+        // div itself bigger to take its own padding into effect. this makes 
+        // me want to shoot someone, but so it goes.
+        if (OpenLayers.BROWSER_NAME == "msie") {
+            this.contentSize.w += 
+                contentDivPadding.left + contentDivPadding.right;
+            this.contentSize.h += 
+                contentDivPadding.bottom + contentDivPadding.top;
+        }
+
+        if (this.div != null) {
+            this.div.style.width = this.size.w + "px";
+            this.div.style.height = this.size.h + "px";
+        }
+        if (this.contentDiv != null){
+            this.contentDiv.style.width = contentSize.w + "px";
+            this.contentDiv.style.height = contentSize.h + "px";
+        }
+    },  
+
+    /**
+     * APIMethod: updateSize
+     * Auto size the popup so that it precisely fits its contents (as 
+     *     determined by this.contentDiv.innerHTML). Popup size will, of
+     *     course, be limited by the available space on the current map
+     */
+    updateSize: function() {
+        
+        // determine actual render dimensions of the contents by putting its
+        // contents into a fake contentDiv (for the CSS) and then measuring it
+        var preparedHTML = "<div class='" + this.contentDisplayClass+ "'>" + 
+            this.contentDiv.innerHTML + 
+            "</div>";
+ 
+        var containerElement = (this.map) ? this.map.layerContainerDiv
+        								  : document.body;
+        var realSize = OpenLayers.Util.getRenderedDimensions(
+            preparedHTML, null,	{
+                displayClass: this.displayClass,
+                containerElement: containerElement
+            }
+        );
+
+        // is the "real" size of the div is safe to display in our map?
+        var safeSize = this.getSafeContentSize(realSize);
+
+        var newSize = null;
+        if (safeSize.equals(realSize)) {
+            //real size of content is small enough to fit on the map, 
+            // so we use real size.
+            newSize = realSize;
+
+        } else {
+
+            //make a new OL.Size object with the clipped dimensions 
+            // set or null if not clipped.
+            var fixedSize = new OpenLayers.Size();
+            fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null;
+            fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null;
+        
+            if (fixedSize.w && fixedSize.h) {
+                //content is too big in both directions, so we will use 
+                // max popup size (safeSize), knowing well that it will 
+                // overflow both ways.                
+                newSize = safeSize;
+            } else {
+                //content is clipped in only one direction, so we need to 
+                // run getRenderedDimensions() again with a fixed dimension
+                var clippedSize = OpenLayers.Util.getRenderedDimensions(
+                    preparedHTML, fixedSize, {
+                        displayClass: this.contentDisplayClass,
+                        containerElement: containerElement
+                    }
+                );
+                
+                //if the clipped size is still the same as the safeSize, 
+                // that means that our content must be fixed in the 
+                // offending direction. If overflow is 'auto', this means 
+                // we are going to have a scrollbar for sure, so we must 
+                // adjust for that.
+                //
+                var currentOverflow = OpenLayers.Element.getStyle(
+                    this.contentDiv, "overflow"
+                );
+                if ( (currentOverflow != "hidden") && 
+                     (clippedSize.equals(safeSize)) ) {
+                    var scrollBar = OpenLayers.Util.getScrollbarWidth();
+                    if (fixedSize.w) {
+                        clippedSize.h += scrollBar;
+                    } else {
+                        clippedSize.w += scrollBar;
+                    }
+                }
+                
+                newSize = this.getSafeContentSize(clippedSize);
+            }
+        }                        
+        this.setSize(newSize);     
+    },    
+
+    /**
+     * Method: setBackgroundColor
+     * Sets the background color of the popup.
+     *
+     * Parameters:
+     * color - {String} the background color.  eg "#FFBBBB"
+     */
+    setBackgroundColor:function(color) { 
+        if (color != undefined) {
+            this.backgroundColor = color; 
+        }
+        
+        if (this.div != null) {
+            this.div.style.backgroundColor = this.backgroundColor;
+        }
+    },  
+    
+    /**
+     * Method: setOpacity
+     * Sets the opacity of the popup.
+     * 
+     * Parameters:
+     * opacity - {float} A value between 0.0 (transparent) and 1.0 (solid).   
+     */
+    setOpacity:function(opacity) { 
+        if (opacity != undefined) {
+            this.opacity = opacity; 
+        }
+        
+        if (this.div != null) {
+            // for Mozilla and Safari
+            this.div.style.opacity = this.opacity;
+
+            // for IE
+            this.div.style.filter = 'alpha(opacity=' + this.opacity*100 + ')';
+        }
+    },  
+    
+    /**
+     * Method: setBorder
+     * Sets the border style of the popup.
+     *
+     * Parameters:
+     * border - {String} The border style value. eg 2px 
+     */
+    setBorder:function(border) { 
+        if (border != undefined) {
+            this.border = border;
+        }
+        
+        if (this.div != null) {
+            this.div.style.border = this.border;
+        }
+    },      
+    
+    /**
+     * Method: setContentHTML
+     * Allows the user to set the HTML content of the popup.
+     *
+     * Parameters:
+     * contentHTML - {String} HTML for the div.
+     */
+    setContentHTML:function(contentHTML) {
+
+        if (contentHTML != null) {
+            this.contentHTML = contentHTML;
+        }
+       
+        if ((this.contentDiv != null) && 
+            (this.contentHTML != null) &&
+            (this.contentHTML != this.contentDiv.innerHTML)) {
+       
+            this.contentDiv.innerHTML = this.contentHTML;
+       
+            if (this.autoSize) {
+                
+                //if popup has images, listen for when they finish
+                // loading and resize accordingly
+                this.registerImageListeners();
+
+                //auto size the popup to its current contents
+                this.updateSize();
+            }
+        }    
+
+    },
+    
+    /**
+     * Method: registerImageListeners
+     * Called when an image contained by the popup loaded. this function
+     *     updates the popup size, then unregisters the image load listener.
+     */   
+    registerImageListeners: function() { 
+
+        // As the images load, this function will call updateSize() to 
+        // resize the popup to fit the content div (which presumably is now
+        // bigger than when the image was not loaded).
+        // 
+        // If the 'panMapIfOutOfView' property is set, we will pan the newly
+        // resized popup back into view.
+        // 
+        // Note that this function, when called, will have 'popup' and 
+        // 'img' properties in the context.
+        //
+        var onImgLoad = function() {
+            
+            this.popup.updateSize();
+     
+            if ( this.popup.visible() && this.popup.panMapIfOutOfView ) {
+                this.popup.panIntoView();
+            }
+
+            OpenLayers.Event.stopObserving(
+                this.img, "load", this.img._onImageLoad
+            );
+    
+        };
+
+        //cycle through the images and if their size is 0x0, that means that 
+        // they haven't been loaded yet, so we attach the listener, which 
+        // will fire when the images finish loading and will resize the 
+        // popup accordingly to its new size.
+        var images = this.contentDiv.getElementsByTagName("img");
+        for (var i = 0, len = images.length; i < len; i++) {
+            var img = images[i];
+            if (img.width == 0 || img.height == 0) {
+
+                var context = {
+                    'popup': this,
+                    'img': img
+                };
+
+                //expando this function to the image itself before registering
+                // it. This way we can easily and properly unregister it.
+                img._onImgLoad = OpenLayers.Function.bind(onImgLoad, context);
+
+                OpenLayers.Event.observe(img, 'load', img._onImgLoad);
+            }    
+        } 
+    },
+
+    /**
+     * APIMethod: getSafeContentSize
+     * 
+     * Parameters:
+     * size - {<OpenLayers.Size>} Desired size to make the popup.
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} A size to make the popup which is neither smaller
+     *     than the specified minimum size, nor bigger than the maximum 
+     *     size (which is calculated relative to the size of the viewport).
+     */
+    getSafeContentSize: function(size) {
+
+        var safeContentSize = size.clone();
+
+        // if our contentDiv has a css 'padding' set on it by a stylesheet, we 
+        //  must add that to the desired "size". 
+        var contentDivPadding = this.getContentDivPadding();
+        var wPadding = contentDivPadding.left + contentDivPadding.right;
+        var hPadding = contentDivPadding.top + contentDivPadding.bottom;
+
+        // take into account the popup's 'padding' property
+        this.fixPadding();
+        wPadding += this.padding.left + this.padding.right;
+        hPadding += this.padding.top + this.padding.bottom;
+
+        if (this.closeDiv) {
+            var closeDivWidth = parseInt(this.closeDiv.style.width);
+            wPadding += closeDivWidth + contentDivPadding.right;
+        }
+
+        // prevent the popup from being smaller than a specified minimal size
+        if (this.minSize) {
+            safeContentSize.w = Math.max(safeContentSize.w, 
+                (this.minSize.w - wPadding));
+            safeContentSize.h = Math.max(safeContentSize.h, 
+                (this.minSize.h - hPadding));
+        }
+
+        // prevent the popup from being bigger than a specified maximum size
+        if (this.maxSize) {
+            safeContentSize.w = Math.min(safeContentSize.w, 
+                (this.maxSize.w - wPadding));
+            safeContentSize.h = Math.min(safeContentSize.h, 
+                (this.maxSize.h - hPadding));
+        }
+        
+        //make sure the desired size to set doesn't result in a popup that 
+        // is bigger than the map's viewport.
+        //
+        if (this.map && this.map.size) {
+            
+            var extraX = 0, extraY = 0;
+            if (this.keepInMap && !this.panMapIfOutOfView) {
+                var px = this.map.getPixelFromLonLat(this.lonlat);
+                switch (this.relativePosition) {
+                    case "tr":
+                        extraX = px.x;
+                        extraY = this.map.size.h - px.y;
+                        break;
+                    case "tl":
+                        extraX = this.map.size.w - px.x;
+                        extraY = this.map.size.h - px.y;
+                        break;
+                    case "bl":
+                        extraX = this.map.size.w - px.x;
+                        extraY = px.y;
+                        break;
+                    case "br":
+                        extraX = px.x;
+                        extraY = px.y;
+                        break;
+                    default:    
+                        extraX = px.x;
+                        extraY = this.map.size.h - px.y;
+                        break;
+                }
+            }    
+          
+            var maxY = this.map.size.h - 
+                this.map.paddingForPopups.top - 
+                this.map.paddingForPopups.bottom - 
+                hPadding - extraY;
+            
+            var maxX = this.map.size.w - 
+                this.map.paddingForPopups.left - 
+                this.map.paddingForPopups.right - 
+                wPadding - extraX;
+            
+            safeContentSize.w = Math.min(safeContentSize.w, maxX);
+            safeContentSize.h = Math.min(safeContentSize.h, maxY);
+        }
+        
+        return safeContentSize;
+    },
+    
+    /**
+     * Method: getContentDivPadding
+     * Glorious, oh glorious hack in order to determine the css 'padding' of 
+     *     the contentDiv. IE/Opera return null here unless we actually add the 
+     *     popup's main 'div' element (which contains contentDiv) to the DOM. 
+     *     So we make it invisible and then add it to the document temporarily. 
+     *
+     *     Once we've taken the padding readings we need, we then remove it 
+     *     from the DOM (it will actually get added to the DOM in 
+     *     Map.js's addPopup)
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getContentDivPadding: function() {
+
+        //use cached value if we have it
+        var contentDivPadding = this._contentDivPadding;
+        if (!contentDivPadding) {
+
+        	if (this.div.parentNode == null) {
+	        	//make the div invisible and add it to the page        
+	            this.div.style.display = "none";
+	            document.body.appendChild(this.div);
+	    	}
+	            
+            //read the padding settings from css, put them in an OL.Bounds        
+            contentDivPadding = new OpenLayers.Bounds(
+                OpenLayers.Element.getStyle(this.contentDiv, "padding-left"),
+                OpenLayers.Element.getStyle(this.contentDiv, "padding-bottom"),
+                OpenLayers.Element.getStyle(this.contentDiv, "padding-right"),
+                OpenLayers.Element.getStyle(this.contentDiv, "padding-top")
+            );
+    
+            //cache the value
+            this._contentDivPadding = contentDivPadding;
+
+            if (this.div.parentNode == document.body) {
+	            //remove the div from the page and make it visible again
+	            document.body.removeChild(this.div);
+	            this.div.style.display = "";
+            }
+        }
+        return contentDivPadding;
+    },
+
+    /**
+     * Method: addCloseBox
+     * 
+     * Parameters:
+     * callback - {Function} The callback to be called when the close button
+     *     is clicked.
+     */
+    addCloseBox: function(callback) {
+
+        this.closeDiv = OpenLayers.Util.createDiv(
+            this.id + "_close", null, new OpenLayers.Size(17, 17)
+        );
+        this.closeDiv.className = "olPopupCloseBox"; 
+        
+        // use the content div's css padding to determine if we should
+        //  padd the close div
+        var contentDivPadding = this.getContentDivPadding();
+         
+        this.closeDiv.style.right = contentDivPadding.right + "px";
+        this.closeDiv.style.top = contentDivPadding.top + "px";
+        this.groupDiv.appendChild(this.closeDiv);
+
+        var closePopup = callback || function(e) {
+            this.hide();
+            OpenLayers.Event.stop(e);
+        };
+        OpenLayers.Event.observe(this.closeDiv, "touchend", 
+                OpenLayers.Function.bindAsEventListener(closePopup, this));
+        OpenLayers.Event.observe(this.closeDiv, "click", 
+                OpenLayers.Function.bindAsEventListener(closePopup, this));
+    },
+
+    /**
+     * Method: panIntoView
+     * Pans the map such that the popup is totaly viewable (if necessary)
+     */
+    panIntoView: function() {
+        
+        var mapSize = this.map.getSize();
+    
+        //start with the top left corner of the popup, in px, 
+        // relative to the viewport
+        var origTL = this.map.getViewPortPxFromLayerPx( new OpenLayers.Pixel(
+            parseInt(this.div.style.left),
+            parseInt(this.div.style.top)
+        ));
+        var newTL = origTL.clone();
+    
+        //new left (compare to margins, using this.size to calculate right)
+        if (origTL.x < this.map.paddingForPopups.left) {
+            newTL.x = this.map.paddingForPopups.left;
+        } else 
+        if ( (origTL.x + this.size.w) > (mapSize.w - this.map.paddingForPopups.right)) {
+            newTL.x = mapSize.w - this.map.paddingForPopups.right - this.size.w;
+        }
+        
+        //new top (compare to margins, using this.size to calculate bottom)
+        if (origTL.y < this.map.paddingForPopups.top) {
+            newTL.y = this.map.paddingForPopups.top;
+        } else 
+        if ( (origTL.y + this.size.h) > (mapSize.h - this.map.paddingForPopups.bottom)) {
+            newTL.y = mapSize.h - this.map.paddingForPopups.bottom - this.size.h;
+        }
+        
+        var dx = origTL.x - newTL.x;
+        var dy = origTL.y - newTL.y;
+        
+        this.map.pan(dx, dy);
+    },
+
+    /** 
+     * Method: registerEvents
+     * Registers events on the popup.
+     *
+     * Do this in a separate function so that subclasses can 
+     *   choose to override it if they wish to deal differently
+     *   with mouse events
+     * 
+     *   Note in the following handler functions that some special
+     *    care is needed to deal correctly with mousing and popups. 
+     *   
+     *   Because the user might select the zoom-rectangle option and
+     *    then drag it over a popup, we need a safe way to allow the
+     *    mousemove and mouseup events to pass through the popup when
+     *    they are initiated from outside. The same procedure is needed for
+     *    touchmove and touchend events.
+     * 
+     *   Otherwise, we want to essentially kill the event propagation
+     *    for all other events, though we have to do so carefully, 
+     *    without disabling basic html functionality, like clicking on 
+     *    hyperlinks or drag-selecting text.
+     */
+     registerEvents:function() {
+        this.events = new OpenLayers.Events(this, this.div, null, true);
+
+        function onTouchstart(evt) {
+            OpenLayers.Event.stop(evt, true);
+        }
+        this.events.on({
+            "mousedown": this.onmousedown,
+            "mousemove": this.onmousemove,
+            "mouseup": this.onmouseup,
+            "click": this.onclick,
+            "mouseout": this.onmouseout,
+            "dblclick": this.ondblclick,
+            "touchstart": onTouchstart,
+            scope: this
+        });
+        
+     },
+
+    /** 
+     * Method: onmousedown 
+     * When mouse goes down within the popup, make a note of
+     *   it locally, and then do not propagate the mousedown 
+     *   (but do so safely so that user can select text inside)
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmousedown: function (evt) {
+        this.mousedown = true;
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    /** 
+     * Method: onmousemove
+     * If the drag was started within the popup, then 
+     *   do not propagate the mousemove (but do so safely
+     *   so that user can select text inside)
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmousemove: function (evt) {
+        if (this.mousedown) {
+            OpenLayers.Event.stop(evt, true);
+        }
+    },
+
+    /** 
+     * Method: onmouseup
+     * When mouse comes up within the popup, after going down 
+     *   in it, reset the flag, and then (once again) do not 
+     *   propagate the event, but do so safely so that user can 
+     *   select text inside
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmouseup: function (evt) {
+        if (this.mousedown) {
+            this.mousedown = false;
+            OpenLayers.Event.stop(evt, true);
+        }
+    },
+
+    /**
+     * Method: onclick
+     * Ignore clicks, but allowing default browser handling
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onclick: function (evt) {
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    /** 
+     * Method: onmouseout
+     * When mouse goes out of the popup set the flag to false so that
+     *   if they let go and then drag back in, we won't be confused.
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmouseout: function (evt) {
+        this.mousedown = false;
+    },
+    
+    /** 
+     * Method: ondblclick
+     * Ignore double-clicks, but allowing default browser handling
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    ondblclick: function (evt) {
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    CLASS_NAME: "OpenLayers.Popup"
+});
+
+OpenLayers.Popup.WIDTH = 200;
+OpenLayers.Popup.HEIGHT = 200;
+OpenLayers.Popup.COLOR = "white";
+OpenLayers.Popup.OPACITY = 1;
+OpenLayers.Popup.BORDER = "0px";
+/* ======================================================================
+    OpenLayers/Control/ScaleLine.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ScaleLine
+ * The ScaleLine displays a small line indicator representing the current 
+ * map scale on the map. By default it is drawn in the lower left corner of
+ * the map.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ *  
+ * Is a very close copy of:
+ *  - <OpenLayers.Control.Scale>
+ */
+OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: maxWidth
+     * {Integer} Maximum width of the scale line in pixels.  Default is 100.
+     */
+    maxWidth: 100,
+
+    /**
+     * Property: topOutUnits
+     * {String} Units for zoomed out on top bar.  Default is km.
+     */
+    topOutUnits: "km",
+    
+    /**
+     * Property: topInUnits
+     * {String} Units for zoomed in on top bar.  Default is m.
+     */
+    topInUnits: "m",
+
+    /**
+     * Property: bottomOutUnits
+     * {String} Units for zoomed out on bottom bar.  Default is mi.
+     */
+    bottomOutUnits: "mi",
+
+    /**
+     * Property: bottomInUnits
+     * {String} Units for zoomed in on bottom bar.  Default is ft.
+     */
+    bottomInUnits: "ft",
+    
+    /**
+     * Property: eTop
+     * {DOMElement}
+     */
+    eTop: null,
+
+    /**
+     * Property: eBottom
+     * {DOMElement}
+     */
+    eBottom:null,
+    
+    /**
+     * APIProperty: geodesic
+     * {Boolean} Use geodesic measurement. Default is false. The recommended
+     * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
+     * true, the scale will be calculated based on the horizontal size of the
+     * pixel in the center of the map viewport.
+     */
+    geodesic: false,
+
+    /**
+     * Constructor: OpenLayers.Control.ScaleLine
+     * Create a new scale line control.
+     * 
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+
+    /**
+     * Method: draw
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        if (!this.eTop) {
+            // stick in the top bar
+            this.eTop = document.createElement("div");
+            this.eTop.className = this.displayClass + "Top";
+            var theLen = this.topInUnits.length;
+            this.div.appendChild(this.eTop);
+            if((this.topOutUnits == "") || (this.topInUnits == "")) {
+                this.eTop.style.visibility = "hidden";
+            } else {
+                this.eTop.style.visibility = "visible";
+            }
+
+            // and the bottom bar
+            this.eBottom = document.createElement("div");
+            this.eBottom.className = this.displayClass + "Bottom";
+            this.div.appendChild(this.eBottom);
+            if((this.bottomOutUnits == "") || (this.bottomInUnits == "")) {
+                this.eBottom.style.visibility = "hidden";
+            } else {
+                this.eBottom.style.visibility = "visible";
+            }
+        }
+        this.map.events.register('moveend', this, this.update);
+        this.update();
+        return this.div;
+    },
+
+    /** 
+     * Method: getBarLen
+     * Given a number, round it down to the nearest 1,2,5 times a power of 10.
+     * That seems a fairly useful set of number groups to use.
+     * 
+     * Parameters:
+     * maxLen - {float}  the number we're rounding down from
+     * 
+     * Returns:
+     * {Float} the rounded number (less than or equal to maxLen)
+     */
+    getBarLen: function(maxLen) {
+        // nearest power of 10 lower than maxLen
+        var digits = parseInt(Math.log(maxLen) / Math.log(10));
+        var pow10 = Math.pow(10, digits);
+        
+        // ok, find first character
+        var firstChar = parseInt(maxLen / pow10);
+
+        // right, put it into the correct bracket
+        var barLen;
+        if(firstChar > 5) {
+            barLen = 5;
+        } else if(firstChar > 2) {
+            barLen = 2;
+        } else {
+            barLen = 1;
+        }
+
+        // scale it up the correct power of 10
+        return barLen * pow10;
+    },
+
+    /**
+     * Method: update
+     * Update the size of the bars, and the labels they contain.
+     */
+    update: function() {
+        var res = this.map.getResolution();
+        if (!res) {
+            return;
+        }
+
+        var curMapUnits = this.map.getUnits();
+        var inches = OpenLayers.INCHES_PER_UNIT;
+
+        // convert maxWidth to map units
+        var maxSizeData = this.maxWidth * res * inches[curMapUnits];
+        var geodesicRatio = 1;
+        if(this.geodesic === true) {
+            var maxSizeGeodesic = (this.map.getGeodesicPixelSize().w ||
+                0.000001) * this.maxWidth;
+            var maxSizeKilometers = maxSizeData / inches["km"];
+            geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
+            maxSizeData *= geodesicRatio;
+        }
+
+        // decide whether to use large or small scale units     
+        var topUnits;
+        var bottomUnits;
+        if(maxSizeData > 100000) {
+            topUnits = this.topOutUnits;
+            bottomUnits = this.bottomOutUnits;
+        } else {
+            topUnits = this.topInUnits;
+            bottomUnits = this.bottomInUnits;
+        }
+
+        // and to map units units
+        var topMax = maxSizeData / inches[topUnits];
+        var bottomMax = maxSizeData / inches[bottomUnits];
+
+        // now trim this down to useful block length
+        var topRounded = this.getBarLen(topMax);
+        var bottomRounded = this.getBarLen(bottomMax);
+
+        // and back to display units
+        topMax = topRounded / inches[curMapUnits] * inches[topUnits];
+        bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
+
+        // and to pixel units
+        var topPx = topMax / res / geodesicRatio;
+        var bottomPx = bottomMax / res / geodesicRatio;
+        
+        // now set the pixel widths
+        // and the values inside them
+        
+        if (this.eBottom.style.visibility == "visible"){
+            this.eBottom.style.width = Math.round(bottomPx) + "px"; 
+            this.eBottom.innerHTML = bottomRounded + " " + bottomUnits ;
+        }
+            
+        if (this.eTop.style.visibility == "visible"){
+            this.eTop.style.width = Math.round(topPx) + "px";
+            this.eTop.innerHTML = topRounded + " " + topUnits;
+        }
+        
+    }, 
+
+    CLASS_NAME: "OpenLayers.Control.ScaleLine"
+});
+
+/* ======================================================================
+    OpenLayers/Icon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Icon
+ * 
+ * The icon represents a graphical icon on the screen.  Typically used in
+ * conjunction with a <OpenLayers.Marker> to represent markers on a screen.
+ *
+ * An icon has a url, size and position.  It also contains an offset which 
+ * allows the center point to be represented correctly.  This can be
+ * provided either as a fixed offset or a function provided to calculate
+ * the desired offset. 
+ * 
+ */
+OpenLayers.Icon = OpenLayers.Class({
+    
+    /** 
+     * Property: url 
+     * {String}  image url
+     */
+    url: null,
+    
+    /** 
+     * Property: size 
+     * {<OpenLayers.Size>} 
+     */
+    size: null,
+
+    /** 
+     * Property: offset 
+     * {<OpenLayers.Pixel>} distance in pixels to offset the image when being rendered
+     */
+    offset: null,    
+    
+    /** 
+     * Property: calculateOffset 
+     * {<OpenLayers.Pixel>} Function to calculate the offset (based on the size) 
+     */
+    calculateOffset: null,    
+    
+    /** 
+     * Property: imageDiv 
+     * {DOMElement} 
+     */
+    imageDiv: null,
+
+    /** 
+     * Property: px 
+     * {<OpenLayers.Pixel>} 
+     */
+    px: null,
+    
+    /** 
+     * Constructor: OpenLayers.Icon
+     * Creates an icon, which is an image tag in a div.  
+     *
+     * url - {String} 
+     * size - {<OpenLayers.Size>} 
+     * offset - {<OpenLayers.Pixel>}
+     * calculateOffset - {Function} 
+     */
+    initialize: function(url, size, offset, calculateOffset) {
+        this.url = url;
+        this.size = (size) ? size : new OpenLayers.Size(20,20);
+        this.offset = offset ? offset : new OpenLayers.Pixel(-(this.size.w/2), -(this.size.h/2));
+        this.calculateOffset = calculateOffset;
+
+        var id = OpenLayers.Util.createUniqueID("OL_Icon_");
+        this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
+    },
+    
+    /** 
+     * Method: destroy
+     * Nullify references and remove event listeners to prevent circular 
+     * references and memory leaks
+     */
+    destroy: function() {
+        // erase any drawn elements
+        this.erase();
+
+        OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild); 
+        this.imageDiv.innerHTML = "";
+        this.imageDiv = null;
+    },
+
+    /** 
+     * Method: clone
+     * 
+     * Returns:
+     * {<OpenLayers.Icon>} A fresh copy of the icon.
+     */
+    clone: function() {
+        return new OpenLayers.Icon(this.url, 
+                                   this.size, 
+                                   this.offset, 
+                                   this.calculateOffset);
+    },
+    
+    /**
+     * Method: setSize
+     * 
+     * Parameters:
+     * size - {<OpenLayers.Size>} 
+     */
+    setSize: function(size) {
+        if (size != null) {
+            this.size = size;
+        }
+        this.draw();
+    },
+    
+    /**
+     * Method: setUrl
+     * 
+     * Parameters:
+     * url - {String} 
+     */
+    setUrl: function(url) {
+        if (url != null) {
+            this.url = url;
+        }
+        this.draw();
+    },
+
+    /** 
+     * Method: draw
+     * Move the div to the given pixel.
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} 
+     * 
+     * Returns:
+     * {DOMElement} A new DOM Image of this icon set at the location passed-in
+     */
+    draw: function(px) {
+        OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, 
+                                            null, 
+                                            null, 
+                                            this.size, 
+                                            this.url, 
+                                            "absolute");
+        this.moveTo(px);
+        return this.imageDiv;
+    }, 
+
+    /** 
+     * Method: erase
+     * Erase the underlying image element.
+     *
+     */
+    erase: function() {
+        if (this.imageDiv != null && this.imageDiv.parentNode != null) {
+            OpenLayers.Element.remove(this.imageDiv);
+        }
+    }, 
+    
+    /** 
+     * Method: setOpacity
+     * Change the icon's opacity
+     *
+     * Parameters:
+     * opacity - {float} 
+     */
+    setOpacity: function(opacity) {
+        OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, 
+                                            null, null, null, null, opacity);
+
+    },
+    
+    /**
+     * Method: moveTo
+     * move icon to passed in px.
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} 
+     */
+    moveTo: function (px) {
+        //if no px passed in, use stored location
+        if (px != null) {
+            this.px = px;
+        }
+
+        if (this.imageDiv != null) {
+            if (this.px == null) {
+                this.display(false);
+            } else {
+                if (this.calculateOffset) {
+                    this.offset = this.calculateOffset(this.size);  
+                }
+                var offsetPx = this.px.offset(this.offset);
+                OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, offsetPx);
+            }
+        }
+    },
+    
+    /** 
+     * Method: display
+     * Hide or show the icon
+     *
+     * Parameters:
+     * display - {Boolean} 
+     */
+    display: function(display) {
+        this.imageDiv.style.display = (display) ? "" : "none"; 
+    },
+    
+
+    /**
+     * APIMethod: isDrawn
+     * 
+     * Returns:
+     * {Boolean} Whether or not the icon is drawn.
+     */
+    isDrawn: function() {
+        // nodeType 11 for ie, whose nodes *always* have a parentNode
+        // (of type document fragment)
+        var isDrawn = (this.imageDiv && this.imageDiv.parentNode && 
+                       (this.imageDiv.parentNode.nodeType != 11));    
+
+        return isDrawn;   
+    },
+
+    CLASS_NAME: "OpenLayers.Icon"
+});
+/* ======================================================================
+    OpenLayers/Marker.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Events.js
+ * @requires OpenLayers/Icon.js
+ */
+
+/**
+ * Class: OpenLayers.Marker
+ * Instances of OpenLayers.Marker are a combination of a 
+ * <OpenLayers.LonLat> and an <OpenLayers.Icon>.  
+ *
+ * Markers are generally added to a special layer called
+ * <OpenLayers.Layer.Markers>.
+ *
+ * Example:
+ * (code)
+ * var markers = new OpenLayers.Layer.Markers( "Markers" );
+ * map.addLayer(markers);
+ *
+ * var size = new OpenLayers.Size(21,25);
+ * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
+ * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
+ * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
+ * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
+ *
+ * (end)
+ *
+ * Note that if you pass an icon into the Marker constructor, it will take
+ * that icon and use it. This means that you should not share icons between
+ * markers -- you use them once, but you should clone() for any additional
+ * markers using that same icon.
+ */
+OpenLayers.Marker = OpenLayers.Class({
+    
+    /** 
+     * Property: icon 
+     * {<OpenLayers.Icon>} The icon used by this marker.
+     */
+    icon: null,
+
+    /** 
+     * Property: lonlat 
+     * {<OpenLayers.LonLat>} location of object
+     */
+    lonlat: null,
+    
+    /** 
+     * Property: events 
+     * {<OpenLayers.Events>} the event handler.
+     */
+    events: null,
+    
+    /** 
+     * Property: map 
+     * {<OpenLayers.Map>} the map this marker is attached to
+     */
+    map: null,
+    
+    /** 
+     * Constructor: OpenLayers.Marker
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>} the position of this marker
+     * icon - {<OpenLayers.Icon>}  the icon for this marker
+     */
+    initialize: function(lonlat, icon) {
+        this.lonlat = lonlat;
+        
+        var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
+        if (this.icon == null) {
+            this.icon = newIcon;
+        } else {
+            this.icon.url = newIcon.url;
+            this.icon.size = newIcon.size;
+            this.icon.offset = newIcon.offset;
+            this.icon.calculateOffset = newIcon.calculateOffset;
+        }
+        this.events = new OpenLayers.Events(this, this.icon.imageDiv, null);
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Destroy the marker. You must first remove the marker from any 
+     * layer which it has been added to, or you will get buggy behavior.
+     * (This can not be done within the marker since the marker does not
+     * know which layer it is attached to.)
+     */
+    destroy: function() {
+        // erase any drawn features
+        this.erase();
+
+        this.map = null;
+
+        this.events.destroy();
+        this.events = null;
+
+        if (this.icon != null) {
+            this.icon.destroy();
+            this.icon = null;
+        }
+    },
+    
+    /** 
+    * Method: draw
+    * Calls draw on the icon, and returns that output.
+    * 
+    * Parameters:
+    * px - {<OpenLayers.Pixel>}
+    * 
+    * Returns:
+    * {DOMElement} A new DOM Image with this marker's icon set at the 
+    * location passed-in
+    */
+    draw: function(px) {
+        return this.icon.draw(px);
+    }, 
+
+    /** 
+    * Method: erase
+    * Erases any drawn elements for this marker.
+    */
+    erase: function() {
+        if (this.icon != null) {
+            this.icon.erase();
+        }
+    }, 
+
+    /**
+    * Method: moveTo
+    * Move the marker to the new location.
+    *
+    * Parameters:
+    * px - {<OpenLayers.Pixel>} the pixel position to move to
+    */
+    moveTo: function (px) {
+        if ((px != null) && (this.icon != null)) {
+            this.icon.moveTo(px);
+        }           
+        this.lonlat = this.map.getLonLatFromLayerPx(px);
+    },
+
+    /**
+     * APIMethod: isDrawn
+     * 
+     * Returns:
+     * {Boolean} Whether or not the marker is drawn.
+     */
+    isDrawn: function() {
+        var isDrawn = (this.icon && this.icon.isDrawn());
+        return isDrawn;   
+    },
+
+    /**
+     * Method: onScreen
+     *
+     * Returns:
+     * {Boolean} Whether or not the marker is currently visible on screen.
+     */
+    onScreen:function() {
+        
+        var onScreen = false;
+        if (this.map) {
+            var screenBounds = this.map.getExtent();
+            onScreen = screenBounds.containsLonLat(this.lonlat);
+        }    
+        return onScreen;
+    },
+    
+    /**
+     * Method: inflate
+     * Englarges the markers icon by the specified ratio.
+     *
+     * Parameters:
+     * inflate - {float} the ratio to enlarge the marker by (passing 2
+     *                   will double the size).
+     */
+    inflate: function(inflate) {
+        if (this.icon) {
+            var newSize = new OpenLayers.Size(this.icon.size.w * inflate,
+                                              this.icon.size.h * inflate);
+            this.icon.setSize(newSize);
+        }        
+    },
+    
+    /** 
+     * Method: setOpacity
+     * Change the opacity of the marker by changin the opacity of 
+     *   its icon
+     * 
+     * Parameters:
+     * opacity - {float}  Specified as fraction (0.4, etc)
+     */
+    setOpacity: function(opacity) {
+        this.icon.setOpacity(opacity);
+    },
+
+    /**
+     * Method: setUrl
+     * Change URL of the Icon Image.
+     * 
+     * url - {String} 
+     */
+    setUrl: function(url) {
+        this.icon.setUrl(url);
+    },    
+
+    /** 
+     * Method: display
+     * Hide or show the icon
+     * 
+     * display - {Boolean} 
+     */
+    display: function(display) {
+        this.icon.display(display);
+    },
+
+    CLASS_NAME: "OpenLayers.Marker"
+});
+
+
+/**
+ * Function: defaultIcon
+ * Creates a default <OpenLayers.Icon>.
+ * 
+ * Returns:
+ * {<OpenLayers.Icon>} A default OpenLayers.Icon to use for a marker
+ */
+OpenLayers.Marker.defaultIcon = function() {
+    var url = OpenLayers.Util.getImagesLocation() + "marker.png";
+    var size = new OpenLayers.Size(21, 25);
+    var calculateOffset = function(size) {
+                    return new OpenLayers.Pixel(-(size.w/2), -size.h);
+                 };
+
+    return new OpenLayers.Icon(url, size, null, calculateOffset);        
+};
+    
+
+/* ======================================================================
+    OpenLayers/Format/GeoJSON.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/JSON.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GeoJSON
+ * Read and write GeoJSON. Create a new parser with the
+ *     <OpenLayers.Format.GeoJSON> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.JSON>
+ */
+OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {
+
+    /**
+     * APIProperty: ignoreExtraDims
+     * {Boolean} Ignore dimensions higher than 2 when reading geometry
+     * coordinates.
+     */ 
+    ignoreExtraDims: false,
+    
+    /**
+     * Constructor: OpenLayers.Format.GeoJSON
+     * Create a new parser for GeoJSON.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Deserialize a GeoJSON string.
+     *
+     * Parameters:
+     * json - {String} A GeoJSON string
+     * type - {String} Optional string that determines the structure of
+     *     the output.  Supported values are "Geometry", "Feature", and
+     *     "FeatureCollection".  If absent or null, a default of
+     *     "FeatureCollection" is assumed.
+     * filter - {Function} A function which will be called for every key and
+     *     value at every level of the final result. Each value will be
+     *     replaced by the result of the filter function. This can be used to
+     *     reform generic objects into instances of classes, or to transform
+     *     date strings into Date objects.
+     *
+     * Returns: 
+     * {Object} The return depends on the value of the type argument. If type
+     *     is "FeatureCollection" (the default), the return will be an array
+     *     of <OpenLayers.Feature.Vector>. If type is "Geometry", the input json
+     *     must represent a single geometry, and the return will be an
+     *     <OpenLayers.Geometry>.  If type is "Feature", the input json must
+     *     represent a single feature, and the return will be an
+     *     <OpenLayers.Feature.Vector>.
+     */
+    read: function(json, type, filter) {
+        type = (type) ? type : "FeatureCollection";
+        var results = null;
+        var obj = null;
+        if (typeof json == "string") {
+            obj = OpenLayers.Format.JSON.prototype.read.apply(this,
+                                                              [json, filter]);
+        } else { 
+            obj = json;
+        }    
+        if(!obj) {
+            OpenLayers.Console.error("Bad JSON: " + json);
+        } else if(typeof(obj.type) != "string") {
+            OpenLayers.Console.error("Bad GeoJSON - no type: " + json);
+        } else if(this.isValidType(obj, type)) {
+            switch(type) {
+                case "Geometry":
+                    try {
+                        results = this.parseGeometry(obj);
+                    } catch(err) {
+                        OpenLayers.Console.error(err);
+                    }
+                    break;
+                case "Feature":
+                    try {
+                        results = this.parseFeature(obj);
+                        results.type = "Feature";
+                    } catch(err) {
+                        OpenLayers.Console.error(err);
+                    }
+                    break;
+                case "FeatureCollection":
+                    // for type FeatureCollection, we allow input to be any type
+                    results = [];
+                    switch(obj.type) {
+                        case "Feature":
+                            try {
+                                results.push(this.parseFeature(obj));
+                            } catch(err) {
+                                results = null;
+                                OpenLayers.Console.error(err);
+                            }
+                            break;
+                        case "FeatureCollection":
+                            for(var i=0, len=obj.features.length; i<len; ++i) {
+                                try {
+                                    results.push(this.parseFeature(obj.features[i]));
+                                } catch(err) {
+                                    results = null;
+                                    OpenLayers.Console.error(err);
+                                }
+                            }
+                            break;
+                        default:
+                            try {
+                                var geom = this.parseGeometry(obj);
+                                results.push(new OpenLayers.Feature.Vector(geom));
+                            } catch(err) {
+                                results = null;
+                                OpenLayers.Console.error(err);
+                            }
+                    }
+                break;
+            }
+        }
+        return results;
+    },
+    
+    /**
+     * Method: isValidType
+     * Check if a GeoJSON object is a valid representative of the given type.
+     *
+     * Returns:
+     * {Boolean} The object is valid GeoJSON object of the given type.
+     */
+    isValidType: function(obj, type) {
+        var valid = false;
+        switch(type) {
+            case "Geometry":
+                if(OpenLayers.Util.indexOf(
+                    ["Point", "MultiPoint", "LineString", "MultiLineString",
+                     "Polygon", "MultiPolygon", "Box", "GeometryCollection"],
+                    obj.type) == -1) {
+                    // unsupported geometry type
+                    OpenLayers.Console.error("Unsupported geometry type: " +
+                                              obj.type);
+                } else {
+                    valid = true;
+                }
+                break;
+            case "FeatureCollection":
+                // allow for any type to be converted to a feature collection
+                valid = true;
+                break;
+            default:
+                // for Feature types must match
+                if(obj.type == type) {
+                    valid = true;
+                } else {
+                    OpenLayers.Console.error("Cannot convert types from " +
+                                              obj.type + " to " + type);
+                }
+        }
+        return valid;
+    },
+    
+    /**
+     * Method: parseFeature
+     * Convert a feature object from GeoJSON into an
+     *     <OpenLayers.Feature.Vector>.
+     *
+     * Parameters:
+     * obj - {Object} An object created from a GeoJSON object
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature.
+     */
+    parseFeature: function(obj) {
+        var feature, geometry, attributes, bbox;
+        attributes = (obj.properties) ? obj.properties : {};
+        bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;
+        try {
+            geometry = this.parseGeometry(obj.geometry);
+        } catch(err) {
+            // deal with bad geometries
+            throw err;
+        }
+        feature = new OpenLayers.Feature.Vector(geometry, attributes);
+        if(bbox) {
+            feature.bounds = OpenLayers.Bounds.fromArray(bbox);
+        }
+        if(obj.id) {
+            feature.fid = obj.id;
+        }
+        return feature;
+    },
+    
+    /**
+     * Method: parseGeometry
+     * Convert a geometry object from GeoJSON into an <OpenLayers.Geometry>.
+     *
+     * Parameters:
+     * obj - {Object} An object created from a GeoJSON object
+     *
+     * Returns: 
+     * {<OpenLayers.Geometry>} A geometry.
+     */
+    parseGeometry: function(obj) {
+        if (obj == null) {
+            return null;
+        }
+        var geometry, collection = false;
+        if(obj.type == "GeometryCollection") {
+            if(!(OpenLayers.Util.isArray(obj.geometries))) {
+                throw "GeometryCollection must have geometries array: " + obj;
+            }
+            var numGeom = obj.geometries.length;
+            var components = new Array(numGeom);
+            for(var i=0; i<numGeom; ++i) {
+                components[i] = this.parseGeometry.apply(
+                    this, [obj.geometries[i]]
+                );
+            }
+            geometry = new OpenLayers.Geometry.Collection(components);
+            collection = true;
+        } else {
+            if(!(OpenLayers.Util.isArray(obj.coordinates))) {
+                throw "Geometry must have coordinates array: " + obj;
+            }
+            if(!this.parseCoords[obj.type.toLowerCase()]) {
+                throw "Unsupported geometry type: " + obj.type;
+            }
+            try {
+                geometry = this.parseCoords[obj.type.toLowerCase()].apply(
+                    this, [obj.coordinates]
+                );
+            } catch(err) {
+                // deal with bad coordinates
+                throw err;
+            }
+        }
+        // We don't reproject collections because the children are reprojected
+        // for us when they are created.
+        if (this.internalProjection && this.externalProjection && !collection) {
+            geometry.transform(this.externalProjection, 
+                               this.internalProjection); 
+        }                       
+        return geometry;
+    },
+    
+    /**
+     * Property: parseCoords
+     * Object with properties corresponding to the GeoJSON geometry types.
+     *     Property values are functions that do the actual parsing.
+     */
+    parseCoords: {
+        /**
+         * Method: parseCoords.point
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array - {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "point": function(array) {
+            if (this.ignoreExtraDims == false && 
+                  array.length != 2) {
+                    throw "Only 2D points are supported: " + array;
+            }
+            return new OpenLayers.Geometry.Point(array[0], array[1]);
+        },
+        
+        /**
+         * Method: parseCoords.multipoint
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "multipoint": function(array) {
+            var points = [];
+            var p = null;
+            for(var i=0, len=array.length; i<len; ++i) {
+                try {
+                    p = this.parseCoords["point"].apply(this, [array[i]]);
+                } catch(err) {
+                    throw err;
+                }
+                points.push(p);
+            }
+            return new OpenLayers.Geometry.MultiPoint(points);
+        },
+
+        /**
+         * Method: parseCoords.linestring
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array - {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "linestring": function(array) {
+            var points = [];
+            var p = null;
+            for(var i=0, len=array.length; i<len; ++i) {
+                try {
+                    p = this.parseCoords["point"].apply(this, [array[i]]);
+                } catch(err) {
+                    throw err;
+                }
+                points.push(p);
+            }
+            return new OpenLayers.Geometry.LineString(points);
+        },
+        
+        /**
+         * Method: parseCoords.multilinestring
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array - {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "multilinestring": function(array) {
+            var lines = [];
+            var l = null;
+            for(var i=0, len=array.length; i<len; ++i) {
+                try {
+                    l = this.parseCoords["linestring"].apply(this, [array[i]]);
+                } catch(err) {
+                    throw err;
+                }
+                lines.push(l);
+            }
+            return new OpenLayers.Geometry.MultiLineString(lines);
+        },
+        
+        /**
+         * Method: parseCoords.polygon
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "polygon": function(array) {
+            var rings = [];
+            var r, l;
+            for(var i=0, len=array.length; i<len; ++i) {
+                try {
+                    l = this.parseCoords["linestring"].apply(this, [array[i]]);
+                } catch(err) {
+                    throw err;
+                }
+                r = new OpenLayers.Geometry.LinearRing(l.components);
+                rings.push(r);
+            }
+            return new OpenLayers.Geometry.Polygon(rings);
+        },
+
+        /**
+         * Method: parseCoords.multipolygon
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array - {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "multipolygon": function(array) {
+            var polys = [];
+            var p = null;
+            for(var i=0, len=array.length; i<len; ++i) {
+                try {
+                    p = this.parseCoords["polygon"].apply(this, [array[i]]);
+                } catch(err) {
+                    throw err;
+                }
+                polys.push(p);
+            }
+            return new OpenLayers.Geometry.MultiPolygon(polys);
+        },
+
+        /**
+         * Method: parseCoords.box
+         * Convert a coordinate array from GeoJSON into an
+         *     <OpenLayers.Geometry>.
+         *
+         * Parameters:
+         * array - {Object} The coordinates array from the GeoJSON fragment.
+         *
+         * Returns:
+         * {<OpenLayers.Geometry>} A geometry.
+         */
+        "box": function(array) {
+            if(array.length != 2) {
+                throw "GeoJSON box coordinates must have 2 elements";
+            }
+            return new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(array[0][0], array[0][1]),
+                    new OpenLayers.Geometry.Point(array[1][0], array[0][1]),
+                    new OpenLayers.Geometry.Point(array[1][0], array[1][1]),
+                    new OpenLayers.Geometry.Point(array[0][0], array[1][1]),
+                    new OpenLayers.Geometry.Point(array[0][0], array[0][1])
+                ])
+            ]);
+        }
+
+    },
+
+    /**
+     * APIMethod: write
+     * Serialize a feature, geometry, array of features into a GeoJSON string.
+     *
+     * Parameters:
+     * obj - {Object} An <OpenLayers.Feature.Vector>, <OpenLayers.Geometry>,
+     *     or an array of features.
+     * pretty - {Boolean} Structure the output with newlines and indentation.
+     *     Default is false.
+     *
+     * Returns:
+     * {String} The GeoJSON string representation of the input geometry,
+     *     features, or array of features.
+     */
+    write: function(obj, pretty) {
+        var geojson = {
+            "type": null
+        };
+        if(OpenLayers.Util.isArray(obj)) {
+            geojson.type = "FeatureCollection";
+            var numFeatures = obj.length;
+            geojson.features = new Array(numFeatures);
+            for(var i=0; i<numFeatures; ++i) {
+                var element = obj[i];
+                if(!element instanceof OpenLayers.Feature.Vector) {
+                    var msg = "FeatureCollection only supports collections " +
+                              "of features: " + element;
+                    throw msg;
+                }
+                geojson.features[i] = this.extract.feature.apply(
+                    this, [element]
+                );
+            }
+        } else if (obj.CLASS_NAME.indexOf("OpenLayers.Geometry") == 0) {
+            geojson = this.extract.geometry.apply(this, [obj]);
+        } else if (obj instanceof OpenLayers.Feature.Vector) {
+            geojson = this.extract.feature.apply(this, [obj]);
+            if(obj.layer && obj.layer.projection) {
+                geojson.crs = this.createCRSObject(obj);
+            }
+        }
+        return OpenLayers.Format.JSON.prototype.write.apply(this,
+                                                            [geojson, pretty]);
+    },
+
+    /**
+     * Method: createCRSObject
+     * Create the CRS object for an object.
+     *
+     * Parameters:
+     * object - {<OpenLayers.Feature.Vector>} 
+     *
+     * Returns:
+     * {Object} An object which can be assigned to the crs property
+     * of a GeoJSON object.
+     */
+    createCRSObject: function(object) {
+       var proj = object.layer.projection.toString();
+       var crs = {};
+       if (proj.match(/epsg:/i)) {
+           var code = parseInt(proj.substring(proj.indexOf(":") + 1));
+           if (code == 4326) {
+               crs = {
+                   "type": "name",
+                   "properties": {
+                       "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
+                   }
+               };
+           } else {    
+               crs = {
+                   "type": "name",
+                   "properties": {
+                       "name": "EPSG:" + code
+                   }
+               };
+           }    
+       }
+       return crs;
+    },
+    
+    /**
+     * Property: extract
+     * Object with properties corresponding to the GeoJSON types.
+     *     Property values are functions that do the actual value extraction.
+     */
+    extract: {
+        /**
+         * Method: extract.feature
+         * Return a partial GeoJSON object representing a single feature.
+         *
+         * Parameters:
+         * feature - {<OpenLayers.Feature.Vector>}
+         *
+         * Returns:
+         * {Object} An object representing the point.
+         */
+        'feature': function(feature) {
+            var geom = this.extract.geometry.apply(this, [feature.geometry]);
+            var json = {
+                "type": "Feature",
+                "properties": feature.attributes,
+                "geometry": geom
+            };
+            if (feature.fid != null) {
+                json.id = feature.fid;
+            }
+            return json;
+        },
+        
+        /**
+         * Method: extract.geometry
+         * Return a GeoJSON object representing a single geometry.
+         *
+         * Parameters:
+         * geometry - {<OpenLayers.Geometry>}
+         *
+         * Returns:
+         * {Object} An object representing the geometry.
+         */
+        'geometry': function(geometry) {
+            if (geometry == null) {
+                return null;
+            }
+            if (this.internalProjection && this.externalProjection) {
+                geometry = geometry.clone();
+                geometry.transform(this.internalProjection, 
+                                   this.externalProjection);
+            }                       
+            var geometryType = geometry.CLASS_NAME.split('.')[2];
+            var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);
+            var json;
+            if(geometryType == "Collection") {
+                json = {
+                    "type": "GeometryCollection",
+                    "geometries": data
+                };
+            } else {
+                json = {
+                    "type": geometryType,
+                    "coordinates": data
+                };
+            }
+            
+            return json;
+        },
+
+        /**
+         * Method: extract.point
+         * Return an array of coordinates from a point.
+         *
+         * Parameters:
+         * point - {<OpenLayers.Geometry.Point>}
+         *
+         * Returns: 
+         * {Array} An array of coordinates representing the point.
+         */
+        'point': function(point) {
+            return [point.x, point.y];
+        },
+
+        /**
+         * Method: extract.multipoint
+         * Return an array of point coordinates from a multipoint.
+         *
+         * Parameters:
+         * multipoint - {<OpenLayers.Geometry.MultiPoint>}
+         *
+         * Returns:
+         * {Array} An array of point coordinate arrays representing
+         *     the multipoint.
+         */
+        'multipoint': function(multipoint) {
+            var array = [];
+            for(var i=0, len=multipoint.components.length; i<len; ++i) {
+                array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+            }
+            return array;
+        },
+        
+        /**
+         * Method: extract.linestring
+         * Return an array of coordinate arrays from a linestring.
+         *
+         * Parameters:
+         * linestring - {<OpenLayers.Geometry.LineString>}
+         *
+         * Returns:
+         * {Array} An array of coordinate arrays representing
+         *     the linestring.
+         */
+        'linestring': function(linestring) {
+            var array = [];
+            for(var i=0, len=linestring.components.length; i<len; ++i) {
+                array.push(this.extract.point.apply(this, [linestring.components[i]]));
+            }
+            return array;
+        },
+
+        /**
+         * Method: extract.multilinestring
+         * Return an array of linestring arrays from a linestring.
+         * 
+         * Parameters:
+         * linestring - {<OpenLayers.Geometry.MultiLineString>}
+         * 
+         * Returns:
+         * {Array} An array of linestring arrays representing
+         *     the multilinestring.
+         */
+        'multilinestring': function(multilinestring) {
+            var array = [];
+            for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+                array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));
+            }
+            return array;
+        },
+        
+        /**
+         * Method: extract.polygon
+         * Return an array of linear ring arrays from a polygon.
+         *
+         * Parameters:
+         * polygon - {<OpenLayers.Geometry.Polygon>}
+         * 
+         * Returns:
+         * {Array} An array of linear ring arrays representing the polygon.
+         */
+        'polygon': function(polygon) {
+            var array = [];
+            for(var i=0, len=polygon.components.length; i<len; ++i) {
+                array.push(this.extract.linestring.apply(this, [polygon.components[i]]));
+            }
+            return array;
+        },
+
+        /**
+         * Method: extract.multipolygon
+         * Return an array of polygon arrays from a multipolygon.
+         * 
+         * Parameters:
+         * multipolygon - {<OpenLayers.Geometry.MultiPolygon>}
+         * 
+         * Returns:
+         * {Array} An array of polygon arrays representing
+         *     the multipolygon
+         */
+        'multipolygon': function(multipolygon) {
+            var array = [];
+            for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+                array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));
+            }
+            return array;
+        },
+        
+        /**
+         * Method: extract.collection
+         * Return an array of geometries from a geometry collection.
+         * 
+         * Parameters:
+         * collection - {<OpenLayers.Geometry.Collection>}
+         * 
+         * Returns:
+         * {Array} An array of geometry objects representing the geometry
+         *     collection.
+         */
+        'collection': function(collection) {
+            var len = collection.components.length;
+            var array = new Array(len);
+            for(var i=0; i<len; ++i) {
+                array[i] = this.extract.geometry.apply(
+                    this, [collection.components[i]]
+                );
+            }
+            return array;
+        }
+        
+
+    },
+
+    CLASS_NAME: "OpenLayers.Format.GeoJSON" 
+
+});     
+/* ======================================================================
+    OpenLayers/Strategy/Paging.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Paging
+ * Strategy for vector feature paging
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Paging = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * Property: features
+     * {Array(<OpenLayers.Feature.Vector>)} Cached features.
+     */
+    features: null,
+    
+    /**
+     * Property: length
+     * {Integer} Number of features per page.  Default is 10.
+     */
+    length: 10,
+    
+    /**
+     * Property: num
+     * {Integer} The currently displayed page number.
+     */
+    num: null,
+    
+    /**
+     * Property: paging
+     * {Boolean} The strategy is currently changing pages.
+     */
+    paging: false,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Paging
+     * Create a new paging strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    
+    /**
+     * APIMethod: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            this.layer.events.on({
+                "beforefeaturesadded": this.cacheFeatures,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy.  Unregister any listeners, do appropriate
+     *     tear-down.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.clearCache();
+            this.layer.events.un({
+                "beforefeaturesadded": this.cacheFeatures,
+                scope: this
+            });
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: cacheFeatures
+     * Cache features before they are added to the layer.
+     *
+     * Parameters:
+     * event - {Object} The event that this was listening for.  This will come
+     *     with a batch of features to be paged.
+     */
+    cacheFeatures: function(event) {
+        if(!this.paging) {
+            this.clearCache();
+            this.features = event.features;
+            this.pageNext(event);
+        }
+    },
+    
+    /**
+     * Method: clearCache
+     * Clear out the cached features.  This destroys features, assuming
+     *     nothing else has a reference.
+     */
+    clearCache: function() {
+        if(this.features) {
+            for(var i=0; i<this.features.length; ++i) {
+                this.features[i].destroy();
+            }
+        }
+        this.features = null;
+        this.num = null;
+    },
+    
+    /**
+     * APIMethod: pageCount
+     * Get the total count of pages given the current cache of features.
+     *
+     * Returns:
+     * {Integer} The page count.
+     */
+    pageCount: function() {
+        var numFeatures = this.features ? this.features.length : 0;
+        return Math.ceil(numFeatures / this.length);
+    },
+
+    /**
+     * APIMethod: pageNum
+     * Get the zero based page number.
+     *
+     * Returns:
+     * {Integer} The current page number being displayed.
+     */
+    pageNum: function() {
+        return this.num;
+    },
+
+    /**
+     * APIMethod: pageLength
+     * Gets or sets page length.
+     *
+     * Parameters:
+     * newLength: {Integer} Optional length to be set.
+     *
+     * Returns:
+     * {Integer} The length of a page (number of features per page).
+     */
+    pageLength: function(newLength) {
+        if(newLength && newLength > 0) {
+            this.length = newLength;
+        }
+        return this.length;
+    },
+
+    /**
+     * APIMethod: pageNext
+     * Display the next page of features.
+     *
+     * Returns:
+     * {Boolean} A new page was displayed.
+     */
+    pageNext: function(event) {
+        var changed = false;
+        if(this.features) {
+            if(this.num === null) {
+                this.num = -1;
+            }
+            var start = (this.num + 1) * this.length;
+            changed = this.page(start, event);
+        }
+        return changed;
+    },
+
+    /**
+     * APIMethod: pagePrevious
+     * Display the previous page of features.
+     *
+     * Returns:
+     * {Boolean} A new page was displayed.
+     */
+    pagePrevious: function() {
+        var changed = false;
+        if(this.features) {
+            if(this.num === null) {
+                this.num = this.pageCount();
+            }
+            var start = (this.num - 1) * this.length;
+            changed = this.page(start);
+        }
+        return changed;
+    },
+    
+    /**
+     * Method: page
+     * Display the page starting at the given index from the cache.
+     *
+     * Returns:
+     * {Boolean} A new page was displayed.
+     */
+    page: function(start, event) {
+        var changed = false;
+        if(this.features) {
+            if(start >= 0 && start < this.features.length) {
+                var num = Math.floor(start / this.length);
+                if(num != this.num) {
+                    this.paging = true;
+                    var features = this.features.slice(start, start + this.length);
+                    this.layer.removeFeatures(this.layer.features);
+                    this.num = num;
+                    // modify the event if any
+                    if(event && event.features) {
+                        // this.was called by an event listener
+                        event.features = features;
+                    } else {
+                        // this was called directly on the strategy
+                        this.layer.addFeatures(features);
+                    }
+                    this.paging = false;
+                    changed = true;
+                }
+            }
+        }
+        return changed;
+    },
+    
+    CLASS_NAME: "OpenLayers.Strategy.Paging" 
+});
+/* ======================================================================
+    OpenLayers/Popup/Anchored.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Popup.js
+ */
+
+/**
+ * Class: OpenLayers.Popup.Anchored
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Popup>
+ */
+OpenLayers.Popup.Anchored = 
+  OpenLayers.Class(OpenLayers.Popup, {
+
+    /** 
+     * Parameter: relativePosition
+     * {String} Relative position of the popup ("br", "tr", "tl" or "bl").
+     */
+    relativePosition: null,
+    
+    /**
+     * APIProperty: keepInMap 
+     * {Boolean} If panMapIfOutOfView is false, and this property is true, 
+     *     contrain the popup such that it always fits in the available map
+     *     space. By default, this is set. If you are creating popups that are
+     *     near map edges and not allowing pannning, and especially if you have
+     *     a popup which has a fixedRelativePosition, setting this to false may
+     *     be a smart thing to do.
+     *   
+     *     For anchored popups, default is true, since subclasses will
+     *     usually want this functionality.
+     */
+    keepInMap: true,
+
+    /**
+     * Parameter: anchor
+     * {Object} Object to which we'll anchor the popup. Must expose a 
+     *     'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>).
+     */
+    anchor: null,
+
+    /** 
+    * Constructor: OpenLayers.Popup.Anchored
+    * 
+    * Parameters:
+    * id - {String}
+    * lonlat - {<OpenLayers.LonLat>}
+    * contentSize - {<OpenLayers.Size>}
+    * contentHTML - {String}
+    * anchor - {Object} Object which must expose a 'size' <OpenLayers.Size> 
+    *     and 'offset' <OpenLayers.Pixel> (generally an <OpenLayers.Icon>).
+    * closeBox - {Boolean}
+    * closeBoxCallback - {Function} Function to be called on closeBox click.
+    */
+    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
+                        closeBoxCallback) {
+        var newArguments = [
+            id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback
+        ];
+        OpenLayers.Popup.prototype.initialize.apply(this, newArguments);
+
+        this.anchor = (anchor != null) ? anchor 
+                                       : { size: new OpenLayers.Size(0,0),
+                                           offset: new OpenLayers.Pixel(0,0)};
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.anchor = null;
+        this.relativePosition = null;
+        
+        OpenLayers.Popup.prototype.destroy.apply(this, arguments);        
+    },
+
+    /**
+     * APIMethod: show
+     * Overridden from Popup since user might hide popup and then show() it 
+     *     in a new location (meaning we might want to update the relative
+     *     position on the show)
+     */
+    show: function() {
+        this.updatePosition();
+        OpenLayers.Popup.prototype.show.apply(this, arguments);
+    },
+
+    /**
+     * Method: moveTo
+     * Since the popup is moving to a new px, it might need also to be moved
+     *     relative to where the marker is. We first calculate the new 
+     *     relativePosition, and then we calculate the new px where we will 
+     *     put the popup, based on the new relative position. 
+     * 
+     *     If the relativePosition has changed, we must also call 
+     *     updateRelativePosition() to make any visual changes to the popup 
+     *     which are associated with putting it in a new relativePosition.
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     */
+    moveTo: function(px) {
+        var oldRelativePosition = this.relativePosition;
+        this.relativePosition = this.calculateRelativePosition(px);
+        
+        var newPx = this.calculateNewPx(px);
+        
+        var newArguments = new Array(newPx);        
+        OpenLayers.Popup.prototype.moveTo.apply(this, newArguments);
+        
+        //if this move has caused the popup to change its relative position, 
+        // we need to make the appropriate cosmetic changes.
+        if (this.relativePosition != oldRelativePosition) {
+            this.updateRelativePosition();
+        }
+    },
+
+    /**
+     * APIMethod: setSize
+     * 
+     * Parameters:
+     * contentSize - {<OpenLayers.Size>} the new size for the popup's 
+     *     contents div (in pixels).
+     */
+    setSize:function(contentSize) { 
+        OpenLayers.Popup.prototype.setSize.apply(this, arguments);
+
+        if ((this.lonlat) && (this.map)) {
+            var px = this.map.getLayerPxFromLonLat(this.lonlat);
+            this.moveTo(px);
+        }
+    },  
+    
+    /** 
+     * Method: calculateRelativePosition
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {String} The relative position ("br" "tr" "tl" "bl") at which the popup
+     *     should be placed.
+     */
+    calculateRelativePosition:function(px) {
+        var lonlat = this.map.getLonLatFromLayerPx(px);        
+        
+        var extent = this.map.getExtent();
+        var quadrant = extent.determineQuadrant(lonlat);
+        
+        return OpenLayers.Bounds.oppositeQuadrant(quadrant);
+    }, 
+
+    /**
+     * Method: updateRelativePosition
+     * The popup has been moved to a new relative location, so we may want to 
+     *     make some cosmetic adjustments to it. 
+     * 
+     *     Note that in the classic Anchored popup, there is nothing to do 
+     *     here, since the popup looks exactly the same in all four positions.
+     *     Subclasses such as the AnchoredBubble and Framed, however, will 
+     *     want to do something special here.
+     */
+    updateRelativePosition: function() {
+        //to be overridden by subclasses
+    },
+
+    /** 
+     * Method: calculateNewPx
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} The the new px position of the popup on the screen
+     *     relative to the passed-in px.
+     */
+    calculateNewPx:function(px) {
+        var newPx = px.offset(this.anchor.offset);
+        
+        //use contentSize if size is not already set
+        var size = this.size || this.contentSize;
+
+        var top = (this.relativePosition.charAt(0) == 't');
+        newPx.y += (top) ? -size.h : this.anchor.size.h;
+        
+        var left = (this.relativePosition.charAt(1) == 'l');
+        newPx.x += (left) ? -size.w : this.anchor.size.w;
+
+        return newPx;   
+    },
+
+    CLASS_NAME: "OpenLayers.Popup.Anchored"
+});
+/* ======================================================================
+    OpenLayers/Popup/Framed.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Popup/Anchored.js
+ */
+
+/**
+ * Class: OpenLayers.Popup.Framed
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Popup.Anchored>
+ */
+OpenLayers.Popup.Framed =
+  OpenLayers.Class(OpenLayers.Popup.Anchored, {
+
+    /**
+     * Property: imageSrc
+     * {String} location of the image to be used as the popup frame
+     */
+    imageSrc: null,
+
+    /**
+     * Property: imageSize
+     * {<OpenLayers.Size>} Size (measured in pixels) of the image located
+     *     by the 'imageSrc' property.
+     */
+    imageSize: null,
+
+    /**
+     * APIProperty: isAlphaImage
+     * {Boolean} The image has some alpha and thus needs to use the alpha 
+     *     image hack. Note that setting this to true will have no noticeable
+     *     effect in FF or IE7 browsers, but will all but crush the ie6 
+     *     browser. 
+     *     Default is false.
+     */
+    isAlphaImage: false,
+
+    /**
+     * Property: positionBlocks
+     * {Object} Hash of different position blocks (Object/Hashs). Each block 
+     *     will be keyed by a two-character 'relativePosition' 
+     *     code string (ie "tl", "tr", "bl", "br"). Block properties are 
+     *     'offset', 'padding' (self-explanatory), and finally the 'blocks'
+     *     parameter, which is an array of the block objects. 
+     * 
+     *     Each block object must have 'size', 'anchor', and 'position' 
+     *     properties.
+     * 
+     *     Note that positionBlocks should never be modified at runtime.
+     */
+    positionBlocks: null,
+
+    /**
+     * Property: blocks
+     * {Array[Object]} Array of objects, each of which is one "block" of the 
+     *     popup. Each block has a 'div' and an 'image' property, both of 
+     *     which are DOMElements, and the latter of which is appended to the 
+     *     former. These are reused as the popup goes changing positions for
+     *     great economy and elegance.
+     */
+    blocks: null,
+
+    /** 
+     * APIProperty: fixedRelativePosition
+     * {Boolean} We want the framed popup to work dynamically placed relative
+     *     to its anchor but also in just one fixed position. A well designed
+     *     framed popup will have the pixels and logic to display itself in 
+     *     any of the four relative positions, but (understandably), this will
+     *     not be the case for all of them. By setting this property to 'true', 
+     *     framed popup will not recalculate for the best placement each time
+     *     it's open, but will always open the same way. 
+     *     Note that if this is set to true, it is generally advisable to also
+     *     set the 'panIntoView' property to true so that the popup can be 
+     *     scrolled into view (since it will often be offscreen on open)
+     *     Default is false.
+     */
+    fixedRelativePosition: false,
+
+    /** 
+     * Constructor: OpenLayers.Popup.Framed
+     * 
+     * Parameters:
+     * id - {String}
+     * lonlat - {<OpenLayers.LonLat>}
+     * contentSize - {<OpenLayers.Size>}
+     * contentHTML - {String}
+     * anchor - {Object} Object to which we'll anchor the popup. Must expose 
+     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>) 
+     *     (Note that this is generally an <OpenLayers.Icon>).
+     * closeBox - {Boolean}
+     * closeBoxCallback - {Function} Function to be called on closeBox click.
+     */
+    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox, 
+                        closeBoxCallback) {
+
+        OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments);
+
+        if (this.fixedRelativePosition) {
+            //based on our decided relativePostion, set the current padding
+            // this keeps us from getting into trouble 
+            this.updateRelativePosition();
+            
+            //make calculateRelativePosition always return the specified
+            // fixed position.
+            this.calculateRelativePosition = function(px) {
+                return this.relativePosition;
+            };
+        }
+
+        this.contentDiv.style.position = "absolute";
+        this.contentDiv.style.zIndex = 1;
+
+        if (closeBox) {
+            this.closeDiv.style.zIndex = 1;
+        }
+
+        this.groupDiv.style.position = "absolute";
+        this.groupDiv.style.top = "0px";
+        this.groupDiv.style.left = "0px";
+        this.groupDiv.style.height = "100%";
+        this.groupDiv.style.width = "100%";
+    },
+
+    /** 
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.imageSrc = null;
+        this.imageSize = null;
+        this.isAlphaImage = null;
+
+        this.fixedRelativePosition = false;
+        this.positionBlocks = null;
+
+        //remove our blocks
+        for(var i = 0; i < this.blocks.length; i++) {
+            var block = this.blocks[i];
+
+            if (block.image) {
+                block.div.removeChild(block.image);
+            }
+            block.image = null;
+
+            if (block.div) {
+                this.groupDiv.removeChild(block.div);
+            }
+            block.div = null;
+        }
+        this.blocks = null;
+
+        OpenLayers.Popup.Anchored.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: setBackgroundColor
+     */
+    setBackgroundColor:function(color) {
+        //does nothing since the framed popup's entire scheme is based on a 
+        // an image -- changing the background color makes no sense. 
+    },
+
+    /**
+     * APIMethod: setBorder
+     */
+    setBorder:function() {
+        //does nothing since the framed popup's entire scheme is based on a 
+        // an image -- changing the popup's border makes no sense. 
+    },
+
+    /**
+     * Method: setOpacity
+     * Sets the opacity of the popup.
+     * 
+     * Parameters:
+     * opacity - {float} A value between 0.0 (transparent) and 1.0 (solid).   
+     */
+    setOpacity:function(opacity) {
+        //does nothing since we suppose that we'll never apply an opacity
+        // to a framed popup
+    },
+
+    /**
+     * APIMethod: setSize
+     * Overridden here, because we need to update the blocks whenever the size
+     *     of the popup has changed.
+     * 
+     * Parameters:
+     * contentSize - {<OpenLayers.Size>} the new size for the popup's 
+     *     contents div (in pixels).
+     */
+    setSize:function(contentSize) { 
+        OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments);
+
+        this.updateBlocks();
+    },
+
+    /**
+     * Method: updateRelativePosition
+     * When the relative position changes, we need to set the new padding 
+     *     BBOX on the popup, reposition the close div, and update the blocks.
+     */
+    updateRelativePosition: function() {
+
+        //update the padding
+        this.padding = this.positionBlocks[this.relativePosition].padding;
+
+        //update the position of our close box to new padding
+        if (this.closeDiv) {
+            // use the content div's css padding to determine if we should
+            //  padd the close div
+            var contentDivPadding = this.getContentDivPadding();
+
+            this.closeDiv.style.right = contentDivPadding.right + 
+                                        this.padding.right + "px";
+            this.closeDiv.style.top = contentDivPadding.top + 
+                                      this.padding.top + "px";
+        }
+
+        this.updateBlocks();
+    },
+
+    /** 
+     * Method: calculateNewPx
+     * Besides the standard offset as determined by the Anchored class, our 
+     *     Framed popups have a special 'offset' property for each of their 
+     *     positions, which is used to offset the popup relative to its anchor.
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} The the new px position of the popup on the screen
+     *     relative to the passed-in px.
+     */
+    calculateNewPx:function(px) {
+        var newPx = OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(
+            this, arguments
+        );
+
+        newPx = newPx.offset(this.positionBlocks[this.relativePosition].offset);
+
+        return newPx;
+    },
+
+    /**
+     * Method: createBlocks
+     */
+    createBlocks: function() {
+        this.blocks = [];
+
+        //since all positions contain the same number of blocks, we can 
+        // just pick the first position and use its blocks array to create
+        // our blocks array
+        var firstPosition = null;
+        for(var key in this.positionBlocks) {
+            firstPosition = key;
+            break;
+        }
+        
+        var position = this.positionBlocks[firstPosition];
+        for (var i = 0; i < position.blocks.length; i++) {
+
+            var block = {};
+            this.blocks.push(block);
+
+            var divId = this.id + '_FrameDecorationDiv_' + i;
+            block.div = OpenLayers.Util.createDiv(divId, 
+                null, null, null, "absolute", null, "hidden", null
+            );
+
+            var imgId = this.id + '_FrameDecorationImg_' + i;
+            var imageCreator = 
+                (this.isAlphaImage) ? OpenLayers.Util.createAlphaImageDiv
+                                    : OpenLayers.Util.createImage;
+
+            block.image = imageCreator(imgId, 
+                null, this.imageSize, this.imageSrc, 
+                "absolute", null, null, null
+            );
+
+            block.div.appendChild(block.image);
+            this.groupDiv.appendChild(block.div);
+        }
+    },
+
+    /**
+     * Method: updateBlocks
+     * Internal method, called on initialize and when the popup's relative
+     *     position has changed. This function takes care of re-positioning
+     *     the popup's blocks in their appropropriate places.
+     */
+    updateBlocks: function() {
+        if (!this.blocks) {
+            this.createBlocks();
+        }
+        
+        if (this.size && this.relativePosition) {
+            var position = this.positionBlocks[this.relativePosition];
+            for (var i = 0; i < position.blocks.length; i++) {
+    
+                var positionBlock = position.blocks[i];
+                var block = this.blocks[i];
+    
+                // adjust sizes
+                var l = positionBlock.anchor.left;
+                var b = positionBlock.anchor.bottom;
+                var r = positionBlock.anchor.right;
+                var t = positionBlock.anchor.top;
+    
+                //note that we use the isNaN() test here because if the 
+                // size object is initialized with a "auto" parameter, the 
+                // size constructor calls parseFloat() on the string, 
+                // which will turn it into NaN
+                //
+                var w = (isNaN(positionBlock.size.w)) ? this.size.w - (r + l) 
+                                                      : positionBlock.size.w;
+    
+                var h = (isNaN(positionBlock.size.h)) ? this.size.h - (b + t) 
+                                                      : positionBlock.size.h;
+    
+                block.div.style.width = (w < 0 ? 0 : w) + 'px';
+                block.div.style.height = (h < 0 ? 0 : h) + 'px';
+    
+                block.div.style.left = (l != null) ? l + 'px' : '';
+                block.div.style.bottom = (b != null) ? b + 'px' : '';
+                block.div.style.right = (r != null) ? r + 'px' : '';            
+                block.div.style.top = (t != null) ? t + 'px' : '';
+    
+                block.image.style.left = positionBlock.position.x + 'px';
+                block.image.style.top = positionBlock.position.y + 'px';
+            }
+    
+            this.contentDiv.style.left = this.padding.left + "px";
+            this.contentDiv.style.top = this.padding.top + "px";
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Popup.Framed"
+});
+/* ======================================================================
+    OpenLayers/Layer/XYZ.js 
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/** 
+ * Class: OpenLayers.Layer.XYZ
+ * The XYZ class is designed to make it easier for people who have tiles
+ * arranged by a standard XYZ grid. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, {
+    
+    /**
+     * APIProperty: isBaseLayer
+     * Default is true, as this is designed to be a base tile source. 
+     */
+    isBaseLayer: true,
+    
+    /**
+     * APIProperty: sphericalMecator
+     * Whether the tile extents should be set to the defaults for 
+     *    spherical mercator. Useful for things like OpenStreetMap.
+     *    Default is false, except for the OSM subclass.
+     */
+    sphericalMercator: false,
+
+    /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more zoom levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
+     *     setting <serverResolutions> if you only want to expose a subset
+     *     of the server resolutions.
+     */
+    zoomOffset: 0,
+    
+    /**
+     * APIProperty: serverResolutions
+     * {Array} A list of all resolutions available on the server.  Only set this
+     *     property if the map resolutions differs from the server.
+     */
+    serverResolutions: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.XYZ
+     *
+     * Parameters:
+     * name - {String}
+     * url - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, options) {
+        if (options && options.sphericalMercator || this.sphericalMercator) {
+            options = OpenLayers.Util.extend({
+                maxExtent: new OpenLayers.Bounds(
+                    -128 * 156543.03390625,
+                    -128 * 156543.03390625,
+                    128 * 156543.03390625,
+                    128 * 156543.03390625
+                ),
+                maxResolution: 156543.03390625,
+                numZoomLevels: 19,
+                units: "m",
+                projection: "EPSG:900913"
+            }, options);
+        }
+        url = url || this.url;
+        name = name || this.name;
+        var newArguments = [name, url, {}, options];
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },
+    
+    /**
+     * APIMethod: clone
+     * Create a clone of this layer
+     *
+     * Parameters:
+     * obj - {Object} Is this ever used?
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.XYZ>} An exact clone of this OpenLayers.Layer.XYZ
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.XYZ(this.name,
+                                            this.url,
+                                            this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        return obj;
+    },    
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as
+     *          parameters
+     */
+    getURL: function (bounds) {
+        var xyz = this.getXYZ(bounds);
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            var s = '' + xyz.x + xyz.y + xyz.z;
+            url = this.selectUrl(s, url);
+        }
+        
+        return OpenLayers.String.format(url, xyz);
+    },
+    
+    /**
+     * Method: getXYZ
+     * Calculates x, y and z for the given bounds.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {Object} - an object with x, y and z properties.
+     */
+    getXYZ: function(bounds) {
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.maxExtent.left) /
+            (res * this.tileSize.w));
+        var y = Math.round((this.maxExtent.top - bounds.top) /
+            (res * this.tileSize.h));
+        var z = this.serverResolutions != null ?
+            OpenLayers.Util.indexOf(this.serverResolutions, res) :
+            this.map.getZoom() + this.zoomOffset;
+
+        var limit = Math.pow(2, z);
+        if (this.wrapDateLine)
+        {
+           x = ((x % limit) + limit) % limit;
+        }
+
+        return {'x': x, 'y': y, 'z': z};
+    },
+    
+    /* APIMethod: setMap
+     * When the layer is added to a map, then we can fetch our origin 
+     *    (if we don't have one.) 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        if (!this.tileOrigin) { 
+            this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left,
+                                                this.maxExtent.bottom);
+        }                                       
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.XYZ"
+});
+
+
+/**
+ * Class: OpenLayers.Layer.OSM
+ * A class to access OpenStreetMap tiles. By default, uses the OpenStreetMap
+ *    hosted tile.openstreetmap.org 'Mapnik' tileset. If you wish to use
+ *    tiles@home / osmarender layer instead, you can pass a layer like:
+ * 
+ * (code)
+ *     new OpenLayers.Layer.OSM("t@h", 
+ *       "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); 
+ * (end)
+ *
+ * This layer defaults to Spherical Mercator.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.XYZ>
+ */
+OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+     name: "OpenStreetMap",
+     attribution: "Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",
+     sphericalMercator: true,
+     url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png',
+     clone: function(obj) {
+         if (obj == null) {
+             obj = new OpenLayers.Layer.OSM(
+                 this.name, this.url, this.getOptions());
+         }
+         obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+         return obj;
+     },
+     wrapDateLine: true,
+     CLASS_NAME: "OpenLayers.Layer.OSM"
+});
+/* ======================================================================
+    OpenLayers/Handler/Box.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ * @requires OpenLayers/Handler/Drag.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Box
+ * Handler for dragging a rectangle across the map.  Box is displayed 
+ * on mouse down, moves on mouse move, and is finished on mouse up.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Handler> 
+ */
+OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
+
+    /** 
+     * Property: dragHandler 
+     * {<OpenLayers.Handler.Drag>} 
+     */
+    dragHandler: null,
+
+    /**
+     * APIProperty: boxDivClassName
+     * {String} The CSS class to use for drawing the box. Default is
+     *     olHandlerBoxZoomBox
+     */
+    boxDivClassName: 'olHandlerBoxZoomBox',
+    
+    /**
+     * Property: boxOffsets
+     * {Object} Caches box offsets from css. This is used by the getBoxOffsets
+     * method.
+     */
+    boxOffsets: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Box
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} 
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} 
+     *
+     * Named callbacks:
+     * start - Called when the box drag operation starts.
+     * done - Called when the box drag operation is finished.
+     *     The callback should expect to receive a single argument, the box 
+     *     bounds or a pixel. If the box dragging didn't span more than a 5 
+     *     pixel distance, a pixel will be returned instead of a bounds object.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+        this.dragHandler = new OpenLayers.Handler.Drag(
+            this, 
+            {
+                down: this.startBox, 
+                move: this.moveBox, 
+                out: this.removeBox,
+                up: this.endBox
+            }, 
+            {keyMask: this.keyMask}
+        );
+    },
+
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        OpenLayers.Handler.prototype.destroy.apply(this, arguments);
+        if (this.dragHandler) {
+            this.dragHandler.destroy();
+            this.dragHandler = null;
+        }            
+    },
+
+    /**
+     * Method: setMap
+     */
+    setMap: function (map) {
+        OpenLayers.Handler.prototype.setMap.apply(this, arguments);
+        if (this.dragHandler) {
+            this.dragHandler.setMap(map);
+        }
+    },
+
+    /**
+    * Method: startBox
+    *
+    * Parameters:
+    * xy - {<OpenLayers.Pixel>}
+    */
+    startBox: function (xy) {
+        this.callback("start", []);
+        this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
+             new OpenLayers.Pixel(-9999, -9999));
+        this.zoomBox.className = this.boxDivClassName;                                         
+        this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
+        
+        this.map.eventsDiv.appendChild(this.zoomBox);
+        
+        OpenLayers.Element.addClass(
+            this.map.eventsDiv, "olDrawBox"
+        );
+    },
+
+    /**
+    * Method: moveBox
+    */
+    moveBox: function (xy) {
+        var startX = this.dragHandler.start.x;
+        var startY = this.dragHandler.start.y;
+        var deltaX = Math.abs(startX - xy.x);
+        var deltaY = Math.abs(startY - xy.y);
+
+        var offset = this.getBoxOffsets();
+        this.zoomBox.style.width = (deltaX + offset.width + 1) + "px";
+        this.zoomBox.style.height = (deltaY + offset.height + 1) + "px";
+        this.zoomBox.style.left = (xy.x < startX ?
+            startX - deltaX - offset.left : startX - offset.left) + "px";
+        this.zoomBox.style.top = (xy.y < startY ?
+            startY - deltaY - offset.top : startY - offset.top) + "px";
+    },
+
+    /**
+    * Method: endBox
+    */
+    endBox: function(end) {
+        var result;
+        if (Math.abs(this.dragHandler.start.x - end.x) > 5 ||    
+            Math.abs(this.dragHandler.start.y - end.y) > 5) {   
+            var start = this.dragHandler.start;
+            var top = Math.min(start.y, end.y);
+            var bottom = Math.max(start.y, end.y);
+            var left = Math.min(start.x, end.x);
+            var right = Math.max(start.x, end.x);
+            result = new OpenLayers.Bounds(left, bottom, right, top);
+        } else {
+            result = this.dragHandler.start.clone(); // i.e. OL.Pixel
+        } 
+        this.removeBox();
+
+        this.callback("done", [result]);
+    },
+
+    /**
+     * Method: removeBox
+     * Remove the zoombox from the screen and nullify our reference to it.
+     */
+    removeBox: function() {
+        this.map.eventsDiv.removeChild(this.zoomBox);
+        this.zoomBox = null;
+        this.boxOffsets = null;
+        OpenLayers.Element.removeClass(
+            this.map.eventsDiv, "olDrawBox"
+        );
+
+    },
+
+    /**
+     * Method: activate
+     */
+    activate: function () {
+        if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            this.dragHandler.activate();
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    /**
+     * Method: deactivate
+     */
+    deactivate: function () {
+        if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            if (this.dragHandler.deactivate()) {
+                if (this.zoomBox) {
+                    this.removeBox();
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * Method: getBoxOffsets
+     * Determines border offsets for a box, according to the box model.
+     * 
+     * Returns:
+     * {Object} an object with the following offsets:
+     *     - left
+     *     - right
+     *     - top
+     *     - bottom
+     *     - width
+     *     - height
+     */
+    getBoxOffsets: function() {
+        if (!this.boxOffsets) {
+            // Determine the box model. If the testDiv's clientWidth is 3, then
+            // the borders are outside and we are dealing with the w3c box
+            // model. Otherwise, the browser uses the traditional box model and
+            // the borders are inside the box bounds, leaving us with a
+            // clientWidth of 1.
+            var testDiv = document.createElement("div");
+            //testDiv.style.visibility = "hidden";
+            testDiv.style.position = "absolute";
+            testDiv.style.border = "1px solid black";
+            testDiv.style.width = "3px";
+            document.body.appendChild(testDiv);
+            var w3cBoxModel = testDiv.clientWidth == 3;
+            document.body.removeChild(testDiv);
+            
+            var left = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
+                "border-left-width"));
+            var right = parseInt(OpenLayers.Element.getStyle(
+                this.zoomBox, "border-right-width"));
+            var top = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
+                "border-top-width"));
+            var bottom = parseInt(OpenLayers.Element.getStyle(
+                this.zoomBox, "border-bottom-width"));
+            this.boxOffsets = {
+                left: left,
+                right: right,
+                top: top,
+                bottom: bottom,
+                width: w3cBoxModel === false ? left + right : 0,
+                height: w3cBoxModel === false ? top + bottom : 0
+            };
+        }
+        return this.boxOffsets;
+    },
+  
+    CLASS_NAME: "OpenLayers.Handler.Box"
+});
+/* ======================================================================
+    OpenLayers/Control/ZoomBox.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Box.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ZoomBox
+ * The ZoomBox control enables zooming directly to a given extent, by drawing 
+ * a box on the map. The box is drawn by holding down shift, whilst dragging 
+ * the mouse.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.ZoomBox = OpenLayers.Class(OpenLayers.Control, {
+    /**
+     * Property: type
+     * {OpenLayers.Control.TYPE}
+     */
+    type: OpenLayers.Control.TYPE_TOOL,
+
+    /**
+     * Property: out
+     * {Boolean} Should the control be used for zooming out?
+     */
+    out: false,
+
+    /**
+     * Property: alwaysZoom
+     * {Boolean} Always zoom in/out, when box drawed 
+     */
+    alwaysZoom: false,
+
+    /**
+     * Method: draw
+     */    
+    draw: function() {
+        this.handler = new OpenLayers.Handler.Box( this,
+                            {done: this.zoomBox}, {keyMask: this.keyMask} );
+    },
+
+    /**
+     * Method: zoomBox
+     *
+     * Parameters:
+     * position - {<OpenLayers.Bounds>} or {<OpenLayers.Pixel>}
+     */
+    zoomBox: function (position) {
+        if (position instanceof OpenLayers.Bounds) {
+            var bounds;
+            if (!this.out) {
+                var minXY = this.map.getLonLatFromPixel(
+                            new OpenLayers.Pixel(position.left, position.bottom));
+                var maxXY = this.map.getLonLatFromPixel(
+                            new OpenLayers.Pixel(position.right, position.top));
+                bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat,
+                                               maxXY.lon, maxXY.lat);
+            } else {
+                var pixWidth = Math.abs(position.right-position.left);
+                var pixHeight = Math.abs(position.top-position.bottom);
+                var zoomFactor = Math.min((this.map.size.h / pixHeight),
+                    (this.map.size.w / pixWidth));
+                var extent = this.map.getExtent();
+                var center = this.map.getLonLatFromPixel(
+                    position.getCenterPixel());
+                var xmin = center.lon - (extent.getWidth()/2)*zoomFactor;
+                var xmax = center.lon + (extent.getWidth()/2)*zoomFactor;
+                var ymin = center.lat - (extent.getHeight()/2)*zoomFactor;
+                var ymax = center.lat + (extent.getHeight()/2)*zoomFactor;
+                bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax);
+            }
+            // always zoom in/out 
+            var lastZoom = this.map.getZoom(); 
+            this.map.zoomToExtent(bounds);
+            if (lastZoom == this.map.getZoom() && this.alwaysZoom == true){ 
+                this.map.zoomTo(lastZoom + (this.out ? -1 : 1)); 
+            }
+        } else { // it's a pixel
+            if (!this.out) {
+                this.map.setCenter(this.map.getLonLatFromPixel(position),
+                               this.map.getZoom() + 1);
+            } else {
+                this.map.setCenter(this.map.getLonLatFromPixel(position),
+                               this.map.getZoom() - 1);
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.ZoomBox"
+});
+/* ======================================================================
+    OpenLayers/Control/DragPan.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Drag.js
+ */
+
+/**
+ * Class: OpenLayers.Control.DragPan
+ * The DragPan control pans the map with a drag of the mouse.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.DragPan = OpenLayers.Class(OpenLayers.Control, {
+
+    /** 
+     * Property: type
+     * {OpenLayers.Control.TYPES}
+     */
+    type: OpenLayers.Control.TYPE_TOOL,
+    
+    /**
+     * Property: panned
+     * {Boolean} The map moved.
+     */
+    panned: false,
+    
+    /**
+     * Property: interval
+     * {Integer} The number of milliseconds that should ellapse before
+     *     panning the map again. Defaults to 1 millisecond. In most cases
+     *     you won't want to change this value. For slow machines/devices
+     *     larger values can be tried out.
+     */
+    interval: 1,
+    
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, mouse dragging will continue even if the
+     *     mouse cursor leaves the map viewport. Default is false.
+     */
+    documentDrag: false,
+
+    /**
+     * Property: kinetic
+     * {OpenLayers.Kinetic} The OpenLayers.Kinetic object.
+     */
+    kinetic: null,
+
+    /**
+     * APIProperty: enableKinetic
+     * {Boolean} Set this option to enable "kinetic dragging". Can be
+     *     set to true or to an object. If set to an object this
+     *     object will be passed to the {<OpenLayers.Kinetic>}
+     *     constructor. Defaults to false.
+     */
+    enableKinetic: false,
+
+    /**
+     * APIProperty: kineticInterval
+     * {Integer} Interval in milliseconds between 2 steps in the "kinetic
+     *     scrolling". Applies only if enableKinetic is set. Defaults
+     *     to 10 milliseconds.
+     */
+    kineticInterval: 10,
+
+
+    /**
+     * Method: draw
+     * Creates a Drag handler, using <panMap> and
+     * <panMapDone> as callbacks.
+     */    
+    draw: function() {
+        if(this.enableKinetic) {
+            var config = {interval: this.kineticInterval};
+            if(typeof this.enableKinetic === "object") {
+                config = OpenLayers.Util.extend(config, this.enableKinetic);
+            }
+            this.kinetic = new OpenLayers.Kinetic(config);
+        }
+        this.handler = new OpenLayers.Handler.Drag(this, {
+                "move": this.panMap,
+                "done": this.panMapDone,
+                "down": this.panMapStart
+            }, {
+                interval: this.interval,
+                documentDrag: this.documentDrag
+            }
+        );
+    },
+
+    /**
+     * Method: panMapStart
+     */
+    panMapStart: function() {
+        if(this.kinetic) {
+            this.kinetic.begin();
+        }
+    },
+
+    /**
+    * Method: panMap
+    *
+    * Parameters:
+    * xy - {<OpenLayers.Pixel>} Pixel of the mouse position
+    */
+    panMap: function(xy) {
+        if(this.kinetic) {
+            this.kinetic.update(xy);
+        }
+        this.panned = true;
+        this.map.pan(
+            this.handler.last.x - xy.x,
+            this.handler.last.y - xy.y,
+            {dragging: true, animate: false}
+        );
+    },
+    
+    /**
+     * Method: panMapDone
+     * Finish the panning operation.  Only call setCenter (through <panMap>)
+     *     if the map has actually been moved.
+     *
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} Pixel of the mouse position
+     */
+    panMapDone: function(xy) {
+        if(this.panned) {
+            var res = null;
+            if (this.kinetic) {
+                res = this.kinetic.end(xy);
+            }
+            this.map.pan(
+                this.handler.last.x - xy.x,
+                this.handler.last.y - xy.y,
+                {dragging: !!res, animate: false}
+            );
+            if (res) {
+                var self = this;
+                this.kinetic.move(res, function(x, y, end) {
+                    self.map.pan(x, y, {dragging: !end, animate: false});
+                });
+            }
+            this.panned = false;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.DragPan"
+});
+/* ======================================================================
+    OpenLayers/Handler/Click.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Click
+ * A handler for mouse clicks.  The intention of this handler is to give
+ *     controls more flexibility with handling clicks.  Browsers trigger
+ *     click events twice for a double-click.  In addition, the mousedown,
+ *     mousemove, mouseup sequence fires a click event.  With this handler,
+ *     controls can decide whether to ignore clicks associated with a double
+ *     click.  By setting a <pixelTolerance>, controls can also ignore clicks
+ *     that include a drag.  Create a new instance with the
+ *     <OpenLayers.Handler.Click> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler> 
+ */
+OpenLayers.Handler.Click = OpenLayers.Class(OpenLayers.Handler, {
+    /**
+     * APIProperty: delay
+     * {Number} Number of milliseconds between clicks before the event is
+     *     considered a double-click.
+     */
+    delay: 300,
+    
+    /**
+     * APIProperty: single
+     * {Boolean} Handle single clicks.  Default is true.  If false, clicks
+     * will not be reported.  If true, single-clicks will be reported.
+     */
+    single: true,
+    
+    /**
+     * APIProperty: double
+     * {Boolean} Handle double-clicks.  Default is false.
+     */
+    'double': false,
+    
+    /**
+     * APIProperty: pixelTolerance
+     * {Number} Maximum number of pixels between mouseup and mousedown for an
+     *     event to be considered a click.  Default is 0.  If set to an
+     *     integer value, clicks with a drag greater than the value will be
+     *     ignored.  This property can only be set when the handler is
+     *     constructed.
+     */
+    pixelTolerance: 0,
+        
+    /**
+     * APIProperty: dblclickTolerance
+     * {Number} Maximum distance in pixels between clicks for a sequence of 
+     *     events to be considered a double click.  Default is 13.  If the
+     *     distance between two clicks is greater than this value, a double-
+     *     click will not be fired.
+     */
+    dblclickTolerance: 13,
+        
+    /**
+     * APIProperty: stopSingle
+     * {Boolean} Stop other listeners from being notified of clicks.  Default
+     *     is false.  If true, any listeners registered before this one for 
+     *     click or rightclick events will not be notified.
+     */
+    stopSingle: false,
+    
+    /**
+     * APIProperty: stopDouble
+     * {Boolean} Stop other listeners from being notified of double-clicks.
+     *     Default is false.  If true, any click listeners registered before
+     *     this one will not be notified of *any* double-click events.
+     * 
+     * The one caveat with stopDouble is that given a map with two click
+     *     handlers, one with stopDouble true and the other with stopSingle
+     *     true, the stopSingle handler should be activated last to get
+     *     uniform cross-browser performance.  Since IE triggers one click
+     *     with a dblclick and FF triggers two, if a stopSingle handler is
+     *     activated first, all it gets in IE is a single click when the
+     *     second handler stops propagation on the dblclick.
+     */
+    stopDouble: false,
+
+    /**
+     * Property: timerId
+     * {Number} The id of the timeout waiting to clear the <delayedCall>.
+     */
+    timerId: null,
+
+    /**
+     * Property: touch
+     * {Boolean} When a touchstart event is fired, touch will be true and all
+     *     mouse related listeners will do nothing.
+     */
+    touch: false,
+    
+    /**
+     * Property: down
+     * {Object} Object that store relevant information about the last
+     *     mousedown or touchstart. Its 'xy' OpenLayers.Pixel property gives
+     *     the average location of the mouse/touch event. Its 'touches'
+     *     property records clientX/clientY of each touches.
+     */
+    down: null,
+
+    /**
+     * Property: last
+     * {Object} Object that store relevant information about the last
+     *     mousemove or touchmove. Its 'xy' OpenLayers.Pixel property gives
+     *     the average location of the mouse/touch event. Its 'touches'
+     *     property records clientX/clientY of each touches.
+     */
+    last: null,
+
+    /** 
+     * Property: first
+     * {Object} When waiting for double clicks, this object will store 
+     *     information about the first click in a two click sequence.
+     */
+    first: null,
+
+    /**
+     * Property: rightclickTimerId
+     * {Number} The id of the right mouse timeout waiting to clear the 
+     *     <delayedEvent>.
+     */
+    rightclickTimerId: null,
+    
+    /**
+     * Constructor: OpenLayers.Handler.Click
+     * Create a new click handler.
+     * 
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that is making use of
+     *     this handler.  If a handler is being used without a control, the
+     *     handler's setMap method must be overridden to deal properly with
+     *     the map.
+     * callbacks - {Object} An object with keys corresponding to callbacks
+     *     that will be called by the handler. The callbacks should
+     *     expect to recieve a single argument, the click event.
+     *     Callbacks for 'click' and 'dblclick' are supported.
+     * options - {Object} Optional object whose properties will be set on the
+     *     handler.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+    },
+    
+    /**
+     * Method: touchstart
+     * Handle touchstart.
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    touchstart: function(evt) {
+        if (!this.touch) {
+            this.unregisterMouseListeners();
+            this.touch = true;
+        }
+        this.down = this.getEventInfo(evt);
+        this.last = this.getEventInfo(evt);
+        return true;
+    },
+    
+    /**
+     * Method: touchmove
+     *    Store position of last move, because touchend event can have
+     *    an empty "touches" property.
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    touchmove: function(evt) {
+        this.last = this.getEventInfo(evt);
+        return true;
+    },
+
+    /**
+     * Method: touchend
+     *   Correctly set event xy property, and add lastTouches to have
+     *   touches property from last touchstart or touchmove
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    touchend: function(evt) {
+        // touchstart may not have been allowed to propagate
+        if (this.down) {
+            evt.xy = this.last.xy;
+            evt.lastTouches = this.last.touches;
+            this.handleSingle(evt);
+            this.down = null;
+        }
+        return true;
+    },
+    
+    /**
+     * Method: unregisterMouseListeners
+     * In a touch environment, we don't want to handle mouse events.
+     */
+    unregisterMouseListeners: function() {
+        this.map.events.un({
+            mousedown: this.mousedown,
+            mouseup: this.mouseup,
+            click: this.click,
+            dblclick: this.dblclick,
+            scope: this
+        });
+    },
+
+    /**
+     * Method: mousedown
+     * Handle mousedown.
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    mousedown: function(evt) {
+        this.down = this.getEventInfo(evt);
+        this.last = this.getEventInfo(evt);
+        return true;
+    },
+
+    /**
+     * Method: mouseup
+     * Handle mouseup.  Installed to support collection of right mouse events.
+     * 
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    mouseup: function (evt) {
+        var propagate = true;
+
+        // Collect right mouse clicks from the mouseup
+        //  IE - ignores the second right click in mousedown so using
+        //  mouseup instead
+        if (this.checkModifiers(evt) && this.control.handleRightClicks &&
+           OpenLayers.Event.isRightClick(evt)) {
+            propagate = this.rightclick(evt);
+        }
+
+        return propagate;
+    },
+    
+    /**
+     * Method: rightclick
+     * Handle rightclick.  For a dblrightclick, we get two clicks so we need 
+     *     to always register for dblrightclick to properly handle single 
+     *     clicks.
+     *     
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    rightclick: function(evt) {
+        if(this.passesTolerance(evt)) {
+           if(this.rightclickTimerId != null) {
+                //Second click received before timeout this must be 
+                // a double click
+                this.clearTimer();
+                this.callback('dblrightclick', [evt]);
+                return !this.stopDouble;
+            } else { 
+                //Set the rightclickTimerId, send evt only if double is 
+                // true else trigger single
+                var clickEvent = this['double'] ?
+                    OpenLayers.Util.extend({}, evt) : 
+                    this.callback('rightclick', [evt]);
+
+                var delayedRightCall = OpenLayers.Function.bind(
+                    this.delayedRightCall, 
+                    this, 
+                    clickEvent
+                );
+                this.rightclickTimerId = window.setTimeout(
+                    delayedRightCall, this.delay
+                );
+            } 
+        }
+        return !this.stopSingle;
+    },
+    
+    /**
+     * Method: delayedRightCall
+     * Sets <rightclickTimerId> to null.  And optionally triggers the 
+     *     rightclick callback if evt is set.
+     */
+    delayedRightCall: function(evt) {
+        this.rightclickTimerId = null;
+        if (evt) {
+           this.callback('rightclick', [evt]);
+        }
+    },
+    
+    /**
+     * Method: click
+     * Handle click events from the browser.  This is registered as a listener
+     *     for click events and should not be called from other events in this
+     *     handler.
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    click: function(evt) {
+        if (!this.last) {
+            this.last = this.getEventInfo(evt);
+        }
+        this.handleSingle(evt);
+        return !this.stopSingle;
+    },
+
+    /**
+     * Method: dblclick
+     * Handle dblclick.  For a dblclick, we get two clicks in some browsers
+     *     (FF) and one in others (IE).  So we need to always register for
+     *     dblclick to properly handle single clicks.  This method is registered
+     *     as a listener for the dblclick browser event.  It should *not* be
+     *     called by other methods in this handler.
+     *     
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    dblclick: function(evt) {
+        this.handleDouble(evt);
+        return !this.stopDouble;
+    },
+    
+    /** 
+     * Method: handleDouble
+     * Handle double-click sequence.
+     */
+    handleDouble: function(evt) {
+        if (this["double"] && this.passesDblclickTolerance(evt)) {
+            this.callback("dblclick", [evt]);
+        }
+    },
+    
+    /** 
+     * Method: handleSingle
+     * Handle single click sequence.
+     */
+    handleSingle: function(evt) {
+        if (this.passesTolerance(evt)) {
+            if (this.timerId != null) {
+                // already received a click
+                if (this.last.touches && this.last.touches.length === 1) {
+                    // touch device, no dblclick event - this may be a double
+                    if (this["double"]) {
+                        // on Android don't let the browser zoom on the page
+                        OpenLayers.Event.stop(evt);
+                    }
+                    this.handleDouble(evt);
+                }
+                // if we're not in a touch environment we clear the click timer
+                // if we've got a second touch, we'll get two touchend events
+                if (!this.last.touches || this.last.touches.length !== 2) {
+                    this.clearTimer();
+                }
+            } else {
+                // remember the first click info so we can compare to the second
+                this.first = this.getEventInfo(evt);
+                // set the timer, send evt only if single is true
+                //use a clone of the event object because it will no longer 
+                //be a valid event object in IE in the timer callback
+                var clickEvent = this.single ?
+                    OpenLayers.Util.extend({}, evt) : null;
+                this.queuePotentialClick(clickEvent);
+            }
+        }
+    },
+    
+    /** 
+     * Method: queuePotentialClick
+     * This method is separated out largely to make testing easier (so we
+     *     don't have to override window.setTimeout)
+     */
+    queuePotentialClick: function(evt) {
+        this.timerId = window.setTimeout(
+            OpenLayers.Function.bind(this.delayedCall, this, evt),
+            this.delay
+        );
+    },
+
+    /**
+     * Method: passesTolerance
+     * Determine whether the event is within the optional pixel tolerance.  Note
+     *     that the pixel tolerance check only works if mousedown events get to
+     *     the listeners registered here.  If they are stopped by other elements,
+     *     the <pixelTolerance> will have no effect here (this method will always
+     *     return true).
+     *
+     * Returns:
+     * {Boolean} The click is within the pixel tolerance (if specified).
+     */
+    passesTolerance: function(evt) {
+        var passes = true;
+        if (this.pixelTolerance != null && this.down && this.down.xy) {
+            passes = this.pixelTolerance >= this.down.xy.distanceTo(evt.xy);
+            // for touch environments, we also enforce that all touches
+            // start and end within the given tolerance to be considered a click
+            if (passes && this.touch && 
+                this.down.touches.length === this.last.touches.length) {
+                // the touchend event doesn't come with touches, so we check
+                // down and last
+                for (var i=0, ii=this.down.touches.length; i<ii; ++i) {
+                    if (this.getTouchDistance(
+                            this.down.touches[i], 
+                            this.last.touches[i]
+                        ) > this.pixelTolerance) {
+                        passes = false;
+                        break;
+                    }
+                }
+            }
+        }
+        return passes;
+    },
+    
+    /** 
+     * Method: getTouchDistance
+     *
+     * Returns:
+     * {Boolean} The pixel displacement between two touches.
+     */
+    getTouchDistance: function(from, to) {
+        return Math.sqrt(
+            Math.pow(from.clientX - to.clientX, 2) +
+            Math.pow(from.clientY - to.clientY, 2)
+        );
+    },
+    
+    /**
+     * Method: passesDblclickTolerance
+     * Determine whether the event is within the optional double-cick pixel 
+     *     tolerance.
+     *
+     * Returns:
+     * {Boolean} The click is within the double-click pixel tolerance.
+     */
+    passesDblclickTolerance: function(evt) {
+        var passes = true;
+        if (this.down && this.first) {
+            passes = this.down.xy.distanceTo(this.first.xy) <= this.dblclickTolerance;
+        }
+        return passes;
+    },
+
+    /**
+     * Method: clearTimer
+     * Clear the timer and set <timerId> to null.
+     */
+    clearTimer: function() {
+        if (this.timerId != null) {
+            window.clearTimeout(this.timerId);
+            this.timerId = null;
+        }
+        if (this.rightclickTimerId != null) {
+            window.clearTimeout(this.rightclickTimerId);
+            this.rightclickTimerId = null;
+        }
+    },
+    
+    /**
+     * Method: delayedCall
+     * Sets <timerId> to null.  And optionally triggers the click callback if
+     *     evt is set.
+     */
+    delayedCall: function(evt) {
+        this.timerId = null;
+        if (evt) {
+            this.callback("click", [evt]);
+        }
+    },
+
+    /**
+     * Method: getEventInfo
+     * This method allows us to store event information without storing the
+     *     actual event.  In touch devices (at least), the same event is 
+     *     modified between touchstart, touchmove, and touchend.
+     *
+     * Returns:
+     * {Object} An object with event related info.
+     */
+    getEventInfo: function(evt) {
+        var touches;
+        if (evt.touches) {
+            var len = evt.touches.length;
+            touches = new Array(len);
+            var touch;
+            for (var i=0; i<len; i++) {
+                touch = evt.touches[i];
+                touches[i] = {
+                    clientX: touch.clientX,
+                    clientY: touch.clientY
+                };
+            }
+        }
+        return {
+            xy: evt.xy,
+            touches: touches
+        };
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the handler.
+     *
+     * Returns:
+     * {Boolean} The handler was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            this.clearTimer();
+            this.down = null;
+            this.first = null;
+            this.last = null;
+            this.touch = false;
+            deactivated = true;
+        }
+        return deactivated;
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Click"
+});
+/* ======================================================================
+    OpenLayers/Control/Navigation.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/ZoomBox.js
+ * @requires OpenLayers/Control/DragPan.js
+ * @requires OpenLayers/Handler/MouseWheel.js
+ * @requires OpenLayers/Handler/Click.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Navigation
+ * The navigation control handles map browsing with mouse events (dragging,
+ *     double-clicking, and scrolling the wheel).  Create a new navigation 
+ *     control with the <OpenLayers.Control.Navigation> control.  
+ * 
+ *     Note that this control is added to the map by default (if no controls 
+ *     array is sent in the options object to the <OpenLayers.Map> 
+ *     constructor).
+ * 
+ * Inherits:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Navigation = OpenLayers.Class(OpenLayers.Control, {
+
+    /** 
+     * Property: dragPan
+     * {<OpenLayers.Control.DragPan>} 
+     */
+    dragPan: null,
+
+    /**
+     * APIProperty: dragPanOptions
+     * {Object} Options passed to the DragPan control.
+     */
+    dragPanOptions: null,
+
+    /**
+     * Property: pinchZoom
+     * {<OpenLayers.Control.PinchZoom>}
+     */
+    pinchZoom: null,
+
+    /**
+     * APIProperty: pinchZoomOptions
+     * {Object} Options passed to the PinchZoom control.
+     */
+    pinchZoomOptions: null,
+
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} Allow panning of the map by dragging outside map viewport.
+     *     Default is false.
+     */
+    documentDrag: false,
+
+    /** 
+     * Property: zoomBox
+     * {<OpenLayers.Control.ZoomBox>}
+     */
+    zoomBox: null,
+
+    /**
+     * APIProperty: zoomBoxEnabled
+     * {Boolean} Whether the user can draw a box to zoom
+     */
+    zoomBoxEnabled: true, 
+
+    /**
+     * APIProperty: zoomWheelEnabled
+     * {Boolean} Whether the mousewheel should zoom the map
+     */
+    zoomWheelEnabled: true,
+    
+    /**
+     * Property: mouseWheelOptions
+     * {Object} Options passed to the MouseWheel control (only useful if
+     *     <zoomWheelEnabled> is set to true)
+     */
+    mouseWheelOptions: null,
+
+    /**
+     * APIProperty: handleRightClicks
+     * {Boolean} Whether or not to handle right clicks. Default is false.
+     */
+    handleRightClicks: false,
+
+    /**
+     * APIProperty: zoomBoxKeyMask
+     * {Integer} <OpenLayers.Handler> key code of the key, which has to be
+     *    pressed, while drawing the zoom box with the mouse on the screen. 
+     *    You should probably set handleRightClicks to true if you use this
+     *    with MOD_CTRL, to disable the context menu for machines which use
+     *    CTRL-Click as a right click.
+     * Default: <OpenLayers.Handler.MOD_SHIFT
+     */
+    zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT,
+    
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
+     * Constructor: OpenLayers.Control.Navigation
+     * Create a new navigation control
+     * 
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *                    the control
+     */
+    initialize: function(options) {
+        this.handlers = {};
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * Method: destroy
+     * The destroy method is used to perform any clean up before the control
+     * is dereferenced.  Typically this is where event listeners are removed
+     * to prevent memory leaks.
+     */
+    destroy: function() {
+        this.deactivate();
+
+        if (this.dragPan) {
+            this.dragPan.destroy();
+        }
+        this.dragPan = null;
+
+        if (this.zoomBox) {
+            this.zoomBox.destroy();
+        }
+        this.zoomBox = null;
+
+        if (this.pinchZoom) {
+            this.pinchZoom.destroy();
+        }
+        this.pinchZoom = null;
+
+        OpenLayers.Control.prototype.destroy.apply(this,arguments);
+    },
+    
+    /**
+     * Method: activate
+     */
+    activate: function() {
+        this.dragPan.activate();
+        if (this.zoomWheelEnabled) {
+            this.handlers.wheel.activate();
+        }    
+        this.handlers.click.activate();
+        if (this.zoomBoxEnabled) {
+            this.zoomBox.activate();
+        }
+        if (this.pinchZoom) {
+            this.pinchZoom.activate();
+        }
+        return OpenLayers.Control.prototype.activate.apply(this,arguments);
+    },
+
+    /**
+     * Method: deactivate
+     */
+    deactivate: function() {
+        if (this.pinchZoom) {
+            this.pinchZoom.deactivate();
+        }
+        this.zoomBox.deactivate();
+        this.dragPan.deactivate();
+        this.handlers.click.deactivate();
+        this.handlers.wheel.deactivate();
+        return OpenLayers.Control.prototype.deactivate.apply(this,arguments);
+    },
+    
+    /**
+     * Method: draw
+     */
+    draw: function() {
+        // disable right mouse context menu for support of right click events
+        if (this.handleRightClicks) {
+            this.map.viewPortDiv.oncontextmenu = OpenLayers.Function.False;
+        }
+
+        var clickCallbacks = { 
+            'click': this.defaultClick,
+            'dblclick': this.defaultDblClick, 
+            'dblrightclick': this.defaultDblRightClick 
+        };
+        var clickOptions = {
+            'double': true, 
+            'stopDouble': true
+        };
+        this.handlers.click = new OpenLayers.Handler.Click(
+            this, clickCallbacks, clickOptions
+        );
+        this.dragPan = new OpenLayers.Control.DragPan(
+            OpenLayers.Util.extend({
+                map: this.map,
+                documentDrag: this.documentDrag
+            }, this.dragPanOptions)
+        );
+        this.zoomBox = new OpenLayers.Control.ZoomBox(
+                    {map: this.map, keyMask: this.zoomBoxKeyMask});
+        this.dragPan.draw();
+        this.zoomBox.draw();
+        this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
+                                    this, {"up"  : this.wheelUp,
+                                           "down": this.wheelDown},
+                                    this.mouseWheelOptions );
+        if (OpenLayers.Control.PinchZoom) {
+            this.pinchZoom = new OpenLayers.Control.PinchZoom(
+                OpenLayers.Util.extend(
+                    {map: this.map}, this.pinchZoomOptions));
+        }
+    },
+
+    /**
+     * Method: defaultClick
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    defaultClick: function (evt) {
+        if (evt.lastTouches && evt.lastTouches.length == 2) {
+            this.map.zoomOut();
+        }
+    },
+
+    /**
+     * Method: defaultDblClick 
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultDblClick: function (evt) {
+        var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); 
+        this.map.setCenter(newCenter, this.map.zoom + 1);
+    },
+
+    /**
+     * Method: defaultDblRightClick 
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    defaultDblRightClick: function (evt) {
+        var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); 
+        this.map.setCenter(newCenter, this.map.zoom - 1);
+    },
+    
+    /**
+     * Method: wheelChange  
+     *
+     * Parameters:
+     * evt - {Event}
+     * deltaZ - {Integer}
+     */
+    wheelChange: function(evt, deltaZ) {
+        var currentZoom = this.map.getZoom();
+        var newZoom = this.map.getZoom() + Math.round(deltaZ);
+        newZoom = Math.max(newZoom, 0);
+        newZoom = Math.min(newZoom, this.map.getNumZoomLevels());
+        if (newZoom === currentZoom) {
+            return;
+        }
+        var size    = this.map.getSize();
+        var deltaX  = size.w/2 - evt.xy.x;
+        var deltaY  = evt.xy.y - size.h/2;
+        var newRes  = this.map.baseLayer.getResolutionForZoom(newZoom);
+        var zoomPoint = this.map.getLonLatFromPixel(evt.xy);
+        var newCenter = new OpenLayers.LonLat(
+                            zoomPoint.lon + deltaX * newRes,
+                            zoomPoint.lat + deltaY * newRes );
+        this.map.setCenter( newCenter, newZoom );
+    },
+
+    /** 
+     * Method: wheelUp
+     * User spun scroll wheel up
+     * 
+     * Parameters:
+     * evt - {Event}
+     * delta - {Integer}
+     */
+    wheelUp: function(evt, delta) {
+        this.wheelChange(evt, delta || 1);
+    },
+
+    /** 
+     * Method: wheelDown
+     * User spun scroll wheel down
+     * 
+     * Parameters:
+     * evt - {Event}
+     * delta - {Integer}
+     */
+    wheelDown: function(evt, delta) {
+        this.wheelChange(evt, delta || -1);
+    },
+    
+    /**
+     * Method: disableZoomBox
+     */
+    disableZoomBox : function() {
+        this.zoomBoxEnabled = false;
+        this.zoomBox.deactivate();       
+    },
+    
+    /**
+     * Method: enableZoomBox
+     */
+    enableZoomBox : function() {
+        this.zoomBoxEnabled = true;
+        if (this.active) {
+            this.zoomBox.activate();
+        }    
+    },
+    
+    /**
+     * Method: disableZoomWheel
+     */
+    
+    disableZoomWheel : function() {
+        this.zoomWheelEnabled = false;
+        this.handlers.wheel.deactivate();       
+    },
+    
+    /**
+     * Method: enableZoomWheel
+     */
+    
+    enableZoomWheel : function() {
+        this.zoomWheelEnabled = true;
+        if (this.active) {
+            this.handlers.wheel.activate();
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Navigation"
+});
+/* ======================================================================
+    OpenLayers/Control/DrawFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Control.DrawFeature
+ * The DrawFeature control draws point, line or polygon features on a vector
+ * layer when active.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.DrawFeature = OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>}
+     */
+    layer: null,
+
+    /**
+     * Property: callbacks
+     * {Object} The functions that are sent to the handler for callback
+     */
+    callbacks: null,
+    
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     * featureadded - Triggered when a feature is added
+     */
+    EVENT_TYPES: ["featureadded"],
+    
+    /**
+     * APIProperty: multi
+     * {Boolean} Cast features to multi-part geometries before passing to the
+     *     layer.  Default is false.
+     */
+    multi: false,
+
+    /**
+     * APIProperty: featureAdded
+     * {Function} Called after each feature is added
+     */
+    featureAdded: function() {},
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Used to set non-default properties on the control's handler
+     */
+    handlerOptions: null,
+    
+    /**
+     * Constructor: OpenLayers.Control.DrawFeature
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} 
+     * handler - {<OpenLayers.Handler>} 
+     * options - {Object} 
+     */
+    initialize: function(layer, handler, options) {
+        
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.callbacks = OpenLayers.Util.extend(
+            {
+                done: this.drawFeature,
+                modify: function(vertex, feature) {
+                    this.layer.events.triggerEvent(
+                        "sketchmodified", {vertex: vertex, feature: feature}
+                    );
+                },
+                create: function(vertex, feature) {
+                    this.layer.events.triggerEvent(
+                        "sketchstarted", {vertex: vertex, feature: feature}
+                    );
+                }
+            },
+            this.callbacks
+        );
+        this.layer = layer;
+        this.handlerOptions = this.handlerOptions || {};
+        if (!("multi" in this.handlerOptions)) {
+            this.handlerOptions.multi = this.multi;
+        }
+        var sketchStyle = this.layer.styleMap && this.layer.styleMap.styles.temporary;
+        if(sketchStyle) {
+            this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
+                this.handlerOptions.layerOptions,
+                {styleMap: new OpenLayers.StyleMap({"default": sketchStyle})}
+            );
+        }
+        this.handler = new handler(this, this.callbacks, this.handlerOptions);
+    },
+
+    /**
+     * Method: drawFeature
+     */
+    drawFeature: function(geometry) {
+        var feature = new OpenLayers.Feature.Vector(geometry);
+        var proceed = this.layer.events.triggerEvent(
+            "sketchcomplete", {feature: feature}
+        );
+        if(proceed !== false) {
+            feature.state = OpenLayers.State.INSERT;
+            this.layer.addFeatures([feature]);
+            this.featureAdded(feature);
+            this.events.triggerEvent("featureadded",{feature : feature});
+        }
+    },
+    
+    /**
+     * APIMethod: insertXY
+     * Insert a point in the current sketch given x & y coordinates.
+     *
+     * Parameters:
+     * x - {Number} The x-coordinate of the point.
+     * y - {Number} The y-coordinate of the point.
+     */
+    insertXY: function(x, y) {
+        if (this.handler && this.handler.line) {
+            this.handler.insertXY(x, y);
+        }
+    },
+
+    /**
+     * APIMethod: insertDeltaXY
+     * Insert a point given offsets from the previously inserted point.
+     *
+     * Parameters:
+     * dx - {Number} The x-coordinate offset of the point.
+     * dy - {Number} The y-coordinate offset of the point.
+     */
+    insertDeltaXY: function(dx, dy) {
+        if (this.handler && this.handler.line) {
+            this.handler.insertDeltaXY(dx, dy);
+        }
+    },
+
+    /**
+     * APIMethod: insertDirectionLength
+     * Insert a point in the current sketch given a direction and a length.
+     *
+     * Parameters:
+     * direction - {Number} Degrees clockwise from the positive x-axis.
+     * length - {Number} Distance from the previously drawn point.
+     */
+    insertDirectionLength: function(direction, length) {
+        if (this.handler && this.handler.line) {
+            this.handler.insertDirectionLength(direction, length);
+        }
+    },
+
+    /**
+     * APIMethod: insertDeflectionLength
+     * Insert a point in the current sketch given a deflection and a length.
+     *     The deflection should be degrees clockwise from the previously 
+     *     digitized segment.
+     *
+     * Parameters:
+     * deflection - {Number} Degrees clockwise from the previous segment.
+     * length - {Number} Distance from the previously drawn point.
+     */
+    insertDeflectionLength: function(deflection, length) {
+        if (this.handler && this.handler.line) {
+            this.handler.insertDeflectionLength(deflection, length);
+        }
+    },
+    
+    /**
+     * APIMethod: undo
+     * Remove the most recently added point in the current sketch geometry.
+     *
+     * Returns: 
+     * {Boolean} An edit was undone.
+     */
+    undo: function() {
+        return this.handler.undo && this.handler.undo();
+    },
+    
+    /**
+     * APIMethod: redo
+     * Reinsert the most recently removed point resulting from an <undo> call.
+     *     The undo stack is deleted whenever a point is added by other means.
+     *
+     * Returns: 
+     * {Boolean} An edit was redone.
+     */
+    redo: function() {
+        return this.handler.redo && this.handler.redo();
+    },
+    
+    /**
+     * APIMethod: finishSketch
+     * Finishes the sketch without including the currently drawn point.
+     *     This method can be called to terminate drawing programmatically
+     *     instead of waiting for the user to end the sketch.
+     */
+    finishSketch: function() {
+        this.handler.finishGeometry();
+    },
+
+    /**
+     * APIMethod: cancel
+     * Cancel the current sketch.  This removes the current sketch and keeps
+     *     the drawing control active.
+     */
+    cancel: function() {
+        this.handler.cancel();
+    },
+
+    CLASS_NAME: "OpenLayers.Control.DrawFeature"
+});
+/* ======================================================================
+    OpenLayers/Handler/Polygon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Handler/Path.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Polygon
+ * Handler to draw a polygon on the map.  Polygon is displayed on mouse down,
+ * moves on mouse move, and is finished on mouse up.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Handler.Path>
+ *  - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.Polygon = OpenLayers.Class(OpenLayers.Handler.Path, {
+    
+    /** 
+     * APIProperty: holeModifier
+     * {String} Key modifier to trigger hole digitizing.  Acceptable values are
+     *     "altKey", "shiftKey", or "ctrlKey".  If not set, no hole digitizing
+     *     will take place.  Default is null.
+     */
+    holeModifier: null,
+    
+    /**
+     * Property: drawingHole
+     * {Boolean} Currently drawing an interior ring.
+     */
+    drawingHole: false,
+    
+    /**
+     * Parameter: polygon
+     * {<OpenLayers.Feature.Vector>}
+     */
+    polygon: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Polygon
+     * Create a Polygon Handler.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} An optional object with properties to be set on the
+     *           handler
+     *
+     * Named callbacks:
+     * create - Called when a sketch is first created.  Callback called with
+     *     the creation point geometry and sketch feature.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * point - Called as each point is added.  Receives the new point geometry.
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the polygon geometry.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.Path.prototype.initialize.apply(this, arguments);
+    },
+    
+    /**
+     * Method: createFeature
+     * Add temporary geometries
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
+     *     feature.
+     */
+    createFeature: function(pixel) {
+        var lonlat = this.map.getLonLatFromPixel(pixel);
+        var geometry = new OpenLayers.Geometry.Point(
+            lonlat.lon, lonlat.lat
+        );
+        this.point = new OpenLayers.Feature.Vector(geometry);
+        this.line = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LinearRing([this.point.geometry])
+        );
+        this.polygon = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Polygon([this.line.geometry])
+        );
+        this.callback("create", [this.point.geometry, this.getSketch()]);
+        this.point.geometry.clearBounds();
+        this.layer.addFeatures([this.polygon, this.point], {silent: true});
+    },
+
+    /**
+     * Method: addPoint
+     * Add point to geometry.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The pixel location for the new point.
+     */
+    addPoint: function(pixel) {
+        if(!this.drawingHole && this.holeModifier &&
+           this.evt && this.evt[this.holeModifier]) {
+            var geometry = this.point.geometry;
+            var features = this.control.layer.features;
+            var candidate, polygon;
+            // look for intersections, last drawn gets priority
+            for (var i=features.length-1; i>=0; --i) {
+                candidate = features[i].geometry;
+                if ((candidate instanceof OpenLayers.Geometry.Polygon || 
+                    candidate instanceof OpenLayers.Geometry.MultiPolygon) && 
+                    candidate.intersects(geometry)) {
+                    polygon = features[i];
+                    this.control.layer.removeFeatures([polygon], {silent: true});
+                    this.control.layer.events.registerPriority(
+                        "sketchcomplete", this, this.finalizeInteriorRing
+                    );
+                    this.control.layer.events.registerPriority(
+                        "sketchmodified", this, this.enforceTopology
+                    );
+                    polygon.geometry.addComponent(this.line.geometry);
+                    this.polygon = polygon;
+                    this.drawingHole = true;
+                    break;
+                }
+            }
+        }
+        OpenLayers.Handler.Path.prototype.addPoint.apply(this, arguments);
+    },
+
+    /**
+     * Method: getCurrentPointIndex
+     * 
+     * Returns:
+     * {Number} The index of the most recently drawn point.
+     */
+    getCurrentPointIndex: function() {
+        return this.line.geometry.components.length - 2;
+    },
+
+    /**
+     * Method: enforceTopology
+     * Simple topology enforcement for drawing interior rings.  Ensures vertices
+     *     of interior rings are contained by exterior ring.  Other topology 
+     *     rules are enforced in <finalizeInteriorRing> to allow drawing of 
+     *     rings that intersect only during the sketch (e.g. a "C" shaped ring
+     *     that nearly encloses another ring).
+     */
+    enforceTopology: function(event) {
+        var point = event.vertex;
+        var components = this.line.geometry.components;
+        // ensure that vertices of interior ring are contained by exterior ring
+        if (!this.polygon.geometry.intersects(point)) {
+            var last = components[components.length-3];
+            point.x = last.x;
+            point.y = last.y;
+        }
+    },
+
+    /**
+     * Method: finishGeometry
+     * Finish the geometry and send it back to the control.
+     */
+    finishGeometry: function() {
+        var index = this.line.geometry.components.length - 2;
+        this.line.geometry.removeComponent(this.line.geometry.components[index]);
+        this.removePoint();
+        this.finalize();
+    },
+
+    /**
+     * Method: finalizeInteriorRing
+     * Enforces that new ring has some area and doesn't contain vertices of any
+     *     other rings.
+     */
+    finalizeInteriorRing: function() {
+        var ring = this.line.geometry;
+        // ensure that ring has some area
+        var modified = (ring.getArea() !== 0);
+        if (modified) {
+            // ensure that new ring doesn't intersect any other rings
+            var rings = this.polygon.geometry.components;
+            for (var i=rings.length-2; i>=0; --i) {
+                if (ring.intersects(rings[i])) {
+                    modified = false;
+                    break;
+                }
+            }
+            if (modified) {
+                // ensure that new ring doesn't contain any other rings
+                var target;
+                outer: for (var i=rings.length-2; i>0; --i) {
+                    var points = rings[i].components;
+                    for (var j=0, jj=points.length; j<jj; ++j) {
+                        if (ring.containsPoint(points[j])) {
+                            modified = false;
+                            break outer;
+                        }
+                    }
+                }
+            }
+        }
+        if (modified) {
+            if (this.polygon.state !== OpenLayers.State.INSERT) {
+                this.polygon.state = OpenLayers.State.UPDATE;
+            }
+        } else {
+            this.polygon.geometry.removeComponent(ring);
+        }
+        this.restoreFeature();
+        return false;
+    },
+
+    /**
+     * APIMethod: cancel
+     * Finish the geometry and call the "cancel" callback.
+     */
+    cancel: function() {
+        if (this.drawingHole) {
+            this.polygon.geometry.removeComponent(this.line.geometry);
+            this.restoreFeature(true);
+        }
+        return OpenLayers.Handler.Path.prototype.cancel.apply(this, arguments);
+    },
+    
+    /**
+     * Method: restoreFeature
+     * Move the feature from the sketch layer to the target layer.
+     *
+     * Properties: 
+     * cancel - {Boolean} Cancel drawing.  If falsey, the "sketchcomplete" event
+     *     will be fired.
+     */
+    restoreFeature: function(cancel) {
+        this.control.layer.events.unregister(
+            "sketchcomplete", this, this.finalizeInteriorRing
+        );
+        this.control.layer.events.unregister(
+            "sketchmodified", this, this.enforceTopology
+        );
+        this.layer.removeFeatures([this.polygon], {silent: true});
+        this.control.layer.addFeatures([this.polygon], {silent: true});
+        this.drawingHole = false;
+        if (!cancel) {
+            // Re-trigger "sketchcomplete" so other listeners can do their
+            // business.  While this is somewhat sloppy (if a listener is 
+            // registered with registerPriority - not common - between the start
+            // and end of a single ring drawing - very uncommon - it will be 
+            // called twice).
+            // TODO: In 3.0, collapse sketch handlers into geometry specific
+            // drawing controls.
+            this.control.layer.events.triggerEvent(
+                "sketchcomplete", {feature : this.polygon}
+            );
+        }
+    },
+
+    /**
+     * Method: destroyFeature
+     * Destroy temporary geometries
+     *
+     * Parameters:
+     * force - {Boolean} Destroy even if persist is true.
+     */
+    destroyFeature: function(force) {
+        OpenLayers.Handler.Path.prototype.destroyFeature.call(
+            this, force);
+        this.polygon = null;
+    },
+
+    /**
+     * Method: drawFeature
+     * Render geometries on the temporary layer.
+     */
+    drawFeature: function() {
+        this.layer.drawFeature(this.polygon, this.style);
+        this.layer.drawFeature(this.point, this.style);
+    },
+    
+    /**
+     * Method: getSketch
+     * Return the sketch feature.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    getSketch: function() {
+        return this.polygon;
+    },
+
+    /**
+     * Method: getGeometry
+     * Return the sketch geometry.  If <multi> is true, this will return
+     *     a multi-part geometry.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry.Polygon>}
+     */
+    getGeometry: function() {
+        var geometry = this.polygon && this.polygon.geometry;
+        if(geometry && this.multi) {
+            geometry = new OpenLayers.Geometry.MultiPolygon([geometry]);
+        }
+        return geometry;
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Polygon"
+});
+/* ======================================================================
+    OpenLayers/Control/EditingToolbar.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/Panel.js
+ * @requires OpenLayers/Control/Navigation.js
+ * @requires OpenLayers/Control/DrawFeature.js
+ * @requires OpenLayers/Handler/Point.js
+ * @requires OpenLayers/Handler/Path.js
+ * @requires OpenLayers/Handler/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Control.EditingToolbar 
+ * The EditingToolbar is a panel of 4 controls to draw polygons, lines, 
+ * points, or to navigate the map by panning. By default it appears in the 
+ * upper right corner of the map.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control.Panel>
+ */
+OpenLayers.Control.EditingToolbar = OpenLayers.Class(
+  OpenLayers.Control.Panel, {
+
+    /**
+     * Constructor: OpenLayers.Control.EditingToolbar
+     * Create an editing toolbar for a given layer. 
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} 
+     * options - {Object} 
+     */
+    initialize: function(layer, options) {
+        OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
+        
+        this.addControls(
+          [ new OpenLayers.Control.Navigation() ]
+        );  
+        var controls = [
+          new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'}),
+          new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'}),
+          new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'})
+        ];
+        this.addControls(controls);
+    },
+
+    /**
+     * Method: draw
+     * calls the default draw, and then activates mouse defaults.
+     *
+     * Returns:
+     * {DOMElement}
+     */
+    draw: function() {
+        var div = OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);
+        if (this.defaultControl === null) {
+            this.defaultControl = this.controls[0];
+        }
+        return div;
+    },
+
+    CLASS_NAME: "OpenLayers.Control.EditingToolbar"
+});    
+/* ======================================================================
+    Rico/Color.js
+   ====================================================================== */
+
+/** 
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/BaseTypes/Element.js
+ */
+
+
+/*
+ * This file has been edited substantially from the Rico-released version by
+ * the OpenLayers development team.
+ *
+ * This file is licensed under the Apache License, Version 2.0.
+ */
+OpenLayers.Rico = OpenLayers.Rico || {};
+OpenLayers.Rico.Color = OpenLayers.Class({
+
+   initialize: function(red, green, blue) {
+      this.rgb = { r: red, g : green, b : blue };
+   },
+
+   setRed: function(r) {
+      this.rgb.r = r;
+   },
+
+   setGreen: function(g) {
+      this.rgb.g = g;
+   },
+
+   setBlue: function(b) {
+      this.rgb.b = b;
+   },
+
+   setHue: function(h) {
+
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.h = h;
+
+      // convert back to RGB...
+      this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setSaturation: function(s) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.s = s;
+
+      // convert back to RGB and set values...
+      this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setBrightness: function(b) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.b = b;
+
+      // convert back to RGB and set values...
+      this.rgb = OpenLayers.Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+   },
+
+   darken: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+   },
+
+   brighten: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+   },
+
+   blend: function(other) {
+      this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+      this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+      this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+   },
+
+   isBright: function() {
+      var hsb = this.asHSB();
+      return this.asHSB().b > 0.5;
+   },
+
+   isDark: function() {
+      return ! this.isBright();
+   },
+
+   asRGB: function() {
+      return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+   },
+
+   asHex: function() {
+      return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+   },
+
+   asHSB: function() {
+      return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+   },
+
+   toString: function() {
+      return this.asHex();
+   }
+
+});
+
+OpenLayers.Rico.Color.createFromHex = function(hexCode) {
+  if(hexCode.length==4) {
+    var shortHexCode = hexCode; 
+    var hexCode = '#';
+    for(var i=1;i<4;i++) { 
+        hexCode += (shortHexCode.charAt(i) + 
+shortHexCode.charAt(i)); 
+    }
+  }
+   if ( hexCode.indexOf('#') == 0 ) {
+       hexCode = hexCode.substring(1);
+   }
+   var red   = hexCode.substring(0,2);
+   var green = hexCode.substring(2,4);
+   var blue  = hexCode.substring(4,6);
+   return new OpenLayers.Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+};
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+OpenLayers.Rico.Color.createColorFromBackground = function(elem) {
+
+   var actualColor = 
+      OpenLayers.Element.getStyle(OpenLayers.Util.getElement(elem), 
+                                        "backgroundColor");
+
+   if ( actualColor == "transparent" && elem.parentNode ) {
+      return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);
+   }
+   if ( actualColor == null ) {
+      return new OpenLayers.Rico.Color(255,255,255);
+   }
+   if ( actualColor.indexOf("rgb(") == 0 ) {
+      var colors = actualColor.substring(4, actualColor.length - 1 );
+      var colorArray = colors.split(",");
+      return new OpenLayers.Rico.Color( parseInt( colorArray[0] ),
+                            parseInt( colorArray[1] ),
+                            parseInt( colorArray[2] )  );
+
+   }
+   else if ( actualColor.indexOf("#") == 0 ) {
+      return OpenLayers.Rico.Color.createFromHex(actualColor);
+   }
+   else {
+      return new OpenLayers.Rico.Color(255,255,255);
+   }
+};
+
+OpenLayers.Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+   var red   = 0;
+    var green = 0;
+    var blue  = 0;
+
+   if (saturation == 0) {
+      red = parseInt(brightness * 255.0 + 0.5);
+       green = red;
+       blue = red;
+    }
+    else {
+      var h = (hue - Math.floor(hue)) * 6.0;
+      var f = h - Math.floor(h);
+      var p = brightness * (1.0 - saturation);
+      var q = brightness * (1.0 - saturation * f);
+      var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+      switch (parseInt(h)) {
+         case 0:
+            red   = (brightness * 255.0 + 0.5);
+            green = (t * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 1:
+            red   = (q * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 2:
+            red   = (p * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (t * 255.0 + 0.5);
+            break;
+         case 3:
+            red   = (p * 255.0 + 0.5);
+            green = (q * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+         case 4:
+            red   = (t * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+          case 5:
+            red   = (brightness * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (q * 255.0 + 0.5);
+            break;
+        }
+    }
+
+   return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+};
+
+OpenLayers.Rico.Color.RGBtoHSB = function(r, g, b) {
+
+   var hue;
+   var saturation;
+   var brightness;
+
+   var cmax = (r > g) ? r : g;
+   if (b > cmax) {
+      cmax = b;
+   }
+   var cmin = (r < g) ? r : g;
+   if (b < cmin) {
+      cmin = b;
+   }
+   brightness = cmax / 255.0;
+   if (cmax != 0) {
+      saturation = (cmax - cmin)/cmax;
+   } else {
+      saturation = 0;
+   }
+   if (saturation == 0) {
+      hue = 0;
+   } else {
+      var redc   = (cmax - r)/(cmax - cmin);
+        var greenc = (cmax - g)/(cmax - cmin);
+        var bluec  = (cmax - b)/(cmax - cmin);
+
+        if (r == cmax) {
+           hue = bluec - greenc;
+        } else if (g == cmax) {
+           hue = 2.0 + redc - bluec;
+      } else {
+           hue = 4.0 + greenc - redc;
+      }
+        hue = hue / 6.0;
+        if (hue < 0) {
+           hue = hue + 1.0;
+        }
+   }
+
+   return { h : hue, s : saturation, b : brightness };
+};
+
+/* ======================================================================
+    Rico/Corner.js
+   ====================================================================== */
+
+/**
+ * @requires Rico/Color.js
+ */
+
+
+/*
+ * This file has been edited substantially from the Rico-released
+ * version by the OpenLayers development team.
+ *  
+ *  Copyright 2005 Sabre Airline Solutions  
+ *  
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the
+ *  License. You may obtain a copy of the License at
+ *  
+ *         http://www.apache.org/licenses/LICENSE-2.0  
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the * License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or
+ * implied. See the License for the specific language governing
+ * permissions * and limitations under the License.
+ *
+ */
+OpenLayers.Rico = OpenLayers.Rico || {};
+OpenLayers.Rico.Corner = {
+
+    round: function(e, options) {
+        e = OpenLayers.Util.getElement(e);
+        this._setOptions(options);
+
+        var color = this.options.color;
+        if ( this.options.color == "fromElement" ) {
+            color = this._background(e);
+        }
+        var bgColor = this.options.bgColor;
+        if ( this.options.bgColor == "fromParent" ) {
+            bgColor = this._background(e.offsetParent);
+        }
+        this._roundCornersImpl(e, color, bgColor);
+    },
+
+    /**   This is a helper function to change the background
+    *     color of <div> that has had Rico rounded corners added.
+    *
+    *     It seems we cannot just set the background color for the
+    *     outer <div> so each <span> element used to create the
+    *     corners must have its background color set individually.
+    *
+    * @param {DOM} theDiv - A child of the outer <div> that was
+    *                        supplied to the `round` method.
+    *
+    * @param {String} newColor - The new background color to use.
+    */
+    changeColor: function(theDiv, newColor) {
+   
+        theDiv.style.backgroundColor = newColor;
+
+        var spanElements = theDiv.parentNode.getElementsByTagName("span");
+        
+        for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
+            spanElements[currIdx].style.backgroundColor = newColor;
+        }
+    }, 
+
+
+    /**   This is a helper function to change the background
+    *     opacity of <div> that has had Rico rounded corners added.
+    *
+    *     See changeColor (above) for algorithm explanation
+    *
+    * @param {DOM} theDiv A child of the outer <div> that was
+    *                        supplied to the `round` method.
+    *
+    * @param {int} newOpacity The new opacity to use (0-1).
+    */
+    changeOpacity: function(theDiv, newOpacity) {
+   
+        var mozillaOpacity = newOpacity;
+        var ieOpacity = 'alpha(opacity=' + newOpacity * 100 + ')';
+        
+        theDiv.style.opacity = mozillaOpacity;
+        theDiv.style.filter = ieOpacity;
+
+        var spanElements = theDiv.parentNode.getElementsByTagName("span");
+        
+        for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
+            spanElements[currIdx].style.opacity = mozillaOpacity;
+            spanElements[currIdx].style.filter = ieOpacity;
+        }
+
+    },
+
+    /** this function takes care of redoing the rico cornering
+    *    
+    *    you can't just call updateRicoCorners() again and pass it a 
+    *    new options string. you have to first remove the divs that 
+    *    rico puts on top and below the content div.
+    *
+    * @param {DOM} theDiv - A child of the outer <div> that was
+    *                        supplied to the `round` method.
+    *
+    * @param {Object} options - list of options
+    */
+    reRound: function(theDiv, options) {
+
+        var topRico = theDiv.parentNode.childNodes[0];
+        //theDiv would be theDiv.parentNode.childNodes[1]
+        var bottomRico = theDiv.parentNode.childNodes[2];
+       
+        theDiv.parentNode.removeChild(topRico);
+        theDiv.parentNode.removeChild(bottomRico); 
+
+        this.round(theDiv.parentNode, options);
+    }, 
+
+   _roundCornersImpl: function(e, color, bgColor) {
+      if(this.options.border) {
+         this._renderBorder(e,bgColor);
+      }
+      if(this._isTopRounded()) {
+         this._roundTopCorners(e,color,bgColor);
+      }
+      if(this._isBottomRounded()) {
+         this._roundBottomCorners(e,color,bgColor);
+      }
+   },
+
+   _renderBorder: function(el,bgColor) {
+      var borderValue = "1px solid " + this._borderColor(bgColor);
+      var borderL = "border-left: "  + borderValue;
+      var borderR = "border-right: " + borderValue;
+      var style   = "style='" + borderL + ";" + borderR +  "'";
+      el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
+   },
+
+   _roundTopCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=0 ; i < this.options.numSlices ; i++ ) {
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
+      }
+      el.style.paddingTop = 0;
+      el.insertBefore(corner,el.firstChild);
+   },
+
+   _roundBottomCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- ) {
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
+      }
+      el.style.paddingBottom = 0;
+      el.appendChild(corner);
+   },
+
+   _createCorner: function(bgColor) {
+      var corner = document.createElement("div");
+      corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
+      return corner;
+   },
+
+   _createCornerSlice: function(color,bgColor, n, position) {
+      var slice = document.createElement("span");
+
+      var inStyle = slice.style;
+      inStyle.backgroundColor = color;
+      inStyle.display  = "block";
+      inStyle.height   = "1px";
+      inStyle.overflow = "hidden";
+      inStyle.fontSize = "1px";
+
+      var borderColor = this._borderColor(color,bgColor);
+      if ( this.options.border && n == 0 ) {
+         inStyle.borderTopStyle    = "solid";
+         inStyle.borderTopWidth    = "1px";
+         inStyle.borderLeftWidth   = "0px";
+         inStyle.borderRightWidth  = "0px";
+         inStyle.borderBottomWidth = "0px";
+         inStyle.height            = "0px"; // assumes css compliant box model
+         inStyle.borderColor       = borderColor;
+      }
+      else if(borderColor) {
+         inStyle.borderColor = borderColor;
+         inStyle.borderStyle = "solid";
+         inStyle.borderWidth = "0px 1px";
+      }
+
+      if ( !this.options.compact && (n == (this.options.numSlices-1)) ) {
+         inStyle.height = "2px";
+      }
+      this._setMargin(slice, n, position);
+      this._setBorder(slice, n, position);
+      return slice;
+   },
+
+   _setOptions: function(options) {
+      this.options = {
+         corners : "all",
+         color   : "fromElement",
+         bgColor : "fromParent",
+         blend   : true,
+         border  : false,
+         compact : false
+      };
+      OpenLayers.Util.extend(this.options, options || {});
+
+      this.options.numSlices = this.options.compact ? 2 : 4;
+      if ( this._isTransparent() ) {
+         this.options.blend = false;
+      }
+   },
+
+   _whichSideTop: function() {
+      if ( this._hasString(this.options.corners, "all", "top") ) {
+         return "";
+      }
+      if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 ) {
+         return "";
+      }
+      if (this.options.corners.indexOf("tl") >= 0) {
+         return "left";
+      } else if (this.options.corners.indexOf("tr") >= 0) {
+          return "right";
+      }
+      return "";
+   },
+
+   _whichSideBottom: function() {
+      if ( this._hasString(this.options.corners, "all", "bottom") ) {
+         return "";
+      }
+      if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 ) {
+         return "";
+      }
+
+      if(this.options.corners.indexOf("bl") >=0) {
+         return "left";
+      } else if(this.options.corners.indexOf("br")>=0) {
+         return "right";
+      }
+      return "";
+   },
+
+   _borderColor : function(color,bgColor) {
+      if ( color == "transparent" ) {
+         return bgColor;
+      } else if ( this.options.border ) {
+         return this.options.border;
+      } else if ( this.options.blend ) {
+         return this._blend( bgColor, color );
+      } else {
+         return "";
+      }
+   },
+
+
+   _setMargin: function(el, n, corners) {
+      var marginSize = this._marginSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+      if ( whichSide == "left" ) {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.marginRight = marginSize + "px"; el.style.marginLeft  = "0px";
+      }
+      else {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
+      }
+   },
+
+   _setBorder: function(el,n,corners) {
+      var borderSize = this._borderSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+      if ( whichSide == "left" ) {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth  = "0px";
+      }
+      else {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+      }
+      if (this.options.border != false) {
+        el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+      }
+   },
+
+   _marginSize: function(n) {
+      if ( this._isTransparent() ) {
+         return 0;
+      }
+      var marginSizes          = [ 5, 3, 2, 1 ];
+      var blendedMarginSizes   = [ 3, 2, 1, 0 ];
+      var compactMarginSizes   = [ 2, 1 ];
+      var smBlendedMarginSizes = [ 1, 0 ];
+
+      if ( this.options.compact && this.options.blend ) {
+         return smBlendedMarginSizes[n];
+      } else if ( this.options.compact ) {
+         return compactMarginSizes[n];
+      } else if ( this.options.blend ) {
+         return blendedMarginSizes[n];
+      } else {
+         return marginSizes[n];
+      }
+   },
+
+   _borderSize: function(n) {
+      var transparentBorderSizes = [ 5, 3, 2, 1 ];
+      var blendedBorderSizes     = [ 2, 1, 1, 1 ];
+      var compactBorderSizes     = [ 1, 0 ];
+      var actualBorderSizes      = [ 0, 2, 0, 0 ];
+
+      if ( this.options.compact && (this.options.blend || this._isTransparent()) ) {
+         return 1;
+      } else if ( this.options.compact ) {
+         return compactBorderSizes[n];
+      } else if ( this.options.blend ) {
+         return blendedBorderSizes[n];
+      } else if ( this.options.border ) {
+         return actualBorderSizes[n];
+      } else if ( this._isTransparent() ) {
+         return transparentBorderSizes[n];
+      }
+      return 0;
+   },
+
+   _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) { return true; } return false; },
+   _blend: function(c1, c2) { var cc1 = OpenLayers.Rico.Color.createFromHex(c1); cc1.blend(OpenLayers.Rico.Color.createFromHex(c2)); return cc1; },
+   _background: function(el) { try { return OpenLayers.Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
+   _isTransparent: function() { return this.options.color == "transparent"; },
+   _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
+   _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
+   _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
+};
+/* ======================================================================
+    OpenLayers/Popup/AnchoredBubble.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Popup/Anchored.js
+ * @requires Rico/Corner.js
+ */
+
+/**
+ * Class: OpenLayers.Popup.AnchoredBubble
+ * 
+ * Inherits from: 
+ *  - <OpenLayers.Popup.Anchored>
+ */
+OpenLayers.Popup.AnchoredBubble = 
+  OpenLayers.Class(OpenLayers.Popup.Anchored, {
+
+    /**
+     * Property: rounded
+     * {Boolean} Has the popup been rounded yet?
+     */
+    rounded: false, 
+    
+    /** 
+     * Constructor: OpenLayers.Popup.AnchoredBubble
+     * 
+     * Parameters:
+     * id - {String}
+     * lonlat - {<OpenLayers.LonLat>}
+     * contentSize - {<OpenLayers.Size>}
+     * contentHTML - {String}
+     * anchor - {Object} Object to which we'll anchor the popup. Must expose 
+     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>) 
+     *     (Note that this is generally an <OpenLayers.Icon>).
+     * closeBox - {Boolean}
+     * closeBoxCallback - {Function} Function to be called on closeBox click.
+     */
+    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
+                        closeBoxCallback) {
+        
+        this.padding = new OpenLayers.Bounds(
+            0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE,
+            0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE
+        );
+        OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments);
+    },
+
+    /** 
+     * Method: draw
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {DOMElement} Reference to a div that contains the drawn popup.
+     */
+    draw: function(px) {
+        
+        OpenLayers.Popup.Anchored.prototype.draw.apply(this, arguments);
+
+        this.setContentHTML();
+        
+        //set the popup color and opacity           
+        this.setBackgroundColor(); 
+        this.setOpacity();
+
+        return this.div;
+    },
+
+    /**
+     * Method: updateRelativePosition
+     * The popup has been moved to a new relative location, in which case
+     *     we will want to re-do the rico corners.
+     */
+    updateRelativePosition: function() {
+        this.setRicoCorners();
+    },
+
+    /**
+     * APIMethod: setSize
+     * 
+     * Parameters:
+     * contentSize - {<OpenLayers.Size>} the new size for the popup's 
+     *     contents div (in pixels).
+     */
+    setSize:function(contentSize) { 
+        OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments);
+
+        this.setRicoCorners();
+    },  
+
+    /**
+     * APIMethod: setBackgroundColor
+     * 
+     * Parameters:
+     * color - {String}
+     */
+    setBackgroundColor:function(color) { 
+        if (color != undefined) {
+            this.backgroundColor = color; 
+        }
+        
+        if (this.div != null) {
+            if (this.contentDiv != null) {
+                this.div.style.background = "transparent";
+                OpenLayers.Rico.Corner.changeColor(this.groupDiv, 
+                                                   this.backgroundColor);
+            }
+        }
+    },  
+    
+    /**
+     * APIMethod: setOpacity
+     * 
+     * Parameters: 
+     * opacity - {float}
+     */
+    setOpacity:function(opacity) { 
+        OpenLayers.Popup.Anchored.prototype.setOpacity.call(this, opacity);
+        
+        if (this.div != null) {
+            if (this.groupDiv != null) {
+                OpenLayers.Rico.Corner.changeOpacity(this.groupDiv, 
+                                                     this.opacity);
+            }
+        }
+    },  
+ 
+    /** 
+     * Method: setBorder
+     * Always sets border to 0. Bubble Popups can not have a border.
+     * 
+     * Parameters:
+     * border - {Integer}
+     */
+    setBorder:function(border) { 
+        this.border = 0;
+    },      
+ 
+    /** 
+     * Method: setRicoCorners
+     * Update RICO corners according to the popup's current relative postion.
+     */
+    setRicoCorners:function() {
+    
+        var corners = this.getCornersToRound(this.relativePosition);
+        var options = {corners: corners,
+                         color: this.backgroundColor,
+                       bgColor: "transparent",
+                         blend: false};
+
+        if (!this.rounded) {
+            OpenLayers.Rico.Corner.round(this.div, options);
+            this.rounded = true;
+        } else {
+            OpenLayers.Rico.Corner.reRound(this.groupDiv, options);
+            //set the popup color and opacity
+            this.setBackgroundColor(); 
+            this.setOpacity();
+        }
+    },
+
+    /** 
+     * Method: getCornersToRound
+     *  
+     * Returns:
+     * {String} The proper corners string ("tr tl bl br") for rico to round.
+     */
+    getCornersToRound:function() {
+
+        var corners = ['tl', 'tr', 'bl', 'br'];
+
+        //we want to round all the corners _except_ the opposite one. 
+        var corner = OpenLayers.Bounds.oppositeQuadrant(this.relativePosition);
+        OpenLayers.Util.removeItem(corners, corner);
+
+        return corners.join(" ");
+    },
+
+    CLASS_NAME: "OpenLayers.Popup.AnchoredBubble"
+});
+
+/**
+ * Constant: CORNER_SIZE
+ * {Integer} 5. Border space for the RICO corners.
+ */
+OpenLayers.Popup.AnchoredBubble.CORNER_SIZE = 5;
+
+/* ======================================================================
+    OpenLayers/Strategy/BBOX.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.BBOX
+ * A simple strategy that reads new features when the viewport invalidates
+ *     some bounds.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * Property: bounds
+     * {<OpenLayers.Bounds>} The current data bounds (in the same projection
+     *     as the layer - not always the same projection as the map).
+     */
+    bounds: null,
+    
+    /** 
+     * Property: resolution 
+     * {Float} The current data resolution. 
+     */ 
+    resolution: null, 
+           
+    /**
+     * APIProperty: ratio
+     * {Float} The ratio of the data bounds to the viewport bounds (in each
+     *     dimension).  Default is 2.
+     */
+    ratio: 2,
+
+    /** 
+     * Property: resFactor 
+     * {Float} Optional factor used to determine when previously requested 
+     *     features are invalid.  If set, the resFactor will be compared to the
+     *     resolution of the previous request to the current map resolution.
+     *     If resFactor > (old / new) and 1/resFactor < (old / new).  If you
+     *     set a resFactor of 1, data will be requested every time the
+     *     resolution changes.  If you set a resFactor of 3, data will be
+     *     requested if the old resolution is 3 times the new, or if the new is
+     *     3 times the old.  If the old bounds do not contain the new bounds
+     *     new data will always be requested (with or without considering
+     *     resFactor). 
+     */ 
+    resFactor: null, 
+    
+    /**
+     * Property: response
+     * {<OpenLayers.Protocol.Response>} The protocol response object returned
+     *      by the layer protocol.
+     */
+    response: null,
+
+    /**
+     * Constructor: OpenLayers.Strategy.BBOX
+     * Create a new BBOX strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    
+    /**
+     * Method: activate
+     * Set up strategy with regard to reading new batches of remote data.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            this.layer.events.on({
+                "moveend": this.update,
+                scope: this
+            });
+            this.layer.events.on({
+                "refresh": this.update,
+                scope: this
+            });
+            if(this.layer.visibility === true && this.layer.inRange === true) {
+                this.update();
+            } else {
+                this.layer.events.on({
+                    "visibilitychanged": this.update,
+                    scope: this
+                });
+            }
+        }
+        return activated;
+    },
+    
+    /**
+     * Method: deactivate
+     * Tear down strategy with regard to reading new batches of remote data.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.layer.events.un({
+                "moveend": this.update,
+                "refresh": this.update,
+                "visibilitychanged": this.update,
+                scope: this
+            });
+        }
+        return deactivated;
+    },
+
+    /**
+     * Method: update
+     * Callback function called on "moveend" or "refresh" layer events.
+     *
+     * Parameters:
+     * options - {Object} An object with a property named "force", this
+     *      property references a boolean value indicating if new data
+     *      must be incondtionally read.
+     */
+    update: function(options) {
+        var mapBounds = this.getMapBounds();
+        if (mapBounds !== null && ((options && options.force) ||
+                                   this.invalidBounds(mapBounds))) {
+            this.calculateBounds(mapBounds);
+            this.resolution = this.layer.map.getResolution(); 
+            this.triggerRead(options);
+        }
+    },
+    
+    /**
+     * Method: getMapBounds
+     * Get the map bounds expressed in the same projection as this layer.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} Map bounds in the projection of the layer.
+     */
+    getMapBounds: function() {
+        if (this.layer.map === null) {
+            return null;
+        }
+        var bounds = this.layer.map.getExtent();
+        if(bounds && !this.layer.projection.equals(
+                this.layer.map.getProjectionObject())) {
+            bounds = bounds.clone().transform(
+                this.layer.map.getProjectionObject(), this.layer.projection
+            );
+        }
+        return bounds;
+    },
+
+    /**
+     * Method: invalidBounds
+     * Determine whether the previously requested set of features is invalid. 
+     *     This occurs when the new map bounds do not contain the previously 
+     *     requested bounds.  In addition, if <resFactor> is set, it will be 
+     *     considered.
+     *
+     * Parameters:
+     * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
+     *      retrieved from the map object if not provided
+     *
+     * Returns:
+     * {Boolean} 
+     */
+    invalidBounds: function(mapBounds) {
+        if(!mapBounds) {
+            mapBounds = this.getMapBounds();
+        }
+        var invalid = !this.bounds || !this.bounds.containsBounds(mapBounds);
+        if(!invalid && this.resFactor) {
+            var ratio = this.resolution / this.layer.map.getResolution();
+            invalid = (ratio >= this.resFactor || ratio <= (1 / this.resFactor));
+        }
+        return invalid;
+    },
+ 
+    /**
+     * Method: calculateBounds
+     *
+     * Parameters:
+     * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
+     *      retrieved from the map object if not provided
+     */
+    calculateBounds: function(mapBounds) {
+        if(!mapBounds) {
+            mapBounds = this.getMapBounds();
+        }
+        var center = mapBounds.getCenterLonLat();
+        var dataWidth = mapBounds.getWidth() * this.ratio;
+        var dataHeight = mapBounds.getHeight() * this.ratio;
+        this.bounds = new OpenLayers.Bounds(
+            center.lon - (dataWidth / 2),
+            center.lat - (dataHeight / 2),
+            center.lon + (dataWidth / 2),
+            center.lat + (dataHeight / 2)
+        );
+    },
+    
+    /**
+     * Method: triggerRead
+     *
+     * Parameters:
+     * options - Additional options for the protocol's read method (optional)
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} The protocol response object
+     *      returned by the layer protocol.
+     */
+    triggerRead: function(options) {
+        if (this.response) {
+            this.layer.protocol.abort(this.response);
+            this.layer.events.triggerEvent("loadend");
+        }
+        this.layer.events.triggerEvent("loadstart");
+        this.response = this.layer.protocol.read(
+            OpenLayers.Util.applyDefaults({
+                filter: this.createFilter(),
+                callback: this.merge,
+                scope: this
+        }, options));
+    },
+ 
+    /**
+     * Method: createFilter
+     * Creates a spatial BBOX filter. If the layer that this strategy belongs
+     * to has a filter property, this filter will be combined with the BBOX 
+     * filter.
+     * 
+     * Returns
+     * {<OpenLayers.Filter>} The filter object.
+     */
+    createFilter: function() {
+        var filter = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.BBOX,
+            value: this.bounds,
+            projection: this.layer.projection
+        });
+        if (this.layer.filter) {
+            filter = new OpenLayers.Filter.Logical({
+                type: OpenLayers.Filter.Logical.AND,
+                filters: [this.layer.filter, filter]
+            });
+        }
+        return filter;
+    },
+   
+    /**
+     * Method: merge
+     * Given a list of features, determine which ones to add to the layer.
+     *     If the layer projection differs from the map projection, features
+     *     will be transformed from the layer projection to the map projection.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object passed
+     *      by the protocol.
+     */
+    merge: function(resp) {
+        this.layer.destroyFeatures();
+        var features = resp.features;
+        if(features && features.length > 0) {
+            var remote = this.layer.projection;
+            var local = this.layer.map.getProjectionObject();
+            if(!local.equals(remote)) {
+                var geom;
+                for(var i=0, len=features.length; i<len; ++i) {
+                    geom = features[i].geometry;
+                    if(geom) {
+                        geom.transform(remote, local);
+                    }
+                }
+            }
+            this.layer.addFeatures(features);
+        }
+        this.response = null;
+        this.layer.events.triggerEvent("loadend");
+    },
+   
+    CLASS_NAME: "OpenLayers.Strategy.BBOX" 
+});
+/* ======================================================================
+    OpenLayers/Layer/WorldWind.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WorldWind
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.WorldWind = OpenLayers.Class(OpenLayers.Layer.Grid, {
+    
+    DEFAULT_PARAMS: {
+    },
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} WorldWind layer is a base layer by default.
+     */
+    isBaseLayer: true,
+
+    /** 
+     * APIProperty: lzd
+     * {Float} LevelZeroTileSizeDegrees
+     */
+    lzd: null,
+
+    /**
+     * APIProperty: zoomLevels
+     * {Integer} Number of zoom levels.
+     */
+    zoomLevels: null,
+    
+    /**
+     * Constructor: OpenLayers.Layer.WorldWind
+     * 
+     * Parameters:
+     * name - {String} Name of Layer
+     * url - {String} Base URL  
+     * lzd - {Float} Level zero tile size degrees 
+     * zoomLevels - {Integer} number of zoom levels
+     * params - {Object} additional parameters
+     * options - {Object} additional options
+     */
+    initialize: function(name, url, lzd, zoomLevels, params, options) {
+        this.lzd = lzd;
+        this.zoomLevels = zoomLevels;
+        var newArguments = [];
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+        this.params = OpenLayers.Util.applyDefaults(
+            this.params, this.DEFAULT_PARAMS
+        );
+    },
+
+    /**
+     * Method: getZoom
+     * Convert map zoom to WW zoom.
+     */
+    getZoom: function () {
+        var zoom = this.map.getZoom();
+        var extent = this.map.getMaxExtent();
+        zoom = zoom - Math.log(this.maxResolution / (this.lzd/512))/Math.log(2);
+        return zoom;
+    },
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the 
+     *           passed-in bounds and appropriate tile size specified as 
+     *           parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var zoom = this.getZoom();
+        var extent = this.map.getMaxExtent();
+        var deg = this.lzd/Math.pow(2,this.getZoom());
+        var x = Math.floor((bounds.left - extent.left)/deg);
+        var y = Math.floor((bounds.bottom - extent.bottom)/deg);
+        if (this.map.getResolution() <= (this.lzd/512)
+            && this.getZoom() <= this.zoomLevels) {
+            return this.getFullRequestString(
+              { L: zoom, 
+                X: x,
+                Y: y
+              });
+        } else {
+            return OpenLayers.Util.getImagesLocation() + "blank.gif";
+        }
+
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.WorldWind"
+});
+/* ======================================================================
+    OpenLayers/Protocol/WFS/v1_1_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol/WFS/v1.js
+ * @requires OpenLayers/Format/WFST/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.WFS.v1_1_0
+ * A WFS v1.1.0 protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.WFS.v1_1_0> constructor.
+ *
+ * Differences from the v1.0.0 protocol:
+ *  - uses Filter Encoding 1.1.0 instead of 1.0.0
+ *  - uses GML 3 instead of 2 if no format is provided
+ *  
+ * Inherits from:
+ *  - <OpenLayers.Protocol.WFS.v1>
+ */
+OpenLayers.Protocol.WFS.v1_1_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, {
+    
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: "1.1.0",
+    
+    /**
+     * Constructor: OpenLayers.Protocol.WFS.v1_1_0
+     * A class for giving layers WFS v1.1.0 protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (optional).
+     * featurePrefix - {String} Feature namespace alias (optional - only used
+     *     if featureNS is provided).  Default is 'feature'.
+     * geometryName - {String} Name of geometry attribute.  Default is 'the_geom'.
+     * outputFormat - {String} Optional output format to use for WFS GetFeature
+     *     requests. This can be any format advertized by the WFS's
+     *     GetCapabilities response. If set, an appropriate readFormat also
+     *     has to be provided, unless outputFormat is GML3, GML2 or JSON.
+     * readFormat - {<OpenLayers.Format>} An appropriate format parser if
+     *     outputFormat is none of GML3, GML2 or JSON.
+     */
+    initialize: function(options) {
+        OpenLayers.Protocol.WFS.v1.prototype.initialize.apply(this, arguments);
+        if (this.outputFormat && !this.readFormat) {
+            if (this.outputFormat.toLowerCase() == "gml2") {
+                this.readFormat = new OpenLayers.Format.GML.v2({
+                    featureType: this.featureType,
+                    featureNS: this.featureNS,
+                    geometryName: this.geometryName
+                });
+            } else if (this.outputFormat.toLowerCase() == "json") {
+                this.readFormat = new OpenLayers.Format.GeoJSON();
+            }
+        }
+    },
+   
+    CLASS_NAME: "OpenLayers.Protocol.WFS.v1_1_0"
+});
+/* ======================================================================
+    OpenLayers/Format/WMTSCapabilities.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+ 
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities
+ * Read WMTS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * APIProperty: yx
+     * {Object} Members in the yx object are used to determine if a CRS URN
+     *     corresponds to a CRS with y,x axis order.  Member names are CRS URNs
+     *     and values are boolean.  By default, the following CRS URN are 
+     *     assumed to correspond to a CRS with y,x axis order:
+     *
+     * * urn:ogc:def:crs:EPSG::4326
+     */
+    yx: {
+        "urn:ogc:def:crs:EPSG::4326": true
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.WMTSCapabilities
+     * Create a new parser for WMTS capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return information about
+     * the service (offering and observedProperty mostly).
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Info about the WMTS Capabilities
+     */
+
+    /**
+     * APIMethod: createLayer
+     * Create a WMTS layer given a capabilities object.
+     *
+     * Parameters:
+     * capabilities - {Object} The object returned from a <read> call to this 
+     *     format.
+     * config - {Object} Configuration properties for the layer.  Defaults for
+     *     the layer will apply if not provided.
+     *
+     * Required config properties:
+     * layer - {String} The layer identifier.
+     * matrixSet - {String} The matrix set identifier.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMTS>} A properly configured WMTS layer.  Throws an
+     *     error if an incomplete config is provided.  Returns undefined if no
+     *     layer could be created with the provided config.
+     */ 
+    createLayer: function(capabilities, config) {
+        var layer;
+
+        // confirm required properties are supplied in config
+        var required = {
+            layer: true,
+            matrixSet: true
+        };
+        for (var prop in required) {
+            if (!(prop in config)) {
+                throw new Error("Missing property '" + prop + "' in layer configuration.");
+            }
+        }
+
+        var contents = capabilities.contents;
+        var matrixSet = contents.tileMatrixSets[config.matrixSet];
+
+        // find the layer definition with the given identifier
+        var layers = contents.layers;
+        var layerDef;
+        for (var i=0, ii=contents.layers.length; i<ii; ++i) {
+            if (contents.layers[i].identifier === config.layer) {
+                layerDef = contents.layers[i];
+                break;
+            }
+        }
+        
+        if (layerDef && matrixSet) {
+            // get the default style for the layer
+            var style;
+            for (var i=0, ii=layerDef.styles.length; i<ii; ++i) {
+                style = layerDef.styles[i];
+                if (style.isDefault) {
+                    break;
+                }
+            }
+            
+            layer = new OpenLayers.Layer.WMTS(
+                OpenLayers.Util.applyDefaults(config, {
+                    url: capabilities.operationsMetadata.GetTile.dcp.http.get,
+                    name: layerDef.title,
+                    style: style.identifier,
+                    matrixIds: matrixSet.matrixIds
+                })
+            );
+        }
+        return layer;
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WMTSCapabilities" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/Google/v3.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Google.js
+ */
+
+/**
+ * Constant: OpenLayers.Layer.Google.v3
+ * 
+ * Mixin providing functionality specific to the Google Maps API v3. Note that
+ * this layer configures the google.maps.map object with the "disableDefaultUI"
+ * option set to true. Using UI controls that the Google Maps API provides is
+ * not supported by the OpenLayers API.
+ */
+OpenLayers.Layer.Google.v3 = {
+    
+    /**
+     * Constant: DEFAULTS
+     * {Object} It is not recommended to change the properties set here. Note
+     * that Google.v3 layers only work when sphericalMercator is set to true.
+     * 
+     * (code)
+     * {
+     *     maxExtent: new OpenLayers.Bounds(
+     *         -128 * 156543.03390625,
+     *         -128 * 156543.03390625,
+     *         128 * 156543.03390625,
+     *         128 * 156543.03390625
+     *     ),
+     *     sphericalMercator: true,
+     *     maxResolution: 156543.03390625,
+     *     units: "m",
+     *     projection: "EPSG:900913"
+     * }
+     * (end)
+     */
+    DEFAULTS: {
+        maxExtent: new OpenLayers.Bounds(
+            -128 * 156543.03390625,
+            -128 * 156543.03390625,
+            128 * 156543.03390625,
+            128 * 156543.03390625
+        ),
+        sphericalMercator: true,
+        maxResolution: 156543.03390625,
+        units: "m",
+        projection: "EPSG:900913"
+    },
+
+    /**
+     * APIProperty: animationEnabled
+     * {Boolean} If set to true, the transition between zoom levels will be
+     *     animated (if supported by the GMaps API for the device used). Set to
+     *     false to match the zooming experience of other layer types. Default
+     *     is true. Note that the GMaps API does not give us control over zoom
+     *     animation, so if set to false, when zooming, this will make the
+     *     layer temporarily invisible, wait until GMaps reports the map being
+     *     idle, and make it visible again. The result will be a blank layer
+     *     for a few moments while zooming.
+     */
+    animationEnabled: true, 
+
+    /** 
+     * Method: loadMapObject
+     * Load the GMap and register appropriate event listeners. If we can't 
+     *     load GMap2, then display a warning message.
+     */
+    loadMapObject:function() {
+        if (!this.type) {
+            this.type = google.maps.MapTypeId.ROADMAP;
+        }
+        var mapObject;
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // there are already Google layers added to this map
+            mapObject = cache.mapObject;
+            // increment the layer count
+            ++cache.count;
+        } else {
+            // this is the first Google layer for this map
+
+            var container = this.map.viewPortDiv;
+            var div = document.createElement("div");
+            div.id = this.map.id + "_GMapContainer";
+            div.style.position = "absolute";
+            div.style.width = "100%";
+            div.style.height = "100%";
+            container.appendChild(div);
+
+            // create GMap and shuffle elements
+            var center = this.map.getCenter();
+            mapObject = new google.maps.Map(div, {
+                center: center ?
+                    new google.maps.LatLng(center.lat, center.lon) :
+                    new google.maps.LatLng(0, 0),
+                zoom: this.map.getZoom() || 0,
+                mapTypeId: this.type,
+                disableDefaultUI: true,
+                keyboardShortcuts: false,
+                draggable: false,
+                disableDoubleClickZoom: true,
+                scrollwheel: false,
+                streetViewControl: false
+            });
+            
+            // cache elements for use by any other google layers added to
+            // this same map
+            cache = {
+                mapObject: mapObject,
+                count: 1
+            };
+            OpenLayers.Layer.Google.cache[this.map.id] = cache;
+            this.repositionListener = google.maps.event.addListenerOnce(
+                mapObject, 
+                "center_changed", 
+                OpenLayers.Function.bind(this.repositionMapElements, this)
+            );
+        }
+        this.mapObject = mapObject;
+        this.setGMapVisibility(this.visibility);
+    },
+    
+    /**
+     * Method: repositionMapElements
+     *
+     * Waits until powered by and terms of use elements are available and then
+     * moves them so they are clickable.
+     */
+    repositionMapElements: function() {
+
+        // This is the first time any Google layer in this mapObject has been
+        // made visible.  The mapObject needs to know the container size.
+        google.maps.event.trigger(this.mapObject, "resize");
+        
+        var div = this.mapObject.getDiv().firstChild;
+        if (!div || div.childNodes.length < 3) {
+            this.repositionTimer = window.setTimeout(
+                OpenLayers.Function.bind(this.repositionMapElements, this),
+                250
+            );
+            return false;
+        }
+
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        var container = this.map.viewPortDiv;
+        
+        // move the Map Data popup to the container, if any
+        while (div.lastChild.style.display == "none") {
+            container.appendChild(div.lastChild);
+        }
+
+        // move the ToS and branding stuff up to the container div
+        var termsOfUse = div.lastChild;
+        container.appendChild(termsOfUse);
+        termsOfUse.style.zIndex = "1100";
+        termsOfUse.style.bottom = "";
+        termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
+        termsOfUse.style.display = "";
+        cache.termsOfUse = termsOfUse;
+
+        var poweredBy = div.lastChild;
+        container.appendChild(poweredBy);
+        poweredBy.style.zIndex = "1100";
+        poweredBy.style.bottom = "";
+        poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
+        poweredBy.style.display = "";
+        cache.poweredBy = poweredBy;
+
+        this.setGMapVisibility(this.visibility);
+
+    },
+
+    /**
+     * APIMethod: onMapResize
+     */
+    onMapResize: function() {
+        if (this.visibility) {
+            google.maps.event.trigger(this.mapObject, "resize");
+        } else {
+            var cache = OpenLayers.Layer.Google.cache[this.map.id];
+            if (!cache.resized) {
+                var layer = this;
+                google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() {
+                    google.maps.event.trigger(layer.mapObject, "resize");
+                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
+                    delete cache.resized;
+                });
+            }
+            cache.resized = true;
+        }
+    },
+
+    /**
+     * Method: setGMapVisibility
+     * Display the GMap container and associated elements.
+     * 
+     * Parameters:
+     * visible - {Boolean} Display the GMap elements.
+     */
+    setGMapVisibility: function(visible) {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            var type = this.type;
+            var layers = this.map.layers;
+            var layer;
+            for (var i=layers.length-1; i>=0; --i) {
+                layer = layers[i];
+                if (layer instanceof OpenLayers.Layer.Google &&
+                            layer.visibility === true && layer.inRange === true) {
+                    type = layer.type;
+                    visible = true;
+                    break;
+                }
+            }
+            var container = this.mapObject.getDiv();
+            if (visible === true) {
+                this.mapObject.setMapTypeId(type);                
+                container.style.left = "";
+                if (cache.termsOfUse && cache.termsOfUse.style) {
+                    cache.termsOfUse.style.left = "";
+                    cache.termsOfUse.style.display = "";
+                    cache.poweredBy.style.display = "";            
+                }
+                cache.displayed = this.id;
+            } else {
+                delete cache.displayed;
+                container.style.left = "-9999px";
+                if (cache.termsOfUse && cache.termsOfUse.style) {
+                    cache.termsOfUse.style.display = "none";
+                    // move ToU far to the left in addition to setting
+                    // display to "none", because at the end of the GMap
+                    // load sequence, display: none will be unset and ToU
+                    // would be visible after loading a map with a google
+                    // layer that is initially hidden. 
+                    cache.termsOfUse.style.left = "-9999px";
+                    cache.poweredBy.style.display = "none";
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: getMapContainer
+     * 
+     * Returns:
+     * {DOMElement} the GMap container's div
+     */
+    getMapContainer: function() {
+        return this.mapObject.getDiv();
+    },
+    
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
+     * APIMethod: getMapObjectBoundsFromOLBounds
+     * 
+     * Parameters:
+     * olBounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {Object} A MapObject Bounds, translated from olBounds
+     *          Returns null if null value is passed in
+     */
+    getMapObjectBoundsFromOLBounds: function(olBounds) {
+        var moBounds = null;
+        if (olBounds != null) {
+            var sw = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.bottom, olBounds.left) : 
+              new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
+            var ne = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.top, olBounds.right) : 
+              new OpenLayers.LonLat(olBounds.top, olBounds.right);
+            moBounds = new google.maps.LatLngBounds(
+                new google.maps.LatLng(sw.lat, sw.lon),
+                new google.maps.LatLng(ne.lat, ne.lon)
+            );
+        }
+        return moBounds;
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        var size = this.map.getSize();
+        var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center);
+        var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center);
+        var res = this.map.getResolution();
+
+        var delta_x = moPixel.x - (size.w / 2);
+        var delta_y = moPixel.y - (size.h / 2);
+    
+        var lonlat = new OpenLayers.LonLat(
+            lon + delta_x * res,
+            lat - delta_y * res
+        ); 
+
+        if (this.wrapDateLine) {
+            lonlat = lonlat.wrapDateLine(this.maxExtent);
+        }
+        return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
+        var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
+        var res = this.map.getResolution();
+        var extent = this.map.getExtent();
+        var px = new OpenLayers.Pixel(
+            (1/res * (lon - extent.left)),
+            (1/res * (extent.top - lat))
+        );    
+        return this.getMapObjectPixelFromXY(px.x, px.y);
+    },
+
+  
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        if (this.animationEnabled === false && zoom != this.mapObject.zoom) {
+            var mapContainer = this.getMapContainer();
+            google.maps.event.addListenerOnce(
+                this.mapObject, 
+                "idle", 
+                function() {
+                    mapContainer.style.visibility = "";
+                }
+            );
+            mapContainer.style.visibility = "hidden";
+        }
+        this.mapObject.setOptions({
+            center: center,
+            zoom: zoom
+        });
+    },
+   
+    
+  // Bounds
+  
+    /** 
+     * APIMethod: getMapObjectZoomFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object} MapObject Bounds format
+     * 
+     * Returns:
+     * {Object} MapObject Zoom for specified MapObject Bounds
+     */
+    getMapObjectZoomFromMapObjectBounds: function(moBounds) {
+        return this.mapObject.getBoundsZoomLevel(moBounds);
+    },
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var gLatLng;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            gLatLng = new google.maps.LatLng(lonlat.lat, lonlat.lon);
+        } else {
+            gLatLng = new google.maps.LatLng(lat, lon);
+        }
+        return gLatLng;
+    },
+    
+  // Pixel
+    
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new google.maps.Point(x, y);
+    },
+        
+    /**
+     * APIMethod: destroy
+     * Clean up this layer.
+     */
+    destroy: function() {
+        if (this.repositionListener) {
+            google.maps.event.removeListener(this.repositionListener);
+        }
+        if (this.repositionTimer) {
+            window.clearTimeout(this.repositionTimer);
+        }
+        OpenLayers.Layer.Google.prototype.destroy.apply(this, arguments);
+    }
+    
+};
+/* ======================================================================
+    OpenLayers/Format/WPSDescribeProcess.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+ 
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSDescribeProcess
+ * Read WPS DescribeProcess responses. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSDescribeProcess = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        wps: "http://www.opengis.net/wps/1.0.0",
+        ows: "http://www.opengis.net/ows/1.1",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "wps",
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.WPSDescribeProcess
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Parse a WPS DescribeProcess and return an object with its information.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object}
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var info = {};
+        this.readNode(data, info);
+        return info;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wps": {
+            "ProcessDescriptions": function(node, obj) {
+                obj.processDescriptions = {};
+                this.readChildNodes(node, obj.processDescriptions);
+            },
+            "ProcessDescription": function(node, processDescriptions) {
+                var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion");
+                var processDescription = {
+                    processVersion: processVersion,
+                    statusSupported: (node.getAttribute("statusSupported") === "true"),
+                    storeSupported: (node.getAttribute("storeSupported") === "true")
+                };
+                this.readChildNodes(node, processDescription);
+                processDescriptions[processDescription.identifier] = processDescription;
+            },
+            "DataInputs": function(node, processDescription) {
+                processDescription.dataInputs = [];
+                this.readChildNodes(node, processDescription.dataInputs);
+            },
+            "ProcessOutputs": function(node, processDescription) {
+                processDescription.processOutputs = [];
+                this.readChildNodes(node, processDescription.processOutputs);
+            },
+            "Output": function(node, processOutputs) {
+                var output = {};
+                this.readChildNodes(node, output);
+                processOutputs.push(output);
+            },
+            "ComplexOutput": function(node, output) {
+                output.complexOutput = {};
+                this.readChildNodes(node, output.complexOutput);
+            },
+            "Input": function(node, dataInputs) {
+                var input = {
+                    maxOccurs: parseInt(node.getAttribute("maxOccurs")),
+                    minOccurs: parseInt(node.getAttribute("minOccurs"))
+                };
+                this.readChildNodes(node, input);
+                dataInputs.push(input);
+            },
+            "BoundingBoxData": function(node, input) {
+                input.boundingBoxData = {};
+                this.readChildNodes(node, input.boundingBoxData);
+            },
+            "CRS": function(node, obj) {
+                if (!obj.CRSs) {
+                    obj.CRSs = {};
+                }
+                obj.CRSs[this.getChildValue(node)] = true;
+            },
+            "LiteralData": function(node, input) {
+                input.literalData = {};
+                this.readChildNodes(node, input.literalData);
+            },
+            "ComplexData": function(node, input) {
+                input.complexData = {};
+                this.readChildNodes(node,  input.complexData);
+            },
+            "Default": function(node, complexData) {
+                complexData["default"] = {};
+                this.readChildNodes(node,  complexData["default"]);
+            },
+            "Supported": function(node, complexData) {
+                complexData["supported"] = {};
+                this.readChildNodes(node,  complexData["supported"]);
+            },
+            "Format": function(node, obj) {
+                var format = {};
+                this.readChildNodes(node, format);
+                if (!obj.formats) {
+                    obj.formats = {};
+                }
+                obj.formats[format.mimeType] = true;
+            },
+            "MimeType": function(node, format) {
+                format.mimeType = this.getChildValue(node);
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WPSDescribeProcess" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/CSWGetRecords/v2_0_2.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetRecords.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
+ *     A format for creating CSWGetRecords v2.0.2 transactions. 
+ *     Create a new instance with the
+ *     <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        csw: "http://www.opengis.net/cat/csw/2.0.2",
+        dc: "http://purl.org/dc/elements/1.1/",
+        dct: "http://purl.org/dc/terms/",
+        geonet: "http://www.fao.org/geonetwork",
+        ogc: "http://www.opengis.net/ogc",
+        ows: "http://www.opengis.net/ows",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+    
+    /**
+     * Property: defaultPrefix
+     * {String} The default prefix (used by Format.XML).
+     */
+    defaultPrefix: "csw",
+    
+    /**
+     * Property: version
+     * {String} CSW version number.
+     */
+    version: "2.0.2",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/cat/csw/2.0.2
+     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+     */
+    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+    /**
+     * APIProperty: requestId
+     * {String} Value of the requestId attribute of the GetRecords element.
+     */
+    requestId: null,
+
+    /**
+     * APIProperty: resultType
+     * {String} Value of the resultType attribute of the GetRecords element,
+     *     specifies the result type in the GetRecords response, "hits" is
+     *     the default.
+     */
+    resultType: null,
+
+    /**
+     * APIProperty: outputFormat
+     * {String} Value of the outputFormat attribute of the GetRecords element,
+     *     specifies the format of the GetRecords response,
+     *     "application/xml" is the default.
+     */
+    outputFormat: null,
+
+    /**
+     * APIProperty: outputSchema
+     * {String} Value of the outputSchema attribute of the GetRecords element,
+     *     specifies the schema of the GetRecords response.
+     */
+    outputSchema: null,
+
+    /**
+     * APIProperty: startPosition
+     * {String} Value of the startPosition attribute of the GetRecords element,
+     *     specifies the start position (offset+1) for the GetRecords response,
+     *     1 is the default.
+     */
+    startPosition: null,
+
+    /**
+     * APIProperty: maxRecords
+     * {String} Value of the maxRecords attribute of the GetRecords element,
+     *     specifies the maximum number of records in the GetRecords response,
+     *     10 is the default.
+     */
+    maxRecords: null,
+
+    /**
+     * APIProperty: DistributedSearch
+     * {String} Value of the csw:DistributedSearch element, used when writing
+     *     a csw:GetRecords document.
+     */
+    DistributedSearch: null,
+
+    /**
+     * APIProperty: ResponseHandler
+     * {Array({String})} Values of the csw:ResponseHandler elements, used when
+     *     writting a csw:GetRecords document.
+     */
+    ResponseHandler: null,
+
+    /**
+     * APIProperty: Query
+     * {String} Value of the csw:Query element, used when writing a csw:GetRecords
+     *     document.
+     */
+    Query: null,
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
+     * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties (documented as class properties):
+     * - requestId
+     * - resultType
+     * - outputFormat
+     * - outputSchema
+     * - startPosition
+     * - maxRecords
+     * - DistributedSearch
+     * - ResponseHandler
+     * - Query
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Parse the response from a GetRecords request.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var obj = {};
+        this.readNode(data, obj);
+        return obj;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "csw": {
+            "GetRecordsResponse": function(node, obj) {
+                obj.records = [];
+                this.readChildNodes(node, obj);
+                var version = this.getAttributeNS(node, "", 'version');
+                if (version != "") {
+                    obj.version = version;
+                }
+            },
+            "RequestId": function(node, obj) {
+                obj.RequestId = this.getChildValue(node);
+            },
+            "SearchStatus": function(node, obj) {
+                obj.SearchStatus = {};
+                var timestamp = this.getAttributeNS(node, "", 'timestamp');
+                if (timestamp != "") {
+                    obj.SearchStatus.timestamp = timestamp;
+                }
+            },
+            "SearchResults": function(node, obj) {
+                this.readChildNodes(node, obj);
+                var attrs = node.attributes;
+                var SearchResults = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    if ((attrs[i].name == "numberOfRecordsMatched") ||
+                        (attrs[i].name == "numberOfRecordsReturned") ||
+                        (attrs[i].name == "nextRecord")) {
+                        SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
+                    } else {
+                        SearchResults[attrs[i].name] = attrs[i].nodeValue;
+                    }
+                }
+                obj.SearchResults = SearchResults;
+            },
+            "SummaryRecord": function(node, obj) {
+                var record = {type: "SummaryRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "BriefRecord": function(node, obj) {
+                var record = {type: "BriefRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "DCMIRecord": function(node, obj) {
+                var record = {type: "DCMIRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "Record": function(node, obj) {
+                var record = {type: "Record"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "*": function(node, obj) {
+                var name = node.localName || node.nodeName.split(":").pop();
+                obj[name] = this.getChildValue(node);
+            }
+        },
+        "geonet": {
+            "info": function(node, obj) {
+                var gninfo = {};
+                this.readChildNodes(node, gninfo);
+                obj.gninfo = gninfo;
+            }
+        },
+        "dc": {
+            // audience, contributor, coverage, creator, date, description, format,
+            // identifier, language, provenance, publisher, relation, rights,
+            // rightsHolder, source, subject, title, type, URI
+            "*": function(node, obj) {
+                var name = node.localName || node.nodeName.split(":").pop();
+                if (!(OpenLayers.Util.isArray(obj[name]))) {
+                    obj[name] = new Array();
+                }
+                var dc_element = {};
+                var attrs = node.attributes;
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    dc_element[attrs[i].name] = attrs[i].nodeValue;
+                }
+                dc_element.value = this.getChildValue(node);
+                obj[name].push(dc_element);
+            }
+        },
+        "dct": {
+            // abstract, modified, spatial
+            "*": function(node, obj) {
+                var name = node.localName || node.nodeName.split(":").pop();
+                if (!(OpenLayers.Util.isArray(obj[name]))) {
+                    obj[name] = new Array();
+                }
+                obj[name].push(this.getChildValue(node));
+            }
+        },
+        "ows": OpenLayers.Util.applyDefaults({
+            "BoundingBox": function(node, obj) {
+                if (obj.bounds) {
+                    obj.BoundingBox = [{crs: obj.projection, value: 
+                        [
+                            obj.bounds.left, 
+                            obj.bounds.bottom, 
+                            obj.bounds.right, 
+                            obj.bounds.top
+                    ]
+                    }];
+                    delete obj.projection;
+                    delete obj.bounds;
+                }
+                OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
+                    this, arguments);
+            }
+        }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
+    },
+    
+    /**
+     * Method: write
+     * Given an configuration js object, write a CSWGetRecords request. 
+     *
+     * Parameters:
+     * options - {Object} A object mapping the request.
+     *
+     * Returns:
+     * {String} A serialized CSWGetRecords request.
+     */
+    write: function(options) {
+        var node = this.writeNode("csw:GetRecords", options);
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "csw": {
+            "GetRecords": function(options) {
+                if (!options) {
+                    options = {};
+                }
+                var node = this.createElementNSPlus("csw:GetRecords", {
+                    attributes: {
+                        service: "CSW",
+                        version: this.version,
+                        requestId: options.requestId || this.requestId,
+                        resultType: options.resultType || this.resultType,
+                        outputFormat: options.outputFormat || this.outputFormat,
+                        outputSchema: options.outputSchema || this.outputSchema,
+                        startPosition: options.startPosition || this.startPosition,
+                        maxRecords: options.maxRecords || this.maxRecords
+                    }
+                });
+                if (options.DistributedSearch || this.DistributedSearch) {
+                    this.writeNode(
+                        "csw:DistributedSearch",
+                        options.DistributedSearch || this.DistributedSearch,
+                        node
+                    );
+                }
+                var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
+                if (OpenLayers.Util.isArray(ResponseHandler) && ResponseHandler.length > 0) {
+                    // ResponseHandler must be a non-empty array
+                    for(var i=0, len=ResponseHandler.length; i<len; i++) {
+                        this.writeNode(
+                            "csw:ResponseHandler",
+                            ResponseHandler[i],
+                            node
+                        );
+                    }
+                }
+                this.writeNode("Query", options.Query || this.Query, node);
+                return node;
+            },
+            "DistributedSearch": function(options) {
+                var node = this.createElementNSPlus("csw:DistributedSearch", {
+                    attributes: {
+                        hopCount: options.hopCount
+                    }
+                });
+                return node;
+            },
+            "ResponseHandler": function(options) {
+                var node = this.createElementNSPlus("csw:ResponseHandler", {
+                    value: options.value
+                });
+                return node;
+            },
+            "Query": function(options) {
+                if (!options) {
+                    options = {};
+                }
+                var node = this.createElementNSPlus("csw:Query", {
+                    attributes: {
+                        typeNames: options.typeNames || "csw:Record"
+                    }
+                });
+                var ElementName = options.ElementName;
+                if (OpenLayers.Util.isArray(ElementName) && ElementName.length > 0) {
+                    // ElementName must be a non-empty array
+                    for(var i=0, len=ElementName.length; i<len; i++) {
+                        this.writeNode(
+                            "csw:ElementName",
+                            ElementName[i],
+                            node
+                        );
+                    }
+                } else {
+                    this.writeNode(
+                        "csw:ElementSetName",
+                        options.ElementSetName || {value: 'summary'},
+                        node
+                    );
+                }
+                if (options.Constraint) {
+                    this.writeNode(
+                        "csw:Constraint",
+                        options.Constraint,
+                        node
+                    );
+                }
+                if (options.SortBy) {
+                    this.writeNode(
+                        "ogc:SortBy",
+                        options.SortBy,
+                        node
+                    );
+                }
+                return node;
+            },
+            "ElementName": function(options) {
+                var node = this.createElementNSPlus("csw:ElementName", {
+                    value: options.value
+                });
+                return node;
+            },
+            "ElementSetName": function(options) {
+                var node = this.createElementNSPlus("csw:ElementSetName", {
+                    attributes: {
+                        typeNames: options.typeNames
+                    },
+                    value: options.value
+                });
+                return node;
+            },
+            "Constraint": function(options) {
+                var node = this.createElementNSPlus("csw:Constraint", {
+                    attributes: {
+                        version: options.version
+                    }
+                });
+                if (options.Filter) {
+                    var format = new OpenLayers.Format.Filter({
+                        version: options.version
+                    });
+                    node.appendChild(format.write(options.Filter));
+                } else if (options.CqlText) {
+                    var child = this.createElementNSPlus("CqlText", {
+                        value: options.CqlText.value
+                    });
+                    node.appendChild(child);
+                }
+                return node;
+            }
+        },
+        "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
+    },
+   
+    CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2" 
+});
+/* ======================================================================
+    OpenLayers/Marker/Box.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Marker.js
+ */
+
+/**
+ * Class: OpenLayers.Marker.Box
+ *
+ * Inherits from:
+ *  - <OpenLayers.Marker> 
+ */
+OpenLayers.Marker.Box = OpenLayers.Class(OpenLayers.Marker, {
+
+    /** 
+     * Property: bounds 
+     * {<OpenLayers.Bounds>} 
+     */
+    bounds: null,
+
+    /** 
+     * Property: div 
+     * {DOMElement} 
+     */
+    div: null,
+    
+    /** 
+     * Constructor: OpenLayers.Marker.Box
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * borderColor - {String} 
+     * borderWidth - {int} 
+     */
+    initialize: function(bounds, borderColor, borderWidth) {
+        this.bounds = bounds;
+        this.div    = OpenLayers.Util.createDiv();
+        this.div.style.overflow = 'hidden';
+        this.events = new OpenLayers.Events(this, this.div, null);
+        this.setBorder(borderColor, borderWidth);
+    },
+
+    /**
+     * Method: destroy 
+     */    
+    destroy: function() {
+
+        this.bounds = null;
+        this.div = null;
+
+        OpenLayers.Marker.prototype.destroy.apply(this, arguments);
+    },
+
+    /** 
+     * Method: setBorder
+     * Allow the user to change the box's color and border width
+     * 
+     * Parameters:
+     * color - {String} Default is "red"
+     * width - {int} Default is 2
+     */
+    setBorder: function (color, width) {
+        if (!color) {
+            color = "red";
+        }
+        if (!width) {
+            width = 2;
+        }
+        this.div.style.border = width + "px solid " + color;
+    },
+    
+    /** 
+    * Method: draw
+    * 
+    * Parameters:
+    * px - {<OpenLayers.Pixel>} 
+    * sz - {<OpenLayers.Size>} 
+    * 
+    * Returns: 
+    * {DOMElement} A new DOM Image with this marker´s icon set at the 
+    *         location passed-in
+    */
+    draw: function(px, sz) {
+        OpenLayers.Util.modifyDOMElement(this.div, null, px, sz);
+        return this.div;
+    }, 
+
+    /**
+     * Method: onScreen
+     * 
+     * Rreturn:
+     * {Boolean} Whether or not the marker is currently visible on screen.
+     */
+    onScreen:function() {
+        var onScreen = false;
+        if (this.map) {
+            var screenBounds = this.map.getExtent();
+            onScreen = screenBounds.containsBounds(this.bounds, true, true);
+        }    
+        return onScreen;
+    },
+    
+    /**
+     * Method: display
+     * Hide or show the icon
+     * 
+     * Parameters:
+     * display - {Boolean} 
+     */
+    display: function(display) {
+        this.div.style.display = (display) ? "" : "none";
+    },
+
+    CLASS_NAME: "OpenLayers.Marker.Box"
+});
+
+/* ======================================================================
+    OpenLayers/Format/Text.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Text
+ * Read Text format. Create a new instance with the <OpenLayers.Format.Text>
+ *     constructor. This reads text which is formatted like CSV text, using
+ *     tabs as the seperator by default. It provides parsing of data originally
+ *     used in the MapViewerService, described on the wiki. This Format is used
+ *     by the <OpenLayers.Layer.Text> class.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.Text = OpenLayers.Class(OpenLayers.Format, {
+    
+    /**
+     * APIProperty: defaultStyle
+     * defaultStyle allows one to control the default styling of the features.
+     *    It should be a symbolizer hash. By default, this is set to match the
+     *    Layer.Text behavior, which is to use the default OpenLayers Icon.
+     */
+    defaultStyle: null,
+     
+    /**
+     * APIProperty: extractStyles
+     * set to true to extract styles from the TSV files, using information
+     * from the image or icon, iconSize and iconOffset fields. This will result
+     * in features with a symbolizer (style) property set, using the
+     * default symbolizer specified in <defaultStyle>. Set to false if you
+     * wish to use a styleMap or OpenLayers.Style options to style your
+     * layer instead.
+     */
+    extractStyles: true,
+
+    /**
+     * Constructor: OpenLayers.Format.Text
+     * Create a new parser for TSV Text.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        options = options || {};
+
+        if(options.extractStyles !== false) {
+            options.defaultStyle = {
+                'externalGraphic': OpenLayers.Util.getImagesLocation() +
+                                                                "marker.png",
+                'graphicWidth': 21,
+                'graphicHeight': 25,
+                'graphicXOffset': -10.5,
+                'graphicYOffset': -12.5
+            };
+        }
+        
+        OpenLayers.Format.prototype.initialize.apply(this, [options]);
+    }, 
+
+    /**
+     * APIMethod: read
+     * Return a list of features from a Tab Seperated Values text string.
+     * 
+     * Parameters:
+     * data - {String} 
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(text) {
+        var lines = text.split('\n');
+        var columns;
+        var features = [];
+        // length - 1 to allow for trailing new line
+        for (var lcv = 0; lcv < (lines.length - 1); lcv++) {
+            var currLine = lines[lcv].replace(/^\s*/,'').replace(/\s*$/,'');
+        
+            if (currLine.charAt(0) != '#') { /* not a comment */
+            
+                if (!columns) {
+                    //First line is columns
+                    columns = currLine.split('\t');
+                } else {
+                    var vals = currLine.split('\t');
+                    var geometry = new OpenLayers.Geometry.Point(0,0);
+                    var attributes = {};
+                    var style = this.defaultStyle ? 
+                        OpenLayers.Util.applyDefaults({}, this.defaultStyle) :
+                        null;  
+                    var icon, iconSize, iconOffset, overflow;
+                    var set = false;
+                    for (var valIndex = 0; valIndex < vals.length; valIndex++) {
+                        if (vals[valIndex]) {
+                            if (columns[valIndex] == 'point') {
+                                var coords = vals[valIndex].split(',');
+                                geometry.y = parseFloat(coords[0]);
+                                geometry.x = parseFloat(coords[1]);
+                                set = true;
+                            } else if (columns[valIndex] == 'lat') {
+                                geometry.y = parseFloat(vals[valIndex]);
+                                set = true;
+                            } else if (columns[valIndex] == 'lon') {
+                                geometry.x = parseFloat(vals[valIndex]);
+                                set = true;
+                            } else if (columns[valIndex] == 'title')
+                                attributes['title'] = vals[valIndex];
+                            else if (columns[valIndex] == 'image' ||
+                                     columns[valIndex] == 'icon' && style) {
+                                style['externalGraphic'] = vals[valIndex];
+                            } else if (columns[valIndex] == 'iconSize' && style) {
+                                var size = vals[valIndex].split(',');
+                                style['graphicWidth'] = parseFloat(size[0]);
+                                style['graphicHeight'] = parseFloat(size[1]);
+                            } else if (columns[valIndex] == 'iconOffset' && style) {
+                                var offset = vals[valIndex].split(',');
+                                style['graphicXOffset'] = parseFloat(offset[0]);
+                                style['graphicYOffset'] = parseFloat(offset[1]);
+                            } else if (columns[valIndex] == 'description') {
+                                attributes['description'] = vals[valIndex];
+                            } else if (columns[valIndex] == 'overflow') {
+                                attributes['overflow'] = vals[valIndex];
+                            } else {
+                                // For StyleMap filtering, allow additional
+                                // columns to be stored as attributes.
+                                attributes[columns[valIndex]] = vals[valIndex];
+                            }    
+                        }
+                    }
+                    if (set) {
+                      if (this.internalProjection && this.externalProjection) {
+                          geometry.transform(this.externalProjection, 
+                                             this.internalProjection); 
+                      }
+                      var feature = new OpenLayers.Feature.Vector(geometry, attributes, style);
+                      features.push(feature);
+                    }
+                }
+            }
+        }
+        return features;
+    },   
+
+    CLASS_NAME: "OpenLayers.Format.Text" 
+});    
+/* ======================================================================
+    OpenLayers/Layer/Text.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Markers.js
+ * @requires OpenLayers/Format/Text.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Text
+ * This layer creates markers given data in a text file.  The <location>
+ *     property of the layer (specified as a property of the options argument
+ *     in the <OpenLayers.Layer.Text> constructor) points to a tab delimited
+ *     file with data used to create markers.
+ *
+ * The first row of the data file should be a header line with the column names
+ *     of the data. Each column should be delimited by a tab space. The
+ *     possible columns are:
+ *      - *point* lat,lon of the point where a marker is to be placed
+ *      - *lat*  Latitude of the point where a marker is to be placed
+ *      - *lon*  Longitude of the point where a marker is to be placed
+ *      - *icon* or *image* URL of marker icon to use.
+ *      - *iconSize* Size of Icon to use.
+ *      - *iconOffset* Where the top-left corner of the icon is to be placed
+ *            relative to the latitude and longitude of the point.
+ *      - *title* The text of the 'title' is placed inside an 'h2' marker
+ *            inside a popup, which opens when the marker is clicked.
+ *      - *description* The text of the 'description' is placed below the h2
+ *            in the popup. this can be plain text or HTML.
+ *
+ * Example text file:
+ * (code)
+ * lat	lon	title	description	iconSize	iconOffset	icon
+ * 10	20	title	description	21,25		-10,-25		http://www.openlayers.org/dev/img/marker.png
+ * (end)
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Markers>
+ */
+OpenLayers.Layer.Text = OpenLayers.Class(OpenLayers.Layer.Markers, {
+
+    /**
+     * APIProperty: location 
+     * {String} URL of text file.  Must be specified in the "options" argument
+     *   of the constructor. Can not be changed once passed in. 
+     */
+    location:null,
+
+    /** 
+     * Property: features
+     * {Array(<OpenLayers.Feature>)} 
+     */
+    features: null,
+    
+    /**
+     * APIProperty: formatOptions
+     * {Object} Hash of options which should be passed to the format when it is
+     * created. Must be passed in the constructor.
+     */
+    formatOptions: null, 
+
+    /** 
+     * Property: selectedFeature
+     * {<OpenLayers.Feature>}
+     */
+    selectedFeature: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.Text
+     * Create a text layer.
+     * 
+     * Parameters:
+     * name - {String} 
+     * options - {Object} Object with properties to be set on the layer.
+     *     Must include <location> property.
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
+        this.features = new Array();
+    },
+
+    /**
+     * APIMethod: destroy 
+     */
+    destroy: function() {
+        // Warning: Layer.Markers.destroy() must be called prior to calling
+        // clearFeatures() here, otherwise we leak memory. Indeed, if
+        // Layer.Markers.destroy() is called after clearFeatures(), it won't be
+        // able to remove the marker image elements from the layer's div since
+        // the markers will have been destroyed by clearFeatures().
+        OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
+        this.clearFeatures();
+        this.features = null;
+    },
+    
+    /**
+     * Method: loadText
+     * Start the load of the Text data. Don't do this when we first add the layer,
+     * since we may not be visible at any point, and it would therefore be a waste.
+     */
+    loadText: function() {
+        if (!this.loaded) {
+            if (this.location != null) {
+
+                var onFail = function(e) {
+                    this.events.triggerEvent("loadend");
+                };
+
+                this.events.triggerEvent("loadstart");
+                OpenLayers.Request.GET({
+                    url: this.location,
+                    success: this.parseData,
+                    failure: onFail,
+                    scope: this
+                });
+                this.loaded = true;
+            }
+        }    
+    },    
+    
+    /**
+     * Method: moveTo
+     * If layer is visible and Text has not been loaded, load Text. 
+     * 
+     * Parameters:
+     * bounds - {Object} 
+     * zoomChanged - {Object} 
+     * minor - {Object} 
+     */
+    moveTo:function(bounds, zoomChanged, minor) {
+        OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
+        if(this.visibility && !this.loaded){
+            this.loadText();
+        }
+    },
+    
+    /**
+     * Method: parseData
+     *
+     * Parameters:
+     * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>} 
+     */
+    parseData: function(ajaxRequest) {
+        var text = ajaxRequest.responseText;
+        
+        var options = {};
+        
+        OpenLayers.Util.extend(options, this.formatOptions);
+        
+        if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+            options.externalProjection = this.projection;
+            options.internalProjection = this.map.getProjectionObject();
+        }    
+        
+        var parser = new OpenLayers.Format.Text(options);
+        var features = parser.read(text);
+        for (var i=0, len=features.length; i<len; i++) {
+            var data = {};
+            var feature = features[i];
+            var location;
+            var iconSize, iconOffset;
+            
+            location = new OpenLayers.LonLat(feature.geometry.x, 
+                                             feature.geometry.y);
+            
+            if (feature.style.graphicWidth 
+                && feature.style.graphicHeight) {
+                iconSize = new OpenLayers.Size(
+                    feature.style.graphicWidth,
+                    feature.style.graphicHeight);
+            }        
+            
+            // FIXME: At the moment, we only use this if we have an 
+            // externalGraphic, because icon has no setOffset API Method.
+            /**
+             * FIXME FIRST!!
+             * The Text format does all sorts of parseFloating
+             * The result of a parseFloat for a bogus string is NaN.  That
+             * means the three possible values here are undefined, NaN, or a
+             * number.  The previous check was an identity check for null.  This
+             * means it was failing for all undefined or NaN.  A slightly better
+             * check is for undefined.  An even better check is to see if the
+             * value is a number (see #1441).
+             */
+            if (feature.style.graphicXOffset !== undefined
+                && feature.style.graphicYOffset !== undefined) {
+                iconOffset = new OpenLayers.Pixel(
+                    feature.style.graphicXOffset, 
+                    feature.style.graphicYOffset);
+            }
+            
+            if (feature.style.externalGraphic != null) {
+                data.icon = new OpenLayers.Icon(feature.style.externalGraphic, 
+                                                iconSize, 
+                                                iconOffset);
+            } else {
+                data.icon = OpenLayers.Marker.defaultIcon();
+
+                //allows for the case where the image url is not 
+                // specified but the size is. use a default icon
+                // but change the size
+                if (iconSize != null) {
+                    data.icon.setSize(iconSize);
+                }
+            }
+            
+            if ((feature.attributes.title != null) 
+                && (feature.attributes.description != null)) {
+                data['popupContentHTML'] = 
+                    '<h2>'+feature.attributes.title+'</h2>' + 
+                    '<p>'+feature.attributes.description+'</p>';
+            }
+            
+            data['overflow'] = feature.attributes.overflow || "auto"; 
+            
+            var markerFeature = new OpenLayers.Feature(this, location, data);
+            this.features.push(markerFeature);
+            var marker = markerFeature.createMarker();
+            if ((feature.attributes.title != null) 
+                && (feature.attributes.description != null)) {
+              marker.events.register('click', markerFeature, this.markerClick);
+            }
+            this.addMarker(marker);
+        }
+        this.events.triggerEvent("loadend");
+    },
+    
+    /**
+     * Property: markerClick
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    markerClick: function(evt) {
+        var sameMarkerClicked = (this == this.layer.selectedFeature);
+        this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
+        for(var i=0, len=this.layer.map.popups.length; i<len; i++) {
+            this.layer.map.removePopup(this.layer.map.popups[i]);
+        }
+        if (!sameMarkerClicked) {
+            this.layer.map.addPopup(this.createPopup()); 
+        }
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: clearFeatures
+     */
+    clearFeatures: function() {
+        if (this.features != null) {
+            while(this.features.length > 0) {
+                var feature = this.features[0];
+                OpenLayers.Util.removeItem(this.features, feature);
+                feature.destroy();
+            }
+        }        
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Text"
+});
+/* ======================================================================
+    OpenLayers/Handler/RegularPolygon.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Handler/Drag.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.RegularPolygon
+ * Handler to draw a regular polygon on the map.  Polygon is displayed on mouse
+ *     down, moves or is modified on mouse move, and is finished on mouse up.
+ *     The handler triggers callbacks for 'done' and 'cancel'.  Create a new
+ *     instance with the <OpenLayers.Handler.RegularPolygon> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler.Drag>
+ */
+OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
+    
+    /**
+     * APIProperty: sides
+     * {Integer} Number of sides for the regular polygon.  Needs to be greater
+     *     than 2.  Defaults to 4.
+     */
+    sides: 4,
+
+    /**
+     * APIProperty: radius
+     * {Float} Optional radius in map units of the regular polygon.  If this is
+     *     set to some non-zero value, a polygon with a fixed radius will be
+     *     drawn and dragged with mose movements.  If this property is not
+     *     set, dragging changes the radius of the polygon.  Set to null by
+     *     default.
+     */
+    radius: null,
+    
+    /**
+     * APIProperty: snapAngle
+     * {Float} If set to a non-zero value, the handler will snap the polygon
+     *     rotation to multiples of the snapAngle.  Value is an angle measured
+     *     in degrees counterclockwise from the positive x-axis.  
+     */
+    snapAngle: null,
+    
+    /**
+     * APIProperty: snapToggle
+     * {String} If set, snapToggle is checked on mouse events and will set
+     *     the snap mode to the opposite of what it currently is.  To disallow
+     *     toggling between snap and non-snap mode, set freehandToggle to
+     *     null.  Acceptable toggle values are 'shiftKey', 'ctrlKey', and
+     *     'altKey'. Snap mode is only possible if this.snapAngle is set to a
+     *     non-zero value.
+     */
+    snapToggle: 'shiftKey',
+    
+    /**
+     * Property: layerOptions
+     * {Object} Any optional properties to be set on the sketch layer.
+     */
+    layerOptions: null,
+
+    /**
+     * APIProperty: persist
+     * {Boolean} Leave the feature rendered until clear is called.  Default
+     *     is false.  If set to true, the feature remains rendered until
+     *     clear is called, typically by deactivating the handler or starting
+     *     another drawing.
+     */
+    persist: false,
+
+    /**
+     * APIProperty: irregular
+     * {Boolean} Draw an irregular polygon instead of a regular polygon.
+     *     Default is false.  If true, the initial mouse down will represent
+     *     one corner of the polygon bounds and with each mouse movement, the
+     *     polygon will be stretched so the opposite corner of its bounds
+     *     follows the mouse position.  This property takes precedence over
+     *     the radius property.  If set to true, the radius property will
+     *     be ignored.
+     */
+    irregular: false,
+
+    /**
+     * Property: angle
+     * {Float} The angle from the origin (mouse down) to the current mouse
+     *     position, in radians.  This is measured counterclockwise from the
+     *     positive x-axis.
+     */
+    angle: null,
+
+    /**
+     * Property: fixedRadius
+     * {Boolean} The polygon has a fixed radius.  True if a radius is set before
+     *     drawing begins.  False otherwise.
+     */
+    fixedRadius: false,
+
+    /**
+     * Property: feature
+     * {<OpenLayers.Feature.Vector>} The currently drawn polygon feature
+     */
+    feature: null,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>} The temporary drawing layer
+     */
+    layer: null,
+
+    /**
+     * Property: origin
+     * {<OpenLayers.Geometry.Point>} Location of the first mouse down
+     */
+    origin: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.RegularPolygon
+     * Create a new regular polygon handler.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} An object with properties to be set on the handler.
+     *     If the options.sides property is not specified, the number of sides
+     *     will default to 4.
+     *
+     * Named callbacks:
+     * create - Called when a sketch is first created.  Callback called with
+     *     the creation point geometry and sketch feature.
+     * done - Called when the sketch drawing is finished.  The callback will
+     *     recieve a single argument, the sketch geometry.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
+     */
+    initialize: function(control, callbacks, options) {
+        if(!(options && options.layerOptions && options.layerOptions.styleMap)) {
+            this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        }
+
+        OpenLayers.Handler.Drag.prototype.initialize.apply(this,
+                                                [control, callbacks, options]);
+        this.options = (options) ? options : {};
+    },
+    
+    /**
+     * APIMethod: setOptions
+     * 
+     * Parameters:
+     * newOptions - {Object} 
+     */
+    setOptions: function (newOptions) {
+        OpenLayers.Util.extend(this.options, newOptions);
+        OpenLayers.Util.extend(this, newOptions);
+    },
+    
+    /**
+     * APIMethod: activate
+     * Turn on the handler.
+     *
+     * Return:
+     * {Boolean} The handler was successfully activated
+     */
+    activate: function() {
+        var activated = false;
+        if(OpenLayers.Handler.Drag.prototype.activate.apply(this, arguments)) {
+            // create temporary vector layer for rendering geometry sketch
+            var options = OpenLayers.Util.extend({
+                displayInLayerSwitcher: false,
+                // indicate that the temp vector layer will never be out of range
+                // without this, resolution properties must be specified at the
+                // map-level for this temporary layer to init its resolutions
+                // correctly
+                calculateInRange: OpenLayers.Function.True
+            }, this.layerOptions);
+            this.layer = new OpenLayers.Layer.Vector(this.CLASS_NAME, options);
+            this.map.addLayer(this.layer);
+            activated = true;
+        }
+        return activated;
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Turn off the handler.
+     *
+     * Return:
+     * {Boolean} The handler was successfully deactivated
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this, arguments)) {
+            // call the cancel callback if mid-drawing
+            if(this.dragging) {
+                this.cancel();
+            }
+            // If a layer's map property is set to null, it means that that
+            // layer isn't added to the map. Since we ourself added the layer
+            // to the map in activate(), we can assume that if this.layer.map
+            // is null it means that the layer has been destroyed (as a result
+            // of map.destroy() for example.
+            if (this.layer.map != null) {
+                this.layer.destroy(false);
+                if (this.feature) {
+                    this.feature.destroy();
+                }
+            }
+            this.layer = null;
+            this.feature = null;
+            deactivated = true;
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: down
+     * Start drawing a new feature
+     *
+     * Parameters:
+     * evt - {Event} The drag start event
+     */
+    down: function(evt) {
+        this.fixedRadius = !!(this.radius);
+        var maploc = this.map.getLonLatFromPixel(evt.xy);
+        this.origin = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
+        // create the new polygon
+        if(!this.fixedRadius || this.irregular) {
+            // smallest radius should not be less one pixel in map units
+            // VML doesn't behave well with smaller
+            this.radius = this.map.getResolution();
+        }
+        if(this.persist) {
+            this.clear();
+        }
+        this.feature = new OpenLayers.Feature.Vector();
+        this.createGeometry();
+        this.callback("create", [this.origin, this.feature]);
+        this.layer.addFeatures([this.feature], {silent: true});
+        this.layer.drawFeature(this.feature, this.style);
+    },
+    
+    /**
+     * Method: move
+     * Respond to drag move events
+     *
+     * Parameters:
+     * evt - {Evt} The move event
+     */
+    move: function(evt) {
+        var maploc = this.map.getLonLatFromPixel(evt.xy);
+        var point = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
+        if(this.irregular) {
+            var ry = Math.sqrt(2) * Math.abs(point.y - this.origin.y) / 2;
+            this.radius = Math.max(this.map.getResolution() / 2, ry);
+        } else if(this.fixedRadius) {
+            this.origin = point;
+        } else {
+            this.calculateAngle(point, evt);
+            this.radius = Math.max(this.map.getResolution() / 2,
+                                   point.distanceTo(this.origin));
+        }
+        this.modifyGeometry();
+        if(this.irregular) {
+            var dx = point.x - this.origin.x;
+            var dy = point.y - this.origin.y;
+            var ratio;
+            if(dy == 0) {
+                ratio = dx / (this.radius * Math.sqrt(2));
+            } else {
+                ratio = dx / dy;
+            }
+            this.feature.geometry.resize(1, this.origin, ratio);
+            this.feature.geometry.move(dx / 2, dy / 2);
+        }
+        this.layer.drawFeature(this.feature, this.style);
+    },
+
+    /**
+     * Method: up
+     * Finish drawing the feature
+     *
+     * Parameters:
+     * evt - {Event} The mouse up event
+     */
+    up: function(evt) {
+        this.finalize();
+        // the mouseup method of superclass doesn't call the
+        // "done" callback if there's been no move between
+        // down and up
+        if (this.start == this.last) {
+            this.callback("done", [evt.xy]);
+        }
+    },
+
+    /**
+     * Method: out
+     * Finish drawing the feature.
+     *
+     * Parameters:
+     * evt - {Event} The mouse out event
+     */
+    out: function(evt) {
+        this.finalize();
+    },
+
+    /**
+     * Method: createGeometry
+     * Create the new polygon geometry.  This is called at the start of the
+     *     drag and at any point during the drag if the number of sides
+     *     changes.
+     */
+    createGeometry: function() {
+        this.angle = Math.PI * ((1/this.sides) - (1/2));
+        if(this.snapAngle) {
+            this.angle += this.snapAngle * (Math.PI / 180);
+        }
+        this.feature.geometry = OpenLayers.Geometry.Polygon.createRegularPolygon(
+            this.origin, this.radius, this.sides, this.snapAngle
+        );
+    },
+    
+    /**
+     * Method: modifyGeometry
+     * Modify the polygon geometry in place.
+     */
+    modifyGeometry: function() {
+        var angle, point;
+        var ring = this.feature.geometry.components[0];
+        // if the number of sides ever changes, create a new geometry
+        if(ring.components.length != (this.sides + 1)) {
+            this.createGeometry();
+            ring = this.feature.geometry.components[0];
+        }
+        for(var i=0; i<this.sides; ++i) {
+            point = ring.components[i];
+            angle = this.angle + (i * 2 * Math.PI / this.sides);
+            point.x = this.origin.x + (this.radius * Math.cos(angle));
+            point.y = this.origin.y + (this.radius * Math.sin(angle));
+            point.clearBounds();
+        }
+    },
+    
+    /**
+     * Method: calculateAngle
+     * Calculate the angle based on settings.
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>}
+     * evt - {Event}
+     */
+    calculateAngle: function(point, evt) {
+        var alpha = Math.atan2(point.y - this.origin.y,
+                               point.x - this.origin.x);
+        if(this.snapAngle && (this.snapToggle && !evt[this.snapToggle])) {
+            var snapAngleRad = (Math.PI / 180) * this.snapAngle;
+            this.angle = Math.round(alpha / snapAngleRad) * snapAngleRad;
+        } else {
+            this.angle = alpha;
+        }
+    },
+
+    /**
+     * APIMethod: cancel
+     * Finish the geometry and call the "cancel" callback.
+     */
+    cancel: function() {
+        // the polygon geometry gets cloned in the callback method
+        this.callback("cancel", null);
+        this.finalize();
+    },
+
+    /**
+     * Method: finalize
+     * Finish the geometry and call the "done" callback.
+     */
+    finalize: function() {
+        this.origin = null;
+        this.radius = this.options.radius;
+    },
+
+    /**
+     * APIMethod: clear
+     * Clear any rendered features on the temporary layer.  This is called
+     *     when the handler is deactivated, canceled, or done (unless persist
+     *     is true).
+     */
+    clear: function() {
+        if (this.layer) {
+            this.layer.renderer.clear();
+            this.layer.destroyFeatures();
+        }
+    },
+    
+    /**
+     * Method: callback
+     * Trigger the control's named callback with the given arguments
+     *
+     * Parameters:
+     * name - {String} The key for the callback that is one of the properties
+     *     of the handler's callbacks object.
+     * args - {Array} An array of arguments with which to call the callback
+     *     (defined by the control).
+     */
+    callback: function (name, args) {
+        // override the callback method to always send the polygon geometry
+        if (this.callbacks[name]) {
+            this.callbacks[name].apply(this.control,
+                                       [this.feature.geometry.clone()]);
+        }
+        // since sketch features are added to the temporary layer
+        // they must be cleared here if done or cancel
+        if(!this.persist && (name == "done" || name == "cancel")) {
+            this.clear();
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.RegularPolygon"
+});
+/* ======================================================================
+    OpenLayers/Control/SLDSelect.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Layer/WMS.js
+ * @requires OpenLayers/Handler/RegularPolygon.js
+ * @requires OpenLayers/Handler/Polygon.js
+ * @requires OpenLayers/Handler/Path.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Format/SLD/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Control.SLDSelect
+ * Perform selections on WMS layers using Styled Layer Descriptor (SLD)
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.SLDSelect = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * Supported control event types (in addition to those from 
+     * <OpenLayers.Control>):
+     * selected - Triggered when a selection occurs.  Listeners receive an 
+     *     event with *filters* and *layer* properties.  Filters will be an 
+     *     array of OpenLayers.Filter objects created in order to perform 
+     *     the particular selection.
+     */
+    EVENT_TYPES: ["selected"],
+
+    /**
+     * APIProperty: clearOnDeactivate
+     * {Boolean} Should the selection be cleared when the control is 
+     *     deactivated. Default value is false.
+     */
+    clearOnDeactivate: false,
+
+    /**
+     * APIProperty: layers
+     * {Array(<OpenLayers.Layer.WMS>)} The WMS layers this control will work 
+     *     on.
+     */
+    layers: null,
+
+    /**
+     * Property: callbacks
+     * {Object} The functions that are sent to the handler for callback
+     */
+    callbacks: null,
+
+    /**
+     * APIProperty: selectionSymbolizer
+     * {Object} Determines the styling of the selected objects. Default is
+     *     a selection in red.
+     */
+    selectionSymbolizer: {
+        'Polygon': {fillColor: '#FF0000', stroke: false},
+        'Line': {strokeColor: '#FF0000', strokeWidth: 2},
+        'Point': {graphicName: 'square', fillColor: '#FF0000', pointRadius: 5}
+    },
+
+    /**
+     * APIProperty: layerOptions
+     * {Object} The options to apply to the selection layer, by default the
+     *     selection layer will be kept out of the layer switcher.
+     */
+    layerOptions: null,
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Used to set non-default properties on the control's handler
+     */
+    handlerOptions: null,
+
+    /**
+     * APIProperty: sketchStyle
+     * {<OpenLayers.Style>|Object} Style or symbolizer to use for the sketch
+     * handler. The recommended way of styling the sketch layer, however, is
+     * to configure an <OpenLayers.StyleMap> in the layerOptions of the
+     * <handlerOptions>:
+     * 
+     * (code)
+     * new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Path, {
+     *     handlerOptions: {
+     *         layerOptions: {
+     *             styleMap: new OpenLayers.StyleMap({
+     *                 "default": {strokeColor: "yellow"}
+     *             });
+     *         }
+     *     }
+     * });
+     * (end)
+     */
+    sketchStyle: null,
+
+    /**
+     * APIProperty: wfsCache
+     * {Object} Cache to use for storing parsed results from
+     *     <OpenLayers.Format.WFSDescribeFeatureType.read>. If not provided,
+     *     these will be cached on the prototype.
+     */
+    wfsCache: {},
+
+    /**
+     * APIProperty: layerCache
+     * {Object} Cache to use for storing references to the selection layers.
+     *     Normally each source layer will have exactly 1 selection layer of
+     *     type OpenLayers.Layer.WMS. If not provided, layers will
+     *     be cached on the prototype. Note that if <clearOnDeactivate> is
+     *     true, the layer will no longer be cached after deactivating the
+     *     control.
+     */
+    layerCache: {},
+
+    /**
+     * Constructor: OpenLayers.Control.SLDSelect
+     * Create a new control for selecting features in WMS layers using
+     *     Styled Layer Descriptor (SLD).
+     *
+     * Parameters:
+     * handler - {<OpenLayers.Class>} A sketch handler class. This determines
+     *     the type of selection, e.g. box (<OpenLayers.Handler.Box>), point
+     *     (<OpenLayers.Handler.Point>), path (<OpenLayers.Handler.Path>) or
+     *     polygon (<OpenLayers.Handler.Polygon>) selection. To use circle
+     *     type selection, use <OpenLayers.Handler.RegularPolygon> and pass
+     *     the number of desired sides (e.g. 40) as "sides" property to the
+     *     <handlerOptions>.
+     * options - {Object} An object containing all configuration properties for
+     *     the control.
+     *
+     * Valid options:
+     * layers - Array({<OpenLayers.Layer.WMS>}) The layers to perform the
+     *     selection on.
+     */
+    initialize: function(handler, options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+        this.callbacks = OpenLayers.Util.extend({done: this.select, 
+            click: this.select}, this.callbacks);
+        this.handlerOptions = this.handlerOptions || {};
+        this.layerOptions = OpenLayers.Util.applyDefaults(this.layerOptions, {
+            displayInLayerSwitcher: false,
+            tileOptions: {maxGetUrlLength: 2048}
+        });
+        if (this.sketchStyle) {
+            this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
+                this.handlerOptions.layerOptions,
+                {styleMap: new OpenLayers.StyleMap({"default": this.sketchStyle})}
+            );
+        }
+        this.handler = new handler(this, this.callbacks, this.handlerOptions);
+    },
+
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass.
+     */
+    destroy: function() {
+        for (var key in this.layerCache) {
+            delete this.layerCache[key];
+        }
+        for (var key in this.wfsCache) {
+            delete this.wfsCache[key];
+        }
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: coupleLayerVisiblity
+     * Couple the selection layer and the source layer with respect to
+     *     layer visibility. So if the source layer is turned off, the
+     *     selection layer is also turned off.
+     *
+     * Parameters:
+     * evt - {Object}
+     */
+    coupleLayerVisiblity: function(evt) {
+        this.setVisibility(evt.object.getVisibility());
+    },
+
+    /**
+     * Method: createSelectionLayer
+     * Creates a "clone" from the source layer in which the selection can
+     * be drawn. This ensures both the source layer and the selection are 
+     * visible and not only the selection.
+     *
+     * Parameters:
+     * source - {<OpenLayers.Layer.WMS>} The source layer on which the selection
+     *     is performed.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS>} A WMS layer with maxGetUrlLength configured to 2048
+     *     since SLD selections can easily get quite long.
+     */
+    createSelectionLayer: function(source) {
+        // check if we already have a selection layer for the source layer
+        var selectionLayer;
+        if (!this.layerCache[source.id]) {
+            selectionLayer = new OpenLayers.Layer.WMS(source.name, 
+                source.url, source.params, 
+                OpenLayers.Util.applyDefaults(
+                    this.layerOptions,
+                    source.getOptions())
+            );
+            this.layerCache[source.id] = selectionLayer;
+            // make sure the layers are coupled wrt visibility, but only
+            // if they are not displayed in the layer switcher, because in
+            // that case the user cannot control visibility.
+            if (this.layerOptions.displayInLayerSwitcher === false) {
+                source.events.on({
+                    "visibilitychanged": this.coupleLayerVisiblity,
+                    scope: selectionLayer});
+            }
+            this.map.addLayer(selectionLayer);
+        } else {
+            selectionLayer = this.layerCache[source.id];
+        }
+        return selectionLayer;
+    },
+
+    /**
+     * Method: createSLD
+     * Create the SLD document for the layer using the supplied filters.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMS>}
+     * filters - Array({<OpenLayers.Filter>}) The filters to be applied.
+     * geometryAttributes - Array({Object}) The geometry attributes of the 
+     *     layer.
+     *
+     * Returns:
+     * {String} The SLD document generated as a string.
+     */
+    createSLD: function(layer, filters, geometryAttributes) {
+        var sld = {version: "1.0.0", namedLayers: {}};
+        var layerNames = [layer.params.LAYERS].join(",").split(",");
+        for (var i=0, len=layerNames.length; i<len; i++) { 
+            var name = layerNames[i];
+            sld.namedLayers[name] = {name: name, userStyles: []};
+            var symbolizer = this.selectionSymbolizer;
+            var geometryAttribute = geometryAttributes[i];
+            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
+                symbolizer = {Polygon: this.selectionSymbolizer['Polygon']};
+            } else if (geometryAttribute.type.indexOf('LineString') >= 0) {
+                symbolizer = {Line: this.selectionSymbolizer['Line']};
+            } else if (geometryAttribute.type.indexOf('Point') >= 0) {
+                symbolizer = {Point: this.selectionSymbolizer['Point']};
+            }
+            var filter = filters[i];
+            sld.namedLayers[name].userStyles.push({name: 'default', rules: [
+                new OpenLayers.Rule({symbolizer: symbolizer, 
+                    filter: filter, 
+                    maxScaleDenominator: layer.options.minScale})
+            ]});
+        }
+        return new OpenLayers.Format.SLD({srsName: this.map.getProjection()}).write(sld);
+    },
+
+    /**
+     * Method: parseDescribeLayer
+     * Parse the SLD WMS DescribeLayer response and issue the corresponding
+     *     WFS DescribeFeatureType request
+     *
+     * request - {XMLHttpRequest} The request object.
+     */
+    parseDescribeLayer: function(request) {
+        var format = new OpenLayers.Format.WMSDescribeLayer();
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        var describeLayer = format.read(doc);
+        var typeNames = [];
+        var url = null;
+        for (var i=0, len=describeLayer.length; i<len; i++) {
+            // perform a WFS DescribeFeatureType request
+            if (describeLayer[i].owsType == "WFS") {
+                typeNames.push(describeLayer[i].typeName);
+                url = describeLayer[i].owsURL;
+            }
+        }
+        var options = {
+            url: url,
+            params: {
+                SERVICE: "WFS",
+                TYPENAME: typeNames.toString(),
+                REQUEST: "DescribeFeatureType",
+                VERSION: "1.0.0"
+            },
+            callback: function(request) {
+                var format = new OpenLayers.Format.WFSDescribeFeatureType();
+                var doc = request.responseXML;
+                if(!doc || !doc.documentElement) {
+                    doc = request.responseText;
+                }
+                var describeFeatureType = format.read(doc);
+                this.control.wfsCache[this.layer.id] = describeFeatureType;
+                this.control._queue && this.control.applySelection();
+            },
+            scope: this
+        };
+        OpenLayers.Request.GET(options);
+    },
+
+   /**
+    * Method: getGeometryAttributes
+    * Look up the geometry attributes from the WFS DescribeFeatureType response
+    *
+    * Parameters:
+    * layer - {<OpenLayers.Layer.WMS>} The layer for which to look up the 
+    *     geometry attributes.
+    *
+    * Returns:
+    * Array({Object}) Array of geometry attributes
+    */ 
+   getGeometryAttributes: function(layer) {
+        var result = [];
+        var cache = this.wfsCache[layer.id];
+        for (var i=0, len=cache.featureTypes.length; i<len; i++) {
+            var typeName = cache.featureTypes[i];
+            var properties = typeName.properties;
+            for (var j=0, lenj=properties.length; j < lenj; j++) {
+                var property = properties[j];
+                var type = property.type;
+                if ((type.indexOf('LineString') >= 0) ||
+                    (type.indexOf('GeometryAssociationType') >=0) ||
+                    (type.indexOf('GeometryPropertyType') >= 0) ||
+                    (type.indexOf('Point') >= 0) ||
+                    (type.indexOf('Polygon') >= 0) ) {
+                        result.push(property);
+                }
+            }
+        }
+        return result;
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the control. Activating the control will perform a SLD WMS
+     *     DescribeLayer request followed by a WFS DescribeFeatureType request
+     *     so that the proper symbolizers can be chosen based on the geometry
+     *     type.
+     */
+    activate: function() {
+        var activated = OpenLayers.Control.prototype.activate.call(this);
+        if(activated) {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                if (layer && !this.wfsCache[layer.id]) {
+                    var options = {
+                        url: layer.url,
+                        params: {
+                            SERVICE: "WMS",
+                            VERSION: layer.params.VERSION,
+                            LAYERS: layer.params.LAYERS,
+                            REQUEST: "DescribeLayer"
+                        },
+                        callback: this.parseDescribeLayer,
+                        scope: {layer: layer, control: this}
+                    };
+                    OpenLayers.Request.GET(options);
+                }
+            }
+        }
+        return activated;
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control. If clearOnDeactivate is true, remove the
+     *     selection layer(s).
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
+        if(deactivated) {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                if (layer && this.clearOnDeactivate === true) {
+                    var layerCache = this.layerCache;
+                    var selectionLayer = layerCache[layer.id];
+                    if (selectionLayer) {
+                        layer.events.un({
+                            "visibilitychanged": this.coupleLayerVisiblity,
+                            scope: selectionLayer});
+                        selectionLayer.destroy();
+                        delete layerCache[layer.id];
+                    }
+                }
+            }
+        }
+        return deactivated;
+    },
+
+    /**
+     * APIMethod: setLayers
+     * Set the layers on which the selection should be performed.  Call the 
+     *     setLayers method if the layer(s) to be used change and the same 
+     *     control should be used on a new set of layers.
+     *     If the control is already active, it will be active after the new
+     *     set of layers is set.
+     *
+     * Parameters:
+     * layers - {Array(<OpenLayers.Layer.WMS>)}  The new set of layers on which 
+     *     the selection should be performed.
+     */
+    setLayers: function(layers) {
+        if(this.active) {
+            this.deactivate();
+            this.layers = layers;
+            this.activate();
+        } else {
+            this.layers = layers;
+        }
+    },
+
+    /**
+     * Function: createFilter
+     * Create the filter to be used in the SLD.
+     *
+     * Parameters:
+     * geometryAttribute - {Object} Used to get the name of the geometry 
+     *     attribute which is needed for constructing the spatial filter.
+     * geometry - {<OpenLayers.Geometry>} The geometry to use.
+     *
+     * Returns:
+     * {<OpenLayers.Filter.Spatial>} The spatial filter created.
+     */
+    createFilter: function(geometryAttribute, geometry) {
+        var filter = null;
+        if (this.handler instanceof OpenLayers.Handler.RegularPolygon) {
+            // box
+            if (this.handler.irregular === true) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.BBOX,
+                    property: geometryAttribute.name,
+                    value: geometry.getBounds()}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            }
+        } else if (this.handler instanceof OpenLayers.Handler.Polygon) {
+            filter = new OpenLayers.Filter.Spatial({
+                type: OpenLayers.Filter.Spatial.INTERSECTS,
+                property: geometryAttribute.name,
+                value: geometry}
+            );
+        } else if (this.handler instanceof OpenLayers.Handler.Path) {
+            // if source layer is point based, use DWITHIN instead
+            if (geometryAttribute.type.indexOf('Point') >= 0) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.DWITHIN,
+                    property: geometryAttribute.name,
+                    distance: this.map.getExtent().getWidth()*0.01 ,
+                    distanceUnits: this.map.getUnits(),
+                    value: geometry}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            }
+        } else if (this.handler instanceof OpenLayers.Handler.Click) {
+            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.DWITHIN,
+                    property: geometryAttribute.name,
+                    distance: this.map.getExtent().getWidth()*0.01 ,
+                    distanceUnits: this.map.getUnits(),
+                    value: geometry}
+                );
+            }
+        }
+        return filter;
+    },
+
+    /**
+     * Method: select
+     * When the handler is done, use SLD_BODY on the selection layer to
+     *     display the selection in the map.
+     *
+     * Parameters:
+     * geometry - {Object} or {<OpenLayers.Geometry>}
+     */
+    select: function(geometry) {
+        this._queue = function() {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                var geometryAttributes = this.getGeometryAttributes(layer);
+                var filters = [];
+                for (var j=0, lenj=geometryAttributes.length; j<lenj; j++) {
+                    var geometryAttribute = geometryAttributes[j];
+                    if (geometryAttribute !== null) {
+                        // from the click handler we will not get an actual 
+                        // geometry so transform
+                        if (!(geometry instanceof OpenLayers.Geometry)) {
+                            var point = this.map.getLonLatFromPixel(
+                                geometry.xy);
+                            geometry = new OpenLayers.Geometry.Point(
+                                point.lon, point.lat);
+                        }
+                        var filter = this.createFilter(geometryAttribute,
+                        geometry);
+                        if (filter !== null) {
+                            filters.push(filter);
+                        }
+                    }
+                }
+    
+                var selectionLayer = this.createSelectionLayer(layer);
+                var sld = this.createSLD(layer, filters, geometryAttributes);
+    
+                this.events.triggerEvent("selected", {
+                    layer: layer,
+                    filters: filters
+                });
+    
+                selectionLayer.mergeNewParams({SLD_BODY: sld});
+                delete this._queue;
+            }
+        };
+        this.applySelection();
+    },
+    
+    /**
+     * Method: applySelection
+     * Checks if all required wfs data is cached, and applies the selection
+     */
+    applySelection: function() {
+        var canApply = true;
+        for (var i=0, len=this.layers.length; i<len; i++) {
+            if(!this.wfsCache[this.layers[i].id]) {
+                canApply = false;
+                break;
+            }
+        }
+        canApply && this._queue.call(this);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.SLDSelect"
+});
+/* ======================================================================
+    OpenLayers/Control/Scale.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Scale
+ * The Scale control displays the current map scale as a ratio (e.g. Scale = 
+ * 1:1M). By default it is displayed in the lower right corner of the map.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Scale = OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * Parameter: element
+     * {DOMElement}
+     */
+    element: null,
+    
+    /**
+     * APIProperty: geodesic
+     * {Boolean} Use geodesic measurement. Default is false. The recommended
+     * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
+     * true, the scale will be calculated based on the horizontal size of the
+     * pixel in the center of the map viewport.
+     */
+    geodesic: false,
+
+    /**
+     * Constructor: OpenLayers.Control.Scale
+     * 
+     * Parameters:
+     * element - {DOMElement} 
+     * options - {Object} 
+     */
+    initialize: function(element, options) {
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.element = OpenLayers.Util.getElement(element);        
+    },
+
+    /**
+     * Method: draw
+     * 
+     * Returns:
+     * {DOMElement}
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        if (!this.element) {
+            this.element = document.createElement("div");
+            this.div.appendChild(this.element);
+        }
+        this.map.events.register( 'moveend', this, this.updateScale);
+        this.updateScale();
+        return this.div;
+    },
+   
+    /**
+     * Method: updateScale
+     */
+    updateScale: function() {
+        var scale;
+        if(this.geodesic === true) {
+            var units = this.map.getUnits();
+            if(!units) {
+                return;
+            }
+            var inches = OpenLayers.INCHES_PER_UNIT;
+            scale = (this.map.getGeodesicPixelSize().w || 0.000001) *
+                    inches["km"] * OpenLayers.DOTS_PER_INCH;
+        } else {
+            scale = this.map.getScale();
+        }
+            
+        if (!scale) {
+            return;
+        }
+
+        if (scale >= 9500 && scale <= 950000) {
+            scale = Math.round(scale / 1000) + "K";
+        } else if (scale >= 950000) {
+            scale = Math.round(scale / 1000000) + "M";
+        } else {
+            scale = Math.round(scale);
+        }    
+        
+        this.element.innerHTML = OpenLayers.i18n("Scale = 1 : ${scaleDenom}", {'scaleDenom':scale});
+    }, 
+
+    CLASS_NAME: "OpenLayers.Control.Scale"
+});
+
+/* ======================================================================
+    OpenLayers/Layer/MapGuide.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.MapGuide
+ * Instances of OpenLayers.Layer.MapGuide are used to display
+ * data from a MapGuide OS instance.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.MapGuide = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /** 
+     * APIProperty: isBaseLayer
+     * {Boolean} Treat this layer as a base layer.  Default is true.
+     **/
+    isBaseLayer: true,
+    
+    /**
+     * APIProperty: useHttpTile
+     * {Boolean} use a tile cache exposed directly via a webserver rather than the 
+	   *    via mapguide server. This does require extra configuration on the Mapguide Server,
+	   *    and will only work when singleTile is false. The url for the layer must be set to the
+	   *    webserver path rather than the Mapguide mapagent.	  
+	   *    See http://trac.osgeo.org/mapguide/wiki/CodeSamples/Tiles/ServingTilesViaHttp 
+     **/
+    useHttpTile: false,
+    
+    /** 
+     * APIProperty: singleTile
+     * {Boolean} use tile server or request single tile image. 
+     **/
+    singleTile: false,
+    
+    /** 
+     * APIProperty: useOverlay
+     * {Boolean} flag to indicate if the layer should be retrieved using
+     * GETMAPIMAGE (default) or using GETDYNAMICOVERLAY requests.
+     **/
+    useOverlay: false,
+    
+    /** 
+     * APIProperty: useAsyncOverlay
+     * {Boolean} indicates if the MapGuide site supports the asynchronous 
+     * GETDYNAMICOVERLAY requests which is available in MapGuide Enterprise 2010
+     * and MapGuide Open Source v2.0.3 or higher. The newer versions of MG 
+     * is called asynchronously, allows selections to be drawn separately from 
+     * the map and offers styling options.
+     * 
+     * With older versions of MapGuide, set useAsyncOverlay=false.  Note that in
+     * this case a synchronous AJAX call is issued and the mapname and session
+     * parameters must be used to initialize the layer, not the mapdefinition
+     * parameter. Also note that this will issue a synchronous AJAX request 
+     * before the image request can be issued so the users browser may lock
+     * up if the MG Web tier does not respond in a timely fashion.
+     **/
+    useAsyncOverlay: true,
+    
+    /**
+     * Constant: TILE_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs for tiled layer
+     */
+    TILE_PARAMS: {
+         operation: 'GETTILEIMAGE',
+         version: '1.2.0'
+    },
+
+    /**
+     * Constant: SINGLE_TILE_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs for untiled layer
+     */
+    SINGLE_TILE_PARAMS: {
+        operation: 'GETMAPIMAGE',
+        format: 'PNG',
+        locale: 'en',
+        clip: '1',
+        version: '1.0.0'
+    },
+    
+    /**
+     * Constant: OVERLAY_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs for untiled layer
+     */
+    OVERLAY_PARAMS: {
+        operation: 'GETDYNAMICMAPOVERLAYIMAGE',
+        format: 'PNG',
+        locale: 'en',
+        clip: '1',
+        version: '2.0.0'
+    },
+    
+    /** 
+     * Constant: FOLDER_PARAMS
+     * {Object} Hashtable of parameter key/value pairs which describe 
+     * the folder structure for tiles as configured in the mapguide 
+     * serverconfig.ini section [TileServiceProperties]
+     */
+    FOLDER_PARAMS: {
+        tileColumnsPerFolder: 30,
+        tileRowsPerFolder: 30,
+        format: 'png',
+        querystring: null
+    },	
+
+    /** 
+     * Property: defaultSize
+     * {<OpenLayers.Size>} Tile size as produced by MapGuide server
+     **/
+    defaultSize: new OpenLayers.Size(300,300),
+
+    /** 
+     * Property: tileOriginCorner
+     * {String} MapGuide tile server uses top-left as tile origin
+     **/
+    tileOriginCorner: "tl",
+
+    /**
+     * Constructor: OpenLayers.Layer.MapGuide
+     * Create a new Mapguide layer, either tiled or untiled.  
+     *
+     * For tiled layers, the 'groupName' and 'mapDefinition' values 
+     * must be specified as parameters in the constructor.
+     *
+     * For untiled base layers, specify either combination of 'mapName' and
+     * 'session', or 'mapDefinition' and 'locale'.  
+     *
+     * For older versions of MapGuide and overlay layers, set useAsyncOverlay 
+     * to false and in this case mapName and session are required parameters 
+     * for the constructor.
+     *
+     * NOTE: MapGuide OS uses a DPI value and degrees to meters conversion 
+     * factor that are different than the defaults used in OpenLayers, 
+     * so these must be adjusted accordingly in your application.  
+     * See the MapGuide example for how to set these values for MGOS.
+     *
+     * Parameters:
+     * name - {String} Name of the layer displayed in the interface
+     * url - {String} Location of the MapGuide mapagent executable
+     *            (e.g. http://localhost:8008/mapguide/mapagent/mapagent.fcgi)
+     * params - {Object} hashtable of additional parameters to use. Some
+     *     parameters may require additional code on the server. The ones that
+     *     you may want to use are: 
+     *   - mapDefinition - {String} The MapGuide resource definition
+     *            (e.g. Library://Samples/Gmap/Maps/gmapTiled.MapDefinition)
+     *   - locale - Locale setting 
+     *            (for untiled overlays layers only)
+     *   - mapName - {String} Name of the map as stored in the MapGuide session.
+     *          (for untiled layers with a session parameter only)
+     *   - session - { String} MapGuide session ID 
+     *            (for untiled overlays layers only)
+     *   - basemaplayergroupname - {String} GroupName for tiled MapGuide layers only
+     *   - format - Image format to be returned (for untiled overlay layers only)
+     *   - showLayers - {String} A comma separated list of GUID's for the
+     *       layers to display eg: 'cvc-xcv34,453-345-345sdf'.
+     *   - hideLayers - {String} A comma separated list of GUID's for the
+     *       layers to hide eg: 'cvc-xcv34,453-345-345sdf'.
+     *   - showGroups - {String} A comma separated list of GUID's for the
+     *       groups to display eg: 'cvc-xcv34,453-345-345sdf'.
+     *   - hideGroups - {String} A comma separated list of GUID's for the
+     *       groups to hide eg: 'cvc-xcv34,453-345-345sdf'
+     *   - selectionXml - {String} A selection xml string Some server plumbing
+     *       is required to read such a value.
+     * options - {Object} Hashtable of extra options to tag onto the layer; 
+     *          will vary depending if tiled or untiled maps are being requested
+     */
+    initialize: function(name, url, params, options) {
+        
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, arguments);
+        
+        // unless explicitly set in options, if the layer is transparent, 
+        // it will be an overlay
+        if (options == null || options.isBaseLayer == null) {
+            this.isBaseLayer = ((this.transparent != "true") && 
+                                (this.transparent != true));
+        }
+
+        if (options && options.useOverlay!=null) {
+          this.useOverlay = options.useOverlay;
+        }
+        
+        //initialize for untiled layers
+        if (this.singleTile) {
+          if (this.useOverlay) {
+            OpenLayers.Util.applyDefaults(
+                           this.params,
+                           this.OVERLAY_PARAMS
+                           );
+            if (!this.useAsyncOverlay) {
+              this.params.version = "1.0.0";
+            }
+          } else {
+            OpenLayers.Util.applyDefaults(
+                           this.params,
+                           this.SINGLE_TILE_PARAMS
+                           );
+          }         
+        } else {
+            //initialize for tiled layers
+            if (this.useHttpTile) {
+                OpenLayers.Util.applyDefaults(
+                               this.params,
+                               this.FOLDER_PARAMS
+                               );
+            } else {
+                OpenLayers.Util.applyDefaults(
+                               this.params,
+                               this.TILE_PARAMS
+                               );
+            }
+            this.setTileSize(this.defaultSize); 
+        }
+    },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.MapGuide>} An exact clone of this layer
+     */
+    clone: function (obj) {
+      if (obj == null) {
+            obj = new OpenLayers.Layer.MapGuide(this.name,
+                                           this.url,
+                                           this.params,
+                                           this.getOptions());
+      }
+      //get all additions from superclasses
+      obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+      return obj;
+    },
+
+    /**
+     * Method: getURL
+     * Return a query string for this layer
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox 
+     *                                for the request
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also 
+     *          the passed-in bounds and appropriate tile size specified 
+     *          as parameters.
+     */
+    getURL: function (bounds) {
+        var url;
+        var center = bounds.getCenterLonLat();
+        var mapSize = this.map.getSize();
+
+        if (this.singleTile) {
+          //set up the call for GETMAPIMAGE or GETDYNAMICMAPOVERLAY with
+          //dynamic map parameters
+          var params = {
+            setdisplaydpi: OpenLayers.DOTS_PER_INCH,
+            setdisplayheight: mapSize.h*this.ratio,
+            setdisplaywidth: mapSize.w*this.ratio,
+            setviewcenterx: center.lon,
+            setviewcentery: center.lat,
+            setviewscale: this.map.getScale()
+          };
+          
+          if (this.useOverlay && !this.useAsyncOverlay) {
+            //first we need to call GETVISIBLEMAPEXTENT to set the extent
+            var getVisParams = {};
+            getVisParams = OpenLayers.Util.extend(getVisParams, params);
+            getVisParams.operation = "GETVISIBLEMAPEXTENT";
+            getVisParams.version = "1.0.0";
+            getVisParams.session = this.params.session;
+            getVisParams.mapName = this.params.mapName;
+            getVisParams.format = 'text/xml';
+            url = this.getFullRequestString( getVisParams );
+            
+            OpenLayers.Request.GET({url: url, async: false});
+          }
+          //construct the full URL
+          url = this.getFullRequestString( params );
+        } else {
+
+          //tiled version
+          var currentRes = this.map.getResolution();
+          var colidx = Math.floor((bounds.left-this.maxExtent.left)/currentRes);
+          colidx = Math.round(colidx/this.tileSize.w);
+          var rowidx = Math.floor((this.maxExtent.top-bounds.top)/currentRes);
+          rowidx = Math.round(rowidx/this.tileSize.h);
+
+          if (this.useHttpTile){
+	          url = this.getImageFilePath(
+                   {
+                       tilecol: colidx,
+                       tilerow: rowidx,
+                       scaleindex: this.resolutions.length - this.map.zoom - 1
+                    });
+		  
+          } else {
+            url = this.getFullRequestString(
+                   {
+                       tilecol: colidx,
+                       tilerow: rowidx,
+                       scaleindex: this.resolutions.length - this.map.zoom - 1
+                    });
+          }
+       }
+       return url;
+    },
+
+    /**
+     * Method: getFullRequestString
+     * getFullRequestString on MapGuide layers is special, because we 
+     * do a regular expression replace on ',' in parameters to '+'.
+     * This is why it is subclassed here.
+     *
+     * Parameters:
+     * altUrl - {String} Alternative base URL to use.
+     *
+     * Returns:
+     * {String} A string with the layer's url appropriately encoded for MapGuide
+     */
+    getFullRequestString:function(newParams, altUrl) {
+        // use layer's url unless altUrl passed in
+        var url = (altUrl == null) ? this.url : altUrl;
+        
+        // if url is not a string, it should be an array of strings, 
+        //  in which case we will randomly select one of them in order
+        //  to evenly distribute requests to different urls.
+        if (typeof url == "object") {
+            url = url[Math.floor(Math.random()*url.length)];
+        }   
+        // requestString always starts with url
+        var requestString = url;        
+
+        // create a new params hashtable with all the layer params and the 
+        // new params together. then convert to string
+        var allParams = OpenLayers.Util.extend({}, this.params);
+        allParams = OpenLayers.Util.extend(allParams, newParams);
+        // ignore parameters that are already in the url search string
+        var urlParams = OpenLayers.Util.upperCaseObject(
+                            OpenLayers.Util.getParameters(url));
+        for(var key in allParams) {
+            if(key.toUpperCase() in urlParams) {
+                delete allParams[key];
+            }
+        }
+        var paramsString = OpenLayers.Util.getParameterString(allParams);
+        
+        /* MapGuide needs '+' seperating things like bounds/height/width.
+           Since typically this is URL encoded, we use a slight hack: we
+           depend on the list-like functionality of getParameterString to
+           leave ',' only in the case of list items (since otherwise it is
+           encoded) then do a regular expression replace on the , characters
+           to '+' */
+        paramsString = paramsString.replace(/,/g, "+");
+        
+        if (paramsString != "") {
+            var lastServerChar = url.charAt(url.length - 1);
+            if ((lastServerChar == "&") || (lastServerChar == "?")) {
+                requestString += paramsString;
+            } else {
+                if (url.indexOf('?') == -1) {
+                    //serverPath has no ? -- add one
+                    requestString += '?' + paramsString;
+                } else {
+                    //serverPath contains ?, so must already have paramsString at the end
+                    requestString += '&' + paramsString;
+                }
+            }
+        }
+        return requestString;
+    },
+
+     /** 
+     * Method: getImageFilePath
+     * special handler to request mapguide tiles from an http exposed tilecache 
+     *
+     * Parameters:
+     * altUrl - {String} Alternative base URL to use.
+     *
+     * Returns:
+     * {String} A string with the url for the tile image
+     */
+    getImageFilePath:function(newParams, altUrl) {
+        // use layer's url unless altUrl passed in
+        var url = (altUrl == null) ? this.url : altUrl;
+        
+        // if url is not a string, it should be an array of strings, 
+        //  in which case we will randomly select one of them in order
+        //  to evenly distribute requests to different urls.
+        if (typeof url == "object") {
+            url = url[Math.floor(Math.random()*url.length)];
+        }   
+        // requestString always starts with url
+        var requestString = url;        
+
+        var tileRowGroup = "";
+        var tileColGroup = "";
+        
+        if (newParams.tilerow < 0) {
+          tileRowGroup =  '-';
+        }
+          
+        if (newParams.tilerow == 0 ) {
+          tileRowGroup += '0';
+        } else {
+          tileRowGroup += Math.floor(Math.abs(newParams.tilerow/this.params.tileRowsPerFolder)) * this.params.tileRowsPerFolder;
+        }
+          
+        if (newParams.tilecol < 0) {
+          tileColGroup =  '-';
+        }
+        
+        if (newParams.tilecol == 0) {
+          tileColGroup += '0';
+        } else {
+          tileColGroup += Math.floor(Math.abs(newParams.tilecol/this.params.tileColumnsPerFolder)) * this.params.tileColumnsPerFolder;
+        }					
+        
+        var tilePath = '/S' + Math.floor(newParams.scaleindex)
+                + '/' + this.params.basemaplayergroupname
+                + '/R' + tileRowGroup
+                + '/C' + tileColGroup
+                + '/' + (newParams.tilerow % this.params.tileRowsPerFolder) 
+                + '_' + (newParams.tilecol % this.params.tileColumnsPerFolder) 
+                + '.' + this.params.format;
+    
+        if (this.params.querystring) {
+               tilePath += "?" + this.params.querystring;
+        }
+        
+        requestString += tilePath;
+        return requestString;
+    },
+    
+    /** 
+     * Method: calculateGridLayout
+     * Generate parameters for the grid layout. This  
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * origin - {<OpenLayers.LonLat>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, origin, resolution) {
+        var tilelon = resolution * this.tileSize.w;
+        var tilelat = resolution * this.tileSize.h;
+        
+        var offsetlon = bounds.left - origin.lon;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = origin.lon + tilecol * tilelon;
+        
+        var offsetlat = origin.lat - bounds.top + tilelat; 
+        var tilerow = Math.floor(offsetlat/tilelat) - this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = tilerowremain * this.tileSize.h;
+        var tileoffsetlat = origin.lat - tilelat*tilerow;
+        
+        return { 
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.MapGuide"
+});
+/* ======================================================================
+    OpenLayers/Control/Measure.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Measure
+ * Allows for drawing of features for measurements.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * Supported control event types (in addition to those from <OpenLayers.Control>):
+     * measure - Triggered when a measurement sketch is complete.  Listeners
+     *      will receive an event with measure, units, order, and geometry
+     *      properties.
+     * measurepartial - Triggered when a new point is added to the
+     *      measurement sketch or if the <immediate> property is true and the
+     *      measurement sketch is modified.  Listeners receive an event with measure,
+     *      units, order, and geometry.
+     */
+    EVENT_TYPES: ['measure', 'measurepartial'],
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Used to set non-default properties on the control's handler
+     */
+    handlerOptions: null,
+    
+    /**
+     * Property: callbacks
+     * {Object} The functions that are sent to the handler for callback
+     */
+    callbacks: null,
+    
+    /**
+     * Property: displaySystem
+     * {String} Display system for output measurements.  Supported values
+     *     are 'english', 'metric', and 'geographic'.  Default is 'metric'.
+     */
+    displaySystem: 'metric',
+    
+    /**
+     * Property: geodesic
+     * {Boolean} Calculate geodesic metrics instead of planar metrics.  This
+     *     requires that geometries can be transformed into Geographic/WGS84
+     *     (if that is not already the map projection).  Default is false.
+     */
+    geodesic: false,
+    
+    /**
+     * Property: displaySystemUnits
+     * {Object} Units for various measurement systems.  Values are arrays
+     *     of unit abbreviations (from OpenLayers.INCHES_PER_UNIT) in decreasing
+     *     order of length.
+     */
+    displaySystemUnits: {
+        geographic: ['dd'],
+        english: ['mi', 'ft', 'in'],
+        metric: ['km', 'm']
+    },
+
+    /**
+     * Property: delay
+     * {Number} Number of milliseconds between clicks before the event is
+     *     considered a double-click.  The "measurepartial" event will not
+     *     be triggered if the sketch is completed within this time.  This
+     *     is required for IE where creating a browser reflow (if a listener
+     *     is modifying the DOM by displaying the measurement values) messes
+     *     with the dblclick listener in the sketch handler.
+     */
+    partialDelay: 300,
+
+    /**
+     * Property: delayedTrigger
+     * {Number} Timeout id of trigger for measurepartial.
+     */
+    delayedTrigger: null,
+
+    /**
+     * APIProperty: persist
+     * {Boolean} Keep the temporary measurement sketch drawn after the
+     *     measurement is complete.  The geometry will persist until a new
+     *     measurement is started, the control is deactivated, or <cancel> is
+     *     called.
+     */
+    persist: false,
+
+    /**
+     * APIProperty: immediate
+     * {Boolean} Activates the immediate measurement so that the "measurepartial"
+     *     event is also fired once the measurement sketch is modified.
+     *     Default is false.
+     */
+    immediate : false,
+
+    /**
+     * Constructor: OpenLayers.Control.Measure
+     * 
+     * Parameters:
+     * handler - {<OpenLayers.Handler>} 
+     * options - {Object} 
+     */
+    initialize: function(handler, options) {
+        // concatenate events specific to measure with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.Measure.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        var callbacks = {done: this.measureComplete,
+            point: this.measurePartial};
+        if (this.immediate){
+            callbacks.modify = this.measureImmediate;
+        }
+        this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
+
+        // let the handler options override, so old code that passes 'persist' 
+        // directly to the handler does not need an update
+        this.handlerOptions = OpenLayers.Util.extend(
+            {persist: this.persist}, this.handlerOptions
+        );
+        this.handler = new handler(this, this.callbacks, this.handlerOptions);
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        this.cancelDelay();
+        return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: cancel
+     * Stop the control from measuring.  If <persist> is true, the temporary
+     *     sketch will be erased.
+     */
+    cancel: function() {
+        this.cancelDelay();
+        this.handler.cancel();
+    },
+
+    /**
+     * APIMethod: setImmediate
+     * Sets the <immediate> property. Changes the activity of immediate
+     * measurement.
+     */
+    setImmediate: function(immediate) {
+        this.immediate = immediate;
+        if (this.immediate){
+            this.callbacks.modify = this.measureImmediate;
+        } else {
+            delete this.callbacks.modify;
+        }
+    },
+    
+    /**
+     * Method: updateHandler
+     *
+     * Parameters:
+     * handler - {Function} One of the sketch handler constructors.
+     * options - {Object} Options for the handler.
+     */
+    updateHandler: function(handler, options) {
+        var active = this.active;
+        if(active) {
+            this.deactivate();
+        }
+        this.handler = new handler(this, this.callbacks, options);
+        if(active) {
+            this.activate();
+        }
+    },
+
+    /**
+     * Method: measureComplete
+     * Called when the measurement sketch is done.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     */
+    measureComplete: function(geometry) {
+        this.cancelDelay();
+        this.measure(geometry, "measure");
+    },
+    
+    /**
+     * Method: measurePartial
+     * Called each time a new point is added to the measurement sketch.
+     *
+     * Parameters:
+     * point - {<OpenLayers.Geometry.Point>} The last point added.
+     * geometry - {<OpenLayers.Geometry>} The sketch geometry.
+     */
+    measurePartial: function(point, geometry) {
+        this.cancelDelay();
+        geometry = geometry.clone();
+        // when we're wating for a dblclick, we have to trigger measurepartial
+        // after some delay to deal with reflow issues in IE
+        if (this.handler.freehandMode(this.handler.evt)) {
+            // no dblclick in freehand mode
+            this.measure(geometry, "measurepartial");
+        } else {
+            this.delayedTrigger = window.setTimeout(
+                OpenLayers.Function.bind(function() {
+                    this.delayedTrigger = null;
+                    this.measure(geometry, "measurepartial");
+                }, this),
+                this.partialDelay
+            );
+        }
+    },
+
+    /**
+     * Method: measureImmediate
+     * Called each time the measurement sketch is modified.
+     * 
+     * Parameters: point - {<OpenLayers.Geometry.Point>} The point at the
+     * mouseposition. feature - {<OpenLayers.Feature.Vector>} The sketch feature.
+     */
+    measureImmediate : function(point, feature, drawing) {
+        if (drawing && this.delayedTrigger === null &&
+                                !this.handler.freehandMode(this.handler.evt)) {
+            this.measure(feature.geometry, "measurepartial");
+        }
+    },
+
+    /**
+     * Method: cancelDelay
+     * Cancels the delay measurement that measurePartial began.
+     */
+    cancelDelay: function() {
+        if (this.delayedTrigger !== null) {
+            window.clearTimeout(this.delayedTrigger);
+            this.delayedTrigger = null;
+        }
+    },
+
+    /**
+     * Method: measure
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * eventType - {String}
+     */
+    measure: function(geometry, eventType) {
+        var stat, order;
+        if(geometry.CLASS_NAME.indexOf('LineString') > -1) {
+            stat = this.getBestLength(geometry);
+            order = 1;
+        } else {
+            stat = this.getBestArea(geometry);
+            order = 2;
+        }
+        this.events.triggerEvent(eventType, {
+            measure: stat[0],
+            units: stat[1],
+            order: order,
+            geometry: geometry
+        });
+    },
+    
+    /**
+     * Method: getBestArea
+     * Based on the <displaySystem> returns the area of a geometry.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {Array([Float, String])}  Returns a two item array containing the
+     *     area and the units abbreviation.
+     */
+    getBestArea: function(geometry) {
+        var units = this.displaySystemUnits[this.displaySystem];
+        var unit, area;
+        for(var i=0, len=units.length; i<len; ++i) {
+            unit = units[i];
+            area = this.getArea(geometry, unit);
+            if(area > 1) {
+                break;
+            }
+        }
+        return [area, unit];
+    },
+    
+    /**
+     * Method: getArea
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * units - {String} Unit abbreviation
+     *
+     * Returns:
+     * {Float} The geometry area in the given units.
+     */
+    getArea: function(geometry, units) {
+        var area, geomUnits;
+        if(this.geodesic) {
+            area = geometry.getGeodesicArea(this.map.getProjectionObject());
+            geomUnits = "m";
+        } else {
+            area = geometry.getArea();
+            geomUnits = this.map.getUnits();
+        }
+        var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units];
+        if(inPerDisplayUnit) {
+            var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[geomUnits];
+            area *= Math.pow((inPerMapUnit / inPerDisplayUnit), 2);
+        }
+        return area;
+    },
+    
+    /**
+     * Method: getBestLength
+     * Based on the <displaySystem> returns the length of a geometry.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {Array([Float, String])}  Returns a two item array containing the
+     *     length and the units abbreviation.
+     */
+    getBestLength: function(geometry) {
+        var units = this.displaySystemUnits[this.displaySystem];
+        var unit, length;
+        for(var i=0, len=units.length; i<len; ++i) {
+            unit = units[i];
+            length = this.getLength(geometry, unit);
+            if(length > 1) {
+                break;
+            }
+        }
+        return [length, unit];
+    },
+
+    /**
+     * Method: getLength
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * units - {String} Unit abbreviation
+     *
+     * Returns:
+     * {Float} The geometry length in the given units.
+     */
+    getLength: function(geometry, units) {
+        var length, geomUnits;
+        if(this.geodesic) {
+            length = geometry.getGeodesicLength(this.map.getProjectionObject());
+            geomUnits = "m";
+        } else {
+            length = geometry.getLength();
+            geomUnits = this.map.getUnits();
+        }
+        var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units];
+        if(inPerDisplayUnit) {
+            var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[geomUnits];
+            length *= (inPerMapUnit / inPerDisplayUnit);
+        }
+        return length;
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Measure"
+});
+/* ======================================================================
+    OpenLayers/Format/WMC/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1_0_0
+ * Read and write WMC version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMC.v1>
+ */
+OpenLayers.Format.WMC.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.WMC.v1, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/context
+     *     http://schemas.opengis.net/context/1.0.0/context.xsd
+     */
+    schemaLocation: "http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd",
+
+    /**
+     * Constructor: OpenLayers.Format.WMC.v1_0_0
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.WMC> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMC.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Method: read_wmc_SRS
+     */
+    read_wmc_SRS: function(layerContext, node) {
+        var srs    = this.getChildValue(node);
+        if (typeof layerContext.projections != "object") {
+            layerContext.projections = {};
+        }
+        var values = srs.split(/ +/);
+        for (var i=0, len=values.length; i<len; i++) {
+            layerContext.projections[values[i]] = true;
+        }
+    },
+
+    /**
+     * Method: write_wmc_Layer
+     * Create a Layer node given a layer context object. This method adds
+     *     elements specific to version 1.0.0.
+     *
+     * Parameters:
+     * context - {Object} A layer context object.}
+     *
+     * Returns:
+     * {Element} A WMC Layer element node.
+     */
+    write_wmc_Layer: function(context) {
+        var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
+            this, [context]
+        );
+    
+        // optional SRS element(s)
+        if (context.srs) {
+            var projections = [];
+            for(var name in context.srs) {
+                projections.push(name);
+            }
+            node.appendChild(this.createElementDefaultNS("SRS", projections.join(" ")));
+        }
+
+        // optional FormatList element
+        node.appendChild(this.write_wmc_FormatList(context));
+
+        // optional StyleList element
+        node.appendChild(this.write_wmc_StyleList(context));
+        
+        // optional DimensionList element
+        if (context.dimensions) {
+            node.appendChild(this.write_wmc_DimensionList(context));
+        }
+
+        // OpenLayers specific properties go in an Extension element
+        node.appendChild(this.write_wmc_LayerExtension(context));
+    },    
+
+    CLASS_NAME: "OpenLayers.Format.WMC.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMTSCapabilities/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMTSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities.v1_0_0
+ * Read WMTS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMTSCapabilities>
+ */
+OpenLayers.Format.WMTSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.OWSCommon.v1_1_0, {
+        
+    /**
+     * Property: version
+     * {String} The parser version ("1.0.0").
+     */
+    version: "1.0.0",
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        wmts: "http://www.opengis.net/wmts/1.0",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: yx
+     * {Object} Members in the yx object are used to determine if a CRS URN
+     *     corresponds to a CRS with y,x axis order.  Member names are CRS URNs
+     *     and values are boolean.  Defaults come from the 
+     *     <OpenLayers.Format.WMTSCapabilities> prototype.
+     */
+    yx: null,
+
+    /**
+     * Property: defaultPrefix
+     * {String} The default namespace alias for creating element nodes.
+     */
+    defaultPrefix: "wmts",
+
+    /**
+     * Constructor: OpenLayers.Format.WMTSCapabilities.v1_0_0
+     * Create a new parser for WMTS capabilities version 1.0.0. 
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+        var yx = OpenLayers.Util.extend(
+            {}, OpenLayers.Format.WMTSCapabilities.prototype.yx
+        );
+        this.yx = OpenLayers.Util.extend(yx, this.yx);
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return info about the WMTS.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the SOS service.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        capabilities.version = this.version;
+        return capabilities;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {        
+        "wmts": {
+            "Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Contents": function(node, obj) {
+                obj.contents = {};                
+                obj.contents.layers = [];
+                obj.contents.tileMatrixSets = {};                
+                this.readChildNodes(node, obj.contents);
+            },
+            "Layer": function(node, obj) {
+                var layer = {
+                    styles: [],
+                    formats: [],
+                    tileMatrixSetLinks: []
+                };
+                layer.layers = [];
+                this.readChildNodes(node, layer);
+                obj.layers.push(layer);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                style.isDefault = (node.getAttribute("isDefault") === "true");
+                this.readChildNodes(node, style);
+                obj.styles.push(style);
+            },
+            "Format": function(node, obj) {
+                obj.formats.push(this.getChildValue(node)); 
+            },
+            "TileMatrixSetLink": function(node, obj) {
+                var tileMatrixSetLink = {};
+                this.readChildNodes(node, tileMatrixSetLink);
+                obj.tileMatrixSetLinks.push(tileMatrixSetLink);
+            },
+            "TileMatrixSet": function(node, obj) {
+                // node could be child of wmts:Contents or wmts:TileMatrixSetLink
+                // duck type wmts:Contents by looking for layers
+                if (obj.layers) {
+                    // TileMatrixSet as object type in schema
+                    var tileMatrixSet = {
+                        matrixIds: []
+                    };
+                    this.readChildNodes(node, tileMatrixSet);
+                    obj.tileMatrixSets[tileMatrixSet.identifier] = tileMatrixSet;
+                } else {
+                    // TileMatrixSet as string type in schema
+                    obj.tileMatrixSet = this.getChildValue(node);
+                }
+            },
+            "TileMatrix": function(node, obj) {
+                var tileMatrix = {
+                    supportedCRS: obj.supportedCRS
+                };
+                this.readChildNodes(node, tileMatrix);
+                obj.matrixIds.push(tileMatrix);
+            },
+            "ScaleDenominator": function(node, obj) {
+                obj.scaleDenominator = parseFloat(this.getChildValue(node)); 
+            },
+            "TopLeftCorner": function(node, obj) {                
+                var topLeftCorner = this.getChildValue(node);
+                var coords = topLeftCorner.split(" ");
+                // decide on axis order for the given CRS
+                var yx;
+                if (obj.supportedCRS) {
+                    // extract out version from URN
+                    var crs = obj.supportedCRS.replace(
+                        /urn:ogc:def:crs:(\w+):.+:(\w+)$/, 
+                        "urn:ogc:def:crs:$1::$2"
+                    );
+                    yx = !!this.yx[crs];
+                }
+                if (yx) {
+                    obj.topLeftCorner = new OpenLayers.LonLat(
+                        coords[1], coords[0]
+                    );
+                } else {
+                    obj.topLeftCorner = new OpenLayers.LonLat(
+                        coords[0], coords[1]
+                    );
+                }
+            },
+            "TileWidth": function(node, obj) {
+                obj.tileWidth = parseInt(this.getChildValue(node)); 
+            },
+            "TileHeight": function(node, obj) {
+                obj.tileHeight = parseInt(this.getChildValue(node)); 
+            },
+            "MatrixWidth": function(node, obj) {
+                obj.matrixWidth = parseInt(this.getChildValue(node)); 
+            },
+            "MatrixHeight": function(node, obj) {
+                obj.matrixHeight = parseInt(this.getChildValue(node)); 
+            },
+            "ResourceURL": function(node, obj) {
+                obj.resourceUrl = obj.resourceUrl || {};
+                obj.resourceUrl[node.getAttribute("resourceType")] = {
+                    format: node.getAttribute("format"),
+                    template: node.getAttribute("template")
+                };
+            },
+            // not used for now, can be added in the future though
+            /*"Themes": function(node, obj) {
+                obj.themes = [];
+                this.readChildNodes(node, obj.themes);
+            },
+            "Theme": function(node, obj) {
+                var theme = {};                
+                this.readChildNodes(node, theme);
+                obj.push(theme);
+            },*/
+            "WSDL": function(node, obj) {
+                obj.wsdl = {};
+                obj.wsdl.href = node.getAttribute("xlink:href");
+                // TODO: other attributes of <WSDL> element                
+            },
+            "ServiceMetadataURL": function(node, obj) {
+                obj.serviceMetadataUrl = {};
+                obj.serviceMetadataUrl.href = node.getAttribute("xlink:href");
+                // TODO: other attributes of <ServiceMetadataURL> element                
+            }            
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },    
+    
+    CLASS_NAME: "OpenLayers.Format.WMTSCapabilities.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Popup/FramedCloud.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Popup/Framed.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/BaseTypes/Bounds.js
+ * @requires OpenLayers/BaseTypes/Pixel.js
+ * @requires OpenLayers/BaseTypes/Size.js
+ */
+
+/**
+ * Class: OpenLayers.Popup.FramedCloud
+ * 
+ * Inherits from: 
+ *  - <OpenLayers.Popup.Framed>
+ */
+OpenLayers.Popup.FramedCloud = 
+  OpenLayers.Class(OpenLayers.Popup.Framed, {
+
+    /** 
+     * Property: contentDisplayClass
+     * {String} The CSS class of the popup content div.
+     */
+    contentDisplayClass: "olFramedCloudPopupContent",
+
+    /**
+     * APIProperty: autoSize
+     * {Boolean} Framed Cloud is autosizing by default.
+     */
+    autoSize: true,
+
+    /**
+     * APIProperty: panMapIfOutOfView
+     * {Boolean} Framed Cloud does pan into view by default.
+     */
+    panMapIfOutOfView: true,
+
+    /**
+     * APIProperty: imageSize
+     * {<OpenLayers.Size>}
+     */
+    imageSize: new OpenLayers.Size(1276, 736),
+
+    /**
+     * APIProperty: isAlphaImage
+     * {Boolean} The FramedCloud does not use an alpha image (in honor of the 
+     *     good ie6 folk out there)
+     */
+    isAlphaImage: false,
+
+    /** 
+     * APIProperty: fixedRelativePosition
+     * {Boolean} The Framed Cloud popup works in just one fixed position.
+     */
+    fixedRelativePosition: false,
+
+    /**
+     * Property: positionBlocks
+     * {Object} Hash of differen position blocks, keyed by relativePosition
+     *     two-character code string (ie "tl", "tr", "bl", "br")
+     */
+    positionBlocks: {
+        "tl": {
+            'offset': new OpenLayers.Pixel(44, 0),
+            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
+            'blocks': [
+                { // top-left
+                    size: new OpenLayers.Size('auto', 'auto'),
+                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
+                    position: new OpenLayers.Pixel(0, 0)
+                },
+                { //top-right
+                    size: new OpenLayers.Size(22, 'auto'),
+                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
+                    position: new OpenLayers.Pixel(-1238, 0)
+                },
+                { //bottom-left
+                    size: new OpenLayers.Size('auto', 19),
+                    anchor: new OpenLayers.Bounds(0, 32, 22, null),
+                    position: new OpenLayers.Pixel(0, -631)
+                },
+                { //bottom-right
+                    size: new OpenLayers.Size(22, 18),
+                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
+                    position: new OpenLayers.Pixel(-1238, -632)
+                },
+                { // stem
+                    size: new OpenLayers.Size(81, 35),
+                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
+                    position: new OpenLayers.Pixel(0, -688)
+                }
+            ]
+        },
+        "tr": {
+            'offset': new OpenLayers.Pixel(-45, 0),
+            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
+            'blocks': [
+                { // top-left
+                    size: new OpenLayers.Size('auto', 'auto'),
+                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
+                    position: new OpenLayers.Pixel(0, 0)
+                },
+                { //top-right
+                    size: new OpenLayers.Size(22, 'auto'),
+                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
+                    position: new OpenLayers.Pixel(-1238, 0)
+                },
+                { //bottom-left
+                    size: new OpenLayers.Size('auto', 19),
+                    anchor: new OpenLayers.Bounds(0, 32, 22, null),
+                    position: new OpenLayers.Pixel(0, -631)
+                },
+                { //bottom-right
+                    size: new OpenLayers.Size(22, 19),
+                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
+                    position: new OpenLayers.Pixel(-1238, -631)
+                },
+                { // stem
+                    size: new OpenLayers.Size(81, 35),
+                    anchor: new OpenLayers.Bounds(0, 0, null, null),
+                    position: new OpenLayers.Pixel(-215, -687)
+                }
+            ]
+        },
+        "bl": {
+            'offset': new OpenLayers.Pixel(45, 0),
+            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
+            'blocks': [
+                { // top-left
+                    size: new OpenLayers.Size('auto', 'auto'),
+                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
+                    position: new OpenLayers.Pixel(0, 0)
+                },
+                { //top-right
+                    size: new OpenLayers.Size(22, 'auto'),
+                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
+                    position: new OpenLayers.Pixel(-1238, 0)
+                },
+                { //bottom-left
+                    size: new OpenLayers.Size('auto', 21),
+                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
+                    position: new OpenLayers.Pixel(0, -629)
+                },
+                { //bottom-right
+                    size: new OpenLayers.Size(22, 21),
+                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
+                    position: new OpenLayers.Pixel(-1238, -629)
+                },
+                { // stem
+                    size: new OpenLayers.Size(81, 33),
+                    anchor: new OpenLayers.Bounds(null, null, 0, 0),
+                    position: new OpenLayers.Pixel(-101, -674)
+                }
+            ]
+        },
+        "br": {
+            'offset': new OpenLayers.Pixel(-44, 0),
+            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
+            'blocks': [
+                { // top-left
+                    size: new OpenLayers.Size('auto', 'auto'),
+                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
+                    position: new OpenLayers.Pixel(0, 0)
+                },
+                { //top-right
+                    size: new OpenLayers.Size(22, 'auto'),
+                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
+                    position: new OpenLayers.Pixel(-1238, 0)
+                },
+                { //bottom-left
+                    size: new OpenLayers.Size('auto', 21),
+                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
+                    position: new OpenLayers.Pixel(0, -629)
+                },
+                { //bottom-right
+                    size: new OpenLayers.Size(22, 21),
+                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
+                    position: new OpenLayers.Pixel(-1238, -629)
+                },
+                { // stem
+                    size: new OpenLayers.Size(81, 33),
+                    anchor: new OpenLayers.Bounds(0, null, null, 0),
+                    position: new OpenLayers.Pixel(-311, -674)
+                }
+            ]
+        }
+    },
+
+    /**
+     * APIProperty: minSize
+     * {<OpenLayers.Size>}
+     */
+    minSize: new OpenLayers.Size(105, 10),
+
+    /**
+     * APIProperty: maxSize
+     * {<OpenLayers.Size>}
+     */
+    maxSize: new OpenLayers.Size(1200, 660),
+
+    /** 
+     * Constructor: OpenLayers.Popup.FramedCloud
+     * 
+     * Parameters:
+     * id - {String}
+     * lonlat - {<OpenLayers.LonLat>}
+     * contentSize - {<OpenLayers.Size>}
+     * contentHTML - {String}
+     * anchor - {Object} Object to which we'll anchor the popup. Must expose 
+     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>) 
+     *     (Note that this is generally an <OpenLayers.Icon>).
+     * closeBox - {Boolean}
+     * closeBoxCallback - {Function} Function to be called on closeBox click.
+     */
+    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox, 
+                        closeBoxCallback) {
+
+        this.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.png';
+        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments);
+        this.contentDiv.className = this.contentDisplayClass;
+    },
+
+    /** 
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Popup.FramedCloud"
+});
+/* ======================================================================
+    OpenLayers/Tile/Image/IFrame.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Constant: OpenLayers.Tile.Image.IFrame
+ * Mixin for tiles that use form-encoded POST requests to get images from
+ * remote services. Images will be loaded using HTTP-POST into an IFrame.
+ *
+ * This mixin will be applied to <OpenLayers.Tile.Image> instances
+ * configured with <OpenLayers.Tile.Image.allowPost> or
+ * <OpenLayers.Tile.Image.enforcePost> set to true.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Tile.Image>
+ */
+OpenLayers.Tile.Image.IFrame = {
+    
+    /**
+     * Property: useIFrame
+     * {Boolean} true if we are currently using an IFrame to render POST
+     * responses, false if we are using an img element to render GET responses.
+     */ 
+    useIFrame: null,
+
+    /**
+     * Method: clear
+     * Removes the iframe from DOM (avoids back-button problems).
+     */
+    clear: function() {
+        if (this.useIFrame) {
+            if (this.imgDiv) {
+                var iFrame = this.imgDiv.firstChild;
+                OpenLayers.Event.stopObservingElement(iFrame);
+                this.imgDiv.removeChild(iFrame);
+                delete iFrame;
+            }
+        } else {
+            OpenLayers.Tile.Image.prototype.clear.apply(this, arguments);
+        }
+    },
+
+    /**
+     * Method: renderTile
+     */
+     renderTile: function() {
+        if (OpenLayers.Tile.Image.prototype.renderTile.apply(this, arguments) &&
+                                                            this.useIFrame) {
+            // create a html form and add it temporary to the layer div
+            var form = this.createRequestForm();
+            this.imgDiv.appendChild(form);
+
+            // submit the form (means fetching the image)
+            form.submit();
+            this.imgDiv.removeChild(form);
+            delete form;
+        }
+        return true;
+    },
+
+    /**
+     * Method: initImgDiv
+     * Creates the imgDiv property on the tile.
+     */
+    initImgDiv: function() {
+        this.useIFrame = this.maxGetUrlLength !== null && !this.layer.async &&
+            this.url.length > this.maxGetUrlLength;
+        if (this.imgDiv != null) {
+            var nodeName = this.imgDiv.nodeName.toLowerCase();
+            if ((this.useIFrame && nodeName == "img") ||
+                                        (!this.useIFrame && nodeName == "div")) {
+                // switch between get and post
+                this.removeImgDiv();
+                this.imgDiv = null;
+            }
+        }
+        if (this.useIFrame) {
+            if (this.imgDiv == null) {
+                var eventPane = document.createElement("div");
+
+                if(OpenLayers.BROWSER_NAME == "msie") {
+                    // IE cannot handle events on elements without backgroundcolor.
+                    // So we use this little hack to make elements transparent
+                    eventPane.style.backgroundColor = '#FFFFFF';
+                    eventPane.style.filter          = 'chroma(color=#FFFFFF)';
+                }
+
+                OpenLayers.Util.modifyDOMElement(eventPane, null,
+                    new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
+
+                this.imgDiv = document.createElement("div");
+                this.imgDiv.appendChild(eventPane);
+
+                OpenLayers.Util.modifyDOMElement(this.imgDiv, this.id, null,
+                    this.layer.getImageSize(), "relative");
+                this.imgDiv.className = 'olTileImage';
+
+                this.frame.appendChild(this.imgDiv); 
+                this.layer.div.appendChild(this.frame); 
+
+                if(this.layer.opacity != null) {
+
+                    OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null,
+                                                     null, null, null, null, 
+                                                     this.layer.opacity);
+                }
+
+                // we need this reference to check back the viewRequestID
+                this.imgDiv.map = this.layer.map;
+            }
+            this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
+
+        } else {
+            OpenLayers.Tile.Image.prototype.initImgDiv.apply(this, arguments);
+        }
+    },
+
+    /**
+     * Method: createIFrame
+     * Create the IFrame which shows the image.
+     *
+     * Returns:
+     * {DOMElement} Iframe
+     */
+    createIFrame: function() {
+        var id = this.id+'_iFrame';
+        var iframe;
+        if(OpenLayers.BROWSER_NAME == "msie") {
+            // InternetExplorer does not set the name attribute of an iFrame 
+            // properly via DOM manipulation, so we need to do it on our own with
+            // this hack.
+            iframe = document.createElement('<iframe name="'+id+'">');
+
+            // IFrames in InternetExplorer are not transparent, if you set the
+            // backgroundColor transparent. This is a workarround to get 
+            // transparent iframes.
+            iframe.style.backgroundColor = '#FFFFFF';
+            iframe.style.filter          = 'chroma(color=#FFFFFF)';
+        }
+        else {
+            iframe = document.createElement('iframe');
+            iframe.style.backgroundColor = 'transparent';
+        
+            // iframe.name needs to be an unique id, otherwise it 
+            // could happen that other iframes are overwritten.
+            iframe.name = id;
+        }
+        iframe.id = id;
+
+        // some special properties to avoid scaling the images and scrollbars 
+        // in the iframe
+        iframe.scrolling             = 'no';
+        iframe.marginWidth           = '0px';
+        iframe.marginHeight          = '0px';
+        iframe.frameBorder           = '0';
+
+        OpenLayers.Util.modifyDOMElement(iframe, id, 
+            new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
+
+        //bind a listener to the onload of the iframe so that we
+        // can register when a tile has finished loading.
+        var onload = function() {
+            //normally isLoading should always be true here but there are some
+            // right funky conditions where loading and then reloading a tile
+            // with the same url *really*fast*. this check prevents sending
+            // a 'loadend' if the msg has already been sent
+            //
+            if (this.isLoading) {
+                this.isLoading = false;
+                this.events.triggerEvent("loadend");
+            }
+        };
+        OpenLayers.Event.observe(iframe, 'load',
+            OpenLayers.Function.bind(onload, this));
+
+        return iframe;
+    },
+    
+    /**
+     * Method: createRequestForm
+     * Create the html <form> element with width, height, bbox and all 
+     * parameters specified in the layer params.
+     *
+     * Returns: 
+     * {DOMElement} The form element which sends the HTTP-POST request to the
+     *              WMS. 
+     */
+    createRequestForm: function() {
+        // creation of the form element
+        var form = document.createElement('form');
+        form.method = 'POST';
+        var cacheId = this.layer.params["_OLSALT"];
+        cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
+        form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
+
+        // insert the iframe, which has been removed to avoid back-button
+        // problems
+        this.imgDiv.insertBefore(this.createIFrame(), this.imgDiv.firstChild);
+
+        form.target = this.id+'_iFrame';
+
+        // adding all parameters in layer params as hidden fields to the html
+        // form element
+        var imageSize = this.layer.getImageSize();
+        var params = OpenLayers.Util.getParameters(this.url);
+            
+        for(var par in params) {
+            var field = document.createElement('input');
+            field.type  = 'hidden';
+            field.name  = par;
+            field.value = params[par];
+            form.appendChild(field);
+        }   
+
+        return form;
+    }
+};
+
+/* ======================================================================
+    OpenLayers/Geometry/Rectangle.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Geometry.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry.Rectangle
+ * This class is *not supported*, and probably isn't what you're looking for.
+ *     Instead, most users probably want something like:
+ *     (code)
+ *     var poly = new OpenLayers.Bounds(0,0,10,10).toGeometry();
+ *     (end)
+ *     This will create a rectangular Polygon geometry. 
+ * 
+ * Inherits:
+ *  - <OpenLayers.Geometry>
+ */
+
+OpenLayers.Geometry.Rectangle = OpenLayers.Class(OpenLayers.Geometry, {
+
+    /** 
+     * Property: x
+     * {Float}
+     */
+    x: null,
+
+    /** 
+     * Property: y
+     * {Float}
+     */
+    y: null,
+
+    /** 
+     * Property: width
+     * {Float}
+     */
+    width: null,
+
+    /** 
+     * Property: height
+     * {Float}
+     */
+    height: null,
+
+    /**
+     * Constructor: OpenLayers.Geometry.Rectangle
+     * 
+     * Parameters:
+     * points - {Array(<OpenLayers.Geometry.Point>)}
+     */
+    initialize: function(x, y, width, height) {
+        OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
+        
+        this.x = x;
+        this.y = y;
+
+        this.width = width;
+        this.height = height;
+    },
+    
+    /**
+     * Method: calculateBounds
+     * Recalculate the bounds for the geometry.
+     */
+    calculateBounds: function() {
+        this.bounds = new OpenLayers.Bounds(this.x, this.y,
+                                            this.x + this.width, 
+                                            this.y + this.height);
+    },
+    
+    
+    /**
+     * APIMethod: getLength
+     * 
+     * Returns:
+     * {Float} The length of the geometry
+     */
+    getLength: function() {
+        var length = (2 * this.width) + (2 * this.height);
+        return length;
+    },
+
+    /**
+     * APIMethod: getArea
+     * 
+     * Returns:
+     * {Float} The area of the geometry
+     */
+    getArea: function() {
+        var area = this.width * this.height;
+        return area;
+    },    
+
+    CLASS_NAME: "OpenLayers.Geometry.Rectangle"
+});
+/* ======================================================================
+    OpenLayers/Strategy/Refresh.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Refresh
+ * A strategy that refreshes the layer. By default the strategy waits for a
+ *     call to <refresh> before refreshing.  By configuring the strategy with 
+ *     the <interval> option, refreshing can take place automatically.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Refresh = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * Property: force
+     * {Boolean} Force a refresh on the layer. Default is false.
+     */
+    force: false,
+
+    /**
+     * Property: interval
+     * {Number} Auto-refresh. Default is 0.  If > 0, layer will be refreshed 
+     *     every N milliseconds.
+     */
+    interval: 0,
+    
+    /**
+     * Property: timer
+     * {Number} The id of the timer.
+     */
+    timer: null,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Refresh
+     * Create a new Refresh strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+   
+    /**
+     * APIMethod: activate
+     * Activate the strategy. Register any listeners, do appropriate setup.
+     * 
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            if(this.layer.visibility === true) {
+                this.start();
+            } 
+            this.layer.events.on({
+                "visibilitychanged": this.reset,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy. Unregister any listeners, do appropriate
+     *     tear-down.
+     * 
+     * Returns:
+     * {Boolean} True if the strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.stop();
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: reset
+     * Start or cancel the refresh interval depending on the visibility of 
+     *     the layer.
+     */
+    reset: function() {
+        if(this.layer.visibility === true) {
+            this.start();
+        } else {
+            this.stop();
+        }
+    },
+    
+    /**
+     * Method: start
+     * Start the refresh interval. 
+     */
+    start: function() {
+        if(this.interval && typeof this.interval === "number" && 
+            this.interval > 0) {
+
+            this.timer = window.setInterval(
+                OpenLayers.Function.bind(this.refresh, this),
+                this.interval);
+        }
+    },
+    
+    /**
+     * APIMethod: refresh
+     * Tell the strategy to refresh which will refresh the layer.
+     */
+    refresh: function() {
+        if (this.layer && this.layer.refresh && 
+            typeof this.layer.refresh == "function") {
+
+            this.layer.refresh({force: this.force});
+        }
+    },
+   
+    /**
+     * Method: stop
+     * Cancels the refresh interval. 
+     */
+    stop: function() {
+        if(this.timer !== null) {
+            window.clearInterval(this.timer);
+            this.timer = null;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Strategy.Refresh" 
+});
+/* ======================================================================
+    OpenLayers/Format/SOSCapabilities/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/SOSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSCapabilities.v1_0_0
+ * Read SOS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.SOSCapabilities>
+ */
+OpenLayers.Format.SOSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.SOSCapabilities, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        sos: "http://www.opengis.net/sos/1.0",
+        gml: "http://www.opengis.net/gml",
+        xlink: "http://www.w3.org/1999/xlink"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.SOSCapabilities.v1_0_0
+     * Create a new parser for SOS capabilities version 1.0.0. 
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return info about the SOS.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the SOS service.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        return capabilities;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "TimePeriod": function(node, obj) {
+                obj.timePeriod = {};
+                this.readChildNodes(node, obj.timePeriod);
+            },
+            "beginPosition": function(node, timePeriod) {
+                timePeriod.beginPosition = this.getChildValue(node);
+            },
+            "endPosition": function(node, timePeriod) {
+                timePeriod.endPosition = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.GML.v3.prototype.readers["gml"]),
+        "sos": {
+            "Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Contents": function(node, obj) {
+                obj.contents = {};
+                this.readChildNodes(node, obj.contents);
+            },
+            "ObservationOfferingList": function(node, contents) {
+                contents.offeringList = {};
+                this.readChildNodes(node, contents.offeringList);
+            },
+            "ObservationOffering": function(node, offeringList) {
+                var id = this.getAttributeNS(node, this.namespaces.gml, "id");
+                offeringList[id] = {
+                    procedures: [],
+                    observedProperties: [],
+                    featureOfInterestIds: [],
+                    responseFormats: [],
+                    resultModels: [],
+                    responseModes: []
+                };
+                this.readChildNodes(node, offeringList[id]);
+            },
+            "time": function(node, offering) {
+                offering.time = {};
+                this.readChildNodes(node, offering.time);
+            },
+            "procedure": function(node, offering) {
+                offering.procedures.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "observedProperty": function(node, offering) {
+                offering.observedProperties.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "featureOfInterest": function(node, offering) {
+                offering.featureOfInterestIds.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "responseFormat": function(node, offering) {
+                offering.responseFormats.push(this.getChildValue(node));
+            },
+            "resultModel": function(node, offering) {
+                offering.resultModels.push(this.getChildValue(node));
+            },
+            "responseMode": function(node, offering) {
+                offering.responseModes.push(this.getChildValue(node));;
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },    
+    
+    CLASS_NAME: "OpenLayers.Format.SOSCapabilities.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Handler/Pinch.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Pinch
+ * The pinch handler is used to deal with sequences of browser events related
+ *     to pinch gestures. The handler is used by controls that want to know
+ *     when a pinch sequence begins, when a pinch is happening, and when it has
+ *     finished.
+ *
+ * Controls that use the pinch handler typically construct it with callbacks
+ *     for 'start', 'move', and 'done'.  Callbacks for these keys are
+ *     called when the pinch begins, with each change, and when the pinch is
+ *     done.
+ *
+ * Create a new pinch handler with the <OpenLayers.Handler.Pinch> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.Pinch = OpenLayers.Class(OpenLayers.Handler, {
+
+    /**
+     * Property: started
+     * {Boolean} When a touchstart event is received, we want to record it,
+     *     but not set 'pinching' until the touchmove get started after
+     *     starting.
+     */
+    started: false,
+
+    /**
+     * Property: stopDown
+     * {Boolean} Stop propagation of touchstart events from getting to
+     *     listeners on the same element. Default is false.
+     */
+    stopDown: false,
+
+    /**
+     * Property: pinching
+     * {Boolean}
+     */
+    pinching: false,
+
+    /**
+     * Property: last
+     * {Object} Object that store informations related to pinch last touch.
+     */
+    last: null,
+
+    /**
+     * Property: start
+     * {Object} Object that store informations related to pinch touchstart.
+     */
+    start: null,
+
+    /**
+     * Constructor: OpenLayers.Handler.Pinch
+     * Returns OpenLayers.Handler.Pinch
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that is making use of
+     *     this handler.  If a handler is being used without a control, the
+     *     handlers setMap method must be overridden to deal properly with
+     *     the map.
+     * callbacks - {Object} An object containing functions to be called when
+     *     the pinch operation start, change, or is finished. The callbacks
+     *     should expect to receive an object argument, which contains
+     *     information about scale, distance, and position of touch points.
+     * options - {Object}
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * Method: touchstart
+     * Handle touchstart events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchstart: function(evt) {
+        var propagate = true;
+        this.pinching = false;
+        if (OpenLayers.Event.isMultiTouch(evt)) {
+            this.started = true;
+            this.last = this.start = {
+                distance: this.getDistance(evt.touches),
+                delta: 0,
+                scale: 1
+            };
+            this.callback("start", [evt, this.start]);
+            propagate = !this.stopDown;
+        } else {
+            this.started = false;
+            this.start = null;
+            this.last = null;
+        }
+        // prevent document dragging
+        OpenLayers.Event.stop(evt);
+        return propagate;
+    },
+
+    /**
+     * Method: touchmove
+     * Handle touchmove events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchmove: function(evt) {
+        if (this.started && OpenLayers.Event.isMultiTouch(evt)) {
+            this.pinching = true;
+            var current = this.getPinchData(evt);
+            this.callback("move", [evt, current]);
+            this.last = current;
+            // prevent document dragging
+            OpenLayers.Event.stop(evt);
+        }
+        return true;
+    },
+
+    /**
+     * Method: touchend
+     * Handle touchend events
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean} Let the event propagate.
+     */
+    touchend: function(evt) {
+        if (this.started) {
+            this.started = false;
+            this.pinching = false;
+            this.callback("done", [evt, this.start, this.last]);
+            this.start = null;
+            this.last = null;
+        }
+        return true;
+    },
+
+    /**
+     * Method: activate
+     * Activate the handler.
+     *
+     * Returns:
+     * {Boolean} The handler was successfully activated.
+     */
+    activate: function() {
+        var activated = false;
+        if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+            this.pinching = false;
+            activated = true;
+        }
+        return activated;
+    },
+
+    /**
+     * Method: deactivate
+     * Deactivate the handler.
+     *
+     * Returns:
+     * {Boolean} The handler was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            this.started = false;
+            this.pinching = false;
+            this.start = null;
+            this.last = null;
+            deactivated = true;
+        }
+        return deactivated;
+    },
+
+    /**
+     * Method: getDistance
+     * Get the distance in pixels between two touches.
+     *
+     * Parameters:
+     * touches - {Array(Object)}
+     *
+     * Returns:
+     * {Number} The distance in pixels.
+     */
+    getDistance: function(touches) {
+        var t0 = touches[0];
+        var t1 = touches[1];
+        return Math.sqrt(
+            Math.pow(t0.clientX - t1.clientX, 2) +
+            Math.pow(t0.clientY - t1.clientY, 2)
+        );
+    },
+
+
+    /**
+     * Method: getPinchData
+     * Get informations about the pinch event.
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Object} Object that contains data about the current pinch.
+     */
+    getPinchData: function(evt) {
+        var distance = this.getDistance(evt.touches);
+        var scale = distance / this.start.distance;
+        return {
+            distance: distance,
+            delta: this.last.distance - distance,
+            scale: scale
+        };
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Pinch"
+});
+
+/* ======================================================================
+    OpenLayers/Control/NavToolbar.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/Panel.js
+ * @requires OpenLayers/Control/Navigation.js
+ * @requires OpenLayers/Control/ZoomBox.js
+ */
+
+/**
+ * Class: OpenLayers.Control.NavToolbar
+ * This Toolbar is an alternative to the Navigation control that displays
+ *     the state of the control, and provides a UI for changing state to
+ *     use the zoomBox via a Panel control.
+ *
+ * If you wish to change the properties of the Navigation control used
+ *     in the NavToolbar, see: 
+ *     http://trac.openlayers.org/wiki/Toolbars#SubclassingNavToolbar 
+ * 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control.Panel>
+ */
+OpenLayers.Control.NavToolbar = OpenLayers.Class(OpenLayers.Control.Panel, {
+
+    /**
+     * Constructor: OpenLayers.Control.NavToolbar 
+     * Add our two mousedefaults controls.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
+        this.addControls([
+          new OpenLayers.Control.Navigation(),
+          new OpenLayers.Control.ZoomBox()
+        ]);
+    },
+
+    /**
+     * Method: draw 
+     * calls the default draw, and then activates mouse defaults.
+     */
+    draw: function() {
+        var div = OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);
+        if (this.defaultControl === null) {
+            this.defaultControl = this.controls[0];
+        }
+        return div;
+    },
+
+    CLASS_NAME: "OpenLayers.Control.NavToolbar"
+});
+/* ======================================================================
+    OpenLayers/Tile/WFS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+ 
+/**
+ * @requires OpenLayers/Tile.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ */
+
+/**
+ * Class: OpenLayers.Tile.WFS
+ * Instances of OpenLayers.Tile.WFS are used to manage the image tiles
+ * used by various layers.  Create a new image tile with the
+ * <OpenLayers.Tile.WFS> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Tile>
+ */
+OpenLayers.Tile.WFS = OpenLayers.Class(OpenLayers.Tile, {
+
+    /** 
+     * Property: features 
+     * {Array(<OpenLayers.Feature>)} list of features in this tile 
+     */
+    features: null,
+
+    /** 
+     * Property: url 
+     * {String} 
+     */
+    url: null,
+    
+    /** 
+     * Property: request 
+     * {<OpenLayers.Request.XMLHttpRequest>} 
+     */ 
+    request: null,     
+    
+    /** TBD 3.0 - reorder the parameters to the init function to put URL 
+     *             as last, so we can continue to call tile.initialize() 
+     *             without changing the arguments. 
+     * 
+     * Constructor: OpenLayers.Tile.WFS
+     * Constructor for a new <OpenLayers.Tile.WFS> instance.
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} layer that the tile will go in.
+     * position - {<OpenLayers.Pixel>}
+     * bounds - {<OpenLayers.Bounds>}
+     * url - {<String>}
+     * size - {<OpenLayers.Size>}
+     */   
+    initialize: function(layer, position, bounds, url, size) {
+        OpenLayers.Tile.prototype.initialize.apply(this, arguments);
+        this.url = url;        
+        this.features = [];
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        OpenLayers.Tile.prototype.destroy.apply(this, arguments);
+        this.destroyAllFeatures();
+        this.features = null;
+        this.url = null;
+        if(this.request) {
+            this.request.abort();
+            //this.request.destroy();
+            this.request = null;
+        }
+    },
+
+    /** 
+     * Method: clear
+     *  Clear the tile of any bounds/position-related data so that it can 
+     *   be reused in a new location.
+     */
+    clear: function() {
+        this.destroyAllFeatures();
+    },
+    
+    /**
+     * Method: draw
+     * Check that a tile should be drawn, and load features for it.
+     */
+    draw:function() {
+        if (OpenLayers.Tile.prototype.draw.apply(this, arguments)) {
+            if (this.isLoading) {
+                //if already loading, send 'reload' instead of 'loadstart'.
+                this.events.triggerEvent("reload"); 
+            } else {
+                this.isLoading = true;
+                this.events.triggerEvent("loadstart");
+            }
+            this.loadFeaturesForRegion(this.requestSuccess);
+        }
+    },
+
+    /** 
+    * Method: loadFeaturesForRegion
+    * Abort any pending requests and issue another request for data. 
+    *
+    * Input are function pointers for what to do on success and failure.
+    *
+    * Parameters:
+    * success - {function}
+    * failure - {function}
+    */
+    loadFeaturesForRegion:function(success, failure) {
+        if(this.request) {
+            this.request.abort();
+        }
+        this.request = OpenLayers.Request.GET({
+            url: this.url,
+            success: success,
+            failure: failure,
+            scope: this
+        });
+    },
+    
+    /**
+    * Method: requestSuccess
+    * Called on return from request succcess. Adds results via 
+    * layer.addFeatures in vector mode, addResults otherwise. 
+    *
+    * Parameters:
+    * request - {<OpenLayers.Request.XMLHttpRequest>}
+    */
+    requestSuccess:function(request) {
+        if (this.features) {
+            var doc = request.responseXML;
+            if (!doc || !doc.documentElement) {
+                doc = request.responseText; 
+            }
+            if (this.layer.vectorMode) {
+                this.layer.addFeatures(this.layer.formatObject.read(doc));
+            } else {
+                var xml = new OpenLayers.Format.XML();
+                if (typeof doc == "string") {
+                    doc = xml.read(doc);
+                }
+                var resultFeatures = xml.getElementsByTagNameNS(
+                    doc, "http://www.opengis.net/gml", "featureMember"
+                );
+                this.addResults(resultFeatures);
+            }
+        }
+        if (this.events) {
+            this.events.triggerEvent("loadend"); 
+        }
+
+        //request produced with success, we can delete the request object.
+        //this.request.destroy();
+        this.request = null;
+    },
+
+    /**
+     * Method: addResults
+     * Construct new feature via layer featureClass constructor, and add to
+     * this.features.
+     * 
+     * Parameters:
+     * results - {Object}
+     */
+    addResults: function(results) {
+        for (var i=0; i < results.length; i++) {
+            var feature = new this.layer.featureClass(this.layer, 
+                                                      results[i]);
+            this.features.push(feature);
+        }
+    },
+
+
+    /** 
+     * Method: destroyAllFeatures
+     * Iterate through and call destroy() on each feature, removing it from
+     *   the local array
+     */
+    destroyAllFeatures: function() {
+        while(this.features.length > 0) {
+            var feature = this.features.shift();
+            feature.destroy();
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Tile.WFS"
+  }
+);
+/* ======================================================================
+    OpenLayers/Control/Geolocate.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Geolocate
+ * The Geolocate control wraps w3c geolocation API into control that can be
+ * bound to a map, and generate events on location update
+ *
+ * To use this control requires to load the proj4js library if the projection
+ * of the map is not EPSG:4326 or EPSG:900913.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Geolocate = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * Supported event types:
+     *  - *locationupdated* Triggered when browser return a new position
+     *  - *locationfailed* Triggered when geolocation has failed
+     *  - *locationuncapable* Triggered when control is activated on a browser
+     *  which doesn't support geolocation
+     */
+    EVENT_TYPES: ["locationupdated", "locationfailed", "locationuncapable"],
+
+    /**
+     * Property: geolocation
+     * {Object} The geolocation engine, as a property to be possibly mocked.
+     */
+    geolocation: navigator.geolocation,
+
+    /**
+     * APIProperty: bind
+     * {Boolean} If true, map center will be set on location update.
+     */
+    bind: true,
+
+    /**
+     * APIProperty: watch
+     * {Boolean} If true, position will be update regularly.
+     */
+    watch: false,
+
+    /**
+     * APIProperty: geolocationOptions
+     * {Object} Options to pass to the navigator's geolocation API. See
+     *     <http://dev.w3.org/geo/api/spec-source.html>. No specific
+     *     option is passed to the geolocation API by default.
+     */
+    geolocationOptions: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Geolocate
+     * Create a new control to deal with browser geolocation API
+     *
+     */
+    initialize: function(options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.Geolocate.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        this.geolocationOptions = {};
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+        this.deactivate();
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: activate
+     * Activates the control.
+     *
+     * Returns:
+     * {Boolean} The control was effectively activated.
+     */
+    activate: function () {
+        if (!this.geolocation) {
+            this.events.triggerEvent("locationuncapable");
+            return false;
+        }
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            if (this.watch) {
+                this.watchId = this.geolocation.watchPosition(
+                    OpenLayers.Function.bind(this.geolocate, this),
+                    OpenLayers.Function.bind(this.failure, this),
+                    this.geolocationOptions
+                );
+            } else {
+                this.getCurrentLocation();
+            }
+            return true;
+        }
+        return false;
+    },
+
+    /**
+     * Method: deactivate
+     * Deactivates the control.
+     *
+     * Returns:
+     * {Boolean} The control was effectively deactivated.
+     */
+    deactivate: function () {
+        if (this.active && this.watchId !== null) {
+            this.geolocation.clearWatch(this.watchId);
+        }
+        return OpenLayers.Control.prototype.deactivate.apply(
+            this, arguments
+        );
+    },
+
+    /**
+     * Method: geolocate
+     * Activates the control.
+     *
+     */
+    geolocate: function (position) {
+        var center = new OpenLayers.LonLat(
+            position.coords.longitude,
+            position.coords.latitude
+        ).transform(
+            new OpenLayers.Projection("EPSG:4326"),
+            this.map.getProjectionObject()
+        );
+        if (this.bind) {
+            this.map.setCenter(center);
+        }
+        this.events.triggerEvent("locationupdated", {
+            position: position,
+            point: new OpenLayers.Geometry.Point(
+                center.lon, center.lat
+            )
+        });
+    },
+
+    /**
+     * APIMethod: getCurrentLocation
+     *
+     * Returns:
+     * {Boolean} Returns true if a event will be fired (successfull
+     * registration)
+     */
+    getCurrentLocation: function() {
+        if (!this.active || this.watch) {
+            return false;
+        }
+        this.geolocation.getCurrentPosition(
+            OpenLayers.Function.bind(this.geolocate, this),
+            OpenLayers.Function.bind(this.failure, this),
+            this.geolocationOptions
+        );
+        return true;
+    },
+
+    /**
+     * Method: failure
+     * method called on browser's geolocation failure
+     *
+     */
+    failure: function (error) {
+        this.events.triggerEvent("locationfailed", {error: error});
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Geolocate"
+});
+/* ======================================================================
+    OpenLayers/Layer/ArcGIS93Rest.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.ArcGIS93Rest
+ * Instances of OpenLayers.Layer.ArcGIS93Rest are used to display data from
+ *     ESRI ArcGIS Server 9.3 (and up?) Mapping Services using the REST API.
+ *     Create a new ArcGIS93Rest layer with the <OpenLayers.Layer.ArcGIS93Rest>
+ *     constructor.  More detail on the REST API is available at
+ *     http://sampleserver1.arcgisonline.com/ArcGIS/SDK/REST/index.html ;
+ *     specifically, the URL provided to this layer should be an export service
+ *     URL: http://sampleserver1.arcgisonline.com/ArcGIS/SDK/REST/export.html 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.ArcGIS93Rest = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Constant: DEFAULT_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs 
+     */
+    DEFAULT_PARAMS: { 
+      format: "png"
+    },
+        
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} Default is true for ArcGIS93Rest layer
+     */
+    isBaseLayer: true,
+ 
+ 
+    /**
+     * Constructor: OpenLayers.Layer.ArcGIS93Rest
+     * Create a new ArcGIS93Rest layer object.
+     *
+     * Example:
+     * (code)
+     * var arcims = new OpenLayers.Layer.ArcGIS93Rest("MyName",
+     *                                    "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/export", 
+     *                                    {
+     *                                      layers: "0,1,2"
+     *                                    });
+     * (end)
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the ArcGIS server REST service
+     * options - {Object} An object with key/value pairs representing the
+     *                    options and option values.
+     * Valid Options:
+     *        format: {String} MIME type of desired image type.
+     *        layers: {String} Comma-separated list of layers to display.
+     *        srs: {String} Projection ID.
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        //uppercase params
+        params = OpenLayers.Util.upperCaseObject(params);
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+        OpenLayers.Util.applyDefaults(
+                       this.params, 
+                       OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
+                       );
+                       
+        //layer is transparent        
+        if (this.params.TRANSPARENT && 
+            this.params.TRANSPARENT.toString().toLowerCase() == "true") {
+            
+            // unless explicitly set in options, make layer an overlay
+            if ( (options == null) || (!options.isBaseLayer) ) {
+                this.isBaseLayer = false;
+            } 
+            
+            // jpegs can never be transparent, so intelligently switch the 
+            //  format, depending on the browser's capabilities
+            if (this.params.FORMAT == "jpg") {
+                this.params.FORMAT = OpenLayers.Util.alphaHack() ? "gif"
+                                                                 : "png";
+            }
+        }
+    },    
+
+    
+    /**
+     * Method: destroy
+     * Destroy this layer
+     */
+    destroy: function() {
+        // for now, nothing special to do here. 
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);  
+    },   
+    
+    /**
+         * Method: clone
+         * Create a clone of this layer
+         *
+         * Returns:
+         * {<OpenLayers.Layer.ArcGIS93Rest>} An exact clone of this layer
+         */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.ArcGIS93Rest(this.name,
+                                           this.url,
+                                           this.params,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+    
+    
+    /**
+     * Method: getURL
+     * Return an image url this layer.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
+     *                                request.
+     *
+     * Returns:
+     * {String} A string with the map image's url.
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+
+        // ArcGIS Server only wants the numeric portion of the projection ID.
+        var projWords = this.projection.getCode().split(":");
+        var srid = projWords[projWords.length - 1];
+
+        var imageSize = this.getImageSize(); 
+        var newParams = {
+            'BBOX': bounds.toBBOX(),
+            'SIZE': imageSize.w + "," + imageSize.h,
+            // We always want image, the other options were json, image with a whole lotta html around it, etc.
+            'F': "image",
+            'BBOXSR': srid,
+            'IMAGESR': srid
+        };
+
+        // Now add the filter parameters.
+        if (this.layerDefs) {
+            var layerDefStrList = [];
+            var layerID;
+            for(layerID in this.layerDefs) {
+                if (this.layerDefs.hasOwnProperty(layerID)) {
+                    if (this.layerDefs[layerID]) {
+                        layerDefStrList.push(layerID);
+                        layerDefStrList.push(":");
+                        layerDefStrList.push(this.layerDefs[layerID]);
+                        layerDefStrList.push(";");
+                    }
+                }
+            }
+            if (layerDefStrList.length > 0) {
+                newParams['LAYERDEFS'] = layerDefStrList.join("");
+            }
+        }
+        var requestString = this.getFullRequestString(newParams);
+        return requestString;
+    },
+    
+    /**
+     * Method: setLayerFilter
+     * addTile creates a tile, initializes it, and adds it to the layer div. 
+     *
+     * Parameters:
+     * id - {String} The id of the layer to which the filter applies.
+     * queryDef - {String} A sql-ish query filter, for more detail see the ESRI
+     *                     documentation at http://sampleserver1.arcgisonline.com/ArcGIS/SDK/REST/export.html
+     */
+    setLayerFilter: function ( id, queryDef ) {
+        if (!this.layerDefs) {
+            this.layerDefs = {};
+        }
+        if (queryDef) {
+            this.layerDefs[id] = queryDef;
+        } else {
+            delete this.layerDefs[id];
+        }
+    },
+    
+    /**
+     * Method: clearLayerFilter
+     * Clears layer filters, either from a specific layer,
+     * or all of them.
+     *
+     * Parameters:
+     * id - {String} The id of the layer from which to remove any
+     *               filter.  If unspecified/blank, all filters
+     *               will be removed.
+     */
+    clearLayerFilter: function ( id ) {
+        if (id) {
+            delete this.layerDefs[id];
+        } else {
+            delete this.layerDefs;
+        }
+    },
+    
+    /**
+     * APIMethod: mergeNewParams
+     * Catch changeParams and uppercase the new params to be merged in
+     *     before calling changeParams on the super class.
+     * 
+     *     Once params have been changed, the tiles will be reloaded with
+     *     the new parameters.
+     * 
+     * Parameters:
+     * newParams - {Object} Hashtable of new params to use
+     */
+    mergeNewParams:function(newParams) {
+        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
+        var newArguments = [upperParams];
+        return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this, 
+                                                             newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.ArcGIS93Rest"
+});
+/* ======================================================================
+    OpenLayers/Layer/MapServer.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.MapServer
+ * Instances of OpenLayers.Layer.MapServer are used to display
+ * data from a MapServer CGI instance.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.MapServer = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Constant: DEFAULT_PARAMS
+     * {Object} Hashtable of default parameter key/value pairs 
+     */
+    DEFAULT_PARAMS: {
+        mode: "map",
+        map_imagetype: "png"
+    },
+
+    /**
+     * Constructor: OpenLayers.Layer.MapServer
+     * Create a new MapServer layer object
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the MapServer CGI
+     *       (e.g. http://www2.dmsolutions.ca/cgi-bin/mapserv)
+     * params - {Object} An object with key/value pairs representing the
+     *          GetMap query string parameters and parameter values.
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+
+        this.params = OpenLayers.Util.applyDefaults(
+            this.params, this.DEFAULT_PARAMS
+        );
+
+        // unless explicitly set in options, if the layer is transparent, 
+        // it will be an overlay
+        if (options == null || options.isBaseLayer == null) {
+            this.isBaseLayer = ((this.params.transparent != "true") && 
+                                (this.params.transparent != true));
+        }
+    },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.MapServer>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Layer.MapServer(this.name,
+                                           this.url,
+                                           this.params,
+                                           this.getOptions());
+        }
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+    
+    /**
+     * Method: getURL
+     * Return a query string for this layer
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox 
+     *                                for the request
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also 
+     *          the passed-in bounds and appropriate tile size specified 
+     *          as parameters.
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        // Make a list, so that getFullRequestString uses literal "," 
+        var extent = [bounds.left, bounds. bottom, bounds.right, bounds.top];
+
+        var imageSize = this.getImageSize(); 
+        
+        // make lists, so that literal ','s are used 
+        var url = this.getFullRequestString(
+                     {mapext:   extent,
+                      imgext:   extent,
+                      map_size: [imageSize.w, imageSize.h],
+                      imgx:     imageSize.w / 2,
+                      imgy:     imageSize.h / 2,
+                      imgxy:    [imageSize.w, imageSize.h]
+                      });
+        
+        return url;
+    },
+    
+    /** 
+     * Method: getFullRequestString
+     * combine the layer's url with its params and these newParams. 
+     *   
+     * Parameter:
+     * newParams - {Object} New parameters that should be added to the 
+     *                      request string.
+     * altUrl - {String} (optional) Replace the URL in the full request  
+     *                              string with the provided URL.
+     * 
+     * Returns: 
+     * {String} A string with the layer's url and parameters embedded in it.
+     */
+    getFullRequestString:function(newParams, altUrl) {
+        // use layer's url unless altUrl passed in
+        var url = (altUrl == null) ? this.url : altUrl;
+        
+        // create a new params hashtable with all the layer params and the 
+        // new params together. then convert to string
+        var allParams = OpenLayers.Util.extend({}, this.params);
+        allParams = OpenLayers.Util.extend(allParams, newParams);
+        var paramsString = OpenLayers.Util.getParameterString(allParams);
+        
+        // if url is not a string, it should be an array of strings, 
+        // in which case we will deterministically select one of them in 
+        // order to evenly distribute requests to different urls.
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(paramsString, url);
+        }   
+        
+        // ignore parameters that are already in the url search string
+        var urlParams = OpenLayers.Util.upperCaseObject(
+                            OpenLayers.Util.getParameters(url));
+        for(var key in allParams) {
+            if(key.toUpperCase() in urlParams) {
+                delete allParams[key];
+            }
+        }
+        paramsString = OpenLayers.Util.getParameterString(allParams);
+        
+        // requestString always starts with url
+        var requestString = url;        
+
+        // MapServer needs '+' seperating things like bounds/height/width.
+        //   Since typically this is URL encoded, we use a slight hack: we
+        //  depend on the list-like functionality of getParameterString to
+        //  leave ',' only in the case of list items (since otherwise it is
+        //  encoded) then do a regular expression replace on the , characters
+        //  to '+'
+        //
+        paramsString = paramsString.replace(/,/g, "+");
+        
+        if (paramsString != "") {
+            var lastServerChar = url.charAt(url.length - 1);
+            if ((lastServerChar == "&") || (lastServerChar == "?")) {
+                requestString += paramsString;
+            } else {
+                if (url.indexOf('?') == -1) {
+                    //serverPath has no ? -- add one
+                    requestString += '?' + paramsString;
+                } else {
+                    //serverPath contains ?, so must already have paramsString at the end
+                    requestString += '&' + paramsString;
+                }
+            }
+        }
+        return requestString;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.MapServer"
+});
+/* ======================================================================
+    OpenLayers/Layer/MapServer/Untiled.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+ 
+/**
+ * @requires OpenLayers/Layer/MapServer.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.MapServer.Untiled
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.MapServer
+ *     and pass the option 'singleTile' as true.
+ * 
+ * Inherits from: 
+ *  - <OpenLayers.Layer.MapServer>
+ */
+OpenLayers.Layer.MapServer.Untiled = OpenLayers.Class(OpenLayers.Layer.MapServer, {
+
+    /**
+     * APIProperty: singleTile
+     * {singleTile} Always true for untiled.
+     */
+    singleTile: true,
+
+    /**
+     * Constructor: OpenLayers.Layer.MapServer.Untiled
+     *
+     * Parameters:
+     * name - {String} 
+     * url - {String} 
+     * params - {Object} 
+     * options - {Object} 
+     */
+    initialize: function(name, url, params, options) {
+        OpenLayers.Layer.MapServer.prototype.initialize.apply(this, arguments);
+        
+        var msg = "The OpenLayers.Layer.MapServer.Untiled class is deprecated and " +
+                  "will be removed in 3.0. Instead, you should use the " +
+                  "normal OpenLayers.Layer.MapServer class, passing it the option " +
+                  "'singleTile' as true.";
+        OpenLayers.Console.warn(msg);
+    },    
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.MapServer.Untiled>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.MapServer.Untiled(this.name,
+                                                         this.url,
+                                                         this.params,
+                                                         this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.MapServer.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        
+        return obj;
+    }, 
+
+    CLASS_NAME: "OpenLayers.Layer.MapServer.Untiled"
+});
+/* ======================================================================
+    OpenLayers/Handler/Hover.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Hover
+ * The hover handler is to be used to emulate mouseovers on objects
+ *      on the map that aren't DOM elements. For example one can use
+ *      this handler to send WMS/GetFeatureInfo requests as the user
+ *      moves the mouve over the map.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Handler> 
+ */
+OpenLayers.Handler.Hover = OpenLayers.Class(OpenLayers.Handler, {
+
+    /**
+     * APIProperty: delay
+     * {Integer} - Number of milliseconds between mousemoves before
+     *      the event is considered a hover. Default is 500.
+     */
+    delay: 500,
+    
+    /**
+     * APIProperty: pixelTolerance
+     * {Integer} - Maximum number of pixels between mousemoves for
+     *      an event to be considered a hover. Default is null.
+     */
+    pixelTolerance: null,
+
+    /**
+     * APIProperty: stopMove
+     * {Boolean} - Stop other listeners from being notified on mousemoves.
+     *      Default is false.
+     */
+    stopMove: false,
+
+    /**
+     * Property: px
+     * {<OpenLayers.Pixel>} - The location of the last mousemove, expressed
+     *      in pixels.
+     */
+    px: null,
+
+    /**
+     * Property: timerId
+     * {Number} - The id of the timer.
+     */
+    timerId: null,
+ 
+    /**
+     * Constructor: OpenLayers.Handler.Hover
+     * Construct a hover handler.
+     *
+     * Parameters:
+     * control - {<OpenLayers.Control>} The control that initialized this
+     *     handler.  The control is assumed to have a valid map property; that
+     *     map is used in the handler's own setMap method.
+     * callbacks - {Object} An object with keys corresponding to callbacks
+     *     that will be called by the handler. The callbacks should
+     *     expect to receive a single argument, the event. Callbacks for
+     *     'move', the mouse is moving, and 'pause', the mouse is pausing,
+     *     are supported.
+     * options - {Object} An optional object whose properties will be set on
+     *     the handler.
+     */
+    initialize: function(control, callbacks, options) {
+        OpenLayers.Handler.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * Method: mousemove
+     * Called when the mouse moves on the map.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    mousemove: function(evt) {
+        if(this.passesTolerance(evt.xy)) {
+            this.clearTimer();
+            this.callback('move', [evt]);
+            this.px = evt.xy;
+            // clone the evt so original properties can be accessed even
+            // if the browser deletes them during the delay
+            evt = OpenLayers.Util.extend({}, evt);
+            this.timerId = window.setTimeout(
+                OpenLayers.Function.bind(this.delayedCall, this, evt),
+                this.delay
+            );
+        }
+        return !this.stopMove;
+    },
+
+    /**
+     * Method: mouseout
+     * Called when the mouse goes out of the map.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    mouseout: function(evt) {
+        if (OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) {
+            this.clearTimer();
+            this.callback('move', [evt]);
+        }
+        return true;
+    },
+
+    /**
+     * Method: passesTolerance
+     * Determine whether the mouse move is within the optional pixel tolerance.
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {Boolean} The mouse move is within the pixel tolerance.
+     */
+    passesTolerance: function(px) {
+        var passes = true;
+        if(this.pixelTolerance && this.px) {
+            var dpx = Math.sqrt(
+                Math.pow(this.px.x - px.x, 2) +
+                Math.pow(this.px.y - px.y, 2)
+            );
+            if(dpx < this.pixelTolerance) {
+                passes = false;
+            }
+        }
+        return passes;
+    },
+
+    /**
+     * Method: clearTimer
+     * Clear the timer and set <timerId> to null.
+     */
+    clearTimer: function() {
+        if(this.timerId != null) {
+            window.clearTimeout(this.timerId);
+            this.timerId = null;
+        }
+    },
+
+    /**
+     * Method: delayedCall
+     * Triggers pause callback.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     */
+    delayedCall: function(evt) {
+        this.callback('pause', [evt]);
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the handler.
+     *
+     * Returns:
+     * {Boolean} The handler was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+            this.clearTimer();
+            deactivated = true;
+        }
+        return deactivated;
+    },
+
+    CLASS_NAME: "OpenLayers.Handler.Hover"
+});
+/* ======================================================================
+    OpenLayers/Control/GetFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Handler/Box.js
+ * @requires OpenLayers/Handler/Hover.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Control.GetFeature
+ * Gets vector features for locations underneath the mouse cursor. Can be
+ *     configured to act on click, hover or dragged boxes. Uses an
+ *     <OpenLayers.Protocol> that supports spatial filters to retrieve
+ *     features from a server and fires events that notify applications of the
+ *     selected features. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.GetFeature = OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * APIProperty: protocol
+     * {<OpenLayers.Protocol>} Required. The protocol used for fetching
+     *     features.
+     */
+    protocol: null,
+    
+    /**
+     * APIProperty: multipleKey
+     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+     *     the <multiple> property to true.  Default is null.
+     */
+    multipleKey: null,
+    
+    /**
+     * APIProperty: toggleKey
+     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+     *     the <toggle> property to true.  Default is null.
+     */
+    toggleKey: null,
+    
+    /**
+     * Property: modifiers
+     * {Object} The event modifiers to use, according to the current event
+     *     being handled by this control's handlers
+     */
+    modifiers: null,
+    
+    /**
+     * APIProperty: multiple
+     * {Boolean} Allow selection of multiple geometries.  Default is false.
+     */
+    multiple: false, 
+
+    /**
+     * APIProperty: click
+     * {Boolean} Use a click handler for selecting/unselecting features. If
+     *     both <click> and <box> are set to true, the click handler takes
+     *     precedence over the box handler if a box with zero extent was
+     *     selected.  Default is true.
+     */
+    click: true,
+
+    /**
+     * APIProperty: single
+     * {Boolean} Tells whether select by click should select a single
+     *     feature. If set to false, all matching features are selected.
+     *     If set to true, only the best matching feature is selected.
+     *     This option has an effect only of the <click> option is set
+     *     to true. Default is true.
+     */
+    single: true,
+    
+    /**
+     * APIProperty: clickout
+     * {Boolean} Unselect features when clicking outside any feature.
+     *     Applies only if <click> is true.  Default is true.
+     */
+    clickout: true,
+    
+    /**
+     * APIProperty: toggle
+     * {Boolean} Unselect a selected feature on click.  Applies only if
+     *     <click> is true.  Default is false.
+     */
+    toggle: false,
+
+    /**
+     * APIProperty: clickTolerance
+     * {Integer} Tolerance for the filter query in pixels. This has the
+     *     same effect as the tolerance parameter on WMS GetFeatureInfo
+     *     requests.  Will be ignored for box selections.  Applies only if
+     *     <click> or <hover> is true.  Default is 5.  Note that this not
+     *     only affects requests on click, but also on hover.
+     */
+    clickTolerance: 5,
+    
+    /**
+     * APIProperty: hover
+     * {Boolean} Send feature requests on mouse moves.  Default is false.
+     */
+    hover: false,
+
+    /**
+     * APIProperty: box
+     * {Boolean} Allow feature selection by drawing a box. If set to
+     *     true set <click> to false to disable the click handler and
+     *     rely on the box handler only, even for "zero extent" boxes.
+     *     See the description of the <click> option for additional
+     *     information.  Default is false.
+     */
+    box: false,
+    
+    /**
+     * APIProperty: maxFeatures
+     * {Integer} Maximum number of features to return from a query in single mode
+     *     if supported by the <protocol>. This set of features is then used to
+     *     determine the best match client-side. Default is 10.
+     */
+    maxFeatures: 10,
+    
+    /**
+     * Property: features
+     * {Object} Hash of {<OpenLayers.Feature.Vector>}, keyed by fid, holding
+     *     the currently selected features
+     */
+    features: null,
+    
+    /**
+     * Proeprty: hoverFeature
+     * {<OpenLayers.Feature.Vector>} The feature currently selected by the
+     *     hover handler
+     */
+    hoverFeature: null,
+    
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Additional options for the handlers used by this control. This
+     *     is a hash with the keys "click", "box" and "hover".
+     */
+    handlerOptions: null,
+    
+    /**
+     * Property: handlers
+     * {Object} Object with references to multiple <OpenLayers.Handler>
+     *     instances.
+     */
+    handlers: null,
+
+    /**
+     * Property: hoverResponse
+     * {<OpenLayers.Protocol.Response>} The response object associated with
+     *     the currently running hover request (if any).
+     */
+    hoverResponse: null,
+    
+    /**
+     * Property: filterType
+     * {<String>} The type of filter to use when sending off a request. 
+     *     Possible values: 
+     *     OpenLayers.Filter.Spatial.<BBOX|INTERSECTS|WITHIN|CONTAINS>
+     *     Defaults to: OpenLayers.Filter.Spatial.BBOX
+     */
+    filterType: OpenLayers.Filter.Spatial.BBOX,
+
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     * beforefeatureselected - Triggered when <click> is true before a
+     *      feature is selected. The event object has a feature property with
+     *      the feature about to select
+     * featureselected - Triggered when <click> is true and a feature is
+     *      selected. The event object has a feature property with the
+     *      selected feature
+     * beforefeaturesselected - Triggered when <click> is true before a
+     *      set of features is selected. The event object is an array of
+     *      feature properties with the features about to be selected.  
+     *      Return false after receiving this event to discontinue processing
+     *      of all featureselected events and the featuresselected event.
+     * featuresselected - Triggered when <click> is true and a set of
+     *      features is selected.  The event object is an array of feature
+     *      properties of the selected features
+     * featureunselected - Triggered when <click> is true and a feature is
+     *      unselected. The event object has a feature property with the
+     *      unselected feature
+     * clickout - Triggered when when <click> is true and no feature was
+     *      selected.
+     * hoverfeature - Triggered when <hover> is true and the mouse has
+     *      stopped over a feature
+     * outfeature - Triggered when <hover> is true and the mouse moves
+     *      moved away from a hover-selected feature
+     */
+    EVENT_TYPES: ["featureselected", "featuresselected", "featureunselected", 
+        "clickout", "beforefeatureselected", "beforefeaturesselected", 
+        "hoverfeature", "outfeature"],
+
+    /**
+     * Constructor: OpenLayers.Control.GetFeature
+     * Create a new control for fetching remote features.
+     *
+     * Parameters:
+     * options - {Object} A configuration object which at least has to contain
+     *     a <protocol> property (if not, it has to be set before a request is
+     *     made)
+     */
+    initialize: function(options) {
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+
+        options.handlerOptions = options.handlerOptions || {};
+
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        this.features = {};
+
+        this.handlers = {};
+        
+        if(this.click) {
+            this.handlers.click = new OpenLayers.Handler.Click(this,
+                {click: this.selectClick}, this.handlerOptions.click || {});
+        }
+
+        if(this.box) {
+            this.handlers.box = new OpenLayers.Handler.Box(
+                this, {done: this.selectBox},
+                OpenLayers.Util.extend(this.handlerOptions.box, {
+                    boxDivClassName: "olHandlerBoxSelectFeature"
+                })
+            ); 
+        }
+        
+        if(this.hover) {
+            this.handlers.hover = new OpenLayers.Handler.Hover(
+                this, {'move': this.cancelHover, 'pause': this.selectHover},
+                OpenLayers.Util.extend(this.handlerOptions.hover, {
+                    'delay': 250
+                })
+            );
+        }
+    },
+    
+    /**
+     * Method: activate
+     * Activates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively activated.
+     */
+    activate: function () {
+        if (!this.active) {
+            for(var i in this.handlers) {
+                this.handlers[i].activate();
+            }
+        }
+        return OpenLayers.Control.prototype.activate.apply(
+            this, arguments
+        );
+    },
+
+    /**
+     * Method: deactivate
+     * Deactivates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively deactivated.
+     */
+    deactivate: function () {
+        if (this.active) {
+            for(var i in this.handlers) {
+                this.handlers[i].deactivate();
+            }
+        }
+        return OpenLayers.Control.prototype.deactivate.apply(
+            this, arguments
+        );
+    },
+    
+    /**
+     * Method: selectClick
+     * Called on click
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    selectClick: function(evt) {
+        var bounds = this.pixelToBounds(evt.xy);
+        
+        this.setModifiers(evt);
+        this.request(bounds, {single: this.single});
+    },
+
+    /**
+     * Method: selectBox
+     * Callback from the handlers.box set up when <box> selection is on
+     *
+     * Parameters:
+     * position - {<OpenLayers.Bounds>}  
+     */
+    selectBox: function(position) {
+        var bounds;
+        if (position instanceof OpenLayers.Bounds) {
+            var minXY = this.map.getLonLatFromPixel(
+                new OpenLayers.Pixel(position.left, position.bottom)
+            );
+            var maxXY = this.map.getLonLatFromPixel(
+                new OpenLayers.Pixel(position.right, position.top)
+            );
+            bounds = new OpenLayers.Bounds(
+                minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
+            );
+            
+        } else {
+            if(this.click) {
+                // box without extent - let the click handler take care of it
+                return;
+            }
+            bounds = this.pixelToBounds(position);
+        }
+        this.setModifiers(this.handlers.box.dragHandler.evt);
+        this.request(bounds);
+    },
+    
+    /**
+     * Method selectHover
+     * Callback from the handlers.hover set up when <hover> selection is on
+     *
+     * Parameters:
+     * evt {Object} - event object with an xy property
+     */
+    selectHover: function(evt) {
+        var bounds = this.pixelToBounds(evt.xy);
+        this.request(bounds, {single: true, hover: true});
+    },
+
+    /**
+     * Method: cancelHover
+     * Callback from the handlers.hover set up when <hover> selection is on
+     */
+    cancelHover: function() {
+        if (this.hoverResponse) {
+            this.protocol.abort(this.hoverResponse);
+            this.hoverResponse = null;
+
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+        }
+    },
+
+    /**
+     * Method: request
+     * Sends a GetFeature request to the WFS
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} bounds for the request's BBOX filter
+     * options - {Object} additional options for this method.
+     * 
+     * Supported options include:
+     * single - {Boolean} A single feature should be returned.
+     *     Note that this will be ignored if the protocol does not
+     *     return the geometries of the features.
+     * hover - {Boolean} Do the request for the hover handler.
+     */
+    request: function(bounds, options) {
+        options = options || {};
+        var filter = new OpenLayers.Filter.Spatial({
+            type: this.filterType, 
+            value: bounds
+        });
+        
+        // Set the cursor to "wait" to tell the user we're working.
+        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+
+        var response = this.protocol.read({
+            maxFeatures: options.single == true ? this.maxFeatures : undefined,
+            filter: filter,
+            callback: function(result) {
+                if(result.success()) {
+                    if(result.features.length) {
+                        if(options.single == true) {
+                            this.selectBestFeature(result.features,
+                                bounds.getCenterLonLat(), options);
+                        } else {
+                            this.select(result.features);
+                        }
+                    } else if(options.hover) {
+                        this.hoverSelect();
+                    } else {
+                        this.events.triggerEvent("clickout");
+                        if(this.clickout) {
+                            this.unselectAll();
+                        }
+                    }
+                }
+                // Reset the cursor.
+                OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+            },
+            scope: this
+        });
+        if(options.hover == true) {
+            this.hoverResponse = response;
+        }
+    },
+
+    /**
+     * Method: selectBestFeature
+     * Selects the feature from an array of features that is the best match
+     *     for the click position.
+     * 
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)}
+     * clickPosition - {<OpenLayers.LonLat>}
+     * options - {Object} additional options for this method
+     * 
+     * Supported options include:
+     * hover - {Boolean} Do the selection for the hover handler.
+     */
+    selectBestFeature: function(features, clickPosition, options) {
+        options = options || {};
+        if(features.length) {
+            var point = new OpenLayers.Geometry.Point(clickPosition.lon,
+                clickPosition.lat);
+            var feature, resultFeature, dist;
+            var minDist = Number.MAX_VALUE;
+            for(var i=0; i<features.length; ++i) {
+                feature = features[i];
+                if(feature.geometry) {
+                    dist = point.distanceTo(feature.geometry, {edge: false});
+                    if(dist < minDist) {
+                        minDist = dist;
+                        resultFeature = feature;
+                        if(minDist == 0) {
+                            break;
+                        }
+                    }
+                }
+            }
+            
+            if(options.hover == true) {
+                this.hoverSelect(resultFeature);
+            } else {
+                this.select(resultFeature || features);
+            } 
+        }
+    },
+    
+    /**
+     * Method: setModifiers
+     * Sets the multiple and toggle modifiers according to the current event
+     * 
+     * Parameters:
+     * evt {<OpenLayers.Event>}
+     */
+    setModifiers: function(evt) {
+        this.modifiers = {
+            multiple: this.multiple || (this.multipleKey && evt[this.multipleKey]),
+            toggle: this.toggle || (this.toggleKey && evt[this.toggleKey])
+        };        
+    },
+
+    /**
+     * Method: select
+     * Add feature to the hash of selected features and trigger the
+     * featureselected and featuresselected events.
+     * 
+     * Parameters:
+     * features - {<OpenLayers.Feature.Vector>} or an array of features
+     */
+    select: function(features) {
+        if(!this.modifiers.multiple && !this.modifiers.toggle) {
+            this.unselectAll();
+        }
+        if(!(OpenLayers.Util.isArray(features))) {
+            features = [features];
+        }
+        
+        var cont = this.events.triggerEvent("beforefeaturesselected", {
+            features: features
+        });
+        if(cont !== false) {
+            var selectedFeatures = [];
+            var feature;
+            for(var i=0, len=features.length; i<len; ++i) {
+                feature = features[i];
+                if(this.features[feature.fid || feature.id]) {
+                    if(this.modifiers.toggle) {
+                        this.unselect(this.features[feature.fid || feature.id]);
+                    }
+                } else {
+                    cont = this.events.triggerEvent("beforefeatureselected", {
+                        feature: feature
+                    });
+                    if(cont !== false) {
+                        this.features[feature.fid || feature.id] = feature;
+                        selectedFeatures.push(feature);
+                
+                        this.events.triggerEvent("featureselected",
+                            {feature: feature});
+                    }
+                }
+            }
+            this.events.triggerEvent("featuresselected", {
+                features: selectedFeatures
+            });
+        }
+    },
+    
+    /**
+     * Method: hoverSelect
+     * Sets/unsets the <hoverFeature>
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} the feature to hover-select.
+     *     If none is provided, the current <hoverFeature> will be nulled and
+     *     the outfeature event will be triggered.
+     */
+    hoverSelect: function(feature) {
+        var fid = feature ? feature.fid || feature.id : null;
+        var hfid = this.hoverFeature ?
+            this.hoverFeature.fid || this.hoverFeature.id : null;
+            
+        if(hfid && hfid != fid) {
+            this.events.triggerEvent("outfeature",
+                {feature: this.hoverFeature});
+            this.hoverFeature = null;
+        }
+        if(fid && fid != hfid) {
+            this.events.triggerEvent("hoverfeature", {feature: feature});
+            this.hoverFeature = feature;
+        }
+    },
+
+    /**
+     * Method: unselect
+     * Remove feature from the hash of selected features and trigger the
+     * featureunselected event.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     */
+    unselect: function(feature) {
+        delete this.features[feature.fid || feature.id];
+        this.events.triggerEvent("featureunselected", {feature: feature});
+    },
+    
+    /**
+     * Method: unselectAll
+     * Unselect all selected features.
+     */
+    unselectAll: function() {
+        // we'll want an option to supress notification here
+        for(var fid in this.features) {
+            this.unselect(this.features[fid]);
+        }
+    },
+    
+    /** 
+     * Method: setMap
+     * Set the map property for the control. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        for(var i in this.handlers) {
+            this.handlers[i].setMap(map);
+        }
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+    
+    /**
+     * Method: pixelToBounds
+     * Takes a pixel as argument and creates bounds after adding the
+     * <clickTolerance>.
+     * 
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>}
+     */
+    pixelToBounds: function(pixel) {
+        var llPx = pixel.add(-this.clickTolerance/2, this.clickTolerance/2);
+        var urPx = pixel.add(this.clickTolerance/2, -this.clickTolerance/2);
+        var ll = this.map.getLonLatFromPixel(llPx);
+        var ur = this.map.getLonLatFromPixel(urPx);
+        return new OpenLayers.Bounds(ll.lon, ll.lat, ur.lon, ur.lat);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.GetFeature"
+});
+/* ======================================================================
+    OpenLayers/Format/QueryStringFilter.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Filter/Comparison.js
+ */
+
+/**
+ * Class: OpenLayers.Format.QueryStringFilter
+ * Parser for reading a query string and creating a simple filter.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.QueryStringFilter = (function() {
+
+    /** 
+     * Map the OpenLayers.Filter.Comparison types to the operation strings of 
+     * the protocol.
+     */
+    var cmpToStr = {};
+    cmpToStr[OpenLayers.Filter.Comparison.EQUAL_TO] = "eq";
+    cmpToStr[OpenLayers.Filter.Comparison.NOT_EQUAL_TO] = "ne";
+    cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN] = "lt";
+    cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO] = "lte";
+    cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN] = "gt";
+    cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO] = "gte";
+    cmpToStr[OpenLayers.Filter.Comparison.LIKE] = "ilike";
+
+    /**
+     * Function: regex2value
+     * Convert the value from a regular expression string to a LIKE/ILIKE
+     * string known to the web service.
+     *
+     * Parameters:
+     * value - {String} The regex string.
+     *
+     * Returns:
+     * {String} The converted string.
+     */
+    function regex2value(value) {
+
+        // highly sensitive!! Do not change this without running the
+        // Protocol/HTTP.html unit tests
+
+        // convert % to \%
+        value = value.replace(/%/g, "\\%");
+
+        // convert \\. to \\_ (\\.* occurences converted later)
+        value = value.replace(/\\\\\.(\*)?/g, function($0, $1) {
+            return $1 ? $0 : "\\\\_";
+        });
+
+        // convert \\.* to \\%
+        value = value.replace(/\\\\\.\*/g, "\\\\%");
+
+        // convert . to _ (\. and .* occurences converted later)
+        value = value.replace(/(\\)?\.(\*)?/g, function($0, $1, $2) {
+            return $1 || $2 ? $0 : "_";
+        });
+
+        // convert .* to % (\.* occurnces converted later)
+        value = value.replace(/(\\)?\.\*/g, function($0, $1) {
+            return $1 ? $0 : "%";
+        });
+
+        // convert \. to .
+        value = value.replace(/\\\./g, ".");
+
+        // replace \* with * (watching out for \\*)
+        value = value.replace(/(\\)?\\\*/g, function($0, $1) {
+            return $1 ? $0 : "*";
+        });
+
+        return value;
+    }
+    
+    return OpenLayers.Class(OpenLayers.Format, {
+        
+        /**
+         * Property: wildcarded.
+         * {Boolean} If true percent signs are added around values
+         *     read from LIKE filters, for example if the protocol
+         *     read method is passed a LIKE filter whose property
+         *     is "foo" and whose value is "bar" the string
+         *     "foo__ilike=%bar%" will be sent in the query string;
+         *     defaults to false.
+         */
+        wildcarded: false,
+
+        /**
+         * APIProperty: srsInBBOX
+         * {Boolean} Include the SRS identifier in BBOX query string parameter.  
+         *     Default is false.  If true and the layer has a projection object set,
+         *     any BBOX filter will be serialized with a fifth item identifying the
+         *     projection.  E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
+         */
+        srsInBBOX: false,
+
+        /**
+         * APIMethod: write
+         * Serialize an <OpenLayers.Filter> objects using the "simple" filter syntax for 
+         *     query string parameters.  This function must be called as a method of
+         *     a protocol instance.
+         *
+         * Parameters:
+         * filter - {<OpenLayers.Filter>} filter to convert.
+         * params - {Object} The parameters object.
+         *
+         * Returns:
+         * {Object} The resulting parameters object.
+         */
+        write: function(filter, params) {
+            params = params || {};
+            var className = filter.CLASS_NAME;
+            var filterType = className.substring(className.lastIndexOf(".") + 1);
+            switch (filterType) {
+                case "Spatial":
+                    switch (filter.type) {
+                        case OpenLayers.Filter.Spatial.BBOX:
+                            params.bbox = filter.value.toArray();
+                            if (this.srsInBBOX && filter.projection) {
+                                params.bbox.push(filter.projection.getCode());
+                            }
+                            break;
+                        case OpenLayers.Filter.Spatial.DWITHIN:
+                            params.tolerance = filter.distance;
+                            // no break here
+                        case OpenLayers.Filter.Spatial.WITHIN:
+                            params.lon = filter.value.x;
+                            params.lat = filter.value.y;
+                            break;
+                        default:
+                            OpenLayers.Console.warn(
+                                "Unknown spatial filter type " + filter.type);
+                    }
+                    break;
+                case "Comparison":
+                    var op = cmpToStr[filter.type];
+                    if (op !== undefined) {
+                        var value = filter.value;
+                        if (filter.type == OpenLayers.Filter.Comparison.LIKE) {
+                            value = regex2value(value);
+                            if (this.wildcarded) {
+                                value = "%" + value + "%";
+                            }
+                        }
+                        params[filter.property + "__" + op] = value;
+                        params.queryable = params.queryable || [];
+                        params.queryable.push(filter.property);
+                    } else {
+                        OpenLayers.Console.warn(
+                            "Unknown comparison filter type " + filter.type);
+                    }
+                    break;
+                case "Logical":
+                    if (filter.type === OpenLayers.Filter.Logical.AND) {
+                        for (var i=0,len=filter.filters.length; i<len; i++) {
+                            params = this.write(filter.filters[i], params);
+                        }
+                    } else {
+                        OpenLayers.Console.warn(
+                            "Unsupported logical filter type " + filter.type);
+                    }
+                    break;
+                default:
+                    OpenLayers.Console.warn("Unknown filter type " + filterType);
+            }
+            return params;
+        },
+        
+        CLASS_NAME: "OpenLayers.Format.QueryStringFilter"
+        
+    });
+
+
+})();
+/* ======================================================================
+    OpenLayers/Control/MousePosition.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.MousePosition
+ * The MousePosition control displays geographic coordinates of the mouse
+ * pointer, as it is moved about the map.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.MousePosition = OpenLayers.Class(OpenLayers.Control, {
+    
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /** 
+     * Property: element
+     * {DOMElement} 
+     */
+    element: null,
+    
+    /** 
+     * APIProperty: prefix
+     * {String}
+     */
+    prefix: '',
+    
+    /** 
+     * APIProperty: separator
+     * {String}
+     */
+    separator: ', ',
+    
+    /** 
+     * APIProperty: suffix
+     * {String}
+     */
+    suffix: '',
+    
+    /** 
+     * APIProperty: numDigits
+     * {Integer}
+     */
+    numDigits: 5,
+    
+    /** 
+     * APIProperty: granularity
+     * {Integer} 
+     */
+    granularity: 10,
+
+    /**
+     * APIProperty: emptyString 
+     * {String} Set this to some value to set when the mouse is outside the
+     *     map.
+     */
+    emptyString: null,
+    
+    /** 
+     * Property: lastXy
+     * {<OpenLayers.Pixel>}
+     */
+    lastXy: null,
+
+    /**
+     * APIProperty: displayProjection
+     * {<OpenLayers.Projection>} The projection in which the 
+     * mouse position is displayed
+     */
+    displayProjection: null, 
+    
+    /**
+     * Constructor: OpenLayers.Control.MousePosition
+     * 
+     * Parameters:
+     * options - {Object} Options for control.
+     */
+
+    /**
+     * Method: destroy
+     */
+     destroy: function() {
+         this.deactivate();
+         OpenLayers.Control.prototype.destroy.apply(this, arguments);
+     },
+
+    /**
+     * APIMethod: activate
+     */
+    activate: function() {
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.map.events.register('mousemove', this, this.redraw);
+            this.map.events.register('mouseout', this, this.reset);
+            this.redraw();
+            return true;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.map.events.unregister('mousemove', this, this.redraw);
+            this.map.events.unregister('mouseout', this, this.reset);
+            this.element.innerHTML = "";
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    /**
+     * Method: draw
+     * {DOMElement}
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+
+        if (!this.element) {
+            this.div.left = "";
+            this.div.top = "";
+            this.element = this.div;
+        }
+        
+        return this.div;
+    },
+   
+    /**
+     * Method: redraw  
+     */
+    redraw: function(evt) {
+
+        var lonLat;
+
+        if (evt == null) {
+            this.reset();
+            return;
+        } else {
+            if (this.lastXy == null ||
+                Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
+                Math.abs(evt.xy.y - this.lastXy.y) > this.granularity)
+            {
+                this.lastXy = evt.xy;
+                return;
+            }
+
+            lonLat = this.map.getLonLatFromPixel(evt.xy);
+            if (!lonLat) { 
+                // map has not yet been properly initialized
+                return;
+            }    
+            if (this.displayProjection) {
+                lonLat.transform(this.map.getProjectionObject(), 
+                                 this.displayProjection );
+            }      
+            this.lastXy = evt.xy;
+            
+        }
+        
+        var newHtml = this.formatOutput(lonLat);
+
+        if (newHtml != this.element.innerHTML) {
+            this.element.innerHTML = newHtml;
+        }
+    },
+
+    /**
+     * Method: reset
+     */
+    reset: function(evt) {
+        if (this.emptyString != null) {
+            this.element.innerHTML = this.emptyString;
+        }
+    },
+
+    /**
+     * Method: formatOutput
+     * Override to provide custom display output
+     *
+     * Parameters:
+     * lonLat - {<OpenLayers.LonLat>} Location to display
+     */
+    formatOutput: function(lonLat) {
+        var digits = parseInt(this.numDigits);
+        var newHtml =
+            this.prefix +
+            lonLat.lon.toFixed(digits) +
+            this.separator + 
+            lonLat.lat.toFixed(digits) +
+            this.suffix;
+        return newHtml;
+    },
+
+    CLASS_NAME: "OpenLayers.Control.MousePosition"
+});
+/* ======================================================================
+    OpenLayers/Protocol/HTTP.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Protocol.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ */
+
+/**
+ * TODO: remove this dependency in 3.0
+ * @requires OpenLayers/Format/QueryStringFilter.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.HTTP
+ * A basic HTTP protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.HTTP> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, {
+
+    /**
+     * Property: url
+     * {String} Service URL, read-only, set through the options
+     *     passed to constructor.
+     */
+    url: null,
+
+    /**
+     * Property: headers
+     * {Object} HTTP request headers, read-only, set through the options
+     *     passed to the constructor,
+     *     Example: {'Content-Type': 'plain/text'}
+     */
+    headers: null,
+
+    /**
+     * Property: params
+     * {Object} Parameters of GET requests, read-only, set through the options
+     *     passed to the constructor,
+     *     Example: {'bbox': '5,5,5,5'}
+     */
+    params: null,
+    
+    /**
+     * Property: callback
+     * {Object} Function to be called when the <read>, <create>,
+     *     <update>, <delete> or <commit> operation completes, read-only,
+     *     set through the options passed to the constructor.
+     */
+    callback: null,
+
+    /**
+     * Property: scope
+     * {Object} Callback execution scope, read-only, set through the
+     *     options passed to the constructor.
+     */
+    scope: null,
+
+    /**
+     * Property: readWithPOST
+     * {Boolean} true if read operations are done with POST requests
+     *     instead of GET, defaults to false.
+     */
+    readWithPOST: false,
+
+    /**
+     * Property: wildcarded.
+     * {Boolean} If true percent signs are added around values
+     *     read from LIKE filters, for example if the protocol
+     *     read method is passed a LIKE filter whose property
+     *     is "foo" and whose value is "bar" the string
+     *     "foo__ilike=%bar%" will be sent in the query string;
+     *     defaults to false.
+     */
+    wildcarded: false,
+
+    /**
+     * APIProperty: srsInBBOX
+     * {Boolean} Include the SRS identifier in BBOX query string parameter.  
+     *     Default is false.  If true and the layer has a projection object set,
+     *     any BBOX filter will be serialized with a fifth item identifying the
+     *     projection.  E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
+     */
+    srsInBBOX: false,
+
+    /**
+     * Constructor: OpenLayers.Protocol.HTTP
+     * A class for giving layers generic HTTP protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options include:
+     * url - {String}
+     * headers - {Object} 
+     * params - {Object}
+     * format - {<OpenLayers.Format>}
+     * callback - {Function}
+     * scope - {Object}
+     */
+    initialize: function(options) {
+        options = options || {};
+        this.params = {};
+        this.headers = {};
+        OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
+
+        if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) {
+            var format = new OpenLayers.Format.QueryStringFilter({
+                wildcarded: this.wildcarded,
+                srsInBBOX: this.srsInBBOX
+            });
+            this.filterToParams = function(filter, params) {
+                return format.write(filter, params);
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        this.params = null;
+        this.headers = null;
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: filterToParams
+     * Optional method to translate an <OpenLayers.Filter> object into an object
+     *     that can be serialized as request query string provided.  If a custom
+     *     method is not provided, the filter will be serialized using the 
+     *     <OpenLayers.Protocol.simpleFilterSerializer> method.
+     *
+     * Parameters:
+     * filter - {<OpenLayers.Filter>} filter to convert.
+     * params - {Object} The parameters object.
+     *
+     * Returns:
+     * {Object} The resulting parameters object.
+     */
+    
+    /**
+     * APIMethod: read
+     * Construct a request for reading new features.
+     *
+     * Parameters:
+     * options - {Object} Optional object for configuring the request.
+     *     This object is modified and should not be reused.
+     *
+     * Valid options:
+     * url - {String} Url for the request.
+     * params - {Object} Parameters to get serialized as a query string.
+     * headers - {Object} Headers to be set on the request.
+     * filter - {<OpenLayers.Filter>} Filter to get serialized as a
+     *     query string.
+     * readWithPOST - {Boolean} If the request should be done with POST.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
+     *     references the HTTP request, this object is also passed to the
+     *     callback function when the request completes, its "features" property
+     *     is then populated with the the features received from the server.
+     */
+    read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
+        options = options || {};
+        options.params = OpenLayers.Util.applyDefaults(
+            options.params, this.options.params);
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        if (options.filter && this.filterToParams) {
+            options.params = this.filterToParams(
+                options.filter, options.params
+            );
+        }
+        var readWithPOST = (options.readWithPOST !== undefined) ?
+                           options.readWithPOST : this.readWithPOST;
+        var resp = new OpenLayers.Protocol.Response({requestType: "read"});
+        if(readWithPOST) {
+            resp.priv = OpenLayers.Request.POST({
+                url: options.url,
+                callback: this.createCallback(this.handleRead, resp, options),
+                data: OpenLayers.Util.getParameterString(options.params),
+                headers: {
+                    "Content-Type": "application/x-www-form-urlencoded"
+                }
+            });
+        } else {
+            resp.priv = OpenLayers.Request.GET({
+                url: options.url,
+                callback: this.createCallback(this.handleRead, resp, options),
+                params: options.params,
+                headers: options.headers
+            });
+        }
+        return resp;
+    },
+
+    /**
+     * Method: handleRead
+     * Individual callbacks are created for read, create and update, should
+     *     a subclass need to override each one separately.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     the user callback.
+     * options - {Object} The user options passed to the read call.
+     */
+    handleRead: function(resp, options) {
+        this.handleResponse(resp, options);
+    },
+
+    /**
+     * APIMethod: create
+     * Construct a request for writing newly created features.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})} or
+     *     {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *     This object is modified and should not be reused.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *     object, whose "priv" property references the HTTP request, this 
+     *     object is also passed to the callback function when the request
+     *     completes, its "features" property is then populated with the
+     *     the features received from the server.
+     */
+    create: function(features, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var resp = new OpenLayers.Protocol.Response({
+            reqFeatures: features,
+            requestType: "create"
+        });
+
+        resp.priv = OpenLayers.Request.POST({
+            url: options.url,
+            callback: this.createCallback(this.handleCreate, resp, options),
+            headers: options.headers,
+            data: this.format.write(features)
+        });
+
+        return resp;
+    },
+
+    /**
+     * Method: handleCreate
+     * Called the the request issued by <create> is complete.  May be overridden
+     *     by subclasses.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     any user callback.
+     * options - {Object} The user options passed to the create call.
+     */
+    handleCreate: function(resp, options) {
+        this.handleResponse(resp, options);
+    },
+
+    /**
+     * APIMethod: update
+     * Construct a request updating modified feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *     This object is modified and should not be reused.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *     object, whose "priv" property references the HTTP request, this 
+     *     object is also passed to the callback function when the request
+     *     completes, its "features" property is then populated with the
+     *     the feature received from the server.
+     */
+    update: function(feature, options) {
+        options = options || {};
+        var url = options.url ||
+                  feature.url ||
+                  this.options.url + "/" + feature.fid;
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var resp = new OpenLayers.Protocol.Response({
+            reqFeatures: feature,
+            requestType: "update"
+        });
+
+        resp.priv = OpenLayers.Request.PUT({
+            url: url,
+            callback: this.createCallback(this.handleUpdate, resp, options),
+            headers: options.headers,
+            data: this.format.write(feature)
+        });
+
+        return resp;
+    },
+
+    /**
+     * Method: handleUpdate
+     * Called the the request issued by <update> is complete.  May be overridden
+     *     by subclasses.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     any user callback.
+     * options - {Object} The user options passed to the update call.
+     */
+    handleUpdate: function(resp, options) {
+        this.handleResponse(resp, options);
+    },
+
+    /**
+     * APIMethod: delete
+     * Construct a request deleting a removed feature.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * options - {Object} Optional object for configuring the request.
+     *     This object is modified and should not be reused.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+     *     object, whose "priv" property references the HTTP request, this 
+     *     object is also passed to the callback function when the request
+     *     completes.
+     */
+    "delete": function(feature, options) {
+        options = options || {};
+        var url = options.url ||
+                  feature.url ||
+                  this.options.url + "/" + feature.fid;
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+
+        var resp = new OpenLayers.Protocol.Response({
+            reqFeatures: feature,
+            requestType: "delete"
+        });
+
+        resp.priv = OpenLayers.Request.DELETE({
+            url: url,
+            callback: this.createCallback(this.handleDelete, resp, options),
+            headers: options.headers
+        });
+
+        return resp;
+    },
+
+    /**
+     * Method: handleDelete
+     * Called the the request issued by <delete> is complete.  May be overridden
+     *     by subclasses.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     any user callback.
+     * options - {Object} The user options passed to the delete call.
+     */
+    handleDelete: function(resp, options) {
+        this.handleResponse(resp, options);
+    },
+
+    /**
+     * Method: handleResponse
+     * Called by CRUD specific handlers.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     any user callback.
+     * options - {Object} The user options passed to the create, read, update,
+     *     or delete call.
+     */
+    handleResponse: function(resp, options) {
+        var request = resp.priv;
+        if(options.callback) {
+            if(request.status >= 200 && request.status < 300) {
+                // success
+                if(resp.requestType != "delete") {
+                    resp.features = this.parseFeatures(request);
+                }
+                resp.code = OpenLayers.Protocol.Response.SUCCESS;
+            } else {
+                // failure
+                resp.code = OpenLayers.Protocol.Response.FAILURE;
+            }
+            options.callback.call(options.scope, resp);
+        }
+    },
+
+    /**
+     * Method: parseFeatures
+     * Read HTTP response body and return features.
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     *
+     * Returns:
+     * {Array({<OpenLayers.Feature.Vector>})} or
+     *     {<OpenLayers.Feature.Vector>} Array of features or a single feature.
+     */
+    parseFeatures: function(request) {
+        var doc = request.responseXML;
+        if (!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        if (!doc || doc.length <= 0) {
+            return null;
+        }
+        return this.format.read(doc);
+    },
+
+    /**
+     * APIMethod: commit
+     * Iterate over each feature and take action based on the feature state.
+     *     Possible actions are create, update and delete.
+     *
+     * Parameters:
+     * features - {Array({<OpenLayers.Feature.Vector>})}
+     * options - {Object} Optional object for setting up intermediate commit
+     *     callbacks.
+     *
+     * Valid options:
+     * create - {Object} Optional object to be passed to the <create> method.
+     * update - {Object} Optional object to be passed to the <update> method.
+     * delete - {Object} Optional object to be passed to the <delete> method.
+     * callback - {Function} Optional function to be called when the commit
+     *     is complete.
+     * scope - {Object} Optional object to be set as the scope of the callback.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Protocol.Response>)} An array of response objects,
+     *     one per request made to the server, each object's "priv" property
+     *     references the corresponding HTTP request.
+     */
+    commit: function(features, options) {
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        var resp = [], nResponses = 0;
+        
+        // Divide up features before issuing any requests.  This properly
+        // counts requests in the event that any responses come in before
+        // all requests have been issued.
+        var types = {};
+        types[OpenLayers.State.INSERT] = [];
+        types[OpenLayers.State.UPDATE] = [];
+        types[OpenLayers.State.DELETE] = [];
+        var feature, list, requestFeatures = [];
+        for(var i=0, len=features.length; i<len; ++i) {
+            feature = features[i];
+            list = types[feature.state];
+            if(list) {
+                list.push(feature);
+                requestFeatures.push(feature); 
+            }
+        }
+        // tally up number of requests
+        var nRequests = (types[OpenLayers.State.INSERT].length > 0 ? 1 : 0) +
+            types[OpenLayers.State.UPDATE].length +
+            types[OpenLayers.State.DELETE].length;
+        
+        // This response will be sent to the final callback after all the others
+        // have been fired.
+        var success = true;
+        var finalResponse = new OpenLayers.Protocol.Response({
+            reqFeatures: requestFeatures        
+        });
+        
+        function insertCallback(response) {
+            var len = response.features ? response.features.length : 0;
+            var fids = new Array(len);
+            for(var i=0; i<len; ++i) {
+                fids[i] = response.features[i].fid;
+            }   
+            finalResponse.insertIds = fids;
+            callback.apply(this, [response]);
+        }
+ 
+        function callback(response) {
+            this.callUserCallback(response, options);
+            success = success && response.success();
+            nResponses++;
+            if (nResponses >= nRequests) {
+                if (options.callback) {
+                    finalResponse.code = success ? 
+                        OpenLayers.Protocol.Response.SUCCESS :
+                        OpenLayers.Protocol.Response.FAILURE;
+                    options.callback.apply(options.scope, [finalResponse]);
+                }    
+            }
+        }
+
+        // start issuing requests
+        var queue = types[OpenLayers.State.INSERT];
+        if(queue.length > 0) {
+            resp.push(this.create(
+                queue, OpenLayers.Util.applyDefaults(
+                    {callback: insertCallback, scope: this}, options.create
+                )
+            ));
+        }
+        queue = types[OpenLayers.State.UPDATE];
+        for(var i=queue.length-1; i>=0; --i) {
+            resp.push(this.update(
+                queue[i], OpenLayers.Util.applyDefaults(
+                    {callback: callback, scope: this}, options.update
+                ))
+            );
+        }
+        queue = types[OpenLayers.State.DELETE];
+        for(var i=queue.length-1; i>=0; --i) {
+            resp.push(this["delete"](
+                queue[i], OpenLayers.Util.applyDefaults(
+                    {callback: callback, scope: this}, options["delete"]
+                ))
+            );
+        }
+        return resp;
+    },
+
+    /**
+     * APIMethod: abort
+     * Abort an ongoing request, the response object passed to
+     * this method must come from this HTTP protocol (as a result
+     * of a create, read, update, delete or commit operation).
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>}
+     */
+    abort: function(response) {
+        if (response) {
+            response.priv.abort();
+        }
+    },
+
+    /**
+     * Method: callUserCallback
+     * This method is used from within the commit method each time an
+     *     an HTTP response is received from the server, it is responsible
+     *     for calling the user-supplied callbacks.
+     *
+     * Parameters:
+     * resp - {<OpenLayers.Protocol.Response>}
+     * options - {Object} The map of options passed to the commit call.
+     */
+    callUserCallback: function(resp, options) {
+        var opt = options[resp.requestType];
+        if(opt && opt.callback) {
+            opt.callback.call(opt.scope, resp);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.HTTP" 
+});
+/* ======================================================================
+    OpenLayers/Control/Button.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Button 
+ * The Button control is a very simple push-button, for use with 
+ * <OpenLayers.Control.Panel>.
+ * When clicked, the function trigger() is executed.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ *
+ * Use:
+ * (code)
+ * var button = new OpenLayers.Control.Button({
+ *     displayClass: "MyButton", trigger: myFunction
+ * });
+ * panel.addControls([button]);
+ * (end)
+ * 
+ * Will create a button with CSS class MyButtonItemInactive, that
+ *     will call the function MyFunction() when clicked.
+ */
+OpenLayers.Control.Button = OpenLayers.Class(OpenLayers.Control, {
+    /**
+     * Property: type
+     * {Integer} OpenLayers.Control.TYPE_BUTTON.
+     */
+    type: OpenLayers.Control.TYPE_BUTTON,
+    
+    /**
+     * Method: trigger
+     * Called by a control panel when the button is clicked.
+     */
+    trigger: function() {},
+
+    CLASS_NAME: "OpenLayers.Control.Button"
+});
+/* ======================================================================
+    OpenLayers/Strategy/Cluster.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Cluster
+ * Strategy for vector feature clustering.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Cluster = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * APIProperty: distance
+     * {Integer} Pixel distance between features that should be considered a
+     *     single cluster.  Default is 20 pixels.
+     */
+    distance: 20,
+    
+    /**
+     * APIProperty: threshold
+     * {Integer} Optional threshold below which original features will be
+     *     added to the layer instead of clusters.  For example, a threshold
+     *     of 3 would mean that any time there are 2 or fewer features in
+     *     a cluster, those features will be added directly to the layer instead
+     *     of a cluster representing those features.  Default is null (which is
+     *     equivalent to 1 - meaning that clusters may contain just one feature).
+     */
+    threshold: null,
+    
+    /**
+     * Property: features
+     * {Array(<OpenLayers.Feature.Vector>)} Cached features.
+     */
+    features: null,
+    
+    /**
+     * Property: clusters
+     * {Array(<OpenLayers.Feature.Vector>)} Calculated clusters.
+     */
+    clusters: null,
+    
+    /**
+     * Property: clustering
+     * {Boolean} The strategy is currently clustering features.
+     */
+    clustering: false,
+    
+    /**
+     * Property: resolution
+     * {Float} The resolution (map units per pixel) of the current cluster set.
+     */
+    resolution: null,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Cluster
+     * Create a new clustering strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    
+    /**
+     * APIMethod: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            this.layer.events.on({
+                "beforefeaturesadded": this.cacheFeatures,
+                "moveend": this.cluster,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy.  Unregister any listeners, do appropriate
+     *     tear-down.
+     * 
+     * Returns:
+     * {Boolean} The strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.clearCache();
+            this.layer.events.un({
+                "beforefeaturesadded": this.cacheFeatures,
+                "moveend": this.cluster,
+                scope: this
+            });
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: cacheFeatures
+     * Cache features before they are added to the layer.
+     *
+     * Parameters:
+     * event - {Object} The event that this was listening for.  This will come
+     *     with a batch of features to be clustered.
+     *     
+     * Returns:
+     * {Boolean} False to stop features from being added to the layer.
+     */
+    cacheFeatures: function(event) {
+        var propagate = true;
+        if(!this.clustering) {
+            this.clearCache();
+            this.features = event.features;
+            this.cluster();
+            propagate = false;
+        }
+        return propagate;
+    },
+    
+    /**
+     * Method: clearCache
+     * Clear out the cached features.
+     */
+    clearCache: function() {
+        this.features = null;
+    },
+    
+    /**
+     * Method: cluster
+     * Cluster features based on some threshold distance.
+     *
+     * Parameters:
+     * event - {Object} The event received when cluster is called as a
+     *     result of a moveend event.
+     */
+    cluster: function(event) {
+        if((!event || event.zoomChanged) && this.features) {
+            var resolution = this.layer.map.getResolution();
+            if(resolution != this.resolution || !this.clustersExist()) {
+                this.resolution = resolution;
+                var clusters = [];
+                var feature, clustered, cluster;
+                for(var i=0; i<this.features.length; ++i) {
+                    feature = this.features[i];
+                    if(feature.geometry) {
+                        clustered = false;
+                        for(var j=clusters.length-1; j>=0; --j) {
+                            cluster = clusters[j];
+                            if(this.shouldCluster(cluster, feature)) {
+                                this.addToCluster(cluster, feature);
+                                clustered = true;
+                                break;
+                            }
+                        }
+                        if(!clustered) {
+                            clusters.push(this.createCluster(this.features[i]));
+                        }
+                    }
+                }
+                this.layer.removeAllFeatures();
+                if(clusters.length > 0) {
+                    if(this.threshold > 1) {
+                        var clone = clusters.slice();
+                        clusters = [];
+                        var candidate;
+                        for(var i=0, len=clone.length; i<len; ++i) {
+                            candidate = clone[i];
+                            if(candidate.attributes.count < this.threshold) {
+                                Array.prototype.push.apply(clusters, candidate.cluster);
+                            } else {
+                                clusters.push(candidate);
+                            }
+                        }
+                    }
+                    this.clustering = true;
+                    // A legitimate feature addition could occur during this
+                    // addFeatures call.  For clustering to behave well, features
+                    // should be removed from a layer before requesting a new batch.
+                    this.layer.addFeatures(clusters);
+                    this.clustering = false;
+                }
+                this.clusters = clusters;
+            }
+        }
+    },
+    
+    /**
+     * Method: clustersExist
+     * Determine whether calculated clusters are already on the layer.
+     *
+     * Returns:
+     * {Boolean} The calculated clusters are already on the layer.
+     */
+    clustersExist: function() {
+        var exist = false;
+        if(this.clusters && this.clusters.length > 0 &&
+           this.clusters.length == this.layer.features.length) {
+            exist = true;
+            for(var i=0; i<this.clusters.length; ++i) {
+                if(this.clusters[i] != this.layer.features[i]) {
+                    exist = false;
+                    break;
+                }
+            }
+        }
+        return exist;
+    },
+    
+    /**
+     * Method: shouldCluster
+     * Determine whether to include a feature in a given cluster.
+     *
+     * Parameters:
+     * cluster - {<OpenLayers.Feature.Vector>} A cluster.
+     * feature - {<OpenLayers.Feature.Vector>} A feature.
+     *
+     * Returns:
+     * {Boolean} The feature should be included in the cluster.
+     */
+    shouldCluster: function(cluster, feature) {
+        var cc = cluster.geometry.getBounds().getCenterLonLat();
+        var fc = feature.geometry.getBounds().getCenterLonLat();
+        var distance = (
+            Math.sqrt(
+                Math.pow((cc.lon - fc.lon), 2) + Math.pow((cc.lat - fc.lat), 2)
+            ) / this.resolution
+        );
+        return (distance <= this.distance);
+    },
+    
+    /**
+     * Method: addToCluster
+     * Add a feature to a cluster.
+     *
+     * Parameters:
+     * cluster - {<OpenLayers.Feature.Vector>} A cluster.
+     * feature - {<OpenLayers.Feature.Vector>} A feature.
+     */
+    addToCluster: function(cluster, feature) {
+        cluster.cluster.push(feature);
+        cluster.attributes.count += 1;
+    },
+    
+    /**
+     * Method: createCluster
+     * Given a feature, create a cluster.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A cluster.
+     */
+    createCluster: function(feature) {
+        var center = feature.geometry.getBounds().getCenterLonLat();
+        var cluster = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(center.lon, center.lat),
+            {count: 1}
+        );
+        cluster.cluster = [feature];
+        return cluster;
+    },
+
+    CLASS_NAME: "OpenLayers.Strategy.Cluster" 
+});
+/* ======================================================================
+    OpenLayers/Protocol/SOS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol.js
+ */
+
+/**
+ * Function: OpenLayers.Protocol.SOS
+ * Used to create a versioned SOS protocol.  Default version is 1.0.0.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol>} An SOS protocol for the given version.
+ */
+OpenLayers.Protocol.SOS = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Protocol.SOS.DEFAULTS
+    );
+    var cls = OpenLayers.Protocol.SOS["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported SOS version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Protocol.SOS.DEFAULTS
+ */
+OpenLayers.Protocol.SOS.DEFAULTS = {
+    "version": "1.0.0"
+};
+/* ======================================================================
+    OpenLayers/Format/GeoRSS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GeoRSS
+ * Read/write GeoRSS parser. Create a new instance with the 
+ *     <OpenLayers.Format.GeoRSS> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GeoRSS = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * APIProperty: rssns
+     * {String} RSS namespace to use. Defaults to
+     *   "http://backend.userland.com/rss2"
+     */
+    rssns: "http://backend.userland.com/rss2",
+    
+    /**
+     * APIProperty: featurens
+     * {String} Feature Attributes namespace.  Defaults to
+     *    "http://mapserver.gis.umn.edu/mapserver"
+     */
+    featureNS: "http://mapserver.gis.umn.edu/mapserver",
+    
+    /**
+     * APIProperty: georssns
+     * {String} GeoRSS namespace to use.  Defaults to
+     *     "http://www.georss.org/georss"
+     */
+    georssns: "http://www.georss.org/georss",
+
+    /**
+     * APIProperty: geons
+     * {String} W3C Geo namespace to use.  Defaults to
+     *     "http://www.w3.org/2003/01/geo/wgs84_pos#"
+     */
+    geons: "http://www.w3.org/2003/01/geo/wgs84_pos#",
+    
+    /**
+     * APIProperty: featureTitle
+     * {String} Default title for features.  Defaults to "Untitled"
+     */
+    featureTitle: "Untitled",
+    
+    /**
+     * APIProperty: featureDescription
+     * {String} Default description for features.  Defaults to "No Description"
+     */
+    featureDescription: "No Description",
+    
+    /**
+     * Property: gmlParse
+     * {Object} GML Format object for parsing features
+     * Non-API and only created if necessary
+     */
+    gmlParser: null,
+
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x)
+     * For GeoRSS the default is (y,x), therefore: false
+     */ 
+    xy: false,
+    
+    /**
+     * Constructor: OpenLayers.Format.GeoRSS
+     * Create a new parser for GeoRSS.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    
+    /**
+     * Method: createGeometryFromItem
+     * Return a geometry from a GeoRSS Item.
+     *
+     * Parameters:
+     * item - {DOMElement} A GeoRSS item node.
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>} A geometry representing the node.
+     */
+    createGeometryFromItem: function(item) {
+        var point = this.getElementsByTagNameNS(item, this.georssns, "point");
+        var lat = this.getElementsByTagNameNS(item, this.geons, 'lat');
+        var lon = this.getElementsByTagNameNS(item, this.geons, 'long');
+        
+        var line = this.getElementsByTagNameNS(item,
+                                                this.georssns,
+                                                "line");
+        var polygon = this.getElementsByTagNameNS(item,
+                                                this.georssns,
+                                                "polygon");
+        var where = this.getElementsByTagNameNS(item, 
+                                                this.georssns, 
+                                                "where");
+        var box = this.getElementsByTagNameNS(item, 
+                                              this.georssns, 
+                                              "box");
+												
+        if (point.length > 0 || (lat.length > 0 && lon.length > 0)) {
+            var location;
+            if (point.length > 0) {
+                location = OpenLayers.String.trim(
+                                point[0].firstChild.nodeValue).split(/\s+/);
+                if (location.length !=2) {
+                    location = OpenLayers.String.trim(
+                                point[0].firstChild.nodeValue).split(/\s*,\s*/);
+                }
+            } else {
+                location = [parseFloat(lat[0].firstChild.nodeValue),
+                                parseFloat(lon[0].firstChild.nodeValue)];
+            }    
+
+            var geometry = new OpenLayers.Geometry.Point(parseFloat(location[1]),
+                                                         parseFloat(location[0]));
+              
+        } else if (line.length > 0) {
+            var coords = OpenLayers.String.trim(this.concatChildValues(line[0])).split(/\s+/);
+            var components = []; 
+            var point;
+            for (var i=0, len=coords.length; i<len; i+=2) {
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[i+1]), 
+                                                     parseFloat(coords[i]));
+                components.push(point);
+            }
+            geometry = new OpenLayers.Geometry.LineString(components);
+        } else if (polygon.length > 0) { 
+            var coords = OpenLayers.String.trim(this.concatChildValues(polygon[0])).split(/\s+/);
+            var components = []; 
+            var point;
+            for (var i=0, len=coords.length; i<len; i+=2) {
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[i+1]), 
+                                                     parseFloat(coords[i]));
+                components.push(point);
+            }
+            geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);
+        } else if (where.length > 0) { 
+            if (!this.gmlParser) {
+              this.gmlParser = new OpenLayers.Format.GML({'xy': this.xy});
+            }
+            var feature = this.gmlParser.parseFeature(where[0]);
+            geometry = feature.geometry;
+        } else if (box.length  > 0) {
+            var coords = OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/);
+            var components = [];
+            var point;
+            if (coords.length > 3) {
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[1]), 
+                                                     parseFloat(coords[0]));
+                components.push(point);
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[1]), 
+                                                     parseFloat(coords[2]));
+                components.push(point);
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[3]), 
+                                                     parseFloat(coords[2]));
+                components.push(point);
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[3]), 
+                                                     parseFloat(coords[0]));
+                components.push(point);
+                point = new OpenLayers.Geometry.Point(parseFloat(coords[1]), 
+                                                     parseFloat(coords[0]));
+                components.push(point);
+            }
+            geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);									 
+        }
+        
+        if (geometry && this.internalProjection && this.externalProjection) {
+            geometry.transform(this.externalProjection, 
+                               this.internalProjection);
+        }
+
+        return geometry;
+    },        
+
+    /**
+     * Method: createFeatureFromItem
+     * Return a feature from a GeoRSS Item.
+     *
+     * Parameters:
+     * item - {DOMElement} A GeoRSS item node.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature representing the item.
+     */
+    createFeatureFromItem: function(item) {
+        var geometry = this.createGeometryFromItem(item);
+     
+        /* Provide defaults for title and description */
+        var title = this.getChildValue(item, "*", "title", this.featureTitle);
+       
+        /* First try RSS descriptions, then Atom summaries */
+        var description = this.getChildValue(
+            item, "*", "description",
+            this.getChildValue(item, "*", "content",
+                this.getChildValue(item, "*", "summary", this.featureDescription)));
+
+        /* If no link URL is found in the first child node, try the
+           href attribute */
+        var link = this.getChildValue(item, "*", "link");
+        if(!link) {
+            try {
+                link = this.getElementsByTagNameNS(item, "*", "link")[0].getAttribute("href");
+            } catch(e) {
+                link = null;
+            }
+        }
+
+        var id = this.getChildValue(item, "*", "id", null);
+        
+        var data = {
+            "title": title,
+            "description": description,
+            "link": link
+        };
+        var feature = new OpenLayers.Feature.Vector(geometry, data);
+        feature.fid = id;
+        return feature;
+    },        
+    
+    /**
+     * Method: getChildValue
+     *
+     * Parameters:
+     * node - {DOMElement}
+     * nsuri - {String} Child node namespace uri ("*" for any).
+     * name - {String} Child node name.
+     * def - {String} Optional string default to return if no child found.
+     *
+     * Returns:
+     * {String} The value of the first child with the given tag name.  Returns
+     *     default value or empty string if none found.
+     */
+    getChildValue: function(node, nsuri, name, def) {
+        var value;
+        var eles = this.getElementsByTagNameNS(node, nsuri, name);
+        if(eles && eles[0] && eles[0].firstChild
+            && eles[0].firstChild.nodeValue) {
+            value = OpenLayers.Format.XML.prototype.getChildValue(eles[0]);
+        } else {
+            value = (def == undefined) ? "" : def;
+        }
+        return value;
+    },
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from a GeoRSS doc
+     *
+     * Parameters:
+     * doc - {Element} 
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)}
+     */
+    read: function(doc) {
+        if (typeof doc == "string") { 
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+
+        /* Try RSS items first, then Atom entries */
+        var itemlist = null;
+        itemlist = this.getElementsByTagNameNS(doc, '*', 'item');
+        if (itemlist.length == 0) {
+            itemlist = this.getElementsByTagNameNS(doc, '*', 'entry');
+        }
+        
+        var numItems = itemlist.length;
+        var features = new Array(numItems);
+        for(var i=0; i<numItems; i++) {
+            features[i] = this.createFeatureFromItem(itemlist[i]);
+        }
+        return features;
+    },
+    
+
+    /**
+     * APIMethod: write
+     * Accept Feature Collection, and return a string. 
+     * 
+     * Parameters: 
+     * features - {Array(<OpenLayers.Feature.Vector>)} List of features to serialize into a string.
+     */
+    write: function(features) {
+        var georss;
+        if(OpenLayers.Util.isArray(features)) {
+            georss = this.createElementNS(this.rssns, "rss");
+            for(var i=0, len=features.length; i<len; i++) {
+                georss.appendChild(this.createFeatureXML(features[i]));
+            }
+        } else {
+            georss = this.createFeatureXML(features);
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [georss]);
+    },
+
+    /**
+     * Method: createFeatureXML
+     * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     *
+     * Returns:
+     * {DOMElement}
+     */
+    createFeatureXML: function(feature) {
+        var geometryNode = this.buildGeometryNode(feature.geometry);
+        var featureNode = this.createElementNS(this.rssns, "item");
+        var titleNode = this.createElementNS(this.rssns, "title");
+        titleNode.appendChild(this.createTextNode(feature.attributes.title ? feature.attributes.title : ""));
+        var descNode = this.createElementNS(this.rssns, "description");
+        descNode.appendChild(this.createTextNode(feature.attributes.description ? feature.attributes.description : ""));
+        featureNode.appendChild(titleNode);
+        featureNode.appendChild(descNode);
+        if (feature.attributes.link) {
+            var linkNode = this.createElementNS(this.rssns, "link");
+            linkNode.appendChild(this.createTextNode(feature.attributes.link));
+            featureNode.appendChild(linkNode);
+        }    
+        for(var attr in feature.attributes) {
+            if (attr == "link" || attr == "title" || attr == "description") { continue; } 
+            var attrText = this.createTextNode(feature.attributes[attr]); 
+            var nodename = attr;
+            if (attr.search(":") != -1) {
+                nodename = attr.split(":")[1];
+            }    
+            var attrContainer = this.createElementNS(this.featureNS, "feature:"+nodename);
+            attrContainer.appendChild(attrText);
+            featureNode.appendChild(attrContainer);
+        }    
+        featureNode.appendChild(geometryNode);
+        return featureNode;
+    },    
+    
+    /** 
+     * Method: buildGeometryNode
+     * builds a GeoRSS node with a given geometry
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {DOMElement} A gml node.
+     */
+    buildGeometryNode: function(geometry) {
+        if (this.internalProjection && this.externalProjection) {
+            geometry = geometry.clone();
+            geometry.transform(this.internalProjection, 
+                               this.externalProjection);
+        }
+        var node;
+        // match Polygon
+        if (geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
+            node = this.createElementNS(this.georssns, 'georss:polygon');
+            
+            node.appendChild(this.buildCoordinatesNode(geometry.components[0]));
+        }
+        // match LineString
+        else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
+            node = this.createElementNS(this.georssns, 'georss:line');
+            
+            node.appendChild(this.buildCoordinatesNode(geometry));
+        }
+        // match Point
+        else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+            node = this.createElementNS(this.georssns, 'georss:point');
+            node.appendChild(this.buildCoordinatesNode(geometry));
+        } else {
+            throw "Couldn't parse " + geometry.CLASS_NAME;
+        }  
+        return node;         
+    },
+    
+    /** 
+     * Method: buildCoordinatesNode
+     * 
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     */
+    buildCoordinatesNode: function(geometry) {
+        var points = null;
+        
+        if (geometry.components) {
+            points = geometry.components;
+        }
+
+        var path;
+        if (points) {
+            var numPoints = points.length;
+            var parts = new Array(numPoints);
+            for (var i = 0; i < numPoints; i++) {
+                parts[i] = points[i].y + " " + points[i].x;
+            }
+            path = parts.join(" ");
+        } else {
+            path = geometry.y + " " + geometry.x;
+        }
+        return this.createTextNode(path);
+    },
+
+    CLASS_NAME: "OpenLayers.Format.GeoRSS" 
+});     
+/* ======================================================================
+    OpenLayers/Format/WPSCapabilities.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+ 
+/**
+ * Class: OpenLayers.Format.WPSCapabilities
+ * Read WPS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WPSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * Constructor: OpenLayers.Format.WPSCapabilities
+     * Create a new parser for WPS Capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return information about
+     * the service.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Info about the WPS
+     */
+    
+    CLASS_NAME: "OpenLayers.Format.WPSCapabilities" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WPSCapabilities/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WPSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSCapabilities.v1_0_0
+ * Read WPS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        wps: "http://www.opengis.net/wps/1.0.0",
+        xlink: "http://www.w3.org/1999/xlink"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.WPSCapabilities.v1_0_0
+     * Create a new parser for WPS capabilities version 1.0.0. 
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return info about the WPS.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the WPS service.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        return capabilities;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wps": {
+            "Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "ProcessOfferings": function(node, obj) {
+                obj.processOfferings = {};
+                this.readChildNodes(node, obj.processOfferings);
+            },
+            "Process": function(node, processOfferings) {
+                var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion");
+                var process = {processVersion: processVersion};
+                this.readChildNodes(node, process);
+                processOfferings[process.identifier] = process;
+            },
+            "Languages": function(node, obj) {
+                obj.languages = [];
+                this.readChildNodes(node, obj.languages);
+            },
+            "Default": function(node, languages) {
+                var language = {isDefault: true};
+                this.readChildNodes(node, language);
+                languages.push(language);
+            },
+            "Supported": function(node, languages) {
+                var language = {};
+                this.readChildNodes(node, language);     
+                languages.push(language);
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },    
+    
+    CLASS_NAME: "OpenLayers.Format.WPSCapabilities.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Control/PinchZoom.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Handler/Pinch.js
+ */
+
+/**
+ * Class: OpenLayers.Control.PinchZoom
+ *
+ * Inherits:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.PinchZoom = OpenLayers.Class(OpenLayers.Control, {
+
+    /** 
+     * Property: type
+     * {OpenLayers.Control.TYPES}
+     */
+    type: OpenLayers.Control.TYPE_TOOL,
+
+    /**
+     * Property: containerOrigin
+     * {Object} Cached object representing the layer container origin (in pixels).
+     */
+    containerOrigin: null,
+
+    /**
+     * Property: pinchOrigin
+     * {Object} Cached object representing the pinch start (in pixels).
+     */
+    pinchOrigin: null,    
+    
+    /**
+     * Property: currentCenter
+     * {Object} Cached object representing the latest pinch center (in pixels).
+     */
+    currentCenter: null,    
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+    
+    /**
+     * Constructor: OpenLayers.Control.PinchZoom
+     * Create a control for zooming with pinch gestures.  This works on devices
+     *     with multi-touch support.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *                    the control
+     */
+    initialize: function(options) {
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+        this.handler = new OpenLayers.Handler.Pinch(this, {
+            start: this.pinchStart,
+            move: this.pinchMove,
+            done: this.pinchDone
+        }, this.handlerOptions);
+    },
+    
+    /**
+     * APIMethod: activate
+     * Activate this control.  Must be called after the control is added to a 
+     * map.
+     *
+     * Returns:
+     * {Boolean} The control was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Control.prototype.activate.apply(this,arguments);
+        if (activated) {
+            this.map.events.on({
+                moveend: this.updateContainerOrigin,
+                scope: this
+            });
+            this.updateContainerOrigin();
+        }
+        return activated;
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate this control.
+     *
+     * Returns:
+     * {Boolean} The control was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Control.prototype.deactivate.apply(this,arguments);
+        if (this.map && this.map.events) {
+            this.map.events.un({
+                moveend: this.updateContainerOrigin,
+                scope: this
+            });
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: updateContainerOrigin
+     * Must be called each time the layer container origin changes.
+     */
+    updateContainerOrigin: function() {
+        var container = this.map.layerContainerDiv;
+        this.containerOrigin = {
+            x: parseInt(container.style.left, 10),
+            y: parseInt(container.style.top, 10)
+        };
+    },
+
+    /**
+     * Method: pinchStart
+     *
+     * Parameters:
+     * evt - {Event}
+     * pinchData - {Object} pinch data object related to the current touchmove
+     *     of the pinch gesture. This give us the current scale of the pinch.
+     */
+    pinchStart: function(evt, pinchData) {
+        this.pinchOrigin = evt.xy;
+        this.currentCenter = evt.xy;
+    },
+    
+    /**
+     * Method: pinchMove
+     *
+     * Parameters:
+     * evt - {Event}
+     * pinchData - {Object} pinch data object related to the current touchmove
+     *     of the pinch gesture. This give us the current scale of the pinch.
+     */
+    pinchMove: function(evt, pinchData) {
+        var scale = pinchData.scale;
+        var containerOrigin = this.containerOrigin;
+        var pinchOrigin = this.pinchOrigin;
+        var current = evt.xy;
+
+        var dx = Math.round((current.x - pinchOrigin.x) + (scale - 1) * (containerOrigin.x - pinchOrigin.x));
+        var dy = Math.round((current.y - pinchOrigin.y) + (scale - 1) * (containerOrigin.y - pinchOrigin.y));
+
+        this.applyTransform(
+            "translate(" + dx + "px, " + dy + "px) scale(" + scale + ")"
+        );
+        this.currentCenter = current;
+    },
+    
+    /**
+     * Method: applyTransform
+     * Applies the given transform to layers.
+     */
+    applyTransform: function(transform) {
+        var style = this.map.layerContainerDiv.style;
+        style['-webkit-transform'] = transform;
+        style['-moz-transform'] = transform;
+    },
+    
+    /**
+     * Method: pinchDone
+     *
+     * Parameters:
+     * evt - {Event}
+     * start - {Object} pinch data object related to the touchstart event that
+     *     started the pinch gesture.
+     * last - {Object} pinch data object related to the last touchmove event
+     *     of the pinch gesture. This give us the final scale of the pinch.
+     */
+    pinchDone: function(evt, start, last) {
+        this.applyTransform("");
+        var zoom = this.map.getZoomForResolution(this.map.getResolution() / last.scale, true);
+        if (zoom !== this.map.getZoom() || !this.currentCenter.equals(this.pinchOrigin)) {
+            var resolution = this.map.getResolutionForZoom(zoom);
+
+            var location = this.map.getLonLatFromPixel(this.pinchOrigin);
+            var zoomPixel = this.currentCenter;        
+            var size = this.map.getSize();
+
+            location.lon += resolution * ((size.w / 2) - zoomPixel.x);
+            location.lat -= resolution * ((size.h / 2) - zoomPixel.y);
+
+            this.map.setCenter(location, zoom);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.PinchZoom"
+
+});
+/* ======================================================================
+    OpenLayers/Control/TouchNavigation.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control/DragPan.js
+ * @requires OpenLayers/Control/PinchZoom.js
+ * @requires OpenLayers/Handler/Click.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TouchNavigation
+ * The navigation control handles map browsing with touch events (dragging,
+ *     double-tapping, tap with two fingers, and pinch zoom).  Create a new 
+ *     control with the <OpenLayers.Control.TouchNavigation> constructor.
+ *
+ * If you’re only targeting touch enabled devices with your mapping application,
+ *     you can create a map with only a TouchNavigation control. The 
+ *     <OpenLayers.Control.Navigation> control is mobile ready by default, but 
+ *     you can generate a smaller build of the library by only including this
+ *     touch navigation control if you aren't concerned about mouse interaction.
+ *
+ * Inherits:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TouchNavigation = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: dragPan
+     * {<OpenLayers.Control.DragPan>}
+     */
+    dragPan: null,
+
+    /**
+     * APIProperty: dragPanOptions
+     * {Object} Options passed to the DragPan control.
+     */
+    dragPanOptions: null,
+
+    /**
+     * Property: pinchZoom
+     * {<OpenLayers.Control.PinchZoom>}
+     */
+    pinchZoom: null,
+
+    /**
+     * APIProperty: pinchZoomOptions
+     * {Object} Options passed to the PinchZoom control.
+     */
+    pinchZoomOptions: null,
+
+    /**
+     * APIProperty: clickHandlerOptions
+     * {Object} Options passed to the Click handler.
+     */
+    clickHandlerOptions: null,
+
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} Allow panning of the map by dragging outside map viewport.
+     *     Default is false.
+     */
+    documentDrag: false,
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
+     * Constructor: OpenLayers.Control.TouchNavigation
+     * Create a new navigation control
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *                    the control
+     */
+    initialize: function(options) {
+        this.handlers = {};
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * Method: destroy
+     * The destroy method is used to perform any clean up before the control
+     * is dereferenced.  Typically this is where event listeners are removed
+     * to prevent memory leaks.
+     */
+    destroy: function() {
+        this.deactivate();
+        if(this.dragPan) {
+            this.dragPan.destroy();
+        }
+        this.dragPan = null;
+        if (this.pinchZoom) {
+            this.pinchZoom.destroy();
+            delete this.pinchZoom;
+        }
+        OpenLayers.Control.prototype.destroy.apply(this,arguments);
+    },
+
+    /**
+     * Method: activate
+     */
+    activate: function() {
+        if(OpenLayers.Control.prototype.activate.apply(this,arguments)) {
+            this.dragPan.activate();
+            this.handlers.click.activate();
+            this.pinchZoom.activate();
+            return true;
+        }
+        return false;
+    },
+
+    /**
+     * Method: deactivate
+     */
+    deactivate: function() {
+        if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)) {
+            this.dragPan.deactivate();
+            this.handlers.click.deactivate();
+            this.pinchZoom.deactivate();
+            return true;
+        }
+        return false;
+    },
+    
+    /**
+     * Method: draw
+     */
+    draw: function() {
+        var clickCallbacks = {
+            click: this.defaultClick,
+            dblclick: this.defaultDblClick
+        };
+        var clickOptions = OpenLayers.Util.extend({
+            "double": true,
+            stopDouble: true,
+            pixelTolerance: 2
+        }, this.clickHandlerOptions);
+        this.handlers.click = new OpenLayers.Handler.Click(
+            this, clickCallbacks, clickOptions
+        );
+        this.dragPan = new OpenLayers.Control.DragPan(
+            OpenLayers.Util.extend({
+                map: this.map,
+                documentDrag: this.documentDrag
+            }, this.dragPanOptions)
+        );
+        this.dragPan.draw();
+        this.pinchZoom = new OpenLayers.Control.PinchZoom(
+            OpenLayers.Util.extend({map: this.map}, this.pinchZoomOptions)
+        );
+    },
+
+    /**
+     * Method: defaultClick
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    defaultClick: function (evt) {
+        if(evt.lastTouches && evt.lastTouches.length == 2) {
+            this.map.zoomOut();
+        }
+    },
+
+    /**
+     * Method: defaultDblClick
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    defaultDblClick: function (evt) {
+        var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
+        this.map.setCenter(newCenter, this.map.zoom + 1);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.TouchNavigation"
+});
+/* ======================================================================
+    OpenLayers/Style2.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Symbolizer/Point.js
+ * @requires OpenLayers/Symbolizer/Line.js
+ * @requires OpenLayers/Symbolizer/Polygon.js
+ * @requires OpenLayers/Symbolizer/Text.js
+ * @requires OpenLayers/Symbolizer/Raster.js
+ */
+
+/**
+ * Class: OpenLayers.Style2
+ * This class represents a collection of rules for rendering features.
+ */
+OpenLayers.Style2 = OpenLayers.Class({
+
+    /**
+     * Property: id
+     * {String} A unique id for this session.
+     */
+    id: null,
+    
+    /**
+     * APIProperty: name
+     * {String} Style identifier.
+     */
+    name: null,
+    
+    /**
+     * APIProperty: title
+     * {String} Title of this style.
+     */
+    title: null,
+    
+    /**
+     * APIProperty: description
+     * {String} Description of this style.
+     */
+    description: null,
+
+    /**
+     * APIProperty: layerName
+     * {<String>} Name of the layer that this style belongs to, usually
+     *     according to the NamedLayer attribute of an SLD document.
+     */
+    layerName: null,
+    
+    /**
+     * APIProperty: isDefault
+     * {Boolean}
+     */
+    isDefault: false,
+     
+    /** 
+     * APIProperty: rules 
+     * {Array(<OpenLayers.Rule>)} Collection of rendering rules.
+     */
+    rules: null,
+    
+    /** 
+     * Constructor: OpenLayers.Style2
+     * Creates a style representing a collection of rendering rules.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     style.  Any documented properties may be set at construction.
+     *
+     * Return:
+     * {<OpenLayers.Style2>} A new style object.
+     */
+    initialize: function(config) {
+        OpenLayers.Util.extend(this, config);
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        for (var i=0, len=this.rules.length; i<len; i++) {
+            this.rules[i].destroy();
+        }
+        delete this.rules;
+    },
+
+    /**
+     * APIMethod: clone
+     * Clones this style.
+     * 
+     * Returns:
+     * {<OpenLayers.Style2>} Clone of this style.
+     */
+    clone: function() {
+        var config = OpenLayers.Util.extend({}, this);
+        // clone rules
+        if (this.rules) {
+            config.rules = [];
+            for (var i=0, len=this.rules.length; i<len; ++i) {
+                config.rules.push(this.rules[i].clone());
+            }
+        }
+        return new OpenLayers.Style2(config);
+    },
+    
+    CLASS_NAME: "OpenLayers.Style2"
+});
+/* ======================================================================
+    OpenLayers/Format/WFS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFS
+ * Read/Write WFS. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.GML>
+ */
+OpenLayers.Format.WFS = OpenLayers.Class(OpenLayers.Format.GML, {
+    
+    /** 
+     * Property: layer
+     */
+    layer: null,
+    
+    /**
+     * APIProperty: wfsns
+     */
+    wfsns: "http://www.opengis.net/wfs",
+    
+    /**
+     * Property: ogcns
+     */
+    ogcns: "http://www.opengis.net/ogc",
+    
+    /*
+     * Constructor: OpenLayers.Format.WFS
+     * Create a WFS-T formatter. This requires a layer: that layer should
+     * have two properties: geometry_column and typename. The parser
+     * for this format is subclassed entirely from GML: There is a writer 
+     * only, which uses most of the code from the GML layer, and wraps
+     * it in transactional elements.
+     * 
+     * Parameters: 
+     * options - {Object} 
+     * layer - {<OpenLayers.Layer>} 
+     */
+    
+    initialize: function(options, layer) {
+        OpenLayers.Format.GML.prototype.initialize.apply(this, [options]);
+        this.layer = layer;
+        if (this.layer.featureNS) {
+            this.featureNS = this.layer.featureNS;
+        }    
+        if (this.layer.options.geometry_column) {
+            this.geometryName = this.layer.options.geometry_column;
+        }
+        if (this.layer.options.typename) {
+            this.featureName = this.layer.options.typename;
+        }
+    },
+    
+    /**
+     * Method: write 
+     * Takes a feature list, and generates a WFS-T Transaction 
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} 
+     */
+    write: function(features) {
+    
+        var transaction = this.createElementNS(this.wfsns, 'wfs:Transaction');
+        transaction.setAttribute("version","1.0.0");
+        transaction.setAttribute("service","WFS");
+        for (var i=0; i < features.length; i++) {
+            switch (features[i].state) {
+                case OpenLayers.State.INSERT:
+                    transaction.appendChild(this.insert(features[i]));
+                    break;
+                case OpenLayers.State.UPDATE:
+                    transaction.appendChild(this.update(features[i]));
+                    break;
+                case OpenLayers.State.DELETE:
+                    transaction.appendChild(this.remove(features[i]));
+                    break;
+            }
+        }
+        
+        return OpenLayers.Format.XML.prototype.write.apply(this,[transaction]);
+    },
+   
+    /**
+     * Method: createFeatureXML
+     *
+     * Parameters: 
+     * feature - {<OpenLayers.Feature.Vector>}
+     */ 
+    createFeatureXML: function(feature) {
+        var geometryNode = this.buildGeometryNode(feature.geometry);
+        var geomContainer = this.createElementNS(this.featureNS, "feature:" + this.geometryName);
+        geomContainer.appendChild(geometryNode);
+        var featureContainer = this.createElementNS(this.featureNS, "feature:" + this.featureName);
+        featureContainer.appendChild(geomContainer);
+        for(var attr in feature.attributes) {
+            var attrText = this.createTextNode(feature.attributes[attr]); 
+            var nodename = attr;
+            if (attr.search(":") != -1) {
+                nodename = attr.split(":")[1];
+            }    
+            var attrContainer = this.createElementNS(this.featureNS, "feature:" + nodename);
+            attrContainer.appendChild(attrText);
+            featureContainer.appendChild(attrContainer);
+        }    
+        return featureContainer;
+    },
+    
+    /**
+     * Method: insert 
+     * Takes a feature, and generates a WFS-T Transaction "Insert" 
+     *
+     * Parameters: 
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    insert: function(feature) {
+        var insertNode = this.createElementNS(this.wfsns, 'wfs:Insert');
+        insertNode.appendChild(this.createFeatureXML(feature));
+        return insertNode;
+    },
+    
+    /**
+     * Method: update
+     * Takes a feature, and generates a WFS-T Transaction "Update" 
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    update: function(feature) {
+        if (!feature.fid) { OpenLayers.Console.userError(OpenLayers.i18n("noFID")); }
+        var updateNode = this.createElementNS(this.wfsns, 'wfs:Update');
+        updateNode.setAttribute("typeName", this.featurePrefix + ':' + this.featureName); 
+        updateNode.setAttribute("xmlns:" + this.featurePrefix, this.featureNS); 
+
+        var propertyNode = this.createElementNS(this.wfsns, 'wfs:Property');
+        var nameNode = this.createElementNS(this.wfsns, 'wfs:Name');
+        
+        var txtNode = this.createTextNode(this.geometryName);
+        nameNode.appendChild(txtNode);
+        propertyNode.appendChild(nameNode);
+        
+        var valueNode = this.createElementNS(this.wfsns, 'wfs:Value');
+        
+        var geometryNode = this.buildGeometryNode(feature.geometry);
+        
+        if(feature.layer){
+            geometryNode.setAttribute(
+                "srsName", feature.layer.projection.getCode()
+            );
+        }
+        
+        valueNode.appendChild(geometryNode);
+        
+        propertyNode.appendChild(valueNode);
+        updateNode.appendChild(propertyNode);
+        
+         // add in attributes
+        for(var propName in feature.attributes) {
+            propertyNode = this.createElementNS(this.wfsns, 'wfs:Property');
+            nameNode = this.createElementNS(this.wfsns, 'wfs:Name');
+            nameNode.appendChild(this.createTextNode(propName));
+            propertyNode.appendChild(nameNode);
+            valueNode = this.createElementNS(this.wfsns, 'wfs:Value');
+            valueNode.appendChild(this.createTextNode(feature.attributes[propName]));
+            propertyNode.appendChild(valueNode);
+            updateNode.appendChild(propertyNode);
+        }
+        
+        
+        var filterNode = this.createElementNS(this.ogcns, 'ogc:Filter');
+        var filterIdNode = this.createElementNS(this.ogcns, 'ogc:FeatureId');
+        filterIdNode.setAttribute("fid", feature.fid);
+        filterNode.appendChild(filterIdNode);
+        updateNode.appendChild(filterNode);
+
+        return updateNode;
+    },
+    
+    /**
+     * Method: remove 
+     * Takes a feature, and generates a WFS-T Transaction "Delete" 
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} 
+     */
+    remove: function(feature) {
+        if (!feature.fid) { 
+            OpenLayers.Console.userError(OpenLayers.i18n("noFID")); 
+            return false; 
+        }
+        var deleteNode = this.createElementNS(this.wfsns, 'wfs:Delete');
+        deleteNode.setAttribute("typeName", this.featurePrefix + ':' + this.featureName); 
+        deleteNode.setAttribute("xmlns:" + this.featurePrefix, this.featureNS); 
+
+        var filterNode = this.createElementNS(this.ogcns, 'ogc:Filter');
+        var filterIdNode = this.createElementNS(this.ogcns, 'ogc:FeatureId');
+        filterIdNode.setAttribute("fid", feature.fid);
+        filterNode.appendChild(filterIdNode);
+        deleteNode.appendChild(filterNode);
+
+        return deleteNode;
+    },
+
+    /**
+     * APIMethod: destroy
+     * Remove ciruclar ref to layer 
+     */
+    destroy: function() {
+        this.layer = null;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WFS" 
+});    
+/* ======================================================================
+    OpenLayers/Layer/Boxes.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Layer/Markers.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Boxes
+ * Draw divs as 'boxes' on the layer. 
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Markers>
+ */
+OpenLayers.Layer.Boxes = OpenLayers.Class(OpenLayers.Layer.Markers, {
+
+    /**
+     * Constructor: OpenLayers.Layer.Boxes
+     *
+     * Parameters:
+     * name - {String} 
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function (name, options) {
+        OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
+    },
+    
+    /**
+     * Method: drawMarker 
+     * Calculate the pixel location for the marker, create it, and
+     *    add it to the layer's div
+     *
+     * Parameters: 
+     * marker - {<OpenLayers.Marker.Box>} 
+     */
+    drawMarker: function(marker) {
+        var bounds   = marker.bounds;
+        var topleft  = this.map.getLayerPxFromLonLat(
+                            new OpenLayers.LonLat(bounds.left,  bounds.top));
+        var botright = this.map.getLayerPxFromLonLat(
+                             new OpenLayers.LonLat(bounds.right, bounds.bottom));
+        if (botright == null || topleft == null) {
+            marker.display(false);
+        } else {
+            var sz = new OpenLayers.Size(
+                Math.max(1, botright.x - topleft.x),
+                Math.max(1, botright.y - topleft.y));
+            var markerDiv = marker.draw(topleft, sz);
+            if (!marker.drawn) {
+                this.div.appendChild(markerDiv);
+                marker.drawn = true;
+            }
+        }
+    },
+
+
+    /**
+     * APIMethod: removeMarker 
+     * 
+     * Parameters:
+     * marker - {<OpenLayers.Marker.Box>} 
+     */
+    removeMarker: function(marker) {
+        OpenLayers.Util.removeItem(this.markers, marker);
+        if ((marker.div != null) &&
+            (marker.div.parentNode == this.div) ) {
+            this.div.removeChild(marker.div);    
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Boxes"
+});
+/* ======================================================================
+    OpenLayers/Format/WFSCapabilities/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities/v1_0_0
+ * Read WFS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WFSCapabilities>
+ */
+OpenLayers.Format.WFSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.WFSCapabilities.v1, {
+    
+    /**
+     * Constructor: OpenLayers.Format.WFSCapabilities.v1_0_0
+     * Create a new parser for WFS capabilities version 1.0.0.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+    
+    /**
+     * Method: read_cap_Service
+     */
+    read_cap_Service: function(capabilities, node) {
+        var service = {};
+        this.runChildNodes(service, node);
+        capabilities.service = service;
+    },
+
+    /**
+     * Method: read_cap_Fees
+     */
+    read_cap_Fees: function(service, node) {
+        var fees = this.getChildValue(node);
+        if (fees && fees.toLowerCase() != "none") {
+            service.fees = fees;
+        }
+    },
+
+    /**
+     * Method: read_cap_AccessConstraints
+     */
+    read_cap_AccessConstraints: function(service, node) {
+        var constraints = this.getChildValue(node);
+        if (constraints && constraints.toLowerCase() != "none") {
+            service.accessConstraints = constraints;
+        }
+    },
+    
+    /**
+     * Method: read_cap_OnlineResource
+     */
+    read_cap_OnlineResource: function(service, node) {
+        var onlineResource = this.getChildValue(node);
+        if (onlineResource && onlineResource.toLowerCase() != "none") {
+            service.onlineResource = onlineResource;
+        }
+    },
+    
+    /**
+     * Method: read_cap_Keywords
+     */
+    read_cap_Keywords: function(service, node) {
+        var keywords = this.getChildValue(node);
+        if (keywords && keywords.toLowerCase() != "none") {
+            service.keywords = keywords.split(', ');
+        }
+    },
+    
+    /**
+     * Method: read_cap_Capability
+     */
+    read_cap_Capability: function(capabilities, node) {
+        var capability = {};
+        this.runChildNodes(capability, node);
+        capabilities.capability = capability;
+    },
+    
+    /**
+     * Method: read_cap_Request
+     */
+    read_cap_Request: function(obj, node) {
+        var request = {};
+        this.runChildNodes(request, node);
+        obj.request = request;
+    },
+    
+    /**
+     * Method: read_cap_GetFeature
+     */
+    read_cap_GetFeature: function(request, node) {
+        var getfeature = {
+            href: {}, // DCPType
+            formats: [] // ResultFormat
+        };
+        this.runChildNodes(getfeature, node);
+        request.getfeature = getfeature;
+    },
+    
+    /**
+     * Method: read_cap_ResultFormat
+     */
+    read_cap_ResultFormat: function(obj, node) {
+        var children = node.childNodes;
+        var childNode;
+        for(var i=0; i<children.length; i++) {
+            childNode = children[i];
+            if(childNode.nodeType == 1) {
+                obj.formats.push(childNode.nodeName);
+            }
+        }
+    },
+    
+    /**
+     * Method: read_cap_DCPType
+     */
+    read_cap_DCPType: function(obj, node) {
+        this.runChildNodes(obj, node);
+    },
+    
+    /**
+     * Method: read_cap_HTTP
+     */
+    read_cap_HTTP: function(obj, node) {
+        this.runChildNodes(obj.href, node);
+    },
+    
+    /**
+     * Method: read_cap_Get
+     */
+    read_cap_Get: function(obj, node) {
+        obj.get = node.getAttribute("onlineResource");
+    },
+    
+    /**
+     * Method: read_cap_Post
+     */
+    read_cap_Post: function(obj, node) {
+        obj.post = node.getAttribute("onlineResource");
+    },
+
+    /**
+     * Method: read_cap_SRS
+     */
+    read_cap_SRS: function(obj, node) {
+        var srs = this.getChildValue(node);
+        if (srs) {
+            obj.srs = srs;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_0_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/Yahoo.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/SphericalMercator.js
+ * @requires OpenLayers/Layer/EventPane.js
+ * @requires OpenLayers/Layer/FixedZoomLevels.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Yahoo
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.EventPane>
+ *  - <OpenLayers.Layer.FixedZoomLevels>
+ */
+OpenLayers.Layer.Yahoo = OpenLayers.Class(
+  OpenLayers.Layer.EventPane, OpenLayers.Layer.FixedZoomLevels, {
+    
+    /** 
+     * Constant: MIN_ZOOM_LEVEL
+     * {Integer} 0 
+     */
+    MIN_ZOOM_LEVEL: 0,
+    
+    /** 
+     * Constant: MAX_ZOOM_LEVEL
+     * {Integer} 17
+     */
+    MAX_ZOOM_LEVEL: 17,
+
+    /** 
+     * Constant: RESOLUTIONS
+     * {Array(Float)} Hardcode these resolutions so that they are more closely
+     *                tied with the standard wms projection
+     */
+    RESOLUTIONS: [
+        1.40625, 
+        0.703125, 
+        0.3515625, 
+        0.17578125, 
+        0.087890625, 
+        0.0439453125,
+        0.02197265625, 
+        0.010986328125, 
+        0.0054931640625, 
+        0.00274658203125, 
+        0.001373291015625, 
+        0.0006866455078125, 
+        0.00034332275390625, 
+        0.000171661376953125, 
+        0.0000858306884765625, 
+        0.00004291534423828125,
+        0.00002145767211914062,
+        0.00001072883605957031
+    ],
+
+    /**
+     * APIProperty: type
+     * {YahooMapType}
+     */
+    type: null,
+    
+    /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
+     * APIProperty: sphericalMercator
+     * {Boolean} Should the map act as a mercator-projected map? This will
+     * cause all interactions with the map to be in the actual map projection,
+     * which allows support for vector drawing, overlaying other maps, etc. 
+     */
+    sphericalMercator: false, 
+
+    /** 
+     * Constructor: OpenLayers.Layer.Yahoo
+     * 
+     * Parameters:
+     * name - {String}
+     * options - {Object}
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
+        OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
+                                                                    arguments);
+        if(this.sphericalMercator) {
+            OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
+            this.initMercatorParameters();
+        }
+    },
+    
+    /**
+     * Method: loadMapObject
+     */
+    loadMapObject:function() {
+        try { //do not crash! 
+            var size = this.getMapObjectSizeFromOLSize(this.map.getSize());
+            this.mapObject = new YMap(this.div, this.type, size);
+            this.mapObject.disableKeyControls();
+            this.mapObject.disableDragMap();
+
+            //can we do smooth panning? (moveByXY is not an API function)
+            if ( !this.mapObject.moveByXY || 
+                 (typeof this.mapObject.moveByXY != "function" ) ) {
+
+                this.dragPanMapObject = null;
+            }                
+        } catch(e) {}
+    },
+
+    /**
+     * Method: onMapResize
+     * 
+     */
+    onMapResize: function() {
+        try {
+            var size = this.getMapObjectSizeFromOLSize(this.map.getSize());
+            this.mapObject.resizeTo(size);
+        } catch(e) {}     
+    },    
+    
+    
+    /** 
+     * APIMethod: setMap
+     * Overridden from EventPane because we need to remove this yahoo event
+     *     pane which prohibits our drag and drop, and we can only do this 
+     *     once the map has been loaded and centered.
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.EventPane.prototype.setMap.apply(this, arguments);
+
+        this.map.events.register("moveend", this, this.fixYahooEventPane);
+    },
+
+    /** 
+     * Method: fixYahooEventPane
+     * The map has been centered, so the mysterious yahoo eventpane has been
+     *     added. we remove it so that it doesnt mess with *our* event pane.
+     */
+    fixYahooEventPane: function() {
+        var yahooEventPane = OpenLayers.Util.getElement("ygddfdiv");
+        if (yahooEventPane != null) {
+            if (yahooEventPane.parentNode != null) {
+                yahooEventPane.parentNode.removeChild(yahooEventPane);
+            }
+            this.map.events.unregister("moveend", this, 
+                                       this.fixYahooEventPane);
+        }
+    },
+
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n(
+            "getLayerWarning", {'layerType':'Yahoo', 'layerLib':'Yahoo'}
+        );
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*             Translation Functions                    */
+  /*                                                      */
+  /*    The following functions translate GMaps and OL    */ 
+  /*     formats for Pixel, LonLat, Bounds, and Zoom      */
+  /*                                                      */
+  /********************************************************/
+
+
+  //
+  // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom
+  //
+  
+    /**
+     * APIMethod: getOLZoomFromMapObjectZoom
+     * 
+     * Parameters:
+     * gZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} An OpenLayers Zoom level, translated from the passed in gZoom
+     *           Returns null if null value is passed in.
+     */
+    getOLZoomFromMapObjectZoom: function(moZoom) {
+        var zoom = null;
+        if (moZoom != null) {
+            zoom = OpenLayers.Layer.FixedZoomLevels.prototype.getOLZoomFromMapObjectZoom.apply(this, [moZoom]);
+            zoom = 18 - zoom;
+        }
+        return zoom;
+    },
+    
+    /**
+     * APIMethod: getMapObjectZoomFromOLZoom
+     * 
+     * Parameters:
+     * olZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} A MapObject level, translated from the passed in olZoom
+     *           Returns null if null value is passed in
+     */
+    getMapObjectZoomFromOLZoom: function(olZoom) {
+        var zoom = null; 
+        if (olZoom != null) {
+            zoom = OpenLayers.Layer.FixedZoomLevels.prototype.getMapObjectZoomFromOLZoom.apply(this, [olZoom]);
+            zoom = 18 - zoom;
+        }
+        return zoom;
+    },
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.drawZoomAndCenter(center, zoom); 
+    },
+   
+    /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.getCenterLatLon();
+    },
+
+    /**
+     * APIMethod: dragPanMapObject
+     * 
+     * Parameters:
+     * dX - {Integer}
+     * dY - {Integer}
+     */
+    dragPanMapObject: function(dX, dY) {
+        this.mapObject.moveByXY({
+            'x': -dX,
+            'y': dY
+        });
+    },
+    
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.getZoomLevel();
+    },
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        return this.mapObject.convertXYLatLon(moPixel);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        return this.mapObject.convertLatLonXY(moLonLat);
+    },
+
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.Lon, moLonLat.Lat).lon :
+            moLonLat.Lon;
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.Lon, moLonLat.Lat).lat :
+            moLonLat.Lat;
+    },
+
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var yLatLong;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            yLatLong = new YGeoPoint(lonlat.lat, lonlat.lon);
+        } else {
+            yLatLong = new YGeoPoint(lat, lon);
+        }
+        return yLatLong;
+    },
+
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new YCoordPoint(x, y);
+    },
+    
+  // Size
+  
+    /**
+     * APIMethod: getMapObjectSizeFromOLSize
+     * 
+     * Parameters:
+     * olSize - {<OpenLayers.Size>}
+     * 
+     * Returns:
+     * {Object} MapObject Size from olSize parameter
+     */
+    getMapObjectSizeFromOLSize: function(olSize) {
+        return new YSize(olSize.w, olSize.h);
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.Yahoo"
+});
+/* ======================================================================
+    OpenLayers/Layer/PointGrid.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Vector.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.PointGrid
+ * A point grid layer dynamically generates a regularly spaced grid of point
+ *     features.  This is a specialty layer for cases where an application needs
+ *     a regular grid of points.  It can be used, for example, in an editing
+ *     environment to snap to a grid.
+ *
+ * Create a new vector layer with the <OpenLayers.Layer.PointGrid> constructor.
+ * (code)
+ * // create a grid with points spaced at 10 map units
+ * var points = new OpenLayers.Layer.PointGrid({dx: 10, dy: 10});
+ *
+ * // create a grid with different x/y spacing rotated 15 degrees clockwise.
+ * var points = new OpenLayers.Layer.PointGrid({dx: 5, dy: 10, rotation: 15});
+ * (end)
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Vector>
+ */
+OpenLayers.Layer.PointGrid = OpenLayers.Class(OpenLayers.Layer.Vector, {
+
+    /**
+     * APIProperty: dx
+     * {Number} Point grid spacing in the x-axis direction (map units).  
+     * Read-only.  Use the <setSpacing> method to modify this value.
+     */
+    dx: null,
+
+    /**
+     * APIProperty: dy
+     * {Number} Point grid spacing in the y-axis direction (map units).  
+     * Read-only.  Use the <setSpacing> method to modify this value.
+     */
+    dy: null,
+
+    /**
+     * APIProperty: ratio
+     * {Number} Ratio of the desired grid size to the map viewport size.  
+     * Default is 1.5.  Larger ratios mean the grid is recalculated less often 
+     * while panning.  The <maxFeatures> setting has precedence when determining
+     * grid size.  Read-only.  Use the <setRatio> method to modify this value.
+     */
+    ratio: 1.5,
+
+    /**
+     * APIProperty: maxFeatures
+     * {Number} The maximum number of points to generate in the grid.  Default
+     * is 250.  Read-only.  Use the <setMaxFeatures> method to modify this value.
+     */
+    maxFeatures: 250,
+
+    /**
+     * APIProperty: rotation
+     * {Number} Grid rotation (in degrees clockwise from the positive x-axis).
+     * Default is 0.  Read-only.  Use the <setRotation> method to modify this
+     * value.
+     */
+    rotation: 0,
+
+    /**
+     * APIProperty: origin
+     * {OpenLayers.LonLat} Grid origin.  The grid lattice will be aligned with 
+     * the origin.  If not set at construction, the center of the map's maximum 
+     * extent is used.  Read-only.  Use the <setOrigin> method to modify this 
+     * value.
+     */
+    origin: null,
+
+    /**
+     * Property: gridBounds
+     * {<OpenLayers.Bounds>}  Internally cached grid bounds (with optional 
+     * rotation applied).
+     */
+    gridBounds: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.PointGrid
+     * Creates a new point grid layer.
+     *
+     * Parameters:
+     * config - {Object} An object containing all configuration properties for
+     *     the layer.  The <dx> and <dy> properties are required to be set at 
+     *     construction.  Any other layer properties may be set in this object.
+     */
+    initialize: function(config) {
+        config = config || {};
+        OpenLayers.Layer.Vector.prototype.initialize.apply(this, [config.name, config]);
+    },
+    
+    /** 
+     * Method: setMap
+     * The layer has been added to the map. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {        
+        OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
+        map.events.register("moveend", this, this.onMoveEnd);
+    },
+
+    /**
+     * Method: removeMap
+     * The layer has been removed from the map.
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        map.events.unregister("moveend", this, this.onMoveEnd);
+        OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
+    },
+    
+    /**
+     * APIMethod: setRatio
+     * Set the grid <ratio> property and update the grid.  Can only be called
+     *     after the layer has been added to a map with a center/extent.
+     *
+     * Parameters:
+     * ratio - {Number}
+     */
+    setRatio: function(ratio) {
+        this.ratio = ratio;
+        this.updateGrid(true);
+    },
+    
+    /**
+     * APIMethod: setMaxFeatures
+     * Set the grid <maxFeatures> property and update the grid.  Can only be 
+     *     called after the layer has been added to a map with a center/extent.
+     *
+     * Parameters:
+     * maxFeatures - {Number}
+     */
+    setMaxFeatures: function(maxFeatures) {
+        this.maxFeatures = maxFeatures;
+        this.updateGrid(true);
+    },
+
+    /**
+     * APIMethod: setSpacing
+     * Set the grid <dx> and <dy> properties and update the grid.  If only one
+     *     argument is provided, it will be set as <dx> and <dy>.  Can only be 
+     *     called after the layer has been added to a map with a center/extent.
+     *
+     * Parameters:
+     * dx - {Number}
+     * dy - {Number}
+     */
+    setSpacing: function(dx, dy) {
+        this.dx = dx;
+        this.dy = dy || dx;
+        this.updateGrid(true);
+    },
+    
+    /**
+     * APIMethod: setOrigin
+     * Set the grid <origin> property and update the grid.  Can only be called
+     *     after the layer has been added to a map with a center/extent.
+     *
+     * Parameters:
+     * origin - {<OpenLayers.LonLat>}
+     */
+    setOrigin: function(origin) {
+        this.origin = origin;
+        this.updateGrid(true);
+    },
+    
+    /**
+     * APIMethod: getOrigin
+     * Get the grid <origin> property.
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} The grid origin.
+     */
+    getOrigin: function() {
+        if (!this.origin) {
+            this.origin = this.map.getExtent().getCenterLonLat();
+        }
+        return this.origin;
+    },
+    
+    /**
+     * APIMethod: setRotation
+     * Set the grid <rotation> property and update the grid.  Rotation values
+     *     are in degrees clockwise from the positive x-axis (negative values
+     *     for counter-clockwise rotation).  Can only be called after the layer 
+     *     has been added to a map with a center/extent.
+     *
+     * Parameters:
+     * rotation - {Number} Degrees clockwise from the positive x-axis.
+     */
+    setRotation: function(rotation) {
+        this.rotation = rotation;
+        this.updateGrid(true);
+    },
+    
+    /**
+     * Method: onMoveEnd
+     * Listener for map "moveend" events.
+     */
+    onMoveEnd: function() {
+        this.updateGrid();
+    },
+    
+    /**
+     * Method: getViewBounds
+     * Gets the (potentially rotated) view bounds for grid calculations.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getViewBounds: function() {
+        var bounds = this.map.getExtent();
+        if (this.rotation) {
+            var origin = this.getOrigin();
+            var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
+            var rect = bounds.toGeometry();
+            rect.rotate(-this.rotation, rotationOrigin);
+            bounds = rect.getBounds();
+        }
+        return bounds;
+    },
+    
+    /**
+     * Method: updateGrid
+     * Update the grid.
+     *
+     * Parameters:
+     * force - {Boolean} Update the grid even if the previous bounds are still
+     *     valid.
+     */
+    updateGrid: function(force) {
+        if (force || this.invalidBounds()) {
+            var viewBounds = this.getViewBounds();
+            var origin = this.getOrigin();
+            var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
+            var viewBoundsWidth = viewBounds.getWidth();
+            var viewBoundsHeight = viewBounds.getHeight();
+            var aspectRatio = viewBoundsWidth / viewBoundsHeight;
+            var maxHeight = Math.sqrt(this.dx * this.dy * this.maxFeatures / aspectRatio);
+            var maxWidth = maxHeight * aspectRatio; 
+            var gridWidth = Math.min(viewBoundsWidth * this.ratio, maxWidth);
+            var gridHeight = Math.min(viewBoundsHeight * this.ratio, maxHeight);
+            var center = viewBounds.getCenterLonLat();
+            this.gridBounds = new OpenLayers.Bounds(
+                center.lon - (gridWidth / 2),
+                center.lat - (gridHeight / 2),
+                center.lon + (gridWidth / 2),
+                center.lat + (gridHeight / 2)
+            );
+            var rows = Math.floor(gridHeight / this.dy);
+            var cols = Math.floor(gridWidth / this.dx);
+            var gridLeft = origin.lon + (this.dx * Math.ceil((this.gridBounds.left - origin.lon) / this.dx));
+            var gridBottom = origin.lat + (this.dy * Math.ceil((this.gridBounds.bottom - origin.lat) / this.dy));
+            var features = new Array(rows * cols);
+            var x, y, point;
+            for (var i=0; i<cols; ++i) {
+                x = gridLeft + (i * this.dx);
+                for (var j=0; j<rows; ++j) {
+                    y = gridBottom + (j * this.dy);
+                    point = new OpenLayers.Geometry.Point(x, y);
+                    if (this.rotation) {
+                        point.rotate(this.rotation, rotationOrigin);
+                    }
+                    features[(i*rows)+j] = new OpenLayers.Feature.Vector(point);
+                }
+            }
+            this.destroyFeatures(this.features, {silent: true});
+            this.addFeatures(features, {silent: true});
+        }
+    },
+
+    /**
+     * Method: invalidBounds
+     * Determine whether the previously generated point grid is invalid. 
+     *     This occurs when the map bounds extends beyond the previously 
+     *     generated grid bounds.
+     *
+     * Returns:
+     * {Boolean} 
+     */
+    invalidBounds: function() {
+        return !this.gridBounds || !this.gridBounds.containsBounds(this.getViewBounds());
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.PointGrid"
+    
+});
+/* ======================================================================
+    OpenLayers/Layer/Zoomify.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/*
+ * Development supported by a R&D grant DC08P02OUK006 - Old Maps Online
+ * (www.oldmapsonline.org) from Ministry of Culture of the Czech Republic.
+ */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Zoomify
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.Zoomify = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Property: url
+     * {String} URL for root directory with TileGroupX subdirectories.
+     */
+    url: null,
+
+    /**
+     * Property: size
+     * {<OpenLayers.Size>} The Zoomify image size in pixels.
+     */
+    size: null,
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean}
+     */
+    isBaseLayer: true,
+
+    /**
+     * Property: standardTileSize
+     * {Integer} The size of a standard (non-border) square tile in pixels.
+     */
+    standardTileSize: 256,
+
+    /** 
+     * Property: tileOriginCorner
+     * {String} This layer uses top-left as tile origin
+     **/
+    tileOriginCorner: "tl",
+
+    /**
+     * Property: numberOfTiers
+     * {Integer} Depth of the Zoomify pyramid, number of tiers (zoom levels)
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    numberOfTiers: 0,
+
+    /**
+     * Property: tileCountUpToTier
+     * {Array(Integer)} Number of tiles up to the given tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tileCountUpToTier: new Array(),
+
+    /**
+     * Property: tierSizeInTiles
+     * {Array(<OpenLayers.Size>)} Size (in tiles) for each tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierSizeInTiles: new Array(),
+
+    /**
+     * Property: tierImageSize
+     * {Array(<OpenLayers.Size>)} Image size in pixels for each pyramid tier.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierImageSize: new Array(),
+
+    /**
+     * Constructor: OpenLayers.Layer.Zoomify
+     *
+     * Parameters:
+     * name - {String} A name for the layer.
+     * url - {String} - Relative or absolute path to the image or more
+     *        precisly to the TileGroup[X] directories root.
+     *        Flash plugin use the variable name "zoomifyImagePath" for this.
+     * size - {<OpenLayers.Size>} The size (in pixels) of the image.
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, size, options) {
+
+        // initilize the Zoomify pyramid for given size
+        this.initializeZoomify( size );
+
+        var newArguments = [];
+        newArguments.push(name, url, size, {}, options);
+
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },
+
+    /**
+     * Method: initializeZoomify
+     * It generates constants for all tiers of the Zoomify pyramid
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} The size of the image in pixels
+     *
+     */
+    initializeZoomify: function( size ) {
+
+        var imageSize = size.clone();
+        var tiles = new OpenLayers.Size(
+            Math.ceil( imageSize.w / this.standardTileSize ),
+            Math.ceil( imageSize.h / this.standardTileSize )
+            );
+
+        this.tierSizeInTiles.push( tiles );
+        this.tierImageSize.push( imageSize );
+
+        while (imageSize.w > this.standardTileSize ||
+               imageSize.h > this.standardTileSize ) {
+
+            imageSize = new OpenLayers.Size(
+                Math.floor( imageSize.w / 2 ),
+                Math.floor( imageSize.h / 2 )
+                );
+            tiles = new OpenLayers.Size(
+                Math.ceil( imageSize.w / this.standardTileSize ),
+                Math.ceil( imageSize.h / this.standardTileSize )
+                );
+            this.tierSizeInTiles.push( tiles );
+            this.tierImageSize.push( imageSize );
+        }
+
+        this.tierSizeInTiles.reverse();
+        this.tierImageSize.reverse();
+
+        this.numberOfTiers = this.tierSizeInTiles.length;
+
+        this.tileCountUpToTier[0] = 0;
+        for (var i = 1; i < this.numberOfTiers; i++) {
+            this.tileCountUpToTier.push(
+                this.tierSizeInTiles[i-1].w * this.tierSizeInTiles[i-1].h +
+                this.tileCountUpToTier[i-1]
+                );
+        }
+    },
+
+    /**
+     * APIMethod:destroy
+     */
+    destroy: function() {
+        // for now, nothing special to do here.
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
+
+        // Remove from memory the Zoomify pyramid - is that enough?
+        this.tileCountUpToTier.length = 0;
+        this.tierSizeInTiles.length = 0;
+        this.tierImageSize.length = 0;
+
+    },
+
+    /**
+     * APIMethod: clone
+     *
+     * Parameters:
+     * obj - {Object}
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Zoomify>} An exact clone of this <OpenLayers.Layer.Zoomify>
+     */
+    clone: function (obj) {
+
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Zoomify(this.name,
+                                           this.url,
+                                           this.size,
+                                           this.options);
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+        var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+        var z = this.map.getZoom();
+
+        var tileIndex = x + y * this.tierSizeInTiles[z].w + this.tileCountUpToTier[z];
+        var path = "TileGroup" + Math.floor( (tileIndex) / 256 ) +
+            "/" + z + "-" + x + "-" + y + ".jpg";
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(path, url);
+        }
+        return url + path;
+    },
+
+    /**
+     * Method: getImageSize
+     * getImageSize returns size for a particular tile. If bounds are given as
+     * first argument, size is calculated (bottom-right tiles are non square).
+     *
+     */
+    getImageSize: function() {
+        if (arguments.length > 0) {
+            var bounds = this.adjustBounds(arguments[0]);
+            var res = this.map.getResolution();
+            var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+            var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+            var z = this.map.getZoom();
+            var w = this.standardTileSize;
+            var h = this.standardTileSize;
+            if (x == this.tierSizeInTiles[z].w -1 ) {
+                var w = this.tierImageSize[z].w % this.standardTileSize;
+            };
+            if (y == this.tierSizeInTiles[z].h -1 ) {
+                var h = this.tierImageSize[z].h % this.standardTileSize;
+            };
+            return (new OpenLayers.Size(w, h));
+        } else {
+            return this.tileSize;
+        }
+    },
+
+    /**
+     * APIMethod: setMap
+     * When the layer is added to a map, then we can fetch our origin
+     *    (if we don't have one.)
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
+                                                this.map.maxExtent.top);
+    },
+
+    /**
+     * Method: calculateGridLayout
+     * Generate parameters for the grid layout. This
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * origin - {<OpenLayers.LonLat>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, origin, resolution) {
+        var tilelon = resolution * this.tileSize.w;
+        var tilelat = resolution * this.tileSize.h;
+
+        var offsetlon = bounds.left - origin.lon;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = origin.lon + tilecol * tilelon;
+
+        var offsetlat = origin.lat - bounds.top + tilelat;
+        var tilerow = Math.floor(offsetlat/tilelat) - this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = tilerowremain * this.tileSize.h;
+        var tileoffsetlat = origin.lat - tilelat*tilerow;
+
+        return {
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Zoomify"
+});
+/* ======================================================================
+    OpenLayers/Renderer/VML.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Renderer/Elements.js
+ */
+
+/**
+ * Class: OpenLayers.Renderer.VML
+ * Render vector features in browsers with VML capability.  Construct a new
+ * VML renderer with the <OpenLayers.Renderer.VML> constructor.
+ * 
+ * Note that for all calculations in this class, we use (num | 0) to truncate a 
+ * float value to an integer. This is done because it seems that VML doesn't 
+ * support float values.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Renderer.Elements>
+ */
+OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
+
+    /**
+     * Property: xmlns
+     * {String} XML Namespace URN
+     */
+    xmlns: "urn:schemas-microsoft-com:vml",
+    
+    /**
+     * Property: symbolCache
+     * {DOMElement} node holding symbols. This hash is keyed by symbol name,
+     *     and each value is a hash with a "path" and an "extent" property.
+     */
+    symbolCache: {},
+
+    /**
+     * Property: offset
+     * {Object} Hash with "x" and "y" properties
+     */
+    offset: null,
+    
+    /**
+     * Constructor: OpenLayers.Renderer.VML
+     * Create a new VML renderer.
+     *
+     * Parameters:
+     * containerID - {String} The id for the element that contains the renderer
+     */
+    initialize: function(containerID) {
+        if (!this.supported()) { 
+            return; 
+        }
+        if (!document.namespaces.olv) {
+            document.namespaces.add("olv", this.xmlns);
+            var style = document.createStyleSheet();
+            var shapes = ['shape','rect', 'oval', 'fill', 'stroke', 'imagedata', 'group','textbox']; 
+            for (var i = 0, len = shapes.length; i < len; i++) {
+
+                style.addRule('olv\\:' + shapes[i], "behavior: url(#default#VML); " +
+                              "position: absolute; display: inline-block;");
+            }                  
+        }
+        
+        OpenLayers.Renderer.Elements.prototype.initialize.apply(this, 
+                                                                arguments);
+    },
+
+    /**
+     * APIMethod: supported
+     * Determine whether a browser supports this renderer.
+     *
+     * Returns:
+     * {Boolean} The browser supports the VML renderer
+     */
+    supported: function() {
+        return !!(document.namespaces);
+    },    
+
+    /**
+     * Method: setExtent
+     * Set the renderer's extent
+     *
+     * Parameters:
+     * extent - {<OpenLayers.Bounds>}
+     * resolutionChanged - {Boolean}
+     * 
+     * Returns:
+     * {Boolean} true to notify the layer that the new extent does not exceed
+     *     the coordinate range, and the features will not need to be redrawn.
+     */
+    setExtent: function(extent, resolutionChanged) {
+        OpenLayers.Renderer.Elements.prototype.setExtent.apply(this, 
+                                                               arguments);
+        var resolution = this.getResolution();
+    
+        var left = (extent.left/resolution) | 0;
+        var top = (extent.top/resolution - this.size.h) | 0;
+        if (resolutionChanged || !this.offset) {
+            this.offset = {x: left, y: top};
+            left = 0;
+            top = 0;
+        } else {
+            left = left - this.offset.x;
+            top = top - this.offset.y;
+        }
+
+        
+        var org = left + " " + top;
+        this.root.coordorigin = org;
+        var roots = [this.root, this.vectorRoot, this.textRoot];
+        var root;
+        for(var i=0, len=roots.length; i<len; ++i) {
+            root = roots[i];
+
+            var size = this.size.w + " " + this.size.h;
+            root.coordsize = size;
+            
+        }
+        // flip the VML display Y axis upside down so it 
+        // matches the display Y axis of the map
+        this.root.style.flip = "y";
+        
+        return true;
+    },
+
+
+    /**
+     * Method: setSize
+     * Set the size of the drawing surface
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} the size of the drawing surface
+     */
+    setSize: function(size) {
+        OpenLayers.Renderer.prototype.setSize.apply(this, arguments);
+        
+        // setting width and height on all roots to avoid flicker which we
+        // would get with 100% width and height on child roots
+        var roots = [
+            this.rendererRoot,
+            this.root,
+            this.vectorRoot,
+            this.textRoot
+        ];
+        var w = this.size.w + "px";
+        var h = this.size.h + "px";
+        var root;
+        for(var i=0, len=roots.length; i<len; ++i) {
+            root = roots[i];
+            root.style.width = w;
+            root.style.height = h;
+        }
+    },
+
+    /**
+     * Method: getNodeType
+     * Get the node type for a geometry and style
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     * style - {Object}
+     *
+     * Returns:
+     * {String} The corresponding node type for the specified geometry
+     */
+    getNodeType: function(geometry, style) {
+        var nodeType = null;
+        switch (geometry.CLASS_NAME) {
+            case "OpenLayers.Geometry.Point":
+                if (style.externalGraphic) {
+                    nodeType = "olv:rect";
+                } else if (this.isComplexSymbol(style.graphicName)) {
+                    nodeType = "olv:shape";
+                } else {
+                    nodeType = "olv:oval";
+                }
+                break;
+            case "OpenLayers.Geometry.Rectangle":
+                nodeType = "olv:rect";
+                break;
+            case "OpenLayers.Geometry.LineString":
+            case "OpenLayers.Geometry.LinearRing":
+            case "OpenLayers.Geometry.Polygon":
+            case "OpenLayers.Geometry.Curve":
+            case "OpenLayers.Geometry.Surface":
+                nodeType = "olv:shape";
+                break;
+            default:
+                break;
+        }
+        return nodeType;
+    },
+
+    /**
+     * Method: setStyle
+     * Use to set all the style attributes to a VML node.
+     *
+     * Parameters:
+     * node - {DOMElement} An VML element to decorate
+     * style - {Object}
+     * options - {Object} Currently supported options include 
+     *                              'isFilled' {Boolean} and
+     *                              'isStroked' {Boolean}
+     * geometry - {<OpenLayers.Geometry>}
+     */
+    setStyle: function(node, style, options, geometry) {
+        style = style  || node._style;
+        options = options || node._options;
+        var fillColor = style.fillColor;
+
+        if (node._geometryClass === "OpenLayers.Geometry.Point") {
+            if (style.externalGraphic) {
+                options.isFilled = true;
+                if (style.graphicTitle) {
+                    node.title=style.graphicTitle;
+                } 
+                var width = style.graphicWidth || style.graphicHeight;
+                var height = style.graphicHeight || style.graphicWidth;
+                width = width ? width : style.pointRadius*2;
+                height = height ? height : style.pointRadius*2;
+
+                var resolution = this.getResolution();
+                var xOffset = (style.graphicXOffset != undefined) ?
+                    style.graphicXOffset : -(0.5 * width);
+                var yOffset = (style.graphicYOffset != undefined) ?
+                    style.graphicYOffset : -(0.5 * height);
+                
+                node.style.left = (((geometry.x/resolution - this.offset.x)+xOffset) | 0) + "px";
+                node.style.top = (((geometry.y/resolution - this.offset.y)-(yOffset+height)) | 0) + "px";
+                node.style.width = width + "px";
+                node.style.height = height + "px";
+                node.style.flip = "y";
+                
+                // modify fillColor and options for stroke styling below
+                fillColor = "none";
+                options.isStroked = false;
+            } else if (this.isComplexSymbol(style.graphicName)) {
+                var cache = this.importSymbol(style.graphicName);
+                node.path = cache.path;
+                node.coordorigin = cache.left + "," + cache.bottom;
+                var size = cache.size;
+                node.coordsize = size + "," + size;        
+                this.drawCircle(node, geometry, style.pointRadius);
+                node.style.flip = "y";
+            } else {
+                this.drawCircle(node, geometry, style.pointRadius);
+            }
+        }
+
+        // fill 
+        if (options.isFilled) { 
+            node.fillcolor = fillColor; 
+        } else { 
+            node.filled = "false"; 
+        }
+        var fills = node.getElementsByTagName("fill");
+        var fill = (fills.length == 0) ? null : fills[0];
+        if (!options.isFilled) {
+            if (fill) {
+                node.removeChild(fill);
+            }
+        } else {
+            if (!fill) {
+                fill = this.createNode('olv:fill', node.id + "_fill");
+            }
+            fill.opacity = style.fillOpacity;
+
+            if (node._geometryClass === "OpenLayers.Geometry.Point" &&
+                    style.externalGraphic) {
+
+                // override fillOpacity
+                if (style.graphicOpacity) {
+                    fill.opacity = style.graphicOpacity;
+                }
+                
+                fill.src = style.externalGraphic;
+                fill.type = "frame";
+                
+                if (!(style.graphicWidth && style.graphicHeight)) {
+                  fill.aspect = "atmost";
+                }                
+            }
+            if (fill.parentNode != node) {
+                node.appendChild(fill);
+            }
+        }
+
+        // additional rendering for rotated graphics or symbols
+        var rotation = style.rotation;
+        if ((rotation !== undefined || node._rotation !== undefined)) {
+            node._rotation = rotation;
+            if (style.externalGraphic) {
+                this.graphicRotate(node, xOffset, yOffset, style);
+                // make the fill fully transparent, because we now have
+                // the graphic as imagedata element. We cannot just remove
+                // the fill, because this is part of the hack described
+                // in graphicRotate
+                fill.opacity = 0;
+            } else if(node._geometryClass === "OpenLayers.Geometry.Point") {
+                node.style.rotation = rotation || 0;
+            }
+        }
+
+        // stroke 
+        var strokes = node.getElementsByTagName("stroke");
+        var stroke = (strokes.length == 0) ? null : strokes[0];
+        if (!options.isStroked) {
+            node.stroked = false;
+            if (stroke) {
+                stroke.on = false;
+            }
+        } else {
+            if (!stroke) {
+                stroke = this.createNode('olv:stroke', node.id + "_stroke");
+                node.appendChild(stroke);
+            }
+            stroke.on = true;
+            stroke.color = style.strokeColor; 
+            stroke.weight = style.strokeWidth + "px"; 
+            stroke.opacity = style.strokeOpacity;
+            stroke.endcap = style.strokeLinecap == 'butt' ? 'flat' :
+                (style.strokeLinecap || 'round');
+            if (style.strokeDashstyle) {
+                stroke.dashstyle = this.dashStyle(style);
+            }
+        }
+        
+        if (style.cursor != "inherit" && style.cursor != null) {
+            node.style.cursor = style.cursor;
+        }
+        return node;
+    },
+
+    /**
+     * Method: graphicRotate
+     * If a point is to be styled with externalGraphic and rotation, VML fills
+     * cannot be used to display the graphic, because rotation of graphic
+     * fills is not supported by the VML implementation of Internet Explorer.
+     * This method creates a olv:imagedata element inside the VML node,
+     * DXImageTransform.Matrix and BasicImage filters for rotation and
+     * opacity, and a 3-step hack to remove rendering artefacts from the
+     * graphic and preserve the ability of graphics to trigger events.
+     * Finally, OpenLayers methods are used to determine the correct
+     * insertion point of the rotated image, because DXImageTransform.Matrix
+     * does the rotation without the ability to specify a rotation center
+     * point.
+     * 
+     * Parameters:
+     * node    - {DOMElement}
+     * xOffset - {Number} rotation center relative to image, x coordinate
+     * yOffset - {Number} rotation center relative to image, y coordinate
+     * style   - {Object}
+     */
+    graphicRotate: function(node, xOffset, yOffset, style) {
+        var style = style || node._style;
+        var rotation = style.rotation || 0;
+        
+        var aspectRatio, size;
+        if (!(style.graphicWidth && style.graphicHeight)) {
+            // load the image to determine its size
+            var img = new Image();
+            img.onreadystatechange = OpenLayers.Function.bind(function() {
+                if(img.readyState == "complete" ||
+                        img.readyState == "interactive") {
+                    aspectRatio = img.width / img.height;
+                    size = Math.max(style.pointRadius * 2, 
+                        style.graphicWidth || 0,
+                        style.graphicHeight || 0);
+                    xOffset = xOffset * aspectRatio;
+                    style.graphicWidth = size * aspectRatio;
+                    style.graphicHeight = size;
+                    this.graphicRotate(node, xOffset, yOffset, style);
+                }
+            }, this);
+            img.src = style.externalGraphic;
+            
+            // will be called again by the onreadystate handler
+            return;
+        } else {
+            size = Math.max(style.graphicWidth, style.graphicHeight);
+            aspectRatio = style.graphicWidth / style.graphicHeight;
+        }
+        
+        var width = Math.round(style.graphicWidth || size * aspectRatio);
+        var height = Math.round(style.graphicHeight || size);
+        node.style.width = width + "px";
+        node.style.height = height + "px";
+        
+        // Three steps are required to remove artefacts for images with
+        // transparent backgrounds (resulting from using DXImageTransform
+        // filters on svg objects), while preserving awareness for browser
+        // events on images:
+        // - Use the fill as usual (like for unrotated images) to handle
+        //   events
+        // - specify an imagedata element with the same src as the fill
+        // - style the imagedata element with an AlphaImageLoader filter
+        //   with empty src
+        var image = document.getElementById(node.id + "_image");
+        if (!image) {
+            image = this.createNode("olv:imagedata", node.id + "_image");
+            node.appendChild(image);
+        }
+        image.style.width = width + "px";
+        image.style.height = height + "px";
+        image.src = style.externalGraphic;
+        image.style.filter =
+            "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + 
+            "src='', sizingMethod='scale')";
+
+        var rot = rotation * Math.PI / 180;
+        var sintheta = Math.sin(rot);
+        var costheta = Math.cos(rot);
+
+        // do the rotation on the image
+        var filter =
+            "progid:DXImageTransform.Microsoft.Matrix(M11=" + costheta +
+            ",M12=" + (-sintheta) + ",M21=" + sintheta + ",M22=" + costheta +
+            ",SizingMethod='auto expand')\n";
+
+        // set the opacity (needed for the imagedata)
+        var opacity = style.graphicOpacity || style.fillOpacity;
+        if (opacity && opacity != 1) {
+            filter += 
+                "progid:DXImageTransform.Microsoft.BasicImage(opacity=" + 
+                opacity+")\n";
+        }
+        node.style.filter = filter;
+
+        // do the rotation again on a box, so we know the insertion point
+        var centerPoint = new OpenLayers.Geometry.Point(-xOffset, -yOffset);
+        var imgBox = new OpenLayers.Bounds(0, 0, width, height).toGeometry();
+        imgBox.rotate(style.rotation, centerPoint);
+        var imgBounds = imgBox.getBounds();
+
+        node.style.left = Math.round(
+            parseInt(node.style.left) + imgBounds.left) + "px";
+        node.style.top = Math.round(
+            parseInt(node.style.top) - imgBounds.bottom) + "px";
+    },
+
+    /**
+     * Method: postDraw
+     * Does some node postprocessing to work around browser issues:
+     * - Some versions of Internet Explorer seem to be unable to set fillcolor
+     *   and strokecolor to "none" correctly before the fill node is appended
+     *   to a visible vml node. This method takes care of that and sets
+     *   fillcolor and strokecolor again if needed.
+     * - In some cases, a node won't become visible after being drawn. Setting
+     *   style.visibility to "visible" works around that.
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     */
+    postDraw: function(node) {
+        node.style.visibility = "visible";
+        var fillColor = node._style.fillColor;
+        var strokeColor = node._style.strokeColor;
+        if (fillColor == "none" &&
+                node.fillcolor != fillColor) {
+            node.fillcolor = fillColor;
+        }
+        if (strokeColor == "none" &&
+                node.strokecolor != strokeColor) {
+            node.strokecolor = strokeColor;
+        }
+    },
+
+
+    /**
+     * Method: setNodeDimension
+     * Get the geometry's bounds, convert it to our vml coordinate system, 
+     * then set the node's position, size, and local coordinate system.
+     *   
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     */
+    setNodeDimension: function(node, geometry) {
+
+        var bbox = geometry.getBounds();
+        if(bbox) {
+            var resolution = this.getResolution();
+        
+            var scaledBox = 
+                new OpenLayers.Bounds((bbox.left/resolution - this.offset.x) | 0,
+                                      (bbox.bottom/resolution - this.offset.y) | 0,
+                                      (bbox.right/resolution - this.offset.x) | 0,
+                                      (bbox.top/resolution - this.offset.y) | 0);
+            
+            // Set the internal coordinate system to draw the path
+            node.style.left = scaledBox.left + "px";
+            node.style.top = scaledBox.top + "px";
+            node.style.width = scaledBox.getWidth() + "px";
+            node.style.height = scaledBox.getHeight() + "px";
+    
+            node.coordorigin = scaledBox.left + " " + scaledBox.top;
+            node.coordsize = scaledBox.getWidth()+ " " + scaledBox.getHeight();
+        }
+    },
+    
+    /** 
+     * Method: dashStyle
+     * 
+     * Parameters:
+     * style - {Object}
+     * 
+     * Returns:
+     * {String} A VML compliant 'stroke-dasharray' value
+     */
+    dashStyle: function(style) {
+        var dash = style.strokeDashstyle;
+        switch (dash) {
+            case 'solid':
+            case 'dot':
+            case 'dash':
+            case 'dashdot':
+            case 'longdash':
+            case 'longdashdot':
+                return dash;
+            default:
+                // very basic guessing of dash style patterns
+                var parts = dash.split(/[ ,]/);
+                if (parts.length == 2) {
+                    if (1*parts[0] >= 2*parts[1]) {
+                        return "longdash";
+                    }
+                    return (parts[0] == 1 || parts[1] == 1) ? "dot" : "dash";
+                } else if (parts.length == 4) {
+                    return (1*parts[0] >= 2*parts[1]) ? "longdashdot" :
+                        "dashdot";
+                }
+                return "solid";
+        }
+    },
+
+    /**
+     * Method: createNode
+     * Create a new node
+     *
+     * Parameters:
+     * type - {String} Kind of node to draw
+     * id - {String} Id for node
+     *
+     * Returns:
+     * {DOMElement} A new node of the given type and id
+     */
+    createNode: function(type, id) {
+        var node = document.createElement(type);
+        if (id) {
+            node.id = id;
+        }
+        
+        // IE hack to make elements unselectable, to prevent 'blue flash'
+        // while dragging vectors; #1410
+        node.unselectable = 'on';
+        node.onselectstart = OpenLayers.Function.False;
+        
+        return node;    
+    },
+    
+    /**
+     * Method: nodeTypeCompare
+     * Determine whether a node is of a given type
+     *
+     * Parameters:
+     * node - {DOMElement} An VML element
+     * type - {String} Kind of node
+     *
+     * Returns:
+     * {Boolean} Whether or not the specified node is of the specified type
+     */
+    nodeTypeCompare: function(node, type) {
+
+        //split type
+        var subType = type;
+        var splitIndex = subType.indexOf(":");
+        if (splitIndex != -1) {
+            subType = subType.substr(splitIndex+1);
+        }
+
+        //split nodeName
+        var nodeName = node.nodeName;
+        splitIndex = nodeName.indexOf(":");
+        if (splitIndex != -1) {
+            nodeName = nodeName.substr(splitIndex+1);
+        }
+
+        return (subType == nodeName);
+    },
+
+    /**
+     * Method: createRenderRoot
+     * Create the renderer root
+     *
+     * Returns:
+     * {DOMElement} The specific render engine's root element
+     */
+    createRenderRoot: function() {
+        return this.nodeFactory(this.container.id + "_vmlRoot", "div");
+    },
+
+    /**
+     * Method: createRoot
+     * Create the main root element
+     * 
+     * Parameters:
+     * suffix - {String} suffix to append to the id
+     *
+     * Returns:
+     * {DOMElement}
+     */
+    createRoot: function(suffix) {
+        return this.nodeFactory(this.container.id + suffix, "olv:group");
+    },
+    
+    /**************************************
+     *                                    *
+     *     GEOMETRY DRAWING FUNCTIONS     *
+     *                                    *
+     **************************************/
+    
+    /**
+     * Method: drawPoint
+     * Render a point
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement} or false if the point could not be drawn
+     */
+    drawPoint: function(node, geometry) {
+        return this.drawCircle(node, geometry, 1);
+    },
+
+    /**
+     * Method: drawCircle
+     * Render a circle.
+     * Size and Center a circle given geometry (x,y center) and radius
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * radius - {float}
+     * 
+     * Returns:
+     * {DOMElement} or false if the circle could not ne drawn
+     */
+    drawCircle: function(node, geometry, radius) {
+        if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {
+            var resolution = this.getResolution();
+
+            node.style.left = (((geometry.x /resolution - this.offset.x) | 0) - radius) + "px";
+            node.style.top = (((geometry.y /resolution - this.offset.y) | 0) - radius) + "px";
+    
+            var diameter = radius * 2;
+            
+            node.style.width = diameter + "px";
+            node.style.height = diameter + "px";
+            return node;
+        }
+        return false;
+    },
+
+
+    /**
+     * Method: drawLineString
+     * Render a linestring.
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawLineString: function(node, geometry) {
+        return this.drawLine(node, geometry, false);
+    },
+
+    /**
+     * Method: drawLinearRing
+     * Render a linearring
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawLinearRing: function(node, geometry) {
+        return this.drawLine(node, geometry, true);
+    },
+
+    /**
+     * Method: DrawLine
+     * Render a line.
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * closeLine - {Boolean} Close the line? (make it a ring?)
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawLine: function(node, geometry, closeLine) {
+
+        this.setNodeDimension(node, geometry);
+
+        var resolution = this.getResolution();
+        var numComponents = geometry.components.length;
+        var parts = new Array(numComponents);
+
+        var comp, x, y;
+        for (var i = 0; i < numComponents; i++) {
+            comp = geometry.components[i];
+            x = (comp.x/resolution - this.offset.x) | 0;
+            y = (comp.y/resolution - this.offset.y) | 0;
+            parts[i] = " " + x + "," + y + " l ";
+        }
+        var end = (closeLine) ? " x e" : " e";
+        node.path = "m" + parts.join("") + end;
+        return node;
+    },
+
+    /**
+     * Method: drawPolygon
+     * Render a polygon
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawPolygon: function(node, geometry) {
+        this.setNodeDimension(node, geometry);
+
+        var resolution = this.getResolution();
+    
+        var path = [];
+        var j, jj, points, area, first, second, i, ii, comp, pathComp, x, y;
+        for (j=0, jj=geometry.components.length; j<jj; j++) {
+            path.push("m");
+            points = geometry.components[j].components;
+            // we only close paths of interior rings with area
+            area = (j === 0);
+            first = null;
+            second = null;
+            for (i=0, ii=points.length; i<ii; i++) {
+                comp = points[i];
+                x = (comp.x / resolution - this.offset.x) | 0;
+                y = (comp.y / resolution - this.offset.y) | 0;
+                pathComp = " " + x + "," + y;
+                path.push(pathComp);
+                if (i==0) {
+                    path.push(" l");
+                }
+                if (!area) {
+                    // IE improperly renders sub-paths that have no area.
+                    // Instead of checking the area of every ring, we confirm
+                    // the ring has at least three distinct points.  This does
+                    // not catch all non-zero area cases, but it greatly improves
+                    // interior ring digitizing and is a minor performance hit
+                    // when rendering rings with many points.
+                    if (!first) {
+                        first = pathComp;
+                    } else if (first != pathComp) {
+                        if (!second) {
+                            second = pathComp;
+                        } else if (second != pathComp) {
+                            // stop looking
+                            area = true;
+                        }
+                    }
+                }
+            }
+            path.push(area ? " x " : " ");
+        }
+        path.push("e");
+        node.path = path.join("");
+        return node;
+    },
+
+    /**
+     * Method: drawRectangle
+     * Render a rectangle
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawRectangle: function(node, geometry) {
+        var resolution = this.getResolution();
+    
+        node.style.left = ((geometry.x/resolution - this.offset.x) | 0) + "px";
+        node.style.top = ((geometry.y/resolution - this.offset.y) | 0) + "px";
+        node.style.width = ((geometry.width/resolution) | 0) + "px";
+        node.style.height = ((geometry.height/resolution) | 0) + "px";
+        
+        return node;
+    },
+    
+    /**
+     * Method: drawText
+     * This method is only called by the renderer itself.
+     * 
+     * Parameters: 
+     * featureId - {String}
+     * style -
+     * location - {<OpenLayers.Geometry.Point>}
+     */
+    drawText: function(featureId, style, location) {
+        var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "olv:rect");
+        var textbox = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_textbox", "olv:textbox");
+        
+        var resolution = this.getResolution();
+        label.style.left = ((location.x/resolution - this.offset.x) | 0) + "px";
+        label.style.top = ((location.y/resolution - this.offset.y) | 0) + "px";
+        label.style.flip = "y";
+
+        textbox.innerText = style.label;
+
+        if (style.cursor != "inherit" && style.cursor != null) {
+            textbox.style.cursor = style.cursor;
+        }
+        if (style.fontColor) {
+            textbox.style.color = style.fontColor;
+        }
+        if (style.fontOpacity) {
+            textbox.style.filter = 'alpha(opacity=' + (style.fontOpacity * 100) + ')';
+        }
+        if (style.fontFamily) {
+            textbox.style.fontFamily = style.fontFamily;
+        }
+        if (style.fontSize) {
+            textbox.style.fontSize = style.fontSize;
+        }
+        if (style.fontWeight) {
+            textbox.style.fontWeight = style.fontWeight;
+        }
+        if (style.fontStyle) {
+            textbox.style.fontStyle = style.fontStyle;
+        }
+        if(style.labelSelect === true) {
+            label._featureId = featureId;
+            textbox._featureId = featureId;
+            textbox._geometry = location;
+            textbox._geometryClass = location.CLASS_NAME;
+        }
+        textbox.style.whiteSpace = "nowrap";
+        // fun with IE: IE7 in standards compliant mode does not display any
+        // text with a left inset of 0. So we set this to 1px and subtract one
+        // pixel later when we set label.style.left
+        textbox.inset = "1px,0px,0px,0px";
+
+        if(!label.parentNode) {
+            label.appendChild(textbox);
+            this.textRoot.appendChild(label);
+        }
+
+        var align = style.labelAlign || "cm";
+        if (align.length == 1) {
+            align += "m";
+        }
+        var xshift = textbox.clientWidth *
+            (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);
+        var yshift = textbox.clientHeight *
+            (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);
+        label.style.left = parseInt(label.style.left)-xshift-1+"px";
+        label.style.top = parseInt(label.style.top)+yshift+"px";
+        
+    },
+
+    /**
+     * Method: drawSurface
+     * 
+     * Parameters:
+     * node - {DOMElement}
+     * geometry - {<OpenLayers.Geometry>}
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    drawSurface: function(node, geometry) {
+
+        this.setNodeDimension(node, geometry);
+
+        var resolution = this.getResolution();
+    
+        var path = [];
+        var comp, x, y;
+        for (var i=0, len=geometry.components.length; i<len; i++) {
+            comp = geometry.components[i];
+            x = (comp.x / resolution - this.offset.x) | 0;
+            y = (comp.y / resolution - this.offset.y) | 0;
+            if ((i%3)==0 && (i/3)==0) {
+                path.push("m");
+            } else if ((i%3)==1) {
+                path.push(" c");
+            }
+            path.push(" " + x + "," + y);
+        }
+        path.push(" x e");
+
+        node.path = path.join("");
+        return node;
+    },
+    
+    /**
+     * Method: moveRoot
+     * moves this renderer's root to a different renderer.
+     * 
+     * Parameters:
+     * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
+     * root - {DOMElement} optional root node. To be used when this renderer
+     *     holds roots from multiple layers to tell this method which one to
+     *     detach
+     * 
+     * Returns:
+     * {Boolean} true if successful, false otherwise
+     */
+    moveRoot: function(renderer) {
+        var layer = this.map.getLayer(renderer.container.id);
+        if(layer instanceof OpenLayers.Layer.Vector.RootContainer) {
+            layer = this.map.getLayer(this.container.id);
+        }
+        layer && layer.renderer.clear();
+        OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this, arguments);
+        layer && layer.redraw();
+    },
+    
+    /**
+     * Method: importSymbol
+     * add a new symbol definition from the rendererer's symbol hash
+     * 
+     * Parameters:
+     * graphicName - {String} name of the symbol to import
+     * 
+     * Returns:
+     * {Object} - hash of {DOMElement} "symbol" and {Number} "size"
+     */      
+    importSymbol: function (graphicName)  {
+        var id = this.container.id + "-" + graphicName;
+        
+        // check if symbol already exists in the cache
+        var cache = this.symbolCache[id];
+        if (cache) {
+            return cache;
+        }
+        
+        var symbol = OpenLayers.Renderer.symbol[graphicName];
+        if (!symbol) {
+            throw new Error(graphicName + ' is not a valid symbol name');
+        }
+
+        var symbolExtent = new OpenLayers.Bounds(
+                                    Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
+        
+        var pathitems = ["m"];
+        for (var i=0; i<symbol.length; i=i+2) {
+            var x = symbol[i];
+            var y = symbol[i+1];
+            symbolExtent.left = Math.min(symbolExtent.left, x);
+            symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
+            symbolExtent.right = Math.max(symbolExtent.right, x);
+            symbolExtent.top = Math.max(symbolExtent.top, y);
+
+            pathitems.push(x);
+            pathitems.push(y);
+            if (i == 0) {
+                pathitems.push("l");
+            }
+        }
+        pathitems.push("x e");
+        var path = pathitems.join(" ");
+
+        var diff = (symbolExtent.getWidth() - symbolExtent.getHeight()) / 2;
+        if(diff > 0) {
+            symbolExtent.bottom = symbolExtent.bottom - diff;
+            symbolExtent.top = symbolExtent.top + diff;
+        } else {
+            symbolExtent.left = symbolExtent.left + diff;
+            symbolExtent.right = symbolExtent.right - diff;
+        }
+        
+        cache = {
+            path: path,
+            size: symbolExtent.getWidth(), // equals getHeight() now
+            left: symbolExtent.left,
+            bottom: symbolExtent.bottom
+        };
+        this.symbolCache[id] = cache;
+        
+        return cache;
+    },
+    
+    CLASS_NAME: "OpenLayers.Renderer.VML"
+});
+
+/**
+ * Constant: OpenLayers.Renderer.VML.LABEL_SHIFT
+ * {Object}
+ */
+OpenLayers.Renderer.VML.LABEL_SHIFT = {
+    "l": 0,
+    "c": .5,
+    "r": 1,
+    "t": 0,
+    "m": .5,
+    "b": 1
+};
+/* ======================================================================
+    OpenLayers/Layer/MultiMap.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/EventPane.js
+ * @requires OpenLayers/Layer/FixedZoomLevels.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.MultiMap
+ * Note that MultiMap does not fully support the sphericalMercator
+ * option. See Ticket #953 for more details.
+ * *Deprecated*.  Use OpenLayers.Layer.Bing instead. See #3063
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.EventPane>
+ *  - <OpenLayers.Layer.FixedZoomLevels>
+ */
+OpenLayers.Layer.MultiMap = OpenLayers.Class(
+  OpenLayers.Layer.EventPane, OpenLayers.Layer.FixedZoomLevels, {
+    
+    /** 
+     * Constant: MIN_ZOOM_LEVEL
+     * {Integer} 1 
+     */
+    MIN_ZOOM_LEVEL: 1,
+    
+    /** 
+     * Constant: MAX_ZOOM_LEVEL
+     * {Integer} 17
+     */
+    MAX_ZOOM_LEVEL: 17,
+
+    /** 
+     * Constant: RESOLUTIONS
+     * {Array(Float)} Hardcode these resolutions so that they are more closely
+     *                tied with the standard wms projection
+     */
+    RESOLUTIONS: [
+        9, 
+        1.40625,
+        0.703125,
+        0.3515625,
+        0.17578125,
+        0.087890625,
+        0.0439453125,
+        0.02197265625,
+        0.010986328125,
+        0.0054931640625,
+        0.00274658203125,
+        0.001373291015625,
+        0.0006866455078125,
+        0.00034332275390625,
+        0.000171661376953125,
+        0.0000858306884765625,
+        0.00004291534423828125
+    ],
+
+    /**
+     * APIProperty: type
+     * {?}
+     */
+    type: null,
+
+    /** 
+     * Constructor: OpenLayers.Layer.MultiMap
+     * 
+     * Parameters:
+     * name - {String}
+     * options - {Object}
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
+        OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
+                                                                    arguments);
+        if (this.sphericalMercator) {
+            OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
+            this.initMercatorParameters();
+            this.RESOLUTIONS.unshift(10); 
+        }    
+    },
+    
+    /**
+     * Method: loadMapObject
+     */
+    loadMapObject:function() {
+        try { //crash proofing
+            this.mapObject = new MultimapViewer(this.div);
+        } catch (e) { }
+    },
+
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n(
+            "getLayerWarning", {'layerType':"MM", 'layerLib':"MultiMap"}
+        );
+    },
+
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.goToPosition(center, zoom); 
+    },
+   
+    /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.getCurrentPosition();
+    },
+
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.getZoomFactor();
+    },
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        moPixel.x = moPixel.x - (this.map.getSize().w/2);
+        moPixel.y = moPixel.y - (this.map.getSize().h/2);
+        return this.mapObject.getMapPositionAt(moPixel);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        return this.mapObject.geoPosToContainerPixels(moLonLat);
+    },
+
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.lon, moLonLat.lat).lon :
+            moLonLat.lon;
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+            this.forwardMercator(moLonLat.lon, moLonLat.lat).lat :
+            moLonLat.lat;
+    },
+
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var mmLatLon;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            mmLatLon = new MMLatLon(lonlat.lat, lonlat.lon);
+        } else {
+            mmLatLon = new MMLatLon(lat, lon);
+        }
+        return mmLatLon;
+    },
+
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new MMPoint(x, y);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.MultiMap"
+});
+/* ======================================================================
+    OpenLayers/Protocol/WFS/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol/WFS/v1.js
+ * @requires OpenLayers/Format/WFST/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.WFS.v1_0_0
+ * A WFS v1.0.0 protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.WFS.v1_0_0> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol.WFS.v1>
+ */
+OpenLayers.Protocol.WFS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, {
+    
+    /**
+     * Property: version
+     * {String} WFS version number.
+     */
+    version: "1.0.0",
+    
+    /**
+     * Constructor: OpenLayers.Protocol.WFS.v1_0_0
+     * A class for giving layers WFS v1.0.0 protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * featureType - {String} Local (without prefix) feature typeName (required).
+     * featureNS - {String} Feature namespace (optional).
+     * featurePrefix - {String} Feature namespace alias (optional - only used
+     *     if featureNS is provided).  Default is 'feature'.
+     * geometryName - {String} Name of geometry attribute.  Default is 'the_geom'.
+     */
+   
+    CLASS_NAME: "OpenLayers.Protocol.WFS.v1_0_0" 
+});
+/* ======================================================================
+    OpenLayers/Control/WMTSGetFeatureInfo.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Handler/Hover.js
+ * @requires OpenLayers/Request.js
+ * @requires OpenLayers/Format/WMSGetFeatureInfo.js
+ */
+
+/**
+ * Class: OpenLayers.Control.WMTSGetFeatureInfo
+ * The WMTSGetFeatureInfo control uses a WMTS query to get information about a 
+ *     point on the map.  The information may be in a display-friendly format 
+ *     such as HTML, or a machine-friendly format such as GML, depending on the 
+ *     server's capabilities and the client's configuration.  This control 
+ *     handles click or hover events, attempts to parse the results using an 
+ *     OpenLayers.Format, and fires a 'getfeatureinfo' event for each layer
+ *     queried.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.WMTSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
+
+   /**
+     * APIProperty: hover
+     * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
+     *     Default is false.
+     */
+    hover: false,
+    
+    /**
+     * Property: requestEncoding
+     * {String} One of "KVP" or "REST".  Only KVP encoding is supported at this 
+     *     time.
+     */
+    requestEncoding: "KVP",
+
+    /**
+     * APIProperty: drillDown
+     * {Boolean} Drill down over all WMTS layers in the map. When
+     *     using drillDown mode, hover is not possible.  A getfeatureinfo event
+     *     will be fired for each layer queried.
+     */
+    drillDown: false,
+
+    /**
+     * APIProperty: maxFeatures
+     * {Integer} Maximum number of features to return from a WMTS query. This
+     *     sets the feature_count parameter on WMTS GetFeatureInfo
+     *     requests.
+     */
+    maxFeatures: 10,
+
+    /** APIProperty: clickCallback
+     *  {String} The click callback to register in the
+     *      {<OpenLayers.Handler.Click>} object created when the hover
+     *      option is set to false. Default is "click".
+     */
+    clickCallback: "click",
+    
+    /**
+     * Property: layers
+     * {Array(<OpenLayers.Layer.WMTS>)} The layers to query for feature info.
+     *     If omitted, all map WMTS layers will be considered.
+     */
+    layers: null,
+
+    /**
+     * APIProperty: queryVisible
+     * {Boolean} Filter out hidden layers when searching the map for layers to 
+     *     query.  Default is true.
+     */
+    queryVisible: true,
+
+    /**
+     * Property: infoFormat
+     * {String} The mimetype to request from the server
+     */
+    infoFormat: 'text/html',
+    
+    /**
+     * Property: vendorParams
+     * {Object} Additional parameters that will be added to the request, for
+     * WMTS implementations that support them. This could e.g. look like
+     * (start code)
+     * {
+     *     radius: 5
+     * }
+     * (end)
+     */
+    vendorParams: {},
+    
+    /**
+     * Property: format
+     * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
+     *     Default is <OpenLayers.Format.WMSGetFeatureInfo>.
+     */
+    format: null,
+    
+    /**
+     * Property: formatOptions
+     * {Object} Optional properties to set on the format (if one is not provided
+     *     in the <format> property.
+     */
+    formatOptions: null,
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Additional options for the handlers used by this control, e.g.
+     * (start code)
+     * {
+     *     "click": {delay: 100},
+     *     "hover": {delay: 300}
+     * }
+     * (end)
+     */
+    handlerOptions: null,
+    
+    /**
+     * Property: handler
+     * {Object} Reference to the <OpenLayers.Handler> for this control
+     */
+    handler: null,
+    
+    /**
+     * Property: hoverRequest
+     * {<OpenLayers.Request>} contains the currently running hover request
+     *     (if any).
+     */
+    hoverRequest: null,
+    
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types (in addition to those from <OpenLayers.Control>):
+     * beforegetfeatureinfo - Triggered before each request is sent.
+     *      The event object has an *xy* property with the position of the 
+     *      mouse click or hover event that triggers the request and a *layer*
+     *      property referencing the layer about to be queried.  If a listener
+     *      returns false, the request will not be issued.
+     * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
+     *      The event object has a *text* property with the body of the
+     *      response (String), a *features* property with an array of the
+     *      parsed features, an *xy* property with the position of the mouse
+     *      click or hover event that triggered the request, a *layer* property
+     *      referencing the layer queried and a *request* property with the 
+     *      request itself. If drillDown is set to true, one event will be fired
+     *      for each layer queried.
+     * exception - Triggered when a GetFeatureInfo request fails (with a 
+     *      status other than 200) or whenparsing fails.  Listeners will receive 
+     *      an event with *request*, *xy*, and *layer*  properties.  In the case 
+     *      of a parsing error, the event will also contain an *error* property.
+     */
+    EVENT_TYPES: ["beforegetfeatureinfo", "getfeatureinfo", "exception"],
+    
+    /** 
+     * Property: pending
+     * {Number}  The number of pending requests.
+     */
+    pending: 0,
+
+    /**
+     * Constructor: <OpenLayers.Control.WMTSGetFeatureInfo>
+     *
+     * Parameters:
+     * options - {Object} 
+     */
+    initialize: function(options) {
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.WMTSGetFeatureInfo.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+
+        options = options || {};
+        options.handlerOptions = options.handlerOptions || {};
+
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        if (!this.format) {
+            this.format = new OpenLayers.Format.WMSGetFeatureInfo(
+                options.formatOptions
+            );
+        }
+        
+        if (this.drillDown === true) {
+            this.hover = false;
+        }
+
+        if (this.hover) {
+            this.handler = new OpenLayers.Handler.Hover(
+                this, {
+                    move: this.cancelHover,
+                    pause: this.getInfoForHover
+                },
+                OpenLayers.Util.extend(
+                    this.handlerOptions.hover || {}, {delay: 250}
+                )
+            );
+        } else {
+            var callbacks = {};
+            callbacks[this.clickCallback] = this.getInfoForClick;
+            this.handler = new OpenLayers.Handler.Click(
+                this, callbacks, this.handlerOptions.click || {}
+            );
+        }
+    },
+
+    /**
+     * Method: getInfoForClick 
+     * Called on click
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    getInfoForClick: function(evt) {
+        this.request(evt.xy, {});
+    },
+   
+    /**
+     * Method: getInfoForHover
+     * Pause callback for the hover handler
+     *
+     * Parameters:
+     * evt - {Object}
+     */
+    getInfoForHover: function(evt) {
+        this.request(evt.xy, {hover: true});
+    },
+
+    /**
+     * Method: cancelHover
+     * Cancel callback for the hover handler
+     */
+    cancelHover: function() {
+        if (this.hoverRequest) {
+            --this.pending;
+            if (this.pending <= 0) {
+                OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+                this.pending = 0;
+            }            
+            this.hoverRequest.abort();
+            this.hoverRequest = null;
+        }
+    },
+
+    /**
+     * Method: findLayers
+     * Internal method to get the layers, independent of whether we are
+     *     inspecting the map or using a client-provided array
+     */
+    findLayers: function() {
+        var candidates = this.layers || this.map.layers;
+        var layers = [];
+        var layer;
+        for (var i=candidates.length-1; i>=0; --i) {
+            layer = candidates[i];
+            if (layer instanceof OpenLayers.Layer.WMTS &&
+                layer.requestEncoding === this.requestEncoding &&
+                (!this.queryVisible || layer.getVisibility())) {
+                layers.push(layer);
+                if (!this.drillDown || this.hover) {
+                    break;
+                }
+            }
+        }
+        return layers;
+    },
+    
+    /**
+     * Method: buildRequestOptions
+     * Build an object with the relevant options for the GetFeatureInfo request.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMTS>} A WMTS layer.
+     * xy - {<OpenLayers.Pixel>} The position on the map where the 
+     *     mouse event occurred.
+     */
+    buildRequestOptions: function(layer, xy) {
+        var loc = this.map.getLonLatFromPixel(xy);
+        var getTileUrl = layer.getURL(
+            new OpenLayers.Bounds(loc.lon, loc.lat, loc.lon, loc.lat)
+        );
+        var params = OpenLayers.Util.getParameters(getTileUrl);
+        var tileInfo = layer.getTileInfo(loc);
+        OpenLayers.Util.extend(params, {
+            service: "WMTS",
+            version: layer.version,
+            request: "GetFeatureInfo",
+            infoFormat: this.infoFormat,
+            i: tileInfo.i,
+            j: tileInfo.j
+        });
+        OpenLayers.Util.applyDefaults(params, this.vendorParams);
+        return {
+            url: OpenLayers.Util.isArray(layer.url) ? layer.url[0] : layer.url,
+            params: OpenLayers.Util.upperCaseObject(params),
+            callback: function(request) {
+                this.handleResponse(xy, request, layer);
+            },
+            scope: this
+        };
+    },
+
+    /**
+     * Method: request
+     * Sends a GetFeatureInfo request to the WMTS
+     * 
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event 
+     *     occurred.
+     * options - {Object} additional options for this method.
+     * 
+     * Valid options:
+     * - *hover* {Boolean} true if we do the request for the hover handler
+     */
+    request: function(xy, options) {
+        options = options || {};
+        var layers = this.findLayers();
+        if (layers.length > 0) {
+            var issue, layer;
+            for (var i=0, len=layers.length; i<len; i++) {
+                layer = layers[i];
+                issue = this.events.triggerEvent("beforegetfeatureinfo", {
+                    xy: xy,
+                    layer: layer
+                });
+                if (issue !== false) {
+                    ++this.pending;
+                    var requestOptions = this.buildRequestOptions(layer, xy);
+                    var request = OpenLayers.Request.GET(requestOptions);
+                    if (options.hover === true) {
+                        this.hoverRequest = request;
+                    }
+                }
+            }
+            if (this.pending > 0) {
+                OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+            }
+        }
+    },
+
+    /**
+     * Method: handleResponse
+     * Handler for the GetFeatureInfo response.
+     * 
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event 
+     *     occurred.
+     * request - {XMLHttpRequest} The request object.
+     * layer - {<OpenLayers.Layer.WMTS>} The queried layer.
+     */
+    handleResponse: function(xy, request, layer) {
+        --this.pending;
+        if (this.pending <= 0) {
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+            this.pending = 0;
+        }
+        if (request.status && (request.status < 200 || request.status >= 300)) {
+            this.events.triggerEvent("exception", {
+                xy: xy, 
+                request: request,
+                layer: layer
+            });
+        } else {
+            var doc = request.responseXML;
+            if (!doc || !doc.documentElement) {
+                doc = request.responseText;
+            }
+            var features, except;
+            try {
+                features = this.format.read(doc);
+            } catch (error) {
+                except = true;
+                this.events.triggerEvent("exception", {
+                    xy: xy,
+                    request: request,
+                    error: error,
+                    layer: layer
+                });
+            }
+            if (!except) {
+                this.events.triggerEvent("getfeatureinfo", {
+                    text: request.responseText,
+                    features: features,
+                    request: request,
+                    xy: xy,
+                    layer: layer
+                });
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.WMTSGetFeatureInfo"
+});
+/* ======================================================================
+    OpenLayers/Control/Graticule.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Graticule
+ * The Graticule displays a grid of latitude/longitude lines reprojected on
+ * the map.  
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ *  
+ */
+OpenLayers.Control.Graticule = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map. Default is
+     *     true. 
+     */
+    autoActivate: true,
+    
+    /**
+    * APIProperty: intervals
+    * {Array(Float)} A list of possible graticule widths in degrees.
+    */
+    intervals: [ 45, 30, 20, 10, 5, 2, 1,
+                 0.5, 0.2, 0.1, 0.05, 0.01, 
+                 0.005, 0.002, 0.001 ],
+
+    /**
+     * APIProperty: displayInLayerSwitcher
+     * {Boolean} Allows the Graticule control to be switched on and off by 
+     *     LayerSwitcher control. Defaults is true.
+     */
+    displayInLayerSwitcher: true,
+
+    /**
+     * APIProperty: visible
+     * {Boolean} should the graticule be initially visible (default=true)
+     */
+    visible: true,
+
+    /**
+     * APIProperty: numPoints
+     * {Integer} The number of points to use in each graticule line.  Higher
+     * numbers result in a smoother curve for projected maps 
+     */
+    numPoints: 50,
+
+    /**
+     * APIProperty: targetSize
+     * {Integer} The maximum size of the grid in pixels on the map
+     */
+    targetSize: 200,
+
+    /**
+     * APIProperty: layerName
+     * {String} The name to be displayed in the layer switcher, default is set 
+     *     by {<OpenLayers.Lang>}.
+     */
+    layerName: null,
+
+    /**
+     * APIProperty: labelled
+     * {Boolean} Should the graticule lines be labelled?. default=true
+     */
+    labelled: true,
+
+    /**
+     * APIProperty: labelFormat
+     * {String} the format of the labels, default = 'dm'. See
+     * <OpenLayers.Util.getFormattedLonLat> for other options.
+     */
+    labelFormat: 'dm',
+
+    /**
+     * APIProperty: lineSymbolizer
+     * {symbolizer} the symbolizer used to render lines
+     */
+    lineSymbolizer: {
+                strokeColor: "#333",
+                strokeWidth: 1,
+                strokeOpacity: 0.5
+            },
+
+    /**
+     * APIProperty: labelSymbolizer
+     * {symbolizer} the symbolizer used to render labels
+     */
+     labelSymbolizer: {},
+
+    /**
+     * Property: gratLayer
+     * {OpenLayers.Layer.Vector} vector layer used to draw the graticule on
+     */
+    gratLayer: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Graticule
+     * Create a new graticule control to display a grid of latitude longitude
+     * lines.
+     * 
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        options = options || {};
+        options.layerName = options.layerName || OpenLayers.i18n("Graticule");
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        this.labelSymbolizer.stroke = false;
+        this.labelSymbolizer.fill = false;
+        this.labelSymbolizer.label = "${label}";
+        this.labelSymbolizer.labelAlign = "${labelAlign}";
+        this.labelSymbolizer.labelXOffset = "${xOffset}";
+        this.labelSymbolizer.labelYOffset = "${yOffset}";
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.deactivate();        
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);        
+        if (this.gratLayer) {
+            this.gratLayer.destroy();
+            this.gratLayer = null;
+        }
+    },
+    
+    /**
+     * Method: draw
+     *
+     * initializes the graticule layer and does the initial update
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        if (!this.gratLayer) {
+            var gratStyle = new OpenLayers.Style({},{
+                rules: [new OpenLayers.Rule({'symbolizer':
+                    {"Point":this.labelSymbolizer,
+                     "Line":this.lineSymbolizer}
+                })]
+            });
+            this.gratLayer = new OpenLayers.Layer.Vector(this.layerName, {
+                styleMap: new OpenLayers.StyleMap({'default':gratStyle}),
+                visibility: this.visible,
+                displayInLayerSwitcher: this.displayInLayerSwitcher
+            });
+        }
+        return this.div;
+    },
+
+     /**
+     * APIMethod: activate
+     */
+    activate: function() {
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.map.addLayer(this.gratLayer);
+            this.map.events.register('moveend', this, this.update);     
+            this.update();
+            return true;            
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.map.events.unregister('moveend', this, this.update);
+            this.map.removeLayer(this.gratLayer);
+            return true;
+        } else {
+            return false;
+        }
+    },
+    /**
+     * Method: update
+     *
+     * calculates the grid to be displayed and actually draws it
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    update: function() {
+        //wait for the map to be initialized before proceeding
+        var mapBounds = this.map.getExtent();
+        if (!mapBounds) {
+            return;
+        }
+        
+        //clear out the old grid
+        this.gratLayer.destroyFeatures();
+        
+        //get the projection objects required
+        var llProj = new OpenLayers.Projection("EPSG:4326");
+        var mapProj = this.map.getProjectionObject();
+        var mapRes = this.map.getResolution();
+        
+        //if the map is in lon/lat, then the lines are straight and only one
+        //point is required
+        if (mapProj.proj && mapProj.proj.projName == "longlat") {
+            this.numPoints = 1;
+        }
+        
+        //get the map center in EPSG:4326
+        var mapCenter = this.map.getCenter(); //lon and lat here are really map x and y
+        var mapCenterLL = new OpenLayers.Pixel(mapCenter.lon, mapCenter.lat);
+        OpenLayers.Projection.transform(mapCenterLL, mapProj, llProj);
+        
+        /* This block of code determines the lon/lat interval to use for the
+         * grid by calculating the diagonal size of one grid cell at the map
+         * center.  Iterates through the intervals array until the diagonal
+         * length is less than the targetSize option.
+         */
+        //find lat/lon interval that results in a grid of less than the target size
+        var testSq = this.targetSize*mapRes;
+        testSq *= testSq;   //compare squares rather than doing a square root to save time
+        var llInterval;
+        for (var i=0; i<this.intervals.length; ++i) {
+            llInterval = this.intervals[i];   //could do this for both x and y??
+            var delta = llInterval/2;  
+            var p1 = mapCenterLL.offset(new OpenLayers.Pixel(-delta, -delta));  //test coords in EPSG:4326 space
+            var p2 = mapCenterLL.offset(new OpenLayers.Pixel( delta,  delta));
+            OpenLayers.Projection.transform(p1, llProj, mapProj); // convert them back to map projection
+            OpenLayers.Projection.transform(p2, llProj, mapProj);
+            var distSq = (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y);
+            if (distSq <= testSq) {
+                break;
+            }
+        }
+        //alert(llInterval);
+        
+        //round the LL center to an even number based on the interval
+        mapCenterLL.x = Math.floor(mapCenterLL.x/llInterval)*llInterval;
+        mapCenterLL.y = Math.floor(mapCenterLL.y/llInterval)*llInterval;
+        //TODO adjust for minutses/seconds?
+        
+        /* The following 2 blocks calculate the nodes of the grid along a 
+         * line of constant longitude (then latitiude) running through the
+         * center of the map until it reaches the map edge.  The calculation
+         * goes from the center in both directions to the edge.
+         */
+        //get the central longitude line, increment the latitude
+        var iter = 0;
+        var centerLonPoints = [mapCenterLL.clone()];
+        var newPoint = mapCenterLL.clone();
+        var mapXY;
+        do {
+            newPoint = newPoint.offset(new OpenLayers.Pixel(0,llInterval));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLonPoints.unshift(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        newPoint = mapCenterLL.clone();
+        do {          
+            newPoint = newPoint.offset(new OpenLayers.Pixel(0,-llInterval));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLonPoints.push(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        
+        //get the central latitude line, increment the longitude
+        iter = 0;
+        var centerLatPoints = [mapCenterLL.clone()];
+        newPoint = mapCenterLL.clone();
+        do {
+            newPoint = newPoint.offset(new OpenLayers.Pixel(-llInterval, 0));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLatPoints.unshift(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        newPoint = mapCenterLL.clone();
+        do {          
+            newPoint = newPoint.offset(new OpenLayers.Pixel(llInterval, 0));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLatPoints.push(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        
+        //now generate a line for each node in the central lat and lon lines
+        //first loop over constant longitude
+        var lines = [];
+        for(var i=0; i < centerLatPoints.length; ++i) {
+            var lon = centerLatPoints[i].x;
+            var pointList = [];
+            var labelPoint = null;
+            var latEnd = Math.min(centerLonPoints[0].y, 90);
+            var latStart = Math.max(centerLonPoints[centerLonPoints.length - 1].y, -90);
+            var latDelta = (latEnd - latStart)/this.numPoints;
+            var lat = latStart;
+            for(var j=0; j<= this.numPoints; ++j) {
+                var gridPoint = new OpenLayers.Geometry.Point(lon,lat);
+                gridPoint.transform(llProj, mapProj);
+                pointList.push(gridPoint);
+                lat += latDelta;
+                if (gridPoint.y >= mapBounds.bottom && !labelPoint) {
+                    labelPoint = gridPoint;
+                }
+            }
+            if (this.labelled) {
+                //keep track of when this grid line crosses the map bounds to set
+                //the label position
+                //labels along the bottom, add 10 pixel offset up into the map
+                //TODO add option for labels on top
+                var labelPos = new OpenLayers.Geometry.Point(labelPoint.x,mapBounds.bottom);
+                var labelAttrs = {
+                    value: lon,
+                    label: this.labelled?OpenLayers.Util.getFormattedLonLat(lon, "lon", this.labelFormat):"",
+                    labelAlign: "cb",
+                    xOffset: 0,
+                    yOffset: 2
+                }; 
+                this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));
+            }
+            var geom = new OpenLayers.Geometry.LineString(pointList);
+            lines.push(new OpenLayers.Feature.Vector(geom));
+        }
+        
+        //now draw the lines of constant latitude
+        for (var j=0; j < centerLonPoints.length; ++j) {
+            lat = centerLonPoints[j].y;
+            if (lat<-90 || lat>90) {  //latitudes only valid between -90 and 90
+                continue;
+            }
+            var pointList = [];
+            var lonStart = centerLatPoints[0].x;
+            var lonEnd = centerLatPoints[centerLatPoints.length - 1].x;
+            var lonDelta = (lonEnd - lonStart)/this.numPoints;
+            var lon = lonStart;
+            var labelPoint = null;
+            for(var i=0; i <= this.numPoints ; ++i) {
+                var gridPoint = new OpenLayers.Geometry.Point(lon,lat);
+                gridPoint.transform(llProj, mapProj);
+                pointList.push(gridPoint);
+                lon += lonDelta;
+                if (gridPoint.x < mapBounds.right) {
+                    labelPoint = gridPoint;
+                }
+            }
+            if (this.labelled) {
+                //keep track of when this grid line crosses the map bounds to set
+                //the label position
+                //labels along the right, 30 pixel offset left into the map
+                //TODO add option for labels on left
+                var labelPos = new OpenLayers.Geometry.Point(mapBounds.right, labelPoint.y); 
+                var labelAttrs = {
+                    value: lat,
+                    label: this.labelled?OpenLayers.Util.getFormattedLonLat(lat, "lat", this.labelFormat):"",
+                    labelAlign: "rb",
+                    xOffset: -2,
+                    yOffset: 2
+                }; 
+                this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));
+            }
+            var geom = new OpenLayers.Geometry.LineString(pointList);
+            lines.push(new OpenLayers.Feature.Vector(geom));
+          }
+          this.gratLayer.addFeatures(lines);
+    },
+    
+    CLASS_NAME: "OpenLayers.Control.Graticule"
+});
+
+/* ======================================================================
+    OpenLayers/Control/NavigationHistory.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Control/Button.js
+ */
+
+/**
+ * Class: OpenLayers.Control.NavigationHistory
+ * A navigation history control.  This is a meta-control, that creates two
+ *     dependent controls: <previous> and <next>.  Call the trigger method
+ *     on the <previous> and <next> controls to restore previous and next
+ *     history states.  The previous and next controls will become active
+ *     when there are available states to restore and will become deactive
+ *     when there are no states to restore.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.NavigationHistory = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Property: type
+     * {String} Note that this control is not intended to be added directly
+     *     to a control panel.  Instead, add the sub-controls previous and
+     *     next.  These sub-controls are button type controls that activate
+     *     and deactivate themselves.  If this parent control is added to
+     *     a panel, it will act as a toggle.
+     */
+    type: OpenLayers.Control.TYPE_TOGGLE,
+
+    /**
+     * APIProperty: previous
+     * {<OpenLayers.Control>} A button type control whose trigger method restores
+     *     the previous state managed by this control.
+     */
+    previous: null,
+    
+    /**
+     * APIProperty: previousOptions
+     * {Object} Set this property on the options argument of the constructor
+     *     to set optional properties on the <previous> control.
+     */
+    previousOptions: null,
+    
+    /**
+     * APIProperty: next
+     * {<OpenLayers.Control>} A button type control whose trigger method restores
+     *     the next state managed by this control.
+     */
+    next: null,
+
+    /**
+     * APIProperty: nextOptions
+     * {Object} Set this property on the options argument of the constructor
+     *     to set optional properties on the <next> control.
+     */
+    nextOptions: null,
+
+    /**
+     * APIProperty: limit
+     * {Integer} Optional limit on the number of history items to retain.  If
+     *     null, there is no limit.  Default is 50.
+     */
+    limit: 50,
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
+     * Property: clearOnDeactivate
+     * {Boolean} Clear the history when the control is deactivated.  Default
+     *     is false.
+     */
+    clearOnDeactivate: false,
+
+    /**
+     * Property: registry
+     * {Object} An object with keys corresponding to event types.  Values
+     *     are functions that return an object representing the current state.
+     */
+    registry: null,
+
+    /**
+     * Property: nextStack
+     * {Array} Array of items in the history.
+     */
+    nextStack: null,
+
+    /**
+     * Property: previousStack
+     * {Array} List of items in the history.  First item represents the current
+     *     state.
+     */
+    previousStack: null,
+    
+    /**
+     * Property: listeners
+     * {Object} An object containing properties corresponding to event types.
+     *     This object is used to configure the control and is modified on
+     *     construction.
+     */
+    listeners: null,
+    
+    /**
+     * Property: restoring
+     * {Boolean} Currently restoring a history state.  This is set to true
+     *     before calling restore and set to false after restore returns.
+     */
+    restoring: false,
+    
+    /**
+     * Constructor: OpenLayers.Control.NavigationHistory 
+     * 
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        this.registry = OpenLayers.Util.extend({
+            "moveend": this.getState
+        }, this.registry);
+        
+        var previousOptions = {
+            trigger: OpenLayers.Function.bind(this.previousTrigger, this),
+            displayClass: this.displayClass + " " + this.displayClass + "Previous"
+        };
+        OpenLayers.Util.extend(previousOptions, this.previousOptions);
+        this.previous = new OpenLayers.Control.Button(previousOptions);
+        
+        var nextOptions = {
+            trigger: OpenLayers.Function.bind(this.nextTrigger, this),
+            displayClass: this.displayClass + " " + this.displayClass + "Next"
+        };
+        OpenLayers.Util.extend(nextOptions, this.nextOptions);
+        this.next = new OpenLayers.Control.Button(nextOptions);
+
+        this.clear();
+    },
+    
+    /**
+     * Method: onPreviousChange
+     * Called when the previous history stack changes.
+     *
+     * Parameters:
+     * state - {Object} An object representing the state to be restored
+     *     if previous is triggered again or null if no previous states remain.
+     * length - {Integer} The number of remaining previous states that can
+     *     be restored.
+     */
+    onPreviousChange: function(state, length) {
+        if(state && !this.previous.active) {
+            this.previous.activate();
+        } else if(!state && this.previous.active) {
+            this.previous.deactivate();
+        }
+    },
+    
+    /**
+     * Method: onNextChange
+     * Called when the next history stack changes.
+     *
+     * Parameters:
+     * state - {Object} An object representing the state to be restored
+     *     if next is triggered again or null if no next states remain.
+     * length - {Integer} The number of remaining next states that can
+     *     be restored.
+     */
+    onNextChange: function(state, length) {
+        if(state && !this.next.active) {
+            this.next.activate();
+        } else if(!state && this.next.active) {
+            this.next.deactivate();
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Destroy the control.
+     */
+    destroy: function() {
+        OpenLayers.Control.prototype.destroy.apply(this);
+        this.previous.destroy();
+        this.next.destroy();
+        this.deactivate();
+        for(var prop in this) {
+            this[prop] = null;
+        }
+    },
+    
+    /** 
+     * Method: setMap
+     * Set the map property for the control and <previous> and <next> child
+     *     controls.
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        this.map = map;
+        this.next.setMap(map);
+        this.previous.setMap(map);
+    },
+
+    /**
+     * Method: draw
+     * Called when the control is added to the map.
+     */
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        this.next.draw();
+        this.previous.draw();
+    },
+    
+    /**
+     * Method: previousTrigger
+     * Restore the previous state.  If no items are in the previous history
+     *     stack, this has no effect.
+     *
+     * Returns:
+     * {Object} Item representing state that was restored.  Undefined if no
+     *     items are in the previous history stack.
+     */
+    previousTrigger: function() {
+        var current = this.previousStack.shift();
+        var state = this.previousStack.shift();
+        if(state != undefined) {
+            this.nextStack.unshift(current);
+            this.previousStack.unshift(state);
+            this.restoring = true;
+            this.restore(state);
+            this.restoring = false;
+            this.onNextChange(this.nextStack[0], this.nextStack.length);
+            this.onPreviousChange(
+                this.previousStack[1], this.previousStack.length - 1
+            );
+        } else {
+            this.previousStack.unshift(current);
+        }
+        return state;
+    },
+    
+    /**
+     * APIMethod: nextTrigger
+     * Restore the next state.  If no items are in the next history
+     *     stack, this has no effect.  The next history stack is populated
+     *     as states are restored from the previous history stack.
+     *
+     * Returns:
+     * {Object} Item representing state that was restored.  Undefined if no
+     *     items are in the next history stack.
+     */
+    nextTrigger: function() {
+        var state = this.nextStack.shift();
+        if(state != undefined) {
+            this.previousStack.unshift(state);
+            this.restoring = true;
+            this.restore(state);
+            this.restoring = false;
+            this.onNextChange(this.nextStack[0], this.nextStack.length);
+            this.onPreviousChange(
+                this.previousStack[1], this.previousStack.length - 1
+            );
+        }
+        return state;
+    },
+    
+    /**
+     * APIMethod: clear
+     * Clear history.
+     */
+    clear: function() {
+        this.previousStack = [];
+        this.previous.deactivate();
+        this.nextStack = [];
+        this.next.deactivate();
+    },
+
+    /**
+     * Method: getState
+     * Get the current state and return it.
+     *
+     * Returns:
+     * {Object} An object representing the current state.
+     */
+    getState: function() {
+        return {
+            center: this.map.getCenter(),
+            resolution: this.map.getResolution(),
+            projection: this.map.getProjectionObject(),
+            units: this.map.getProjectionObject().getUnits() || 
+                this.map.units || this.map.baseLayer.units
+        };
+    },
+
+    /**
+     * Method: restore
+     * Update the state with the given object.
+     *
+     * Parameters:
+     * state - {Object} An object representing the state to restore.
+     */
+    restore: function(state) {
+        var center, zoom;
+        if (this.map.getProjectionObject() == state.projection) { 
+            zoom = this.map.getZoomForResolution(state.resolution);
+            center = state.center;
+        } else {
+            center = state.center.clone();
+            center.transform(state.projection, this.map.getProjectionObject());
+            var sourceUnits = state.units;
+            var targetUnits = this.map.getProjectionObject().getUnits() || 
+                this.map.units || this.map.baseLayer.units;
+            var resolutionFactor = sourceUnits && targetUnits ? 
+                OpenLayers.INCHES_PER_UNIT[sourceUnits] / OpenLayers.INCHES_PER_UNIT[targetUnits] : 1;
+            zoom = this.map.getZoomForResolution(resolutionFactor*state.resolution); 
+        }
+        this.map.setCenter(center, zoom);
+    },
+    
+    /**
+     * Method: setListeners
+     * Sets functions to be registered in the listeners object.
+     */
+    setListeners: function() {
+        this.listeners = {};
+        for(var type in this.registry) {
+            this.listeners[type] = OpenLayers.Function.bind(function() {
+                if(!this.restoring) {
+                    var state = this.registry[type].apply(this, arguments);
+                    this.previousStack.unshift(state);
+                    if(this.previousStack.length > 1) {
+                        this.onPreviousChange(
+                            this.previousStack[1], this.previousStack.length - 1
+                        );
+                    }
+                    if(this.previousStack.length > (this.limit + 1)) {
+                        this.previousStack.pop();
+                    }
+                    if(this.nextStack.length > 0) {
+                        this.nextStack = [];
+                        this.onNextChange(null, 0);
+                    }
+                }
+                return true;
+            }, this);
+        }
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the control.  This registers any listeners.
+     *
+     * Returns:
+     * {Boolean} Control successfully activated.
+     */
+    activate: function() {
+        var activated = false;
+        if(this.map) {
+            if(OpenLayers.Control.prototype.activate.apply(this)) {
+                if(this.listeners == null) {
+                    this.setListeners();
+                }
+                for(var type in this.listeners) {
+                    this.map.events.register(type, this, this.listeners[type]);
+                }
+                activated = true;
+                if(this.previousStack.length == 0) {
+                    this.initStack();
+                }
+            }
+        }
+        return activated;
+    },
+    
+    /**
+     * Method: initStack
+     * Called after the control is activated if the previous history stack is
+     *     empty.
+     */
+    initStack: function() {
+        if(this.map.getCenter()) {
+            this.listeners.moveend();
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control.  This unregisters any listeners.
+     *
+     * Returns:
+     * {Boolean} Control successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(this.map) {
+            if(OpenLayers.Control.prototype.deactivate.apply(this)) {
+                for(var type in this.listeners) {
+                    this.map.events.unregister(
+                        type, this, this.listeners[type]
+                    );
+                }
+                if(this.clearOnDeactivate) {
+                    this.clear();
+                }
+                deactivated = true;
+            }
+        }
+        return deactivated;
+    },
+    
+    CLASS_NAME: "OpenLayers.Control.NavigationHistory"
+});
+
+/* ======================================================================
+    OpenLayers/Protocol/Script.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Format/GeoJSON.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.Script
+ * A basic Script protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.Script> constructor.  A script protocol is used to
+ *     get around the same origin policy.  It works with services that return
+ *     JSONP - that is, JSON wrapped in a client-specified callback.  The
+ *     protocol handles fetching and parsing of feature data and sends parsed
+ *     features to the <callback> configured with the protocol.  The protocol
+ *     expects features serialized as GeoJSON by default, but can be configured
+ *     to work with other formats by setting the <format> property.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+OpenLayers.Protocol.Script = OpenLayers.Class(OpenLayers.Protocol, {
+
+    /**
+     * APIProperty: url
+     * {String} Service URL.  The service is expected to return serialized 
+     *     features wrapped in a named callback (where the callback name is
+     *     generated by this protocol).
+     *     Read-only, set through the options passed to the constructor.
+     */
+    url: null,
+
+    /**
+     * APIProperty: params
+     * {Object} Query string parameters to be appended to the URL.
+     *     Read-only, set through the options passed to the constructor.
+     *     Example: {maxFeatures: 50}
+     */
+    params: null,
+    
+    /**
+     * APIProperty: callback
+     * {Object} Function to be called when the <read> operation completes.
+     */
+    callback: null,
+
+    /**
+     * APIProperty: scope
+     * {Object} Optional ``this`` object for the callback. Read-only, set 
+     *     through the options passed to the constructor.
+     */
+    scope: null,
+
+    /**
+     * APIProperty: format
+     * {<OpenLayers.Format>} Format for parsing features.  Default is an 
+     *     <OpenLayers.Format.GeoJSON> format.  If an alternative is provided,
+     *     the format's read method must take an object and return an array
+     *     of features.
+     */
+    format: null,
+
+    /**
+     * APIProperty: callbackKey
+     * {String} The name of the query string parameter that the service 
+     *     recognizes as the callback identifier.  Default is "callback".
+     *     This key is used to generate the URL for the script.  For example
+     *     setting <callbackKey> to "myCallback" would result in a URL like 
+     *     http://example.com/?myCallback=...
+     */
+    callbackKey: "callback",
+
+    /**
+     * APIProperty: callbackPrefix
+     * {String} Where a service requires that the callback query string 
+     *     parameter value is prefixed by some string, this value may be set.
+     *     For example, setting <callbackPrefix> to "foo:" would result in a
+     *     URL like http://example.com/?callback=foo:...  Default is "".
+     */
+    callbackPrefix: "",
+
+    /**
+     * Property: pendingRequests
+     * {Object} References all pending requests.  Property names are script 
+     *     identifiers and property values are script elements.
+     */
+    pendingRequests: null,
+
+    /**
+     * APIProperty: srsInBBOX
+     * {Boolean} Include the SRS identifier in BBOX query string parameter.
+     *     Setting this property has no effect if a custom filterToParams method
+     *     is provided.   Default is false.  If true and the layer has a 
+     *     projection object set, any BBOX filter will be serialized with a 
+     *     fifth item identifying the projection.  
+     *     E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
+     */
+    srsInBBOX: false,
+
+    /**
+     * Constructor: OpenLayers.Protocol.Script
+     * A class for giving layers generic Script protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options include:
+     * url - {String}
+     * params - {Object}
+     * callback - {Function}
+     * scope - {Object}
+     */
+    initialize: function(options) {
+        options = options || {};
+        this.params = {};
+        this.pendingRequests = {};
+        OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
+        if (!this.format) {
+            this.format = new OpenLayers.Format.GeoJSON();
+        }
+
+        if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) {
+            var format = new OpenLayers.Format.QueryStringFilter({
+                srsInBBOX: this.srsInBBOX
+            });
+            this.filterToParams = function(filter, params) {
+                return format.write(filter, params);
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: read
+     * Construct a request for reading new features.
+     *
+     * Parameters:
+     * options - {Object} Optional object for configuring the request.
+     *     This object is modified and should not be reused.
+     *
+     * Valid options:
+     * url - {String} Url for the request.
+     * params - {Object} Parameters to get serialized as a query string.
+     * filter - {<OpenLayers.Filter>} Filter to get serialized as a
+     *     query string.
+     *
+     * Returns:
+     * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
+     *     references the injected script.  This object is also passed to the
+     *     callback function when the request completes, its "features" property
+     *     is then populated with the features received from the server.
+     */
+    read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
+        options = OpenLayers.Util.applyDefaults(options, this.options);
+        options.params = OpenLayers.Util.applyDefaults(
+            options.params, this.options.params
+        );
+        if (options.filter && this.filterToParams) {
+            options.params = this.filterToParams(
+                options.filter, options.params
+            );
+        }
+        var response = new OpenLayers.Protocol.Response({requestType: "read"});
+        var request = this.createRequest(
+            options.url, 
+            options.params, 
+            OpenLayers.Function.bind(function(data) {
+                response.data = data;
+                this.handleRead(response, options);
+            }, this)
+        );
+        response.priv = request;
+        return response;
+    },
+
+    /** 
+     * APIMethod: filterToParams 
+     * Optional method to translate an <OpenLayers.Filter> object into an object 
+     *     that can be serialized as request query string provided.  If a custom 
+     *     method is not provided, any filter will not be serialized. 
+     * 
+     * Parameters: 
+     * filter - {<OpenLayers.Filter>} filter to convert. 
+     * params - {Object} The parameters object. 
+     * 
+     * Returns: 
+     * {Object} The resulting parameters object. 
+     */
+
+    /** 
+     * Method: createRequest
+     * Issues a request for features by creating injecting a script in the 
+     *     document head.
+     *
+     * Parameters:
+     * url - {String} Service URL.
+     * params - {Object} Query string parameters.
+     * callback - {Function} Callback to be called with resulting data.
+     *
+     * Returns:
+     * {HTMLScriptElement} The script pending execution.
+     */
+    createRequest: function(url, params, callback) {
+        var id = OpenLayers.Protocol.Script.register(callback);
+        var name = "OpenLayers.Protocol.Script.registry[" + id + "]";
+        params = OpenLayers.Util.extend({}, params);
+        params[this.callbackKey] = this.callbackPrefix + name;
+        url = OpenLayers.Util.urlAppend(
+            url, OpenLayers.Util.getParameterString(params)
+        );
+        var script = document.createElement("script");
+        script.type = "text/javascript";
+        script.src = url;
+        script.id = "OpenLayers_Protocol_Script_" + id;
+        this.pendingRequests[script.id] = script;
+        var head = document.getElementsByTagName("head")[0];
+        head.appendChild(script);
+        return script;
+    },
+    
+    /** 
+     * Method: destroyRequest
+     * Remove a script node associated with a response from the document.  Also
+     *     unregisters the callback and removes the script from the 
+     *     <pendingRequests> object.
+     *
+     * Parameters:
+     * script - {HTMLScriptElement}
+     */
+    destroyRequest: function(script) {
+        OpenLayers.Protocol.Script.unregister(script.id.split("_").pop());
+        delete this.pendingRequests[script.id];
+        if (script.parentNode) {
+            script.parentNode.removeChild(script);
+        }
+    },
+
+    /**
+     * Method: handleRead
+     * Individual callbacks are created for read, create and update, should
+     *     a subclass need to override each one separately.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     the user callback.
+     * options - {Object} The user options passed to the read call.
+     */
+    handleRead: function(response, options) {
+        this.handleResponse(response, options);
+    },
+
+    /**
+     * Method: handleResponse
+     * Called by CRUD specific handlers.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass to
+     *     any user callback.
+     * options - {Object} The user options passed to the create, read, update,
+     *     or delete call.
+     */
+    handleResponse: function(response, options) {
+        if (options.callback) {
+            if (response.data) {
+                response.features = this.parseFeatures(response.data);
+                response.code = OpenLayers.Protocol.Response.SUCCESS;
+            } else {
+                response.code = OpenLayers.Protocol.Response.FAILURE;
+            }
+            this.destroyRequest(response.priv);
+            options.callback.call(options.scope, response);
+        }
+    },
+
+    /**
+     * Method: parseFeatures
+     * Read Script response body and return features.
+     *
+     * Parameters:
+     * data - {Object} The data sent to the callback function by the server.
+     *
+     * Returns:
+     * {Array({<OpenLayers.Feature.Vector>})} or
+     *     {<OpenLayers.Feature.Vector>} Array of features or a single feature.
+     */
+    parseFeatures: function(data) {
+        return this.format.read(data);
+    },
+
+    /**
+     * APIMethod: abort
+     * Abort an ongoing request.  If no response is provided, all pending 
+     *     requests will be aborted.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object returned
+     *     from a <read> request.
+     */
+    abort: function(response) {
+        if (response) {
+            this.destroyRequest(response.priv);
+        } else {
+            for (var key in this.pendingRequests) {
+                this.destroyRequest(this.pendingRequests[key]);
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        this.abort();
+        delete this.params;
+        delete this.format;
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.Script" 
+});
+
+(function() {
+    var o = OpenLayers.Protocol.Script;
+    var counter = 0;
+    o.registry = [];
+    
+    /**
+     * Function: OpenLayers.Protocol.Script.register
+     * Register a callback for a newly created script.
+     *
+     * Parameters:
+     * callback: {Function} The callback to be executed when the newly added
+     *     script loads.  This callback will be called with a single argument
+     *     that is the JSON returned by the service.
+     *
+     * Returns:
+     * {Number} An identifier for retreiving the registered callback.
+     */
+    o.register = function(callback) {
+        var id = ++counter;
+        o.registry[id] = function() {
+            o.unregister(id);
+            callback.apply(this, arguments);
+        };
+        return id;
+    };
+    
+    /**
+     * Function: OpenLayers.Protocol.Script.unregister
+     * Unregister a callback previously registered with the register function.
+     *
+     * Parameters:
+     * id: {Number} The identifer returned by the register function.
+     */
+    o.unregister = function(id) {
+        delete o.registry[id];
+    };
+})();
+/* ======================================================================
+    OpenLayers/Layer/WMS/Post.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+ 
+/**
+ * @requires OpenLayers/Layer/WMS.js
+ * @requires OpenLayers/Tile/Image/IFrame.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMS.Post
+ * Instances of OpenLayers.Layer.WMS.Post are used to retrieve data from OGC
+ * Web Mapping Services via HTTP-POST (application/x-www-form-urlencoded). 
+ * Create a new WMS layer with the <OpenLayers.Layer.WMS.Post> constructor.
+ *
+ * *Deprecated*. Instead of this layer, use <OpenLayers.Layer.WMS> with
+ * <OpenLayers.Tile.Image.maxGetUrlLength> configured in the layer's
+ * <OpenLayers.Layer.WMS.tileOptions>.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.WMS>
+ */
+OpenLayers.Layer.WMS.Post = OpenLayers.Class(OpenLayers.Layer.WMS, {
+
+    /**
+     * APIProperty: unsupportedBrowsers
+     * {Array} Array with browsers, which should use the HTTP-GET protocol 
+     * instead of HTTP-POST for fetching tiles from a WMS .
+     * Defaults to ["mozilla", "firefox", "opera"], because Opera is not able 
+     * to show transparent images in IFrames and Firefox/Mozilla has some ugly 
+     * effects of viewport-shaking when panning the map. Both browsers, Opera
+     * and Firefox/Mozilla, have no problem with long urls, which is the reason
+     * for using POST instead of GET. The strings to pass to this array are
+     * the ones returned by <OpenLayers.BROWSER_NAME>.
+     */
+    unsupportedBrowsers: ["mozilla", "firefox", "opera"],
+
+    /**
+     * Property: SUPPORTED_TRANSITIONS
+     * {Array} 
+     * no supported transitions for this type of layer, because it is not
+     * possible to modify the initialized tiles (iframes)
+     */
+    SUPPORTED_TRANSITIONS: [],
+    
+    /**
+     * Property: usePost
+     * {Boolean}
+     */
+    usePost: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.WMS.Post
+     * Creates a new WMS layer object.
+     *
+     * Example:
+     * (code)
+     * var wms = new OpenLayers.Layer.WMS.Post(
+     *  "NASA Global Mosaic",
+     *  "http://wms.jpl.nasa.gov/wms.cgi",
+     *  {layers: "modis, global_mosaic"});
+     * (end)
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the WMS
+     *                (e.g. http://wms.jpl.nasa.gov/wms.cgi)
+     * params - {Object} An object with key/value pairs representing the
+     *                   GetMap query string parameters and parameter values.
+     * options - {Object} Hashtable of extra options to tag onto the layer.
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.WMS.prototype.initialize.apply(this, newArguments);
+
+        this.usePost = OpenLayers.Util.indexOf(
+            this.unsupportedBrowsers, OpenLayers.BROWSER_NAME) == -1;
+    },
+    
+    /**
+     * Method: addTile
+     * addTile creates a tile, initializes it and adds it as iframe to the
+     * layer div.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.Tile.Image.IFrame>} The added OpenLayers.Tile.Image.IFrame
+     */
+    addTile: function(bounds,position) {
+        return new OpenLayers.Tile.Image(
+            this, position, bounds, null, this.tileSize, {
+                maxGetUrlLength: this.usePost ? 0 : null
+            });
+    },
+
+    CLASS_NAME: 'OpenLayers.Layer.WMS.Post'
+});
+/* ======================================================================
+    OpenLayers/Control/TransformFeature.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Control/DragFeature.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TransformFeature
+ * Control to transform features with a standard transformation box.
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TransformFeature = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     *  - *beforesetfeature* Triggered before a feature is set for
+     *      tranformation. The feature will not be set if a listener returns
+     *      false. Listeners receive a *feature* property, with the feature
+     *      that will be set for transformation. Listeners are allowed to
+     *      set the control's *scale*, *ratio* and *rotation* properties,
+     *      which will set the initial scale, ratio and rotation of the
+     *      feature, like the <setFeature> method's initialParams argument.
+     *  - *setfeature* Triggered when a feature is set for tranformation.
+     *      Listeners receive a *feature* property, with the feature that
+     *      is now set for transformation.
+     *  - *beforetransform* Triggered while dragging, before a feature is
+     *      transformed. The feature will not be transformed if a listener
+     *      returns false (but the box still will). Listeners receive one or
+     *      more of *center*, *scale*, *ratio* and *rotation*. The *center*
+     *      property is an <OpenLayers.Geometry.Point> object with the new
+     *      center of the transformed feature, the others are Floats with the
+     *      scale, ratio or rotation change since the last transformation.
+     *  - *transform* Triggered while dragging, when a feature is transformed.
+     *      Listeners receive an event object with one or more of *center*,
+     *      *scale*, *ratio* and *rotation*. The *center* property is an
+     *      <OpenLayers.Geometry.Point> object with the new center of the
+     *      transformed feature, the others are Floats with the scale, ratio
+     *      or rotation change of the feature since the last transformation.
+     *  - *transformcomplete* Triggered after dragging. Listeners receive
+     *      an event object with the transformed *feature*.
+     */
+    EVENT_TYPES: ["beforesetfeature", "setfeature", "beforetransform",
+        "transform", "transformcomplete"],
+
+    /**
+     * APIProperty: geometryTypes
+     * {Array(String)} To restrict transformation to a limited set of geometry
+     *     types, send a list of strings corresponding to the geometry class
+     *     names.
+     */
+    geometryTypes: null,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>}
+     */
+    layer: null,
+    
+    /**
+     * APIProperty: preserveAspectRatio
+     * {Boolean} set to true to not change the feature's aspect ratio.
+     */
+    preserveAspectRatio: false,
+    
+    /**
+     * APIProperty: rotate
+     * {Boolean} set to false if rotation should be disabled. Default is true.
+     *     To be passed with the constructor or set when the control is not
+     *     active.
+     */
+    rotate: true,
+    
+    /**
+     * APIProperty: feature
+     * {<OpenLayers.Feature.Vector>} Feature currently available for
+     *     transformation. Read-only, use <setFeature> to set it manually.
+     */
+    feature: null,
+    
+    /**
+     * APIProperty: renderIntent
+     * {String|Object} Render intent for the transformation box and
+     *     handles. A symbolizer object can also be provided here.
+     */
+    renderIntent: "temporary",
+    
+    /**
+     * APIProperty: rotationHandleSymbolizer
+     * {Object|String} Optional. A custom symbolizer for the rotation handles.
+     *     A render intent can also be provided here. Defaults to
+     *     (code)
+     *     {
+     *         stroke: false,
+     *         pointRadius: 10,
+     *         fillOpacity: 0,
+     *         cursor: "pointer"
+     *     }
+     *     (end)
+     */
+    rotationHandleSymbolizer: null,
+    
+    /**
+     * APIProperty: box
+     * {<OpenLayers.Feature.Vector>} The transformation box rectangle.
+     *     Read-only.
+     */
+    box: null,
+    
+    /**
+     * APIProperty: center
+     * {<OpenLayers.Geometry.Point>} The center of the feature bounds.
+     * Read-only.
+     */
+    center: null,
+    
+    /**
+     * APIProperty: scale
+     * {Float} The scale of the feature, relative to the scale the time the
+     *     feature was set. Read-only, except for *beforesetfeature*
+     *     listeners.
+     */
+    scale: 1,
+    
+    /**
+     * APIProperty: ratio
+     * {Float} The ratio of the feature relative to the ratio the time the
+     *     feature was set. Read-only, except for *beforesetfeature*
+     *     listeners.
+     */
+    ratio: 1,
+    
+    /**
+     * Property: rotation
+     * {Integer} the current rotation angle of the box. Read-only, except for
+     *     *beforesetfeature* listeners.
+     */
+    rotation: 0,
+    
+    /**
+     * APIProperty: handles
+     * {Array(<OpenLayers.Feature.Vector>)} The 8 handles currently available
+     *     for scaling/resizing. Numbered counterclockwise, starting from the
+     *     southwest corner. Read-only.
+     */
+    handles: null,
+    
+    /**
+     * APIProperty: rotationHandles
+     * {Array(<OpenLayers.Feature.Vector>)} The 4 rotation handles currently
+     *     available for rotating. Numbered counterclockwise, starting from
+     *     the southwest corner. Read-only.
+     */
+    rotationHandles: null,
+    
+    /**
+     * Property: dragControl
+     * {<OpenLayers.Control.DragFeature>}
+     */
+    dragControl: null,
+    
+    /**
+     * Constructor: OpenLayers.Control.TransformFeature
+     * Create a new transform feature control.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} Layer that contains features that
+     *     will be transformed.
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+    initialize: function(layer, options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.TransformFeature.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+        this.layer = layer;
+
+        if(!this.rotationHandleSymbolizer) {
+            this.rotationHandleSymbolizer = {
+                stroke: false,
+                pointRadius: 10,
+                fillOpacity: 0,
+                cursor: "pointer"
+            };
+        }
+
+        this.createBox();
+        this.createControl();        
+    },
+    
+    /**
+     * APIMethod: activate
+     * Activates the control.
+     */
+    activate: function() {
+        var activated = false;
+        if(OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.dragControl.activate();
+            this.layer.addFeatures([this.box]);
+            this.rotate && this.layer.addFeatures(this.rotationHandles);
+            this.layer.addFeatures(this.handles);        
+            activated = true;
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivates the control.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.layer.removeFeatures(this.handles);
+            this.rotate && this.layer.removeFeatures(this.rotationHandles);
+            this.layer.removeFeatures([this.box]);
+            this.dragControl.deactivate();
+            deactivated = true;
+        }
+        if (deactivated) {
+        	this.unsetFeature();
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        this.dragControl.setMap(map);
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: setFeature
+     * Place the transformation box on a feature and start transforming it.
+     * If the control is not active, it will be activated.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * initialParams - {Object} Initial values for rotation, scale or ratio.
+     *     Setting a rotation value here will cause the transformation box to
+     *     start rotated. Setting a scale or ratio will not affect the
+     *     transormation box, but applications may use this to keep track of
+     *     scale and ratio of a feature across multiple transforms.
+     */
+    setFeature: function(feature, initialParams) {
+        initialParams = OpenLayers.Util.applyDefaults(initialParams, {
+            rotation: 0,
+            scale: 1,
+            ratio: 1
+        });
+
+        var oldRotation = this.rotation;
+        var oldCenter = this.center;
+        OpenLayers.Util.extend(this, initialParams);
+
+        var cont = this.events.triggerEvent("beforesetfeature",
+            {feature: feature}
+        );
+        if (cont === false) {
+            return;
+        }
+
+        this.feature = feature;
+        this.activate();
+
+        this._setfeature = true;
+
+        var featureBounds = this.feature.geometry.getBounds();
+        this.box.move(featureBounds.getCenterLonLat());
+        this.box.geometry.rotate(-oldRotation, oldCenter);
+        this._angle = 0;
+
+        var ll;
+        if(this.rotation) {
+            var geom = feature.geometry.clone();
+            geom.rotate(-this.rotation, this.center);
+            var box = new OpenLayers.Feature.Vector(
+                geom.getBounds().toGeometry());
+            box.geometry.rotate(this.rotation, this.center);
+            this.box.geometry.rotate(this.rotation, this.center);
+            this.box.move(box.geometry.getBounds().getCenterLonLat());
+            var llGeom = box.geometry.components[0].components[0];
+            ll = llGeom.getBounds().getCenterLonLat();
+        } else {
+            ll = new OpenLayers.LonLat(featureBounds.left, featureBounds.bottom);
+        }
+        this.handles[0].move(ll);
+        
+        delete this._setfeature;
+
+        this.events.triggerEvent("setfeature", {feature: feature});
+    },
+    
+    /**
+     * APIMethod: unsetFeature
+     * Remove the transformation box off any feature.
+     * If the control is active, it will be deactivated first.
+     */
+    unsetFeature: function() {
+    	if (this.active) {
+    		this.deactivate();
+    	} else {
+	    	this.feature = null;
+	    	this.rotation = 0;
+	    	this.scale = 1;
+	    	this.ratio = 1;
+    	}
+    },
+    
+    /**
+     * Method: createBox
+     * Creates the box with all handles and transformation handles.
+     */
+    createBox: function() {
+        var control = this;
+        
+        this.center = new OpenLayers.Geometry.Point(0, 0);
+        var box = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LineString([
+                new OpenLayers.Geometry.Point(-1, -1),
+                new OpenLayers.Geometry.Point(0, -1),
+                new OpenLayers.Geometry.Point(1, -1),
+                new OpenLayers.Geometry.Point(1, 0),
+                new OpenLayers.Geometry.Point(1, 1),
+                new OpenLayers.Geometry.Point(0, 1),
+                new OpenLayers.Geometry.Point(-1, 1),
+                new OpenLayers.Geometry.Point(-1, 0),
+                new OpenLayers.Geometry.Point(-1, -1)
+            ]), null,
+            typeof this.renderIntent == "string" ? null : this.renderIntent
+        );
+        
+        // Override for box move - make sure that the center gets updated
+        box.geometry.move = function(x, y) {
+            control._moving = true;
+            OpenLayers.Geometry.LineString.prototype.move.apply(this, arguments);
+            control.center.move(x, y);
+            delete control._moving;
+        };
+
+        // Overrides for vertex move, resize and rotate - make sure that
+        // handle and rotationHandle geometries are also moved, resized and
+        // rotated.
+        var vertexMoveFn = function(x, y) {
+            OpenLayers.Geometry.Point.prototype.move.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.move(x, y);
+            this._handle.geometry.move(x, y);
+        };
+        var vertexResizeFn = function(scale, center, ratio) {
+            OpenLayers.Geometry.Point.prototype.resize.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.resize(
+                scale, center, ratio);
+            this._handle.geometry.resize(scale, center, ratio);
+        };
+        var vertexRotateFn = function(angle, center) {
+            OpenLayers.Geometry.Point.prototype.rotate.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.rotate(
+                angle, center);
+            this._handle.geometry.rotate(angle, center);
+        };
+        
+        // Override for handle move - make sure that the box and other handles
+        // are updated, and finally transform the feature.
+        var handleMoveFn = function(x, y) {
+            var oldX = this.x, oldY = this.y;
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            if(control._moving) {
+                return;
+            }
+            var evt = control.dragControl.handlers.drag.evt;
+            var preserveAspectRatio = !control._setfeature &&
+                control.preserveAspectRatio;
+            var reshape = !preserveAspectRatio && !(evt && evt.shiftKey);
+            var oldGeom = new OpenLayers.Geometry.Point(oldX, oldY);
+            var centerGeometry = control.center;
+            this.rotate(-control.rotation, centerGeometry);
+            oldGeom.rotate(-control.rotation, centerGeometry);
+            var dx1 = this.x - centerGeometry.x;
+            var dy1 = this.y - centerGeometry.y;
+            var dx0 = dx1 - (this.x - oldGeom.x);
+            var dy0 = dy1 - (this.y - oldGeom.y);
+            this.x = oldX;
+            this.y = oldY;
+            var scale, ratio = 1;
+            if (reshape) {
+                scale = Math.abs(dy0) < 0.00001 ? 1 : dy1 / dy0;
+                ratio = (Math.abs(dx0) < 0.00001 ? 1 : (dx1 / dx0)) / scale;
+            } else {
+                var l0 = Math.sqrt((dx0 * dx0) + (dy0 * dy0));
+                var l1 = Math.sqrt((dx1 * dx1) + (dy1 * dy1));
+                scale = l1 / l0;
+            }
+
+            // rotate the box to 0 before resizing - saves us some
+            // calculations and is inexpensive because we don't drawFeature.
+            control._moving = true;
+            control.box.geometry.rotate(-control.rotation, centerGeometry);
+            delete control._moving;
+
+            control.box.geometry.resize(scale, centerGeometry, ratio);
+            control.box.geometry.rotate(control.rotation, centerGeometry);
+            control.transformFeature({scale: scale, ratio: ratio});
+        };
+        
+        // Override for rotation handle move - make sure that the box and
+        // other handles are updated, and finally transform the feature.
+        var rotationHandleMoveFn = function(x, y){
+            var oldX = this.x, oldY = this.y;
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            if(control._moving) {
+                return;
+            }
+            var evt = control.dragControl.handlers.drag.evt;
+            var constrain = (evt && evt.shiftKey) ? 45 : 1;
+            var centerGeometry = control.center;
+            var dx1 = this.x - centerGeometry.x;
+            var dy1 = this.y - centerGeometry.y;
+            var dx0 = dx1 - x;
+            var dy0 = dy1 - y;
+            this.x = oldX;
+            this.y = oldY;
+            var a0 = Math.atan2(dy0, dx0);
+            var a1 = Math.atan2(dy1, dx1);
+            var angle = a1 - a0;
+            angle *= 180 / Math.PI;
+            control._angle = (control._angle + angle) % 360;
+            var diff = control.rotation % constrain;
+            if(Math.abs(control._angle) >= constrain || diff !== 0) {
+                angle = Math.round(control._angle / constrain) * constrain -
+                    diff;
+                control._angle = 0;
+                control.box.geometry.rotate(angle, centerGeometry);
+                control.transformFeature({rotation: angle});
+            } 
+        };
+
+        var handles = new Array(8);
+        var rotationHandles = new Array(4);
+        var geom, handle, rotationHandle;
+        for(var i=0; i<8; ++i) {
+            geom = box.geometry.components[i];
+            handle = new OpenLayers.Feature.Vector(geom.clone(), null,
+                typeof this.renderIntent == "string" ? null :
+                this.renderIntent);
+            if(i % 2 == 0) {
+                rotationHandle = new OpenLayers.Feature.Vector(geom.clone(),
+                    null, typeof this.rotationHandleSymbolizer == "string" ?
+                    null : this.rotationHandleSymbolizer);
+                rotationHandle.geometry.move = rotationHandleMoveFn;
+                geom._rotationHandle = rotationHandle;
+                rotationHandles[i/2] = rotationHandle;
+            }
+            geom.move = vertexMoveFn;
+            geom.resize = vertexResizeFn;
+            geom.rotate = vertexRotateFn;
+            handle.geometry.move = handleMoveFn;
+            geom._handle = handle;
+            handles[i] = handle;
+        }
+        
+        this.box = box;
+        this.rotationHandles = rotationHandles;
+        this.handles = handles;
+    },
+    
+    /**
+     * Method: createControl
+     * Creates a DragFeature control for this control.
+     */
+    createControl: function() {
+        var control = this;
+        this.dragControl = new OpenLayers.Control.DragFeature(this.layer, {
+            documentDrag: true,
+            // avoid moving the feature itself - move the box instead
+            moveFeature: function(pixel) {
+                if(this.feature === control.feature) {
+                    this.feature = control.box;
+                }
+                OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,
+                    arguments);
+            },
+            // transform while dragging
+            onDrag: function(feature, pixel) {
+                if(feature === control.box) {
+                    control.transformFeature({center: control.center});
+                    control.drawHandles();
+                }
+            },
+            // set a new feature
+            onStart: function(feature, pixel) {
+                var eligible = !control.geometryTypes ||
+                    OpenLayers.Util.indexOf(control.geometryTypes,
+                        feature.geometry.CLASS_NAME) !== -1;
+                var i = OpenLayers.Util.indexOf(control.handles, feature);
+                i += OpenLayers.Util.indexOf(control.rotationHandles,
+                    feature);
+                if(feature !== control.feature && feature !== control.box &&
+                                                        i == -2 && eligible) {
+                    control.setFeature(feature);
+                }
+            },
+            onComplete: function(feature, pixel) {
+                control.events.triggerEvent("transformcomplete",
+                    {feature: control.feature});
+            }
+        });
+    },
+    
+    /**
+     * Method: drawHandles
+     * Draws the handles to match the box.
+     */
+    drawHandles: function() {
+        var layer = this.layer;
+        for(var i=0; i<8; ++i) {
+            if(this.rotate && i % 2 === 0) {
+                layer.drawFeature(this.rotationHandles[i/2],
+                    this.rotationHandleSymbolizer);
+            }
+            layer.drawFeature(this.handles[i], this.renderIntent);
+        }
+    },
+    
+    /**
+     * Method: transformFeature
+     * Transforms the feature.
+     * 
+     * Parameters:
+     * mods - {Object} An object with optional scale, ratio, rotation and
+     *     center properties.
+     */
+    transformFeature: function(mods) {
+        if(!this._setfeature) {
+            this.scale *= (mods.scale || 1);
+            this.ratio *= (mods.ratio || 1);
+            var oldRotation = this.rotation;
+            this.rotation = (this.rotation + (mods.rotation || 0)) % 360;
+            
+            if(this.events.triggerEvent("beforetransform", mods) !== false) {
+                var feature = this.feature;
+                var geom = feature.geometry;
+                var center = this.center;
+                geom.rotate(-oldRotation, center);
+                if(mods.scale || mods.ratio) {
+                    geom.resize(mods.scale, center, mods.ratio);
+                } else if(mods.center) {
+                    feature.move(mods.center.getBounds().getCenterLonLat());
+                }
+                geom.rotate(this.rotation, center);
+                this.layer.drawFeature(feature);
+                feature.toState(OpenLayers.State.UPDATE);
+                this.events.triggerEvent("transform", mods);
+            }
+        }
+        this.layer.drawFeature(this.box, this.renderIntent);
+        this.drawHandles();
+    },
+        
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass.
+     */
+    destroy: function() {
+        var geom;
+        for(var i=0; i<8; ++i) {
+            geom = this.box.geometry.components[i];
+            geom._handle.destroy();
+            geom._handle = null;
+            geom._rotationHandle && geom._rotationHandle.destroy();
+            geom._rotationHandle = null;
+        }
+        this.box.destroy();
+        this.box = null;
+        this.layer = null;
+        this.dragControl.destroy();
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.TransformFeature"
+});
+/* ======================================================================
+    OpenLayers/Layer/ArcGISCache.js
+   ====================================================================== */
+
+/** 
+ * @requires OpenLayers/Layer/XYZ.js 
+ */ 
+
+/** 
+ * Class: OpenLayers.Layer.ArcGISCache   
+ * Layer for accessing cached map tiles from an ArcGIS Server style mapcache. 
+ * Tile must already be cached for this layer to access it. This does not require 
+ * ArcGIS Server itself.
+ * 
+ * A few attempts have been made at this kind of layer before. See 
+ * http://trac.osgeo.org/openlayers/ticket/1967 
+ * and 
+ * http://trac.osgeo.org/openlayers/browser/sandbox/tschaub/arcgiscache/lib/OpenLayers/Layer/ArcGISCache.js
+ *
+ * Typically the problem encountered is that the tiles seem to "jump around".
+ * This is due to the fact that the actual max extent for the tiles on AGS layers
+ * changes at each zoom level due to the way these caches are constructed.
+ * We have attempted to use the resolutions, tile size, and tile origin
+ * from the cache meta data to make the appropriate changes to the max extent
+ * of the tile to compensate for this behavior.  This must be done as zoom levels change
+ * and before tiles are requested, which is why methods from base classes are overridden.
+ *
+ * For reference, you can access mapcache meta data in two ways. For accessing a 
+ * mapcache through ArcGIS Server, you can simply go to the landing page for the
+ * layer. (ie. http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer)
+ * For accessing it directly through HTTP, there should always be a conf.xml file
+ * in the root directory. 
+ * (ie. http://serverx.esri.com/arcgiscache/DG_County_roads_yesA_backgroundDark/Layers/conf.xml)
+ *  
+ *Inherits from: 
+ *  - <OpenLayers.Layer.XYZ>             
+ */    
+OpenLayers.Layer.ArcGISCache = OpenLayers.Class(OpenLayers.Layer.XYZ, {  
+
+    /**
+     * APIProperty: url
+     * {String | Array} The base URL for the layer cache.  You can also
+     *     provide a list of URL strings for the layer if your cache is
+     *     available from multiple origins.  This must be set before the layer
+     *     is drawn.
+     */
+    url: null,
+    
+   /**
+    * APIProperty: tileOrigin
+    * {<OpenLayers.LonLat>} The location of the tile origin for the cache.
+    *     An ArcGIS cache has it's origin at the upper-left (lowest x value
+    *     and highest y value of the coordinate system).  The units for the
+    *     tile origin should be the same as the units for the cached data.
+    */
+    tileOrigin: null, 
+   
+   /**
+    * APIProperty: tileSize
+    * {<OpenLayers.Size>} This size of each tile. Defaults to 256 by 256 pixels.
+    */
+    tileSize: new OpenLayers.Size(256, 256),
+    
+   /**
+    * APIProperty: useAGS
+    * {Boolean} Indicates if we are going to be accessing the ArcGIS Server (AGS)
+    *     cache via an AGS MapServer or directly through HTTP. When accessing via
+    *     AGS the path structure uses a standard z/y/x structure. But AGS actually
+    *     stores the tile images on disk using a hex based folder structure that looks
+    *     like "http://example.com/mylayer/L00/R00000000/C00000000.png".  Learn more
+    *     about this here:
+    *     http://blogs.esri.com/Support/blogs/mappingcenter/archive/2010/08/20/Checking-Your-Local-Cache-Folders.aspx
+    *     Defaults to true;
+    */    
+    useArcGISServer: true,
+
+   /**
+    * APIProperty: type
+    * {String} Image type for the layer.  This becomes the filename extension
+    *     in tile requests.  Default is "png" (generating a url like
+    *     "http://example.com/mylayer/L00/R00000000/C00000000.png").
+    */
+    type: 'png',
+    
+    /**
+    * APIProperty: useScales
+    * {Boolean} Optional override to indicate that the layer should use 'scale' information
+    *     returned from the server capabilities object instead of 'resolution' information.
+    *     This can be important if your tile server uses an unusual DPI for the tiles.
+    */
+    useScales: false,
+    
+   /**
+    * APIProperty: overrideDPI
+    * {Boolean} Optional override to change the OpenLayers.DOTS_PER_INCH setting based 
+    *     on the tile information in the server capabilities object.  This can be useful 
+    *     if your server has a non-standard DPI setting on its tiles, and you're only using 
+    *     tiles with that DPI.  This value is used while OpenLayers is calculating resolution
+    *     using scales, and is not necessary if you have resolution information. (This is
+    *     typically the case)  Regardless, this setting can be useful, but is dangerous
+    *     because it will impact other layers while calculating resolution.  Only use this
+    *     if you know what you are doing.  (See OpenLayers.Util.getResolutionFromScale)
+    */
+    overrideDPI: false,
+    
+   /**
+    * Constructor: OpenLayers.Layer.ArcGISCache 
+    * Creates a new instance of this class 
+    * 
+    * Parameters: 
+    * name - {String} 
+    * url - {String} 
+    * options - {Object} extra layer options
+    */ 
+    initialize: function(name, url, options) { 
+        OpenLayers.Layer.XYZ.prototype.initialize.apply(this, arguments);
+
+        if (this.resolutions) {        
+            this.serverResolutions = this.resolutions;
+            this.maxExtent = this.getMaxExtentForResolution(this.resolutions[0]);
+        }
+
+        // this block steps through translating the values from the server layer JSON 
+        // capabilities object into values that we can use.  This is also a helpful
+        // reference when configuring this layer directly.
+        if (this.layerInfo) {
+            // alias the object
+            var info = this.layerInfo;
+            
+            // build our extents
+            var startingTileExtent = new OpenLayers.Bounds(
+                info.fullExtent.xmin, 
+                info.fullExtent.ymin, 
+                info.fullExtent.xmax, 
+                info.fullExtent.ymax  
+            );
+
+            // set our projection based on the given spatial reference.
+            // esri uses slightly different IDs, so this may not be comprehensive
+            this.projection = 'EPSG:' + info.spatialReference.wkid;
+            this.sphericalMercator = (info.spatialReference.wkid == 102100);
+            
+            // convert esri units into openlayers units (basic feet or meters only)
+            this.units = (info.units == "esriFeet") ? 'ft' : 'm';
+
+            // optional extended section based on whether or not the server returned
+            // specific tile information
+            if (!!info.tileInfo) {            
+                // either set the tiles based on rows/columns, or specific width/height
+                this.tileSize = new OpenLayers.Size(
+                    info.tileInfo.width || info.tileInfo.cols, 
+                    info.tileInfo.height || info.tileInfo.rows
+                );
+                
+                // this must be set when manually configuring this layer
+                this.tileOrigin = new OpenLayers.LonLat(
+                    info.tileInfo.origin.x, 
+                    info.tileInfo.origin.y
+                );
+
+                var upperLeft = new OpenLayers.Geometry.Point(
+                    startingTileExtent.left, 
+                    startingTileExtent.top
+                );
+                
+                var bottomRight = new OpenLayers.Geometry.Point(
+                    startingTileExtent.right, 
+                    startingTileExtent.bottom
+                );            
+                
+                if (this.useScales) {
+                    this.scales = [];
+                } else {
+                    this.resolutions = [];
+                }
+                
+                this.lods = [];
+                for(var key in info.tileInfo.lods) {
+                    if (info.tileInfo.lods.hasOwnProperty(key)) {
+                        var lod = info.tileInfo.lods[key];
+                        if (this.useScales) {
+                            this.scales.push(lod.scale);
+                        } else {
+                            this.resolutions.push(lod.resolution);
+                        }
+                    
+                        var start = this.getContainingTileCoords(upperLeft, lod.resolution);
+                        lod.startTileCol = start.x;
+                        lod.startTileRow = start.y;
+                    
+                        var end = this.getContainingTileCoords(bottomRight, lod.resolution);
+                        lod.endTileCol = end.x;
+                        lod.endTileRow = end.y;    
+                        this.lods.push(lod);
+                    }
+                }
+
+                this.maxExtent = this.calculateMaxExtentWithLOD(this.lods[0]);
+                this.serverResolutions = this.resolutions;
+                if (this.overrideDPI && info.tileInfo.dpi) {
+                    // see comment above for 'overrideDPI'
+                    OpenLayers.DOTS_PER_INCH = info.tileInfo.dpi;
+                }
+            } 
+       }
+    }, 
+
+   /** 
+    * Method: getContainingTileCoords
+    * Calculates the x/y pixel corresponding to the position of the tile
+    *     that contains the given point and for the for the given resolution.
+    * 
+    * Parameters:
+    * point - {<OpenLayers.Geometry.Point>} 
+    * res - {Float} The resolution for which to compute the extent.
+    * 
+    * Returns: 
+    * {<OpenLayers.Pixel>} The x/y pixel corresponding to the position 
+    * of the upper left tile for the given resolution.
+    */
+    getContainingTileCoords: function(point, res) {
+        return new OpenLayers.Pixel(
+           Math.max(Math.floor((point.x - this.tileOrigin.lon) / (this.tileSize.w * res)),0),
+           Math.max(Math.floor((this.tileOrigin.lat - point.y) / (this.tileSize.h * res)),0)
+        );
+    },
+    
+   /** 
+    * Method: calculateMaxExtentWithLOD
+    * Given a Level of Detail object from the server, this function
+    *     calculates the actual max extent
+    * 
+    * Parameters: 
+    * lod - {Object} a Level of Detail Object from the server capabilities object 
+            representing a particular zoom level
+    * 
+    * Returns: 
+    * {<OpenLayers.Bounds>} The actual extent of the tiles for the given zoom level
+    */
+   calculateMaxExtentWithLOD: function(lod) {
+        // the max extent we're provided with just overlaps some tiles
+        // our real extent is the bounds of all the tiles we touch
+
+        var numTileCols = (lod.endTileCol - lod.startTileCol) + 1;
+        var numTileRows = (lod.endTileRow - lod.startTileRow) + 1;        
+
+        var minX = this.tileOrigin.lon + (lod.startTileCol * this.tileSize.w * lod.resolution);
+        var maxX = minX + (numTileCols * this.tileSize.w * lod.resolution);
+
+        var maxY = this.tileOrigin.lat - (lod.startTileRow * this.tileSize.h * lod.resolution);
+        var minY = maxY - (numTileRows * this.tileSize.h * lod.resolution);
+        return new OpenLayers.Bounds(minX, minY, maxX, maxY);
+   },
+    
+   /** 
+    * Method: calculateMaxExtentWithExtent
+    * Given a 'suggested' max extent from the server, this function uses
+    *     information about the actual tile sizes to determine the actual
+    *     extent of the layer.
+    * 
+    * Parameters: 
+    * extent - {<OpenLayers.Bounds>} The 'suggested' extent for the layer
+    * res - {Float} The resolution for which to compute the extent.
+    * 
+    * Returns: 
+    * {<OpenLayers.Bounds>} The actual extent of the tiles for the given zoom level
+    */
+   calculateMaxExtentWithExtent: function(extent, res) {
+        var upperLeft = new OpenLayers.Geometry.Point(extent.left, extent.top);
+        var bottomRight = new OpenLayers.Geometry.Point(extent.right, extent.bottom);
+        var start = this.getContainingTileCoords(upperLeft, res);
+        var end = this.getContainingTileCoords(bottomRight, res);
+        var lod = {
+            resolution: res,
+            startTileCol: start.x,
+            startTileRow: start.y,
+            endTileCol: end.x,
+            endTileRow: end.y
+        };
+        return this.calculateMaxExtentWithLOD(lod);
+   },
+    
+    /** 
+    * Method: getUpperLeftTileCoord
+    * Calculates the x/y pixel corresponding to the position 
+    *     of the upper left tile for the given resolution.
+    * 
+    * Parameters: 
+    * res - {Float} The resolution for which to compute the extent.
+    * 
+    * Returns: 
+    * {<OpenLayers.Pixel>} The x/y pixel corresponding to the position 
+    * of the upper left tile for the given resolution.
+    */
+    getUpperLeftTileCoord: function(res) {
+        var upperLeft = new OpenLayers.Geometry.Point(
+            this.maxExtent.left,
+            this.maxExtent.top);
+        return this.getContainingTileCoords(upperLeft, res);
+    },
+
+    /** 
+    * Method: getLowerRightTileCoord
+    * Calculates the x/y pixel corresponding to the position 
+    *     of the lower right tile for the given resolution.
+    *  
+    * Parameters: 
+    * res - {Float} The resolution for which to compute the extent.
+    * 
+    * Returns: 
+    * {<OpenLayers.Pixel>} The x/y pixel corresponding to the position
+    * of the lower right tile for the given resolution.
+    */
+    getLowerRightTileCoord: function(res) {
+        var bottomRight = new OpenLayers.Geometry.Point(
+            this.maxExtent.right,
+            this.maxExtent.bottom);
+        return this.getContainingTileCoords(bottomRight, res);
+    },
+    
+   /** 
+    * Method: getMaxExtentForResolution
+    * Since the max extent of a set of tiles can change from zoom level
+    *     to zoom level, we need to be able to calculate that max extent 
+    *     for a given resolution.
+    *
+    * Parameters: 
+    * res - {Float} The resolution for which to compute the extent.
+    * 
+    * Returns: 
+    * {<OpenLayers.Bounds>} The extent for this resolution
+    */ 
+    getMaxExtentForResolution: function(res) {
+        var start = this.getUpperLeftTileCoord(res);
+        var end = this.getLowerRightTileCoord(res);
+
+        var numTileCols = (end.x - start.x) + 1;
+        var numTileRows = (end.y - start.y) + 1;
+
+        var minX = this.tileOrigin.lon + (start.x * this.tileSize.w * res);
+        var maxX = minX + (numTileCols * this.tileSize.w * res);
+        
+        var maxY = this.tileOrigin.lat - (start.y * this.tileSize.h * res);
+        var minY = maxY - (numTileRows * this.tileSize.h * res);
+        return new OpenLayers.Bounds(minX, minY, maxX, maxY);
+    },
+    
+   /** 
+    * APIMethod: clone 
+    * Returns an exact clone of this OpenLayers.Layer.ArcGISCache
+    * 
+    * Parameters: 
+    * [obj] - {Object} optional object to assign the cloned instance to.
+    *  
+    * Returns: 
+    * {<OpenLayers.Layer.ArcGISCache>} clone of this instance 
+    */ 
+    clone: function (obj) { 
+        if (obj == null) { 
+            obj = new OpenLayers.Layer.ArcGISCache(this.name, this.url, this.options);
+        }
+        return OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+    },
+
+    /**
+     * Method: getMaxExtent
+     * Get this layer's maximum extent.
+     *
+     * Returns:
+     * {OpenLayers.Bounds}
+     */
+    getMaxExtent: function() {
+        var resolution = this.map.getResolution();
+        return this.maxExtent = this.getMaxExtentForResolution(resolution);
+    },
+
+    /**
+     * Method: getTileOrigin
+     * Determine the origin for aligning the grid of tiles.  
+     *     The origin will be derived from the layer's <maxExtent> property. 
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>} The tile origin.
+     */
+    getTileOrigin: function() {
+        var extent = this.getMaxExtent();
+        return new OpenLayers.LonLat(extent.left, extent.bottom);
+    },
+
+   /**
+    * Method: getURL
+    * Determine the URL for a tile given the tile bounds.  This is should support
+    *     urls that access tiles through an ArcGIS Server MapServer or directly through
+    *     the hex folder structure using HTTP.  Just be sure to set the useArcGISServer
+    *     property appropriately!  This is basically the same as 
+    *     'OpenLayers.Layer.TMS.getURL',  but with the addition of hex addressing,
+    *     and tile rounding.
+    *
+    * Parameters:
+    * bounds - {<OpenLayers.Bounds>}
+    *
+    * Returns:
+    * {String} The URL for a tile based on given bounds.
+    */
+    getURL: function (bounds) {
+        var res = this.getResolution(); 
+
+        // tile center
+        var originTileX = (this.tileOrigin.lon + (res * this.tileSize.w/2)); 
+        var originTileY = (this.tileOrigin.lat - (res * this.tileSize.h/2));
+
+        var center = bounds.getCenterLonLat();
+        var point = { x: center.lon, y: center.lat };
+        var x = (Math.round(Math.abs((center.lon - originTileX) / (res * this.tileSize.w)))); 
+        var y = (Math.round(Math.abs((originTileY - center.lat) / (res * this.tileSize.h)))); 
+        var z = this.map.getZoom();
+
+        // this prevents us from getting pink tiles (non-existant tiles)
+        if (this.lods) {        
+            var lod = this.lods[this.map.getZoom()];
+            if ((x < lod.startTileCol || x > lod.endTileCol) 
+                || (y < lod.startTileRow || y > lod.endTileRow)) {
+                    return null;
+            }
+        }
+        else {
+            var start = this.getUpperLeftTileCoord(res);
+            var end = this.getLowerRightTileCoord(res);
+            if ((x < start.x || x >= end.x)
+                || (y < start.y || y >= end.y)) {
+                    return null;
+            }        
+        }
+
+        // Construct the url string
+        var url = this.url;
+        var s = '' + x + y + z;
+
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(s, url);
+        }
+
+        // Accessing tiles through ArcGIS Server uses a different path
+        // structure than direct access via the folder structure.
+        if (this.useArcGISServer) {
+            // AGS MapServers have pretty url access to tiles
+            url = url + '/tile/${z}/${y}/${x}';
+        } else {
+            // The tile images are stored using hex values on disk.
+            x = 'C' + this.zeroPad(x, 8, 16);
+            y = 'R' + this.zeroPad(y, 8, 16);
+            z = 'L' + this.zeroPad(z, 2, 16);
+            url = url + '/${z}/${y}/${x}.' + this.type;
+        }
+
+        // Write the values into our formatted url
+        url = OpenLayers.String.format(url, {'x': x, 'y': y, 'z': z});
+
+        return url;
+    },
+
+    /**
+     * Method: zeroPad
+     * Create a zero padded string optionally with a radix for casting numbers.
+     *
+     * Parameters:
+     * num - {Number} The number to be zero padded.
+     * len - {Number} The length of the string to be returned.
+     * radix - {Number} An integer between 2 and 36 specifying the base to use
+     *     for representing numeric values.
+     */
+    zeroPad: function(num, len, radix) {
+        var str = num.toString(radix || 10);
+        while (str.length < len) {
+            str = "0" + str;
+        }
+        return str;
+    },
+
+    CLASS_NAME: 'OpenLayers.Layer.ArcGISCache' 
+}); 
+/* ======================================================================
+    OpenLayers/Control/WMSGetFeatureInfo.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Handler/Hover.js
+ * @requires OpenLayers/Request.js
+ */
+
+/**
+ * Class: OpenLayers.Control.WMSGetFeatureInfo
+ * The WMSGetFeatureInfo control uses a WMS query to get information about a point on the map.  The
+ * information may be in a display-friendly format such as HTML, or a machine-friendly format such 
+ * as GML, depending on the server's capabilities and the client's configuration.  This control 
+ * handles click or hover events, attempts to parse the results using an OpenLayers.Format, and 
+ * fires a 'getfeatureinfo' event with the click position, the raw body of the response, and an 
+ * array of features if it successfully read the response.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
+
+   /**
+     * APIProperty: hover
+     * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
+     *     Default is false.
+     */
+    hover: false,
+
+    /**
+     * APIProperty: drillDown
+     * {Boolean} Drill down over all WMS layers in the map. When
+     *     using drillDown mode, hover is not possible, and an infoFormat that
+     *     returns parseable features is required. Default is false.
+     */
+    drillDown: false,
+
+    /**
+     * APIProperty: maxFeatures
+     * {Integer} Maximum number of features to return from a WMS query. This
+     *     sets the feature_count parameter on WMS GetFeatureInfo
+     *     requests.
+     */
+    maxFeatures: 10,
+
+    /** APIProperty: clickCallback
+     *  {String} The click callback to register in the
+     *      {<OpenLayers.Handler.Click>} object created when the hover
+     *      option is set to false. Default is "click".
+     */
+    clickCallback: "click",
+    
+    /** APIProperty: output
+     *  {String} Either "features" or "object". When triggering a 
+     *      getfeatureinfo request should we pass on an array of features
+     *      or an object with with a "features" property and other properties
+     *      (such as the url of the WMS). Default is "features".
+     */
+    output: "features",
+    
+    /**
+     * Property: layers
+     * {Array(<OpenLayers.Layer.WMS>)} The layers to query for feature info.
+     *     If omitted, all map WMS layers with a url that matches this <url> or
+     *     <layerUrls> will be considered.
+     */
+    layers: null,
+
+    /**
+     * Property: queryVisible
+     * {Boolean} If true, filter out hidden layers when searching the map for
+     *     layers to query.  Default is false.
+     */
+    queryVisible: false,
+
+    /**
+     * Property: url
+     * {String} The URL of the WMS service to use.  If not provided, the url
+     *     of the first eligible layer will be used.
+     */
+    url: null,
+    
+    /**
+     * Property: layerUrls
+     * {Array(String)} Optional list of urls for layers that should be queried.
+     *     This can be used when the layer url differs from the url used for
+     *     making GetFeatureInfo requests (in the case of a layer using cached
+     *     tiles).
+     */
+    layerUrls: null,
+
+    /**
+     * Property: infoFormat
+     * {String} The mimetype to request from the server. If you are using 
+     * drillDown mode and have multiple servers that do not share a common 
+     * infoFormat, you can override the control's infoFormat by providing an 
+     * INFO_FORMAT parameter in your <OpenLayers.Layer.WMS> instance(s).
+     */
+    infoFormat: 'text/html',
+    
+    /**
+     * Property: vendorParams
+     * {Object} Additional parameters that will be added to the request, for
+     * WMS implementations that support them. This could e.g. look like
+     * (start code)
+     * {
+     *     radius: 5
+     * }
+     * (end)
+     */
+    vendorParams: {},
+    
+    /**
+     * Property: format
+     * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
+     *     Default is <OpenLayers.Format.WMSGetFeatureInfo>.
+     */
+    format: null,
+    
+    /**
+     * Property: formatOptions
+     * {Object} Optional properties to set on the format (if one is not provided
+     *     in the <format> property.
+     */
+    formatOptions: null,
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Additional options for the handlers used by this control, e.g.
+     * (start code)
+     * {
+     *     "click": {delay: 100},
+     *     "hover": {delay: 300}
+     * }
+     * (end)
+     */
+    handlerOptions: null,
+    
+    /**
+     * Property: handler
+     * {Object} Reference to the <OpenLayers.Handler> for this control
+     */
+    handler: null,
+    
+    /**
+     * Property: hoverRequest
+     * {<OpenLayers.Request>} contains the currently running hover request
+     *     (if any).
+     */
+    hoverRequest: null,
+    
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types (in addition to those from <OpenLayers.Control>):
+     * beforegetfeatureinfo - Triggered before the request is sent.
+     *      The event object has an *xy* property with the position of the 
+     *      mouse click or hover event that triggers the request.
+     * nogetfeatureinfo - no queryable layers were found.
+     * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
+     *      The event object has a *text* property with the body of the
+     *      response (String), a *features* property with an array of the
+     *      parsed features, an *xy* property with the position of the mouse
+     *      click or hover event that triggered the request, and a *request*
+     *      property with the request itself. If drillDown is set to true and
+     *      multiple requests were issued to collect feature info from all
+     *      layers, *text* and *request* will only contain the response body
+     *      and request object of the last request.
+     */
+    EVENT_TYPES: ["beforegetfeatureinfo", "nogetfeatureinfo", "getfeatureinfo"],
+
+    /**
+     * Constructor: <OpenLayers.Control.WMSGetFeatureInfo>
+     *
+     * Parameters:
+     * options - {Object} 
+     */
+    initialize: function(options) {
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.WMSGetFeatureInfo.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+
+        options = options || {};
+        options.handlerOptions = options.handlerOptions || {};
+
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        if(!this.format) {
+            this.format = new OpenLayers.Format.WMSGetFeatureInfo(
+                options.formatOptions
+            );
+        }
+        
+        if(this.drillDown === true) {
+            this.hover = false;
+        }
+
+        if(this.hover) {
+            this.handler = new OpenLayers.Handler.Hover(
+                   this, {
+                       'move': this.cancelHover,
+                       'pause': this.getInfoForHover
+                   },
+                   OpenLayers.Util.extend(this.handlerOptions.hover || {}, {
+                       'delay': 250
+                   }));
+        } else {
+            var callbacks = {};
+            callbacks[this.clickCallback] = this.getInfoForClick;
+            this.handler = new OpenLayers.Handler.Click(
+                this, callbacks, this.handlerOptions.click || {});
+        }
+    },
+
+    /**
+     * Method: activate
+     * Activates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively activated.
+     */
+    activate: function () {
+        if (!this.active) {
+            this.handler.activate();
+        }
+        return OpenLayers.Control.prototype.activate.apply(
+            this, arguments
+        );
+    },
+
+    /**
+     * Method: deactivate
+     * Deactivates the control.
+     * 
+     * Returns:
+     * {Boolean} The control was effectively deactivated.
+     */
+    deactivate: function () {
+        return OpenLayers.Control.prototype.deactivate.apply(
+            this, arguments
+        );
+    },
+    
+    /**
+     * Method: getInfoForClick 
+     * Called on click
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    getInfoForClick: function(evt) {
+        this.events.triggerEvent("beforegetfeatureinfo", {xy: evt.xy});
+        // Set the cursor to "wait" to tell the user we're working on their
+        // click.
+        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+        this.request(evt.xy, {});
+    },
+   
+    /**
+     * Method: getInfoForHover
+     * Pause callback for the hover handler
+     *
+     * Parameters:
+     * evt - {Object}
+     */
+    getInfoForHover: function(evt) {
+        this.events.triggerEvent("beforegetfeatureinfo", {xy: evt.xy});
+        this.request(evt.xy, {hover: true});
+    },
+
+    /**
+     * Method: cancelHover
+     * Cancel callback for the hover handler
+     */
+    cancelHover: function() {
+        if (this.hoverRequest) {
+            this.hoverRequest.abort();
+            this.hoverRequest = null;
+        }
+    },
+
+    /**
+     * Method: findLayers
+     * Internal method to get the layers, independent of whether we are
+     *     inspecting the map or using a client-provided array
+     */
+    findLayers: function() {
+
+        var candidates = this.layers || this.map.layers;
+        var layers = [];
+        var layer, url;
+        for(var i=0, len=candidates.length; i<len; ++i) {
+            layer = candidates[i];
+            if(layer instanceof OpenLayers.Layer.WMS &&
+               (!this.queryVisible || layer.getVisibility())) {
+                url = OpenLayers.Util.isArray(layer.url) ? layer.url[0] : layer.url;
+                // if the control was not configured with a url, set it
+                // to the first layer url
+                if(this.drillDown === false && !this.url) {
+                    this.url = url;
+                }
+                if(this.drillDown === true || this.urlMatches(url)) {
+                    layers.push(layer);
+                }
+            }
+        }
+        return layers;
+    },
+    
+    /**
+     * Method: urlMatches
+     * Test to see if the provided url matches either the control <url> or one
+     *     of the <layerUrls>.
+     *
+     * Parameters:
+     * url - {String} The url to test.
+     *
+     * Returns:
+     * {Boolean} The provided url matches the control <url> or one of the
+     *     <layerUrls>.
+     */
+    urlMatches: function(url) {
+        var matches = OpenLayers.Util.isEquivalentUrl(this.url, url);
+        if(!matches && this.layerUrls) {
+            for(var i=0, len=this.layerUrls.length; i<len; ++i) {
+                if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[i], url)) {
+                    matches = true;
+                    break;
+                }
+            }
+        }
+        return matches;
+    },
+
+    /**
+     * Method: buildWMSOptions
+     * Build an object with the relevant WMS options for the GetFeatureInfo request
+     *
+     * Parameters:
+     * url - {String} The url to be used for sending the request
+     * layers - {Array(<OpenLayers.Layer.WMS)} An array of layers
+     * clickPosition - {<OpenLayers.Pixel>} The position on the map where the mouse
+     *     event occurred.
+     * format - {String} The format from the corresponding GetMap request
+     */
+    buildWMSOptions: function(url, layers, clickPosition, format) {
+        var layerNames = [], styleNames = [];
+        for (var i = 0, len = layers.length; i < len; i++) { 
+            layerNames = layerNames.concat(layers[i].params.LAYERS);
+            styleNames = styleNames.concat(this.getStyleNames(layers[i]));
+        }
+        var firstLayer = layers[0];
+        // use the firstLayer's projection if it matches the map projection -
+        // this assumes that all layers will be available in this projection
+        var projection = this.map.getProjection();
+        var layerProj = firstLayer.projection;
+        if (layerProj && layerProj.equals(this.map.getProjectionObject())) {
+            projection = layerProj.getCode();
+        }
+        var params = OpenLayers.Util.extend({
+            service: "WMS",
+            version: firstLayer.params.VERSION,
+            request: "GetFeatureInfo",
+            layers: layerNames,
+            query_layers: layerNames,
+            styles: styleNames,
+            bbox: this.map.getExtent().toBBOX(null,
+                firstLayer.reverseAxisOrder()),
+            feature_count: this.maxFeatures,
+            height: this.map.getSize().h,
+            width: this.map.getSize().w,
+            format: format,
+            info_format: firstLayer.params.INFO_FORMAT || this.infoFormat
+        }, (parseFloat(firstLayer.params.VERSION) >= 1.3) ?
+            {
+                crs: projection,
+                i: parseInt(clickPosition.x),
+                j: parseInt(clickPosition.y)
+            } :
+            {
+                srs: projection,
+                x: parseInt(clickPosition.x),
+                y: parseInt(clickPosition.y)
+            }
+        );
+        OpenLayers.Util.applyDefaults(params, this.vendorParams);
+        return {
+            url: url,
+            params: OpenLayers.Util.upperCaseObject(params),
+            callback: function(request) {
+                this.handleResponse(clickPosition, request, url);
+            },
+            scope: this
+        };
+    },
+
+    /**
+     * Method: getStyleNames
+     * Gets the STYLES parameter for the layer. Make sure the STYLES parameter
+     * matches the LAYERS parameter
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMS>}
+     *
+     * Returns:
+     * {Array(String)} The STYLES parameter
+     */
+    getStyleNames: function(layer) {
+        // in the event of a WMS layer bundling multiple layers but not
+        // specifying styles,we need the same number of commas to specify
+        // the default style for each of the layers.  We can't just leave it
+        // blank as we may be including other layers that do specify styles.
+        var styleNames;
+        if (layer.params.STYLES) {
+            styleNames = layer.params.STYLES;
+        } else {
+            if (OpenLayers.Util.isArray(layer.params.LAYERS)) {
+                styleNames = new Array(layer.params.LAYERS.length);
+            } else { // Assume it's a String
+                styleNames = layer.params.LAYERS.replace(/[^,]/g, "");
+            }
+        }
+        return styleNames;
+    },
+
+    /**
+     * Method: request
+     * Sends a GetFeatureInfo request to the WMS
+     * 
+     * Parameters:
+     * clickPosition - {<OpenLayers.Pixel>} The position on the map where the
+     *     mouse event occurred.
+     * options - {Object} additional options for this method.
+     * 
+     * Valid options:
+     * - *hover* {Boolean} true if we do the request for the hover handler
+     */
+    request: function(clickPosition, options) {
+        var layers = this.findLayers();
+        if(layers.length == 0) {
+            this.events.triggerEvent("nogetfeatureinfo");
+            // Reset the cursor.
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+            return;
+        }
+        
+        options = options || {};
+        if(this.drillDown === false) {
+            var wmsOptions = this.buildWMSOptions(this.url, layers,
+                clickPosition, layers[0].params.FORMAT); 
+            var request = OpenLayers.Request.GET(wmsOptions);
+    
+            if (options.hover === true) {
+                this.hoverRequest = request;
+            }
+        } else {
+            this._requestCount = 0;
+            this._numRequests = 0;
+            this.features = [];
+            // group according to service url to combine requests
+            var services = {}, url;
+            for(var i=0, len=layers.length; i<len; i++) {
+                var layer = layers[i];
+                var service, found = false;
+                url = OpenLayers.Util.isArray(layer.url) ? layer.url[0] : layer.url;
+                if(url in services) {
+                    services[url].push(layer);
+                } else {
+                    this._numRequests++;
+                    services[url] = [layer];
+                }
+            }
+            var layers;
+            for (var url in services) {
+                layers = services[url];
+                var wmsOptions = this.buildWMSOptions(url, layers, 
+                    clickPosition, layers[0].params.FORMAT);
+                OpenLayers.Request.GET(wmsOptions); 
+            }
+        }
+    },
+
+    /**
+     * Method: triggerGetFeatureInfo
+     * Trigger the getfeatureinfo event when all is done
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     * xy - {<OpenLayers.Pixel>} The position on the map where the
+     *     mouse event occurred.
+     * features - {Array(<OpenLayers.Feature.Vector>)} or
+     *     {Array({Object}) when output is "object". The object has a url and a
+     *     features property which contains an array of features.
+     */
+    triggerGetFeatureInfo: function(request, xy, features) {
+        this.events.triggerEvent("getfeatureinfo", {
+            text: request.responseText,
+            features: features,
+            request: request,
+            xy: xy
+        });
+
+        // Reset the cursor.
+        OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+    },
+    
+    /**
+     * Method: handleResponse
+     * Handler for the GetFeatureInfo response.
+     * 
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The position on the map where the
+     *     mouse event occurred.
+     * request - {XMLHttpRequest} The request object.
+     * url - {String} The url which was used for this request.
+     */
+    handleResponse: function(xy, request, url) {
+        
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        var features = this.format.read(doc);
+        if (this.drillDown === false) {
+            this.triggerGetFeatureInfo(request, xy, features);
+        } else {
+            this._requestCount++;
+            if (this.output === "object") {
+                this._features = (this._features || []).concat(
+                    {url: url, features: features}
+                );
+            } else {
+            this._features = (this._features || []).concat(features);
+            }
+            if (this._requestCount === this._numRequests) {
+                this.triggerGetFeatureInfo(request, xy, this._features.concat()); 
+                delete this._features;
+                delete this._requestCount;
+                delete this._numRequests;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.WMSGetFeatureInfo"
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_3.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3
+ * Abstract base class for WMS Capabilities version 1.3.X. 
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, 
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1, {
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "WMS_Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "LayerLimit": function(node, obj) {
+                obj.layerLimit = parseInt(this.getChildValue(node));
+            },
+            "MaxWidth": function(node, obj) {
+                obj.maxWidth = parseInt(this.getChildValue(node));
+            },
+            "MaxHeight": function(node, obj) {
+                obj.maxHeight = parseInt(this.getChildValue(node));
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+                bbox.srs  = node.getAttribute("CRS");
+                obj.bbox[bbox.srs] = bbox;
+            },
+            "CRS": function(node, obj) {
+                // CRS is the synonym of SRS
+                this.readers.wms.SRS.apply(this, [node, obj]); 
+            },
+            "EX_GeographicBoundingBox": function(node, obj) {
+                // replacement of LatLonBoundingBox
+                obj.llbbox = [];
+                this.readChildNodes(node, obj.llbbox);
+                
+            },
+            "westBoundLongitude": function(node, obj) {
+                obj[0] = this.getChildValue(node);
+            },
+            "eastBoundLongitude": function(node, obj) {
+                obj[2] = this.getChildValue(node);
+            },
+            "southBoundLatitude": function(node, obj) {
+                obj[1] = this.getChildValue(node);
+            },
+            "northBoundLatitude": function(node, obj) {
+                obj[3] = this.getChildValue(node);
+            },
+            "MinScaleDenominator": function(node, obj) {
+                obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+            },
+            "MaxScaleDenominator": function(node, obj) {
+                obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+            },
+            "Dimension": function(node, obj) {
+                // dimension has extra attributes: default, multipleValues, 
+                // nearestValue, current which used to be part of Extent. It now
+                // also contains the values.
+                var name = node.getAttribute("name").toLowerCase();
+                var dim = {
+                    name: name,
+                    units: node.getAttribute("units"),
+                    unitsymbol: node.getAttribute("unitSymbol"),
+                    nearestVal: node.getAttribute("nearestValue") === "1",
+                    multipleVal: node.getAttribute("multipleValues") === "1",
+                    "default": node.getAttribute("default") || "",
+                    current: node.getAttribute("current") === "1",
+                    values: this.getChildValue(node).split(",")
+                    
+                };
+                // Theoretically there can be more dimensions with the same
+                // name, but with a different unit. Until we meet such a case,
+                // let's just keep the same structure as the WMS 1.1 
+                // GetCapabilities parser uses. We will store the last
+                // one encountered.
+                obj.dimensions[dim.name] = dim;
+            },
+            "Keyword": function(node, obj) {
+                // TODO: should we change the structure of keyword in v1.js?
+                // Make it an object with a value instead of a string?
+                var keyword = {value: this.getChildValue(node), 
+                    vocabulary: node.getAttribute("vocabulary")};
+                if (obj.keywords) {
+                    obj.keywords.push(keyword);
+                }
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),
+        "sld": {
+            "UserDefinedSymbolization": function(node, obj) {
+                this.readers.wms.UserDefinedSymbolization.apply(this, [node, obj]);
+                // add the two extra attributes
+                obj.userSymbols.inlineFeature = parseInt(node.getAttribute("InlineFeature")) == 1;
+                obj.userSymbols.remoteWCS = parseInt(node.getAttribute("RemoteWCS")) == 1;
+            },
+            "DescribeLayer": function(node, obj) {
+                this.readers.wms.DescribeLayer.apply(this, [node, obj]);
+            },
+            "GetLegendGraphic": function(node, obj) {
+                this.readers.wms.GetLegendGraphic.apply(this, [node, obj]);
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_3_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3_0
+ * Read WMS Capabilities version 1.3.0. 
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, 
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1_3>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3_0 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1_3, {
+    
+    /**
+     * Property: version
+     * {String} The specific parser version.
+     */
+    version: "1.3.0",
+    
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3_0" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/CQL.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WKT.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CQL
+ * Read CQL strings to get <OpenLayers.Filter> objects.  Write 
+ *     <OpenLayers.Filter> objects to get CQL strings. Create a new parser with 
+ *     the <OpenLayers.Format.CQL> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format>
+ */
+OpenLayers.Format.CQL = (function() {
+    
+    var tokens = [
+        "PROPERTY", "COMPARISON", "VALUE", "LOGICAL"
+    ],
+
+    patterns = {
+        PROPERTY: /^[_a-zA-Z]\w*/,
+        COMPARISON: /^(=|<>|<=|<|>=|>|LIKE)/i,
+        COMMA: /^,/,
+        LOGICAL: /^(AND|OR)/i,
+        VALUE: /^('\w+'|\d+(\.\d*)?|\.\d+)/,
+        LPAREN: /^\(/,
+        RPAREN: /^\)/,
+        SPATIAL: /^(BBOX|INTERSECTS|DWITHIN|WITHIN|CONTAINS)/i,
+        NOT: /^NOT/i,
+        BETWEEN: /^BETWEEN/i,
+        GEOMETRY: function(text) {
+            var type = /^(POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)/.exec(text);
+            if (type) {
+                var len = text.length;
+                var idx = text.indexOf("(", type[0].length);
+                if (idx > -1) {
+                    var depth = 1;
+                    while (idx < len && depth > 0) {
+                        idx++;
+                        switch(text.charAt(idx)) {
+                            case '(':
+                                depth++;
+                                break;
+                            case ')':
+                                depth--;
+                                break;
+                            default:
+                                // in default case, do nothing
+                        }
+                    }
+                }
+                return [text.substr(0, idx+1)];
+            }
+        },
+        END: /^$/
+    },
+
+    follows = {
+        LPAREN: ['GEOMETRY', 'SPATIAL', 'PROPERTY', 'VALUE', 'LPAREN'],
+        RPAREN: ['NOT', 'LOGICAL', 'END', 'RPAREN'],
+        PROPERTY: ['COMPARISON', 'BETWEEN', 'COMMA'],
+        BETWEEN: ['VALUE'],
+        COMPARISON: ['VALUE'],
+        COMMA: ['GEOMETRY', 'VALUE', 'PROPERTY'],
+        VALUE: ['LOGICAL', 'COMMA', 'RPAREN', 'END'],
+        SPATIAL: ['LPAREN'],
+        LOGICAL: ['NOT', 'VALUE', 'SPATIAL', 'PROPERTY', 'LPAREN'],
+        NOT: ['PROPERTY', 'LPAREN'],
+        GEOMETRY: ['COMMA', 'RPAREN']
+    },
+
+    operators = {
+        '=': OpenLayers.Filter.Comparison.EQUAL_TO,
+        '<>': OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+        '<': OpenLayers.Filter.Comparison.LESS_THAN,
+        '<=': OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,
+        '>': OpenLayers.Filter.Comparison.GREATER_THAN,
+        '>=': OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,
+        'LIKE': OpenLayers.Filter.Comparison.LIKE,
+        'BETWEEN': OpenLayers.Filter.Comparison.BETWEEN
+    },
+
+    operatorReverse = {},
+
+    logicals = {
+        'AND': OpenLayers.Filter.Logical.AND,
+        'OR': OpenLayers.Filter.Logical.OR
+    },
+
+    logicalReverse = {},
+
+    precedence = {
+        'RPAREN': 3,
+        'LOGICAL': 2,
+        'COMPARISON': 1
+    };
+
+    var i;
+    for (i in operators) {
+        if (operators.hasOwnProperty(i)) {
+            operatorReverse[operators[i]] = i;
+        }
+    }
+
+    for (i in logicals) {
+        if (logicals.hasOwnProperty(i)) {
+            logicalReverse[logicals[i]] = i;
+        }
+    }
+
+    function tryToken(text, pattern) {
+        if (pattern instanceof RegExp) {
+            return pattern.exec(text);
+        } else {
+            return pattern(text);
+        }
+    }
+
+    function nextToken(text, tokens) {
+        var i, token, len = tokens.length;
+        for (i=0; i<len; i++) {
+            token = tokens[i];
+            var pat = patterns[token];
+            var matches = tryToken(text, pat);
+            if (matches) {
+                var match = matches[0];
+                var remainder = text.substr(match.length).replace(/^\s*/, "");
+                return {
+                    type: token,
+                    text: match,
+                    remainder: remainder
+                };
+            }
+        }
+
+        var msg = "ERROR: In parsing: [" + text + "], expected one of: ";
+        for (i=0; i<len; i++) {
+            token = tokens[i];
+            msg += "\n    " + token + ": " + patterns[token];
+        }
+
+        throw new Error(msg);
+    }
+
+    function tokenize(text) {
+        var results = [];
+        var token, expect = ["NOT", "GEOMETRY", "SPATIAL", "PROPERTY", "LPAREN"];
+
+        do {
+            token = nextToken(text, expect);
+            text = token.remainder;
+            expect = follows[token.type];
+            if (token.type != "END" && !expect) {
+                throw new Error("No follows list for " + token.type);
+            }
+            results.push(token);
+        } while (token.type != "END");
+
+        return results;
+    }
+
+    function buildAst(tokens) {
+        var operatorStack = [],
+            postfix = [];
+
+        while (tokens.length) {
+            var tok = tokens.shift();
+            switch (tok.type) {
+                case "PROPERTY":
+                case "GEOMETRY":
+                case "VALUE":
+                    postfix.push(tok);
+                    break;
+                case "COMPARISON":
+                case "BETWEEN":
+                case "LOGICAL":
+                    var p = precedence[tok.type];
+
+                    while (operatorStack.length > 0 &&
+                        (precedence[operatorStack[operatorStack.length - 1].type] <= p)
+                    ) {
+                        postfix.push(operatorStack.pop());
+                    }
+
+                    operatorStack.push(tok);
+                    break;
+                case "SPATIAL":
+                case "NOT":
+                case "LPAREN":
+                    operatorStack.push(tok);
+                    break;
+                case "RPAREN":
+                    while (operatorStack.length > 0 &&
+                        (operatorStack[operatorStack.length - 1].type != "LPAREN")
+                    ) {
+                        postfix.push(operatorStack.pop());
+                    }
+                    operatorStack.pop(); // toss out the LPAREN
+
+                    if (operatorStack.length > 0 &&
+                        operatorStack[operatorStack.length-1].type == "SPATIAL") {
+                        postfix.push(operatorStack.pop());
+                    }
+                case "COMMA":
+                case "END":
+                    break;
+                default:
+                    throw new Error("Unknown token type " + tok.type);
+            }
+        }
+
+        while (operatorStack.length > 0) {
+            postfix.push(operatorStack.pop());
+        }
+
+        function buildTree() {
+            var tok = postfix.pop();
+            switch (tok.type) {
+                case "LOGICAL":
+                    var rhs = buildTree(),
+                        lhs = buildTree();
+                    return new OpenLayers.Filter.Logical({
+                        filters: [lhs, rhs],
+                        type: logicals[tok.text.toUpperCase()]
+                    });
+                case "NOT":
+                    var operand = buildTree();
+                    return new OpenLayers.Filter.Logical({
+                        filters: [operand],
+                        type: OpenLayers.Filter.Logical.NOT
+                    });
+                case "BETWEEN":
+                    var min, max, property;
+                    postfix.pop(); // unneeded AND token here
+                    max = buildTree();
+                    min = buildTree();
+                    property = buildTree();
+                    return new OpenLayers.Filter.Comparison({
+                        property: property,
+                        lowerBoundary: min,
+                        upperBoundary: max,
+                        type: OpenLayers.Filter.Comparison.BETWEEN
+                    });
+                case "COMPARISON":
+                    var value = buildTree(),
+                        property = buildTree();
+                    return new OpenLayers.Filter.Comparison({
+                        property: property,
+                        value: value,
+                        type: operators[tok.text.toUpperCase()]
+                    });
+                case "VALUE":
+                    if ((/^'.*'$/).test(tok.text)) {
+                        return tok.text.substr(1, tok.text.length - 2);
+                    } else {
+                        return Number(tok.text);
+                    }
+                case "SPATIAL":
+                    switch(tok.text.toUpperCase()) {
+                        case "BBOX":
+                            var maxy = buildTree(),
+                                maxx = buildTree(),
+                                miny = buildTree(),
+                                minx = buildTree(),
+                                prop = buildTree();
+
+                            return new OpenLayers.Filter.Spatial({
+                                type: OpenLayers.Filter.Spatial.BBOX,
+                                property: prop,
+                                value: OpenLayers.Bounds.fromArray(
+                                    [minx, miny, maxx, maxy]
+                                )
+                            });
+                        case "INTERSECTS":
+                            var value = buildTree(),
+                                property = buildTree();
+                            return new OpenLayers.Filter.Spatial({
+                                type: OpenLayers.Filter.Spatial.INTERSECTS,
+                                property: property,
+                                value: value
+                            });
+                        case "WITHIN":
+                            var value = buildTree(),
+                                property = buildTree();
+                            return new OpenLayers.Filter.Spatial({
+                                type: OpenLayers.Filter.Spatial.WITHIN,
+                                property: property,
+                                value: value
+                            });
+                        case "CONTAINS":
+                            var value = buildTree(),
+                                property = buildTree();
+                            return new OpenLayers.Filter.Spatial({
+                                type: OpenLayers.Filter.Spatial.CONTAINS,
+                                property: property,
+                                value: value
+                            });
+                        case "DWITHIN":
+                            var distance = buildTree(),
+                                value = buildTree(),
+                                property = buildTree();
+                            return new OpenLayers.Filter.Spatial({
+                                type: OpenLayers.Filter.Spatial.DWITHIN,
+                                value: value,
+                                property: property,
+                                distance: Number(distance)
+                            });
+                    }
+                case "GEOMETRY":
+                    return OpenLayers.Geometry.fromWKT(tok.text);
+                default:
+                    return tok.text;
+            }
+        }
+
+        var result = buildTree();
+        if (postfix.length > 0) {
+            var msg = "Remaining tokens after building AST: \n";
+            for (var i = postfix.length - 1; i >= 0; i--) {
+                msg += postfix[i].type + ": " + postfix[i].text + "\n";
+            }
+            throw new Error(msg);
+        }
+
+        return result;
+    }
+
+    return OpenLayers.Class(OpenLayers.Format, {
+        /**
+         * APIMethod: read
+         * Generate a filter from a CQL string.
+
+         * Parameters:
+         * text - {String} The CQL text.
+         *
+         * Returns:
+         * {<OpenLayers.Filter>} A filter based on the CQL text.
+         */
+        read: function(text) { 
+            var result = buildAst(tokenize(text));
+            if (this.keepData) {
+                this.data = result;
+            };
+            return result;
+        },
+
+        /**
+         * APIMethod: write
+         * Convert a filter into a CQL string.
+
+         * Parameters:
+         * filter - {<OpenLayers.Filter>} The filter.
+         *
+         * Returns:
+         * {String} A CQL string based on the filter.
+         */
+        write: function(filter) {
+            if (filter instanceof OpenLayers.Geometry) {
+                return filter.toString();
+            }
+            switch (filter.CLASS_NAME) {
+                case "OpenLayers.Filter.Spatial":
+                    switch(filter.type) {
+                        case OpenLayers.Filter.Spatial.BBOX:
+                            return "BBOX(" +
+                                filter.property + "," +
+                                filter.value.toBBOX() +
+                                ")";
+                        case OpenLayers.Filter.Spatial.DWITHIN:
+                            return "DWITHIN(" +
+                                filter.property + ", " +
+                                this.write(filter.value) + ", " +
+                                filter.distance + ")";
+                        case OpenLayers.Filter.Spatial.WITHIN:
+                            return "WITHIN(" +
+                                filter.property + ", " +
+                                this.write(filter.value) + ")";
+                        case OpenLayers.Filter.Spatial.INTERSECTS:
+                            return "INTERSECTS(" +
+                                filter.property + ", " +
+                                this.write(filter.value) + ")";
+                        case OpenLayers.Filter.Spatial.CONTAINS:
+                            return "CONTAINS(" +
+                                filter.property + ", " +
+                                this.write(filter.value) + ")";
+                        default:
+                            throw new Error("Unknown spatial filter type: " + filter.type);
+                    }
+                case "OpenLayers.Filter.Logical":
+                    if (filter.type == OpenLayers.Filter.Logical.NOT) {
+                        // TODO: deal with precedence of logical operators to 
+                        // avoid extra parentheses (not urgent)
+                        return "NOT (" + this.write(filter.filters[0]) + ")";
+                    } else {
+                        var res = "(";
+                        var first = true;
+                        for (var i = 0; i < filter.filters.length; i++) {
+                            if (first) {
+                                first = false;
+                            } else {
+                                res += ") " + logicalReverse[filter.type] + " (";
+                            }
+                            res += this.write(filter.filters[i]);
+                        }
+                        return res + ")";
+                    }
+                case "OpenLayers.Filter.Comparison":
+                    if (filter.type == OpenLayers.Filter.Comparison.BETWEEN) {
+                        return filter.property + " BETWEEN " + 
+                            this.write(filter.lowerBoundary) + " AND " + 
+                            this.write(filter.upperBoundary);
+                    } else {
+                        
+                        return filter.property +
+                            " " + operatorReverse[filter.type] + " " + 
+                            this.write(filter.value);
+                    }
+                case undefined:
+                    if (typeof filter === "string") {
+                        return "'" + filter + "'";
+                    } else if (typeof filter === "number") {
+                        return String(filter);
+                    }
+                default:
+                    throw new Error("Can't encode: " + filter.CLASS_NAME + " " + filter);
+            }
+        },
+
+        CLASS_NAME: "OpenLayers.Format.CQL"
+
+    });
+})();
+
+/* ======================================================================
+    OpenLayers/Control/Split.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Path.js
+ * @requires OpenLayers/Layer/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Split
+ * Acts as a split feature agent while editing vector features.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.Split = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * Supported control event types (in addition to those from <OpenLayers.Control>):
+     * beforesplit - Triggered before a split occurs.  Listeners receive an
+     *     event object with *source* and *target* properties.
+     * split - Triggered when a split occurs.  Listeners receive an event with
+     *     an *original* property and a *features* property.  The original
+     *     is a reference to the target feature that the sketch or modified
+     *     feature intersects.  The features property is a list of all features
+     *     that result from this single split.  This event is triggered before
+     *     the resulting features are added to the layer (while the layer still
+     *     has a reference to the original).
+     * aftersplit - Triggered after all splits resulting from a single sketch
+     *     or feature modification have occurred.  The original features
+     *     have been destroyed and features that result from the split
+     *     have already been added to the layer.  Listeners receive an event
+     *     with a *source* and *features* property.  The source references the
+     *     sketch or modified feature used as a splitter.  The features
+     *     property is a list of all resulting features.
+     */
+    EVENT_TYPES: ["beforesplit", "split", "aftersplit"],
+    
+    /**
+     * APIProperty: layer
+     * {<OpenLayers.Layer.Vector>} The target layer with features to be split.
+     *     Set at construction or after construction with <setLayer>.
+     */
+    layer: null,
+    
+    /**
+     * Property: source
+     * {<OpenLayers.Layer.Vector>} Optional source layer.  Any newly created
+     *     or modified features from this layer will be used to split features
+     *     on the target layer.  If not provided, a temporary sketch layer will
+     *     be created.
+     */
+    source: null,
+    
+    /**
+     * Property: sourceOptions
+     * {Options} If a temporary sketch layer is created, these layer options
+     *     will be applied.
+     */
+    sourceOptions: null,
+
+    /**
+     * APIProperty: tolerance
+     * {Number} Distance between the calculated intersection and a vertex on
+     *     the source geometry below which the existing vertex will be used
+     *     for the split.  Default is null.
+     */
+    tolerance: null,
+    
+    /**
+     * APIProperty: edge
+     * {Boolean} Allow splits given intersection of edges only.  Default is
+     *     true.  If false, a vertex on the source must be within the
+     *     <tolerance> distance of the calculated intersection for a split
+     *     to occur.
+     */
+    edge: true,
+    
+    /**
+     * APIProperty: deferDelete
+     * {Boolean} Instead of removing features from the layer, set feature
+     *     states of split features to DELETE.  This assumes a save strategy
+     *     or other component is in charge of removing features from the
+     *     layer.  Default is false.  If false, split features will be
+     *     immediately deleted from the layer.
+     */
+    deferDelete: false,
+    
+    /**
+     * APIProperty: mutual
+     * {Boolean} If source and target layers are the same, split source
+     *     features and target features where they intersect.  Default is
+     *     true.  If false, only target features will be split.
+     */
+    mutual: true,
+    
+    /**
+     * APIProperty: targetFilter
+     * {OpenLayers.Filter} Optional filter that will be evaluated
+     *     to determine if a feature from the target layer is eligible for
+     *     splitting.
+     */
+    targetFilter: null,
+    
+    /**
+     * APIProperty: sourceFilter
+     * {OpenLayers.Filter} Optional filter that will be evaluated
+     *     to determine if a feature from the target layer is eligible for
+     *     splitting.
+     */
+    sourceFilter: null,
+    
+    /**
+     * Property: handler
+     * {<OpenLayers.Handler.Path>} The temporary sketch handler created if
+     *     no source layer is provided.
+     */
+    handler: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Split
+     * Creates a new split control. A control is constructed with a target
+     *     layer and an optional source layer. While the control is active,
+     *     creating new features or modifying existing features on the source
+     *     layer will result in splitting any eligible features on the target
+     *     layer.  If no source layer is provided, a temporary sketch layer will
+     *     be created to create lines for splitting features on the target.
+     *
+     * Parameters:
+     * options - {Object} An object containing all configuration properties for
+     *     the control.
+     *
+     * Valid options:
+     * layer - {OpenLayers.Layer.Vector} The target layer.  Features from this
+     *     layer will be split by new or modified features on the source layer
+     *     or temporary sketch layer.
+     * source - {OpenLayers.Layer.Vector} Optional source layer.  If provided
+     *     newly created features or modified features will be used to split
+     *     features on the target layer.  If not provided, a temporary sketch
+     *     layer will be created for drawing lines.
+     * tolerance - {Number} Optional value for the distance between a source
+     *     vertex and the calculated intersection below which the split will
+     *     occur at the vertex.
+     * edge - {Boolean} Allow splits given intersection of edges only.  Default
+     *     is true.  If false, a vertex on the source must be within the
+     *     <tolerance> distance of the calculated intersection for a split
+     *     to occur.
+     * mutual - {Boolean} If source and target are the same, split source
+     *     features and target features where they intersect.  Default is
+     *     true.  If false, only target features will be split.
+     * targetFilter - {OpenLayers.Filter} Optional filter that will be evaluated
+     *     to determine if a feature from the target layer is eligible for
+     *     splitting.
+     * sourceFilter - {OpenLayers.Filter} Optional filter that will be evaluated
+     *     to determine if a feature from the target layer is eligible for
+     *     splitting.
+     */
+    initialize: function(options) {
+        // concatenate events specific to measure with those from the base
+        Array.prototype.push.apply(
+            this.EVENT_TYPES, OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.options = options || {}; // TODO: this could be done by the super
+        
+        // set the source layer if provided
+        if(this.options.source) {
+            this.setSource(this.options.source);
+        }
+    },
+    
+    /**
+     * APIMethod: setSource
+     * Set the source layer for edits layer.
+     *
+     * Parameters:
+     * layer - {OpenLayers.Layer.Vector}  The new source layer layer.  If
+     *     null, a temporary sketch layer will be created.
+     */
+    setSource: function(layer) {
+        if(this.active) {
+            this.deactivate();
+            if(this.handler) {
+                this.handler.destroy();
+                delete this.handler;
+            }
+            this.source = layer;
+            this.activate();
+        } else {
+            this.source = layer;
+        }
+    },
+    
+    /**
+     * APIMethod: activate
+     * Activate the control.  Activating the control registers listeners for
+     *     editing related events so that during feature creation and
+     *     modification, features in the target will be considered for
+     *     splitting.
+     */
+    activate: function() {
+        var activated = OpenLayers.Control.prototype.activate.call(this);
+        if(activated) {
+            if(!this.source) {
+                if(!this.handler) {
+                    this.handler = new OpenLayers.Handler.Path(this,
+                        {done: function(geometry) {
+                            this.onSketchComplete({
+                                feature: new OpenLayers.Feature.Vector(geometry)
+                            });
+                        }},
+                        {layerOptions: this.sourceOptions}
+                    );
+                }
+                this.handler.activate();
+            } else if(this.source.events) {
+                this.source.events.on({
+                    sketchcomplete: this.onSketchComplete,
+                    afterfeaturemodified: this.afterFeatureModified,
+                    scope: this
+                });
+            }
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control.  Deactivating the control unregisters listeners
+     *     so feature editing may proceed without engaging the split agent.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
+        if(deactivated) {
+            if(this.source && this.source.events) {
+                this.layer.events.un({
+                    sketchcomplete: this.onSketchComplete,
+                    afterfeaturemodified: this.afterFeatureModified,
+                    scope: this
+                });
+            }
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: onSketchComplete
+     * Registered as a listener for the sketchcomplete event on the editable
+     *     layer.
+     *
+     * Parameters:
+     * event - {Object} The sketch complete event.
+     *
+     * Returns:
+     * {Boolean} Stop the sketch from being added to the layer (it has been
+     *     split).
+     */
+    onSketchComplete: function(event) {
+        this.feature = null;
+        return !this.considerSplit(event.feature);
+    },
+    
+    /**
+     * Method: afterFeatureModified
+     * Registered as a listener for the afterfeaturemodified event on the
+     *     editable layer.
+     *
+     * Parameters:
+     * event - {Object} The after feature modified event.
+     */
+    afterFeatureModified: function(event) {
+        if(event.modified) {
+            var feature = event.feature;
+            if(feature.geometry instanceof OpenLayers.Geometry.LineString ||
+               feature.geometry instanceof OpenLayers.Geometry.MultiLineString) {
+                this.feature = event.feature;
+                this.considerSplit(event.feature);
+            }
+        }
+    },
+    
+    /**
+     * Method: removeByGeometry
+     * Remove a feature from a list based on the given geometry.
+     *
+     * Parameters:
+     * features - {Array(<OpenLayers.Feature.Vector>)} A list of features.
+     * geometry - {<OpenLayers.Geometry>} A geometry.
+     */
+    removeByGeometry: function(features, geometry) {
+        for(var i=0, len=features.length; i<len; ++i) {
+            if(features[i].geometry === geometry) {
+                features.splice(i, 1);
+                break;
+            }
+        }
+    },
+    
+    /**
+     * Method: isEligible
+     * Test if a target feature is eligible for splitting.
+     *
+     * Parameters:
+     * target - {<OpenLayers.Feature.Vector>} The target feature.
+     *
+     * Returns:
+     * {Boolean} The target is eligible for splitting.
+     */
+    isEligible: function(target) {
+        return (
+            target.state !== OpenLayers.State.DELETE
+        ) && (
+            target.geometry instanceof OpenLayers.Geometry.LineString ||
+            target.geometry instanceof OpenLayers.Geometry.MultiLineString
+        ) && (
+            this.feature !== target
+        ) && (
+            !this.targetFilter ||
+            this.targetFilter.evaluate(target.attributes)
+        );
+    },
+
+    /**
+     * Method: considerSplit
+     * Decide whether or not to split target features with the supplied
+     *     feature.  If <mutual> is true, both the source and target features
+     *     will be split if eligible.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The newly created or modified
+     *     feature.
+     *
+     * Returns:
+     * {Boolean} The supplied feature was split (and destroyed).
+     */
+    considerSplit: function(feature) {
+        var sourceSplit = false;
+        var targetSplit = false;
+        if(!this.sourceFilter ||
+           this.sourceFilter.evaluate(feature.attributes)) {
+            var features = this.layer && this.layer.features || [];
+            var target, results, proceed;
+            var additions = [], removals = [];
+            var mutual = (this.layer === this.source) && this.mutual;
+            var options = {
+                edge: this.edge,
+                tolerance: this.tolerance,
+                mutual: mutual
+            };
+            var sourceParts = [feature.geometry];
+            var targetFeature, targetParts;
+            var source, parts;
+            for(var i=0, len=features.length; i<len; ++i) {
+                targetFeature = features[i];
+                if(this.isEligible(targetFeature)) {
+                    targetParts = [targetFeature.geometry];
+                    // work through source geoms - this array may change
+                    for(var j=0; j<sourceParts.length; ++j) { 
+                        source = sourceParts[j];
+                        // work through target parts - this array may change
+                        for(var k=0; k<targetParts.length; ++k) {
+                            target = targetParts[k];
+                            if(source.getBounds().intersectsBounds(target.getBounds())) {
+                                results = source.split(target, options);
+                                if(results) {
+                                    proceed = this.events.triggerEvent(
+                                        "beforesplit", {source: feature, target: targetFeature}
+                                    );
+                                    if(proceed !== false) {
+                                        if(mutual) {
+                                            parts = results[0];
+                                            // handle parts that result from source splitting
+                                            if(parts.length > 1) {
+                                                // splice in new source parts
+                                                parts.unshift(j, 1); // add args for splice below
+                                                Array.prototype.splice.apply(sourceParts, parts);
+                                                j += parts.length - 3;
+                                            }
+                                            results = results[1];
+                                        }
+                                        // handle parts that result from target splitting
+                                        if(results.length > 1) {
+                                            // splice in new target parts
+                                            results.unshift(k, 1); // add args for splice below
+                                            Array.prototype.splice.apply(targetParts, results);
+                                            k += results.length - 3;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    if(targetParts && targetParts.length > 1) {
+                        this.geomsToFeatures(targetFeature, targetParts);
+                        this.events.triggerEvent("split", {
+                            original: targetFeature,
+                            features: targetParts
+                        });
+                        Array.prototype.push.apply(additions, targetParts);
+                        removals.push(targetFeature);
+                        targetSplit = true;
+                    }
+                }
+            }
+            if(sourceParts && sourceParts.length > 1) {
+                this.geomsToFeatures(feature, sourceParts);
+                this.events.triggerEvent("split", {
+                    original: feature,
+                    features: sourceParts
+                });
+                Array.prototype.push.apply(additions, sourceParts);
+                removals.push(feature);
+                sourceSplit = true;
+            }
+            if(sourceSplit || targetSplit) {
+                // remove and add feature events are suppressed
+                // listen for split event on this control instead
+                if(this.deferDelete) {
+                    // Set state instead of removing.  Take care to avoid
+                    // setting delete for features that have not yet been
+                    // inserted - those should be destroyed immediately.
+                    var feat, destroys = [];
+                    for(var i=0, len=removals.length; i<len; ++i) {
+                        feat = removals[i];
+                        if(feat.state === OpenLayers.State.INSERT) {
+                            destroys.push(feat);
+                        } else {
+                            feat.state = OpenLayers.State.DELETE;
+                            this.layer.drawFeature(feat);
+                        }
+                    }
+                    this.layer.destroyFeatures(destroys, {silent: true});
+                    for(var i=0, len=additions.length; i<len; ++i) {
+                        additions[i].state = OpenLayers.State.INSERT;
+                    }
+                } else {
+                    this.layer.destroyFeatures(removals, {silent: true});
+                }
+                this.layer.addFeatures(additions, {silent: true});
+                this.events.triggerEvent("aftersplit", {
+                    source: feature,
+                    features: additions
+                });
+            }
+        }
+        return sourceSplit;
+    },
+    
+    /**
+     * Method: geomsToFeatures
+     * Create new features given a template feature and a list of geometries.
+     *     The list of geometries is modified in place.  The result will be
+     *     a list of new features.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} The feature to be cloned.
+     * geoms - {Array(<OpenLayers.Geometry>)} List of goemetries.  This will
+     *     become a list of new features.
+     */
+    geomsToFeatures: function(feature, geoms) {
+        var clone = feature.clone();
+        delete clone.geometry;
+        var newFeature;
+        for(var i=0, len=geoms.length; i<len; ++i) {
+            // turn results list from geoms to features
+            newFeature = clone.clone();
+            newFeature.geometry = geoms[i];
+            newFeature.state = OpenLayers.State.INSERT;
+            geoms[i] = newFeature;
+        }
+    },
+    
+    /**
+     * Method: destroy
+     * Clean up the control.
+     */
+    destroy: function() {
+        if(this.active) {
+            this.deactivate(); // TODO: this should be handled by the super
+        }
+        OpenLayers.Control.prototype.destroy.call(this);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.Split"
+});
+/* ======================================================================
+    OpenLayers/Layer/WMTS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMTS
+ * Instances of the WMTS class allow viewing of tiles from a service that 
+ *     implements the OGC WMTS specification version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
+    
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} The layer will be considered a base layer.  Default is true.
+     */
+    isBaseLayer: true,
+
+    /**
+     * Property: version
+     * {String} WMTS version.  Default is "1.0.0".
+     */
+    version: "1.0.0",
+    
+    /**
+     * APIProperty: requestEncoding
+     * {String} Request encoding.  Can be "REST" or "KVP".  Default is "KVP".
+     */
+    requestEncoding: "KVP",
+    
+    /**
+     * APIProperty: url
+     * {String} The base URL for the WMTS service.  Must be provided.
+     */
+    url: null,
+
+    /**
+     * APIProperty: layer
+     * {String} The layer identifier advertised by the WMTS service.  Must be 
+     *     provided.
+     */
+    layer: null,
+    
+    /** 
+     * APIProperty: matrixSet
+     * {String} One of the advertised matrix set identifiers.  Must be provided.
+     */
+    matrixSet: null,
+
+    /** 
+     * APIProperty: style
+     * {String} One of the advertised layer styles.  Must be provided.
+     */
+    style: null,
+    
+    /** 
+     * APIProperty: format
+     * {String} The image MIME type.  Default is "image/jpeg".
+     */
+    format: "image/jpeg",
+    
+    /**
+     * APIProperty: tileOrigin
+     * {<OpenLayers.LonLat>} The top-left corner of the tile matrix in map 
+     *     units.  If the tile origin for each matrix in a set is different,
+     *     the <matrixIds> should include a topLeftCorner property.  If
+     *     not provided, the tile origin will default to the top left corner
+     *     of the layer <maxExtent>.
+     */
+    tileOrigin: null,
+    
+    /**
+     * APIProperty: tileFullExtent
+     * {<OpenLayers.Bounds>}  The full extent of the tile set.  If not supplied,
+     *     the layer's <maxExtent> property will be used.
+     */
+    tileFullExtent: null,
+
+    /**
+     * APIProperty: formatSuffix
+     * {String} For REST request encoding, an image format suffix must be 
+     *     included in the request.  If not provided, the suffix will be derived
+     *     from the <format> property.
+     */
+    formatSuffix: null,    
+
+    /**
+     * APIProperty: matrixIds
+     * {Array} A list of tile matrix identifiers.  If not provided, the matrix
+     *     identifiers will be assumed to be integers corresponding to the 
+     *     map zoom level.  If a list of strings is provided, each item should
+     *     be the matrix identifier that corresponds to the map zoom level.
+     *     Additionally, a list of objects can be provided.  Each object should
+     *     describe the matrix as presented in the WMTS capabilities.  These
+     *     objects should have the propertes shown below.
+     * 
+     * Matrix properties:
+     * identifier - {String} The matrix identifier (required).
+     * topLeftCorner - {<OpenLayers.LonLat>} The top left corner of the 
+     *     matrix.  Must be provided if different than the layer <tileOrigin>.
+     * tileWidth - {Number} The tile width for the matrix.  Must be provided 
+     *     if different than the width given in the layer <tileSize>.
+     * tileHeight - {Number} The tile height for the matrix.  Must be provided 
+     *     if different than the height given in the layer <tileSize>.
+     */
+    matrixIds: null,
+    
+    /**
+     * APIProperty: dimensions
+     * {Array} For RESTful request encoding, extra dimensions may be specified.
+     *     Items in this list should be property names in the <params> object.
+     *     Values of extra dimensions will be determined from the corresponding
+     *     values in the <params> object.
+     */
+    dimensions: null,
+    
+    /**
+     * APIProperty: params
+     * {Object} Extra parameters to include in tile requests.  For KVP 
+     *     <requestEncoding>, these properties will be encoded in the request 
+     *     query string.  For REST <requestEncoding>, these properties will
+     *     become part of the request path, with order determined by the 
+     *     <dimensions> list.
+     */
+    params: null,
+    
+    /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Additionally, if this layer is to be used
+     *     as an overlay and the cache has fewer zoom levels than the base
+     *     layer, you can supply a negative zoomOffset.  For example, if a
+     *     map zoom level of 1 corresponds to your cache level zero, you would
+     *     supply a -1 zoomOffset (and set the maxResolution of the layer
+     *     appropriately).  The zoomOffset value has no effect if complete
+     *     matrix definitions (including scaleDenominator) are supplied in
+     *     the <matrixIds> property.  Defaults to 0 (no zoom offset).
+     */
+    zoomOffset: 0,
+    
+    /**
+     * Property: formatSuffixMap
+     * {Object} a map between WMTS 'format' request parameter and tile image file suffix
+     */
+    formatSuffixMap: {
+        "image/png": "png",
+        "image/png8": "png",
+        "image/png24": "png",
+        "image/png32": "png",
+        "png": "png",
+        "image/jpeg": "jpg",
+        "image/jpg": "jpg",
+        "jpeg": "jpg",
+        "jpg": "jpg"
+    },
+    
+    /**
+     * Property: matrix
+     * {Object} Matrix definition for the current map resolution.  Updated by
+     *     the <updateMatrixProperties> method.
+     */
+    matrix: null,
+    
+    /**
+     * Constructor: OpenLayers.Layer.WMTS
+     * Create a new WMTS layer.
+     *
+     * Example:
+     * (code)
+     * var wmts = new OpenLayers.Layer.WMTS({
+     *     name: "My WMTS Layer",
+     *     url: "http://example.com/wmts", 
+     *     layer: "layer_id",
+     *     style: "default",
+     *     matrixSet: "matrix_id"
+     * });
+     * (end)
+     *
+     * Parameters:
+     * config - {Object} Configuration properties for the layer.
+     *
+     * Required configuration properties:
+     * url - {String} The base url for the service.  See the <url> property.
+     * layer - {String} The layer identifier.  See the <layer> property.
+     * style - {String} The layer style identifier.  See the <style> property.
+     * matrixSet - {String} The tile matrix set identifier.  See the <matrixSet>
+     *     property.
+     *
+     * Any other documented layer properties can be provided in the config object.
+     */
+    initialize: function(config) {
+
+        // confirm required properties are supplied
+        var required = {
+            url: true,
+            layer: true,
+            style: true,
+            matrixSet: true
+        };
+        for (var prop in required) {
+            if (!(prop in config)) {
+                throw new Error("Missing property '" + prop + "' in layer configuration.");
+            }
+        }
+
+        config.params = OpenLayers.Util.upperCaseObject(config.params);
+        var args = [config.name, config.url, config.params, config];
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, args);
+        
+
+        // determine format suffix (for REST)
+        if (!this.formatSuffix) {
+            this.formatSuffix = this.formatSuffixMap[this.format] || this.format.split("/").pop();            
+        }
+
+        // expand matrixIds (may be array of string or array of object)
+        if (this.matrixIds) {
+            var len = this.matrixIds.length;
+            if (len && typeof this.matrixIds[0] === "string") {
+                var ids = this.matrixIds;
+                this.matrixIds = new Array(len);
+                for (var i=0; i<len; ++i) {
+                    this.matrixIds[i] = {identifier: ids[i]};
+                }
+            }
+        }
+
+    },
+    
+    /**
+     * Method: setMap
+     */
+    setMap: function() {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        this.updateMatrixProperties();
+    },
+    
+    /**
+     * Method: updateMatrixProperties
+     * Called when map resolution changes to update matrix related properties.
+     */
+    updateMatrixProperties: function() {
+        this.matrix = this.getMatrix();
+        if (this.matrix) {
+            if (this.matrix.topLeftCorner) {
+                this.tileOrigin = this.matrix.topLeftCorner;
+            }
+            if (this.matrix.tileWidth && this.matrix.tileHeight) {
+                this.tileSize = new OpenLayers.Size(
+                    this.matrix.tileWidth, this.matrix.tileHeight
+                );
+            }
+            if (!this.tileOrigin) { 
+                this.tileOrigin = new OpenLayers.LonLat(
+                    this.maxExtent.left, this.maxExtent.top
+                );
+            }   
+            if (!this.tileFullExtent) { 
+                this.tileFullExtent = this.maxExtent;
+            }
+        }
+    },
+    
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * bound - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to
+     *     do some init work in that case.
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        if (zoomChanged || !this.matrix) {
+            this.updateMatrixProperties();
+        }
+        return OpenLayers.Layer.Grid.prototype.moveTo.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: clone
+     * 
+     * Parameters:
+     * obj - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.WMTS>} An exact clone of this <OpenLayers.Layer.WMTS>
+     */
+    clone: function(obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Layer.WMTS(this.options);
+        }
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+        // copy/set any non-init, non-simple values here
+        return obj;
+    },
+    
+    /**
+     * Method: getMatrix
+     * Get the appropriate matrix definition for the current map resolution.
+     */
+    getMatrix: function() {
+        var matrix;
+        if (!this.matrixIds || this.matrixIds.length === 0) {
+            matrix = {identifier: this.map.getZoom() + this.zoomOffset};
+        } else {
+            // get appropriate matrix given the map scale if possible
+            if ("scaleDenominator" in this.matrixIds[0]) {
+                // scale denominator calculation based on WMTS spec
+                var denom = 
+                    OpenLayers.METERS_PER_INCH * 
+                    OpenLayers.INCHES_PER_UNIT[this.units] * 
+                    this.map.getResolution() / 0.28E-3;
+                var diff = Number.POSITIVE_INFINITY;
+                var delta;
+                for (var i=0, ii=this.matrixIds.length; i<ii; ++i) {
+                    delta = Math.abs(1 - (this.matrixIds[i].scaleDenominator / denom));
+                    if (delta < diff) {
+                        diff = delta;
+                        matrix = this.matrixIds[i];
+                    }
+                }
+            } else {
+                // fall back on zoom as index
+                matrix = this.matrixIds[this.map.getZoom() + this.zoomOffset];
+            }
+        }
+        return matrix;
+    },
+    
+    /** 
+     * Method: getTileInfo
+     * Get tile information for a given location at the current map resolution.
+     *
+     * Parameters:
+     * loc - {<OpenLayers.LonLat} A location in map coordinates.
+     *
+     * Returns:
+     * {Object} An object with "col", "row", "i", and "j" properties.  The col
+     *     and row values are zero based tile indexes from the top left.  The
+     *     i and j values are the number of pixels to the left and top 
+     *     (respectively) of the given location within the target tile.
+     */
+    getTileInfo: function(loc) {
+        var res = this.map.getResolution();
+        
+        var fx = (loc.lon - this.tileOrigin.lon) / (res * this.tileSize.w);
+        var fy = (this.tileOrigin.lat - loc.lat) / (res * this.tileSize.h);
+
+        var col = Math.floor(fx);
+        var row = Math.floor(fy);
+        
+        return {
+            col: col, 
+            row: row,
+            i: Math.floor((fx - col) * this.tileSize.w),
+            j: Math.floor((fy - row) * this.tileSize.h)
+        };
+    },
+    
+    /**
+     * Method: getURL
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {String} A URL for the tile corresponding to the given bounds.
+     */
+    getURL: function(bounds) {
+        bounds = this.adjustBounds(bounds);
+        var url = "";
+        if (!this.tileFullExtent || this.tileFullExtent.intersectsBounds(bounds)) {            
+
+            var center = bounds.getCenterLonLat();            
+            var info = this.getTileInfo(center);
+            var matrixId = this.matrix.identifier;
+
+            if (this.requestEncoding.toUpperCase() === "REST") {
+
+                // include 'version', 'layer' and 'style' in tile resource url
+                var path = this.version + "/" + this.layer + "/" + this.style + "/";
+
+                // append optional dimension path elements
+                if (this.dimensions) {
+                    for (var i=0; i<this.dimensions.length; i++) {
+                        if (this.params[this.dimensions[i]]) {
+                            path = path + this.params[this.dimensions[i]] + "/";
+                        }
+                    }
+                }
+
+                // append other required path elements
+                path = path + this.matrixSet + "/" + this.matrix.identifier + 
+                    "/" + info.row + "/" + info.col + "." + this.formatSuffix;
+                
+                if (OpenLayers.Util.isArray(this.url)) {
+                    url = this.selectUrl(path, this.url);
+                } else {
+                    url = this.url;
+                }
+                if (!url.match(/\/$/)) {
+                    url = url + "/";
+                }
+                url = url + path;
+
+            } else if (this.requestEncoding.toUpperCase() === "KVP") {
+
+                // assemble all required parameters
+                var params = {
+                    SERVICE: "WMTS",
+                    REQUEST: "GetTile",
+                    VERSION: this.version,
+                    LAYER: this.layer,
+                    STYLE: this.style,
+                    TILEMATRIXSET: this.matrixSet,
+                    TILEMATRIX: this.matrix.identifier,
+                    TILEROW: info.row,
+                    TILECOL: info.col,
+                    FORMAT: this.format
+                };
+                url = OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this, [params]);
+
+            }
+        }
+        return url;    
+    },
+    
+    /**
+     * APIMethod: mergeNewParams
+     * Extend the existing layer <params> with new properties.  Tiles will be
+     *     reloaded with updated params in the request.
+     * 
+     * Parameters:
+     * newParams - {Object} Properties to extend to existing <params>.
+     */
+    mergeNewParams: function(newParams) {
+        if (this.requestEncoding.toUpperCase() === "KVP") {
+            return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(
+                this, [OpenLayers.Util.upperCaseObject(newParams)]
+            );
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.WMTS"
+});
+/* ======================================================================
+    OpenLayers/Protocol/SOS/v1_0_0.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Protocol/SOS.js
+ * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.SOS.v1_0_0
+ * An SOS v1.0.0 Protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.SOS.v1_0_0> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+ OpenLayers.Protocol.SOS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol, {
+
+    /**
+     * APIProperty: fois
+     * {Array(String)} Array of features of interest (foi)
+     */
+    fois: null,
+
+    /**
+     * Property: formatOptions
+     * {Object} Optional options for the format.  If a format is not provided,
+     *     this property can be used to extend the default format options.
+     */
+    formatOptions: null,
+   
+    /**
+     * Constructor: OpenLayers.Protocol.SOS
+     * A class for giving layers an SOS protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     * Valid options properties:
+     * url - {String} URL to send requests to (required).
+     * fois - {Array} The features of interest (required).
+     */
+    initialize: function(options) {
+        OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
+        if(!options.format) {
+            this.format = new OpenLayers.Format.SOSGetFeatureOfInterest(
+                this.formatOptions);
+        }
+    },
+   
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        if(this.options && !this.options.format) {
+            this.format.destroy();
+        }
+        this.format = null;
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: read
+     * Construct a request for reading new sensor positions. This is done by
+     *     issuing one GetFeatureOfInterest request.
+     */
+    read: function(options) {
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options || {});
+        var response = new OpenLayers.Protocol.Response({requestType: "read"});
+        var format = this.format;
+        var data = OpenLayers.Format.XML.prototype.write.apply(format,
+            [format.writeNode("sos:GetFeatureOfInterest", {fois: this.fois})]
+        );
+        response.priv = OpenLayers.Request.POST({
+            url: options.url,
+            callback: this.createCallback(this.handleRead, response, options),
+            data: data
+        });
+        return response;
+    },
+   
+    /**
+     * Method: handleRead
+     * Deal with response from the read request.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass
+     *     to the user callback.
+     * options - {Object} The user options passed to the read call.
+     */
+    handleRead: function(response, options) {
+        if(options.callback) {
+            var request = response.priv;
+            if(request.status >= 200 && request.status < 300) {
+                // success
+                response.features = this.parseFeatures(request);
+                response.code = OpenLayers.Protocol.Response.SUCCESS;
+            } else {
+                // failure
+                response.code = OpenLayers.Protocol.Response.FAILURE;
+            }
+            options.callback.call(options.scope, response);
+        }
+    },
+
+    /**
+     * Method: parseFeatures
+     * Read HTTP response body and return features
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     *
+     * Returns:
+     * {Array({<OpenLayers.Feature.Vector>})} Array of features
+     */
+    parseFeatures: function(request) {
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        if(!doc || doc.length <= 0) {
+            return null;
+        }
+        return this.format.read(doc);
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.SOS.v1_0_0"
+});
+/* ======================================================================
+    OpenLayers/Layer/KaMapCache.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Layer/KaMap.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.KaMapCache
+ * 
+ * This class is designed to talk directly to a web-accessible ka-Map
+ * cache generated by the precache2.php script.
+ * 
+ * To create a a new KaMapCache layer, you must indicate also the "i" parameter
+ * (that will be used to calculate the file extension), and another special
+ * parameter, object names "metaTileSize", with "h" (height) and "w" (width)
+ * properties.
+ * 
+ *     // Create a new kaMapCache layer. 
+ *     var kamap_base = new OpenLayers.Layer.KaMapCache(
+ *         "Satellite",
+ *         "http://www.example.org/web/acessible/cache",
+ *         {g: "satellite", map: "world", i: 'png24', metaTileSize: {w: 5, h: 5} }
+ *       );
+ *    
+ *     // Create an kaMapCache overlay layer (using "isBaseLayer: false"). 
+ *     // Forces the output to be a "gif", using the "i" parameter.
+ *     var kamap_overlay = new OpenLayers.Layer.KaMapCache(
+ *         "Streets",
+ *         "http://www.example.org/web/acessible/cache",
+ *         {g: "streets", map: "world", i: "gif", metaTileSize: {w: 5, h: 5} },
+ *         {isBaseLayer: false}
+ *       );
+ *
+ * The cache URLs must look like: 
+ *   var/cache/World/50000/Group_Name/def/t-440320/l20480
+ * 
+ * This means that the cache generated via tile.php will *not* work with
+ *     this class, and should instead use the KaMap layer.
+ *
+ * More information is available in Ticket #1518.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.KaMap>
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.KaMapCache = OpenLayers.Class(OpenLayers.Layer.KaMap, {
+
+    /**
+     * Constant: IMAGE_EXTENSIONS
+     * {Object} Simple hash map to convert format to extension.
+     */
+    IMAGE_EXTENSIONS: {
+        'jpeg': 'jpg',
+        'gif' : 'gif',
+        'png' : 'png',
+        'png8' : 'png',
+        'png24' : 'png',
+        'dithered' : 'png'
+    },
+    
+    /**
+     * Constant: DEFAULT_FORMAT
+     * {Object} Simple hash map to convert format to extension.
+     */
+    DEFAULT_FORMAT: 'jpeg',
+    
+    /**
+     * Constructor: OpenLayers.Layer.KaMapCache
+     * 
+     * Parameters:
+     * name - {String}
+     * url - {String}
+     * params - {Object} Parameters to be sent to the HTTP server in the
+     *    query string for the tile. The format can be set via the 'i'
+     *    parameter (defaults to jpg) , and the map should be set via 
+     *    the 'map' parameter. It has been reported that ka-Map may behave
+     *    inconsistently if your format parameter does not match the format
+     *    parameter configured in your config.php. (See ticket #327 for more
+     *    information.)
+     * options - {Object} Additional options for the layer. Any of the 
+     *     APIProperties listed on this layer, and any layer types it
+     *     extends, can be overridden through the options parameter. 
+     */
+    initialize: function(name, url, params, options) {
+        OpenLayers.Layer.KaMap.prototype.initialize.apply(this, arguments);
+        this.extension = this.IMAGE_EXTENSIONS[this.params.i.toLowerCase() || DEFAULT_FORMAT];
+    },
+
+    /**
+     * Method: getURL
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * 
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the 
+     *          passed-in bounds and appropriate tile size specified as 
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var mapRes = this.map.getResolution();
+        var scale = Math.round((this.map.getScale() * 10000)) / 10000;
+        var pX = Math.round(bounds.left / mapRes);
+        var pY = -Math.round(bounds.top / mapRes);
+
+        var metaX = Math.floor(pX / this.tileSize.w / this.params.metaTileSize.w) * this.tileSize.w * this.params.metaTileSize.w;
+        var metaY = Math.floor(pY / this.tileSize.h / this.params.metaTileSize.h) * this.tileSize.h * this.params.metaTileSize.h;
+
+        // if url is not a string, it should be an array of strings,
+        // in which case we will deterministically select one of them in
+        // order to evenly distribute requests to different urls.
+        //
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(paramsString, url);
+        }  
+    
+        var components = [
+            url,
+            "/",
+            this.params.map,
+            "/",
+            scale,
+            "/",
+            this.params.g.replace(/\s/g, '_'),
+            "/def/t", 
+            metaY,
+            "/l",
+            metaX,
+            "/t",
+            pY,
+            "l",
+            pX,
+            ".",
+            this.extension
+          ];
+          
+        return components.join("");
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.KaMapCache"
+});
+/* ======================================================================
+    OpenLayers/Feature/WFS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Feature.js
+ */
+
+/**
+ * Class: OpenLayers.Feature.WFS
+ * WFS handling class, for use as a featureClass on the WFS layer for handling
+ * 'point' WFS types. Good for subclassing when creating a custom WFS like
+ * XML application.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Feature>
+ */
+OpenLayers.Feature.WFS = OpenLayers.Class(OpenLayers.Feature, {
+      
+    /** 
+     * Constructor: OpenLayers.Feature.WFS
+     * Create a WFS feature.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer>} 
+     * xmlNode - {XMLNode} 
+     */
+    initialize: function(layer, xmlNode) {
+        var newArguments = arguments;
+        var data = this.processXMLNode(xmlNode);
+        newArguments = new Array(layer, data.lonlat, data);
+        OpenLayers.Feature.prototype.initialize.apply(this, newArguments);
+        this.createMarker();
+        this.layer.addMarker(this.marker);
+    },
+    
+    /** 
+     * Method: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        if (this.marker != null) {
+            this.layer.removeMarker(this.marker);  
+        }
+        OpenLayers.Feature.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: processXMLNode
+     * When passed an xmlNode, parses it for a GML point, and passes
+     * back an object describing that point.
+     *
+     * For subclasses of Feature.WFS, this is the feature to change.
+     *
+     * Parameters:
+     * xmlNode - {XMLNode} 
+     * 
+     * Returns:
+     * {Object} Data Object with 'id', 'lonlat', and private properties set
+     */
+    processXMLNode: function(xmlNode) {
+        //this should be overridden by subclasses
+        // must return an Object with 'id' and 'lonlat' values set
+        var point = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, "http://www.opengis.net/gml", "gml", "Point");
+        var text  = OpenLayers.Util.getXmlNodeValue(OpenLayers.Ajax.getElementsByTagNameNS(point[0], "http://www.opengis.net/gml","gml", "coordinates")[0]);
+        var floats = text.split(",");
+        return {lonlat: new OpenLayers.LonLat(parseFloat(floats[0]),
+                                              parseFloat(floats[1])),
+                id: null};
+
+    },
+
+    CLASS_NAME: "OpenLayers.Feature.WFS"
+});
+  
+  
+  
+  
+
+/* ======================================================================
+    OpenLayers/Layer/TileCache.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.TileCache
+ * A read only TileCache layer.  Used to requests tiles cached by TileCache in
+ *     a web accessible cache.  This means that you have to pre-populate your
+ *     cache before this layer can be used.  It is meant only to read tiles
+ *     created by TileCache, and not to make calls to TileCache for tile
+ *     creation.  Create a new instance with the
+ *     <OpenLayers.Layer.TileCache> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.TileCache = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /** 
+     * APIProperty: isBaseLayer
+     * {Boolean} Treat this layer as a base layer.  Default is true.
+     */
+    isBaseLayer: true,
+    
+    /** 
+     * APIProperty: format
+     * {String} Mime type of the images returned.  Default is image/png.
+     */
+    format: 'image/png',
+
+    /**
+     * APIProperty: serverResolutions
+     * {Array} A list of all resolutions available on the server.  Only set this 
+     *     property if the map resolutions differs from the server.
+     */
+    serverResolutions: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.TileCache
+     * Create a new read only TileCache layer.
+     *
+     * Parameters:
+     * name - {String} Name of the layer displayed in the interface
+     * url - {String} Location of the web accessible cache (not the location of
+     *     your tilecache script!)
+     * layername - {String} Layer name as defined in the TileCache 
+     *     configuration
+     * options - {Object} Optional object with properties to be set on the
+     *     layer.  Note that you should speficy your resolutions to match
+     *     your TileCache configuration.  This can be done by setting
+     *     the resolutions array directly (here or on the map), by setting
+     *     maxResolution and numZoomLevels, or by using scale based properties.
+     */
+    initialize: function(name, url, layername, options) {
+        this.layername = layername;
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this,
+                                                         [name, url, {}, options]);
+        this.extension = this.format.split('/')[1].toLowerCase();
+        this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;
+    },    
+
+    /**
+     * APIMethod: clone
+     * obj - {Object} 
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.TileCache>} An exact clone of this 
+     *     <OpenLayers.Layer.TileCache>
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.TileCache(this.name,
+                                                 this.url,
+                                                 this.layername,
+                                                 this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },    
+    
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * 
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the 
+     *     passed-in bounds and appropriate tile size specified as parameters.
+     */
+    getURL: function(bounds) {
+        var res = this.map.getResolution();
+        var bbox = this.maxExtent;
+        var size = this.tileSize;
+        var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));
+        var tileY = Math.round((bounds.bottom - bbox.bottom) / (res * size.h));
+        var tileZ = this.serverResolutions != null ?
+            OpenLayers.Util.indexOf(this.serverResolutions, res) :
+            this.map.getZoom();
+        /**
+         * Zero-pad a positive integer.
+         * number - {Int} 
+         * length - {Int} 
+         *
+         * Returns:
+         * {String} A zero-padded string
+         */
+        function zeroPad(number, length) {
+            number = String(number);
+            var zeros = [];
+            for(var i=0; i<length; ++i) {
+                zeros.push('0');
+            }
+            return zeros.join('').substring(0, length - number.length) + number;
+        }
+        var components = [
+            this.layername,
+            zeroPad(tileZ, 2),
+            zeroPad(parseInt(tileX / 1000000), 3),
+            zeroPad((parseInt(tileX / 1000) % 1000), 3),
+            zeroPad((parseInt(tileX) % 1000), 3),
+            zeroPad(parseInt(tileY / 1000000), 3),
+            zeroPad((parseInt(tileY / 1000) % 1000), 3),
+            zeroPad((parseInt(tileY) % 1000), 3) + '.' + this.extension
+        ];
+        var path = components.join('/'); 
+        var url = this.url;
+        if (OpenLayers.Util.isArray(url)) {
+            url = this.selectUrl(path, url);
+        }
+        url = (url.charAt(url.length - 1) == '/') ? url : url + '/';
+        return url + path;
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.TileCache"
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_1_1.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_1
+ * Read WMS Capabilities version 1.1.1.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_1 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1_1, {
+    
+    /**
+     * Property: version
+     * {String} The specific parser version.
+     */
+    version: "1.1.1",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_1
+     * Create a new parser for WMS capabilities version 1.1.1.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "SRS": function(node, obj) {
+                obj.srs[this.getChildValue(node)] = true;
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1" 
+
+});
+/* ======================================================================
+    OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_1_WMSC
+ * Read WMS-C Capabilities version 1.1.1.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1_1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1_1_1, {
+    
+    /**
+     * Property: version
+     * {String} The specific parser version.
+     */
+    version: "1.1.1",
+    
+    /**
+     * Property: profile
+     * {String} The specific profile
+     */
+    profile: "WMSC",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_1
+     * Create a new parser for WMS-C capabilities version 1.1.1.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.initialize.apply(
+            this, [options]
+        );
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "VendorSpecificCapabilities": function(node, obj) {
+                obj.vendorSpecific = {tileSets: []};
+                this.readChildNodes(node, obj.vendorSpecific);
+            },
+            "TileSet": function(node, vendorSpecific) {
+                var tileset = {srs: {}, bbox: {}, resolutions: []};
+                this.readChildNodes(node, tileset);
+                vendorSpecific.tileSets.push(tileset);
+            },
+            "Resolutions": function(node, tileset) {
+                var res = this.getChildValue(node).split(" ");
+                for (var i=0, len=res.length; i<len; i++) {
+                    if (res[i] != "") {
+                        tileset.resolutions.push(parseFloat(res[i]));
+                    }
+                }
+            },
+            "Width": function(node, tileset) {
+                tileset.width = parseInt(this.getChildValue(node));
+            },
+            "Height": function(node, tileset) {
+                tileset.height = parseInt(this.getChildValue(node));
+            },
+            "Layers": function(node, tileset) {
+                tileset.layers = this.getChildValue(node);
+            },
+            "Styles": function(node, tileset) {
+                tileset.styles = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.readers["wms"])
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC" 
+
+});
+/* ======================================================================
+    OpenLayers/Layer/WFS.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Tile/WFS.js
+ * @requires OpenLayers/Layer/Vector.js
+ * @requires OpenLayers/Layer/Markers.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WFS
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.Vector
+ *     with a Protocol.WFS and one or more Strategies.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Vector>
+ *  - <OpenLayers.Layer.Markers>
+ */
+OpenLayers.Layer.WFS = OpenLayers.Class(
+  OpenLayers.Layer.Vector, OpenLayers.Layer.Markers, {
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} WFS layer is not a base layer by default. 
+     */
+    isBaseLayer: false,
+    
+    /**
+     * Property: tile
+     * {<OpenLayers.Tile.WFS>}
+     */
+    tile: null,    
+    
+    /**
+     * APIProperty: ratio
+     * {Float} The ratio property determines the size of the serverside query
+     *    relative to the map viewport size. By default, we load an area twice
+     *    as big as the map, to allow for panning without immediately reload.
+     *    Setting this to 1 will cause the area of the WFS request to match
+     *    the map area exactly. It is recommended to set this to some number
+     *    at least slightly larger than 1, otherwise accidental clicks can
+     *    cause a data reload, by moving the map only 1 pixel.
+     */
+    ratio: 2,
+
+    /**  
+     * Property: DEFAULT_PARAMS
+     * {Object} Hashtable of default key/value parameters
+     */
+    DEFAULT_PARAMS: { service: "WFS",
+                      version: "1.0.0",
+                      request: "GetFeature"
+                    },
+    
+    /** 
+     * APIProperty: featureClass
+     * {<OpenLayers.Feature>} If featureClass is defined, an old-style markers
+     *     based WFS layer is created instead of a new-style vector layer. If
+     *     sent, this should be a subclass of OpenLayers.Feature
+     */
+    featureClass: null,
+    
+    /**
+      * APIProperty: format
+      * {<OpenLayers.Format>} The format you want the data to be parsed with.
+      * Must be passed in the constructor. Should be a class, not an instance.
+      * This option can only be used if no featureClass is passed / vectorMode
+      * is false: if a featureClass is passed, then this parameter is ignored.
+      */
+    format: null,
+
+    /** 
+     * Property: formatObject
+     * {<OpenLayers.Format>} Internally created/managed format object, used by
+     * the Tile to parse data.
+     */
+    formatObject: null,
+
+    /**
+     * APIProperty: formatOptions
+     * {Object} Hash of options which should be passed to the format when it is
+     * created. Must be passed in the constructor.
+     */
+    formatOptions: null, 
+
+    /**
+     * Property: vectorMode
+     * {Boolean} Should be calculated automatically. Determines whether the
+     *     layer is in vector mode or marker mode.
+     */
+    vectorMode: true, 
+    
+    /**
+     * APIProperty: encodeBBOX
+     * {Boolean} Should the BBOX commas be encoded? The WMS spec says 'no', 
+     *     but some services want it that way. Default false.
+     */
+    encodeBBOX: false,
+    
+    /**
+     * APIProperty: extractAttributes 
+     * {Boolean} Should the WFS layer parse attributes from the retrieved
+     *     GML? Defaults to false. If enabled, parsing is slower, but 
+     *     attributes are available in the attributes property of 
+     *     layer features.
+     */
+    extractAttributes: false,
+
+    /**
+     * Constructor: OpenLayers.Layer.WFS
+     *
+     * Parameters:
+     * name - {String} 
+     * url - {String} 
+     * params - {Object} 
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, params, options) {
+        if (options == undefined) { options = {}; } 
+        
+        if (options.featureClass || 
+            !OpenLayers.Layer.Vector || 
+            !OpenLayers.Feature.Vector) {
+            this.vectorMode = false;
+        }    
+
+        // Uppercase params
+        params = OpenLayers.Util.upperCaseObject(params);
+        
+        // Turn off error reporting, browsers like Safari may work
+        // depending on the setup, and we don't want an unneccesary alert.
+        OpenLayers.Util.extend(options, {'reportError': false});
+        var newArguments = [];
+        newArguments.push(name, options);
+        OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments);
+        if (!this.renderer || !this.vectorMode) {
+            this.vectorMode = false; 
+            if (!options.featureClass) {
+                options.featureClass = OpenLayers.Feature.WFS;
+            }   
+            OpenLayers.Layer.Markers.prototype.initialize.apply(this, 
+                                                                newArguments);
+        }
+        
+        if (this.params && this.params.typename && !this.options.typename) {
+            this.options.typename = this.params.typename;
+        }
+        
+        if (!this.options.geometry_column) {
+            this.options.geometry_column = "the_geom";
+        }    
+        
+        this.params = OpenLayers.Util.applyDefaults(
+            params, 
+            OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
+        );
+        this.url = url;
+    },    
+    
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        if (this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.destroy.apply(this, arguments);
+        } else {    
+            OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
+        }    
+        if (this.tile) {
+            this.tile.destroy();
+        }
+        this.tile = null;
+
+        this.ratio = null;
+        this.featureClass = null;
+        this.format = null;
+
+        if (this.formatObject && this.formatObject.destroy) {
+            this.formatObject.destroy();
+        }
+        this.formatObject = null;
+        
+        this.formatOptions = null;
+        this.vectorMode = null;
+        this.encodeBBOX = null;
+        this.extractAttributes = null;
+    },
+    
+    /**
+     * Method: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        if (this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
+            
+            var options = {
+              'extractAttributes': this.extractAttributes
+            };
+            
+            OpenLayers.Util.extend(options, this.formatOptions);
+            if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+                options.externalProjection = this.projection;
+                options.internalProjection = this.map.getProjectionObject();
+            }    
+            
+            this.formatObject = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
+        } else {    
+            OpenLayers.Layer.Markers.prototype.setMap.apply(this, arguments);
+        }    
+    },
+    
+    /** 
+     * Method: moveTo
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} 
+     * zoomChanged - {Boolean} 
+     * dragging - {Boolean} 
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        if (this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments);
+        } else {
+            OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
+        }    
+
+        // don't load wfs features while dragging, wait for drag end
+        if (dragging) {
+            // TBD try to hide the vector layer while dragging
+            // this.setVisibility(false);
+            // this will probably help for panning performances
+            return false;
+        }
+        
+        if ( zoomChanged ) {
+            if (this.vectorMode) {
+                this.renderer.clear();
+            }
+        }
+        
+    //DEPRECATED - REMOVE IN 3.0
+        // don't load data if current zoom level doesn't match
+        if (this.options.minZoomLevel) {
+            OpenLayers.Console.warn(OpenLayers.i18n('minZoomLevelError'));
+            
+            if (this.map.getZoom() < this.options.minZoomLevel) {
+                return null;
+            }
+        }
+        
+        if (bounds == null) {
+            bounds = this.map.getExtent();
+        }
+
+        var firstRendering = (this.tile == null);
+
+        //does the new bounds to which we need to move fall outside of the 
+        // current tile's bounds?
+        var outOfBounds = (!firstRendering &&
+                           !this.tile.bounds.containsBounds(bounds));
+
+        if (zoomChanged || firstRendering || (!dragging && outOfBounds)) {
+            //determine new tile bounds
+            var center = bounds.getCenterLonLat();
+            var tileWidth = bounds.getWidth() * this.ratio;
+            var tileHeight = bounds.getHeight() * this.ratio;
+            var tileBounds = 
+                new OpenLayers.Bounds(center.lon - (tileWidth / 2),
+                                      center.lat - (tileHeight / 2),
+                                      center.lon + (tileWidth / 2),
+                                      center.lat + (tileHeight / 2));
+
+            //determine new tile size
+            var tileSize = this.map.getSize();
+            tileSize.w = tileSize.w * this.ratio;
+            tileSize.h = tileSize.h * this.ratio;
+
+            //determine new position (upper left corner of new bounds)
+            var ul = new OpenLayers.LonLat(tileBounds.left, tileBounds.top);
+            var pos = this.map.getLayerPxFromLonLat(ul);
+
+            //formulate request url string
+            var url = this.getFullRequestString();
+        
+            var params = null;
+
+            // Cant combine "filter" and "BBOX". This is a cheap hack to help
+            // people out who can't migrate to the WFS protocol immediately.
+            var filter = this.params.filter || this.params.FILTER;
+            if (filter) {
+                params = {FILTER: filter};
+            }
+            else {
+                params = {BBOX: this.encodeBBOX ? tileBounds.toBBOX() 
+                                                    : tileBounds.toArray()};
+            }
+            
+            if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+                var projectedBounds = tileBounds.clone();
+                projectedBounds.transform(this.map.getProjectionObject(), 
+                                          this.projection);
+                if (!filter){
+                    params.BBOX = this.encodeBBOX ? projectedBounds.toBBOX() 
+                                                : projectedBounds.toArray();
+                }
+            }                                  
+
+            url += "&" + OpenLayers.Util.getParameterString(params);
+
+            if (!this.tile) {
+                this.tile = new OpenLayers.Tile.WFS(this, pos, tileBounds, 
+                                                     url, tileSize);
+                this.addTileMonitoringHooks(this.tile);
+                this.tile.draw();
+            } else {
+                if (this.vectorMode) {
+                    this.destroyFeatures();
+                    this.renderer.clear();
+                } else {
+                    this.clearMarkers();
+                }    
+                this.removeTileMonitoringHooks(this.tile);
+                this.tile.destroy();
+                
+                this.tile = null;
+                this.tile = new OpenLayers.Tile.WFS(this, pos, tileBounds, 
+                                                     url, tileSize);
+                this.addTileMonitoringHooks(this.tile);
+                this.tile.draw();
+            } 
+        }
+    },
+
+    /** 
+     * Method: addTileMonitoringHooks
+     * This function takes a tile as input and adds the appropriate hooks to 
+     *     the tile so that the layer can keep track of the loading tile
+     *     (making sure to check that the tile is always the layer's current
+     *     tile before taking any action).
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    addTileMonitoringHooks: function(tile) {
+        tile.onLoadStart = function() {
+            //if this is the the layer's current tile, then trigger 
+            // a 'loadstart'
+            if (this == this.layer.tile) {
+                this.layer.events.triggerEvent("loadstart");
+            }
+        };
+        tile.events.register("loadstart", tile, tile.onLoadStart);
+      
+        tile.onLoadEnd = function() {
+            //if this is the the layer's current tile, then trigger 
+            // a 'tileloaded' and 'loadend'
+            if (this == this.layer.tile) {
+                this.layer.events.triggerEvent("tileloaded");
+                this.layer.events.triggerEvent("loadend");
+            }
+        };
+        tile.events.register("loadend", tile, tile.onLoadEnd);
+        tile.events.register("unload", tile, tile.onLoadEnd);
+    },
+    
+    /** 
+     * Method: removeTileMonitoringHooks
+     * This function takes a tile as input and removes the tile hooks 
+     *     that were added in addTileMonitoringHooks()
+     * 
+     * Parameters: 
+     * tile - {<OpenLayers.Tile>}
+     */
+    removeTileMonitoringHooks: function(tile) {
+        tile.unload();
+        tile.events.un({
+            "loadstart": tile.onLoadStart,
+            "loadend": tile.onLoadEnd,
+            "unload": tile.onLoadEnd,
+            scope: tile
+        });
+    },
+
+    /**
+     * Method: onMapResize
+     * Call the onMapResize method of the appropriate parent class. 
+     */
+    onMapResize: function() {
+        if(this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.onMapResize.apply(this, 
+                                                                arguments);
+        } else {
+            OpenLayers.Layer.Markers.prototype.onMapResize.apply(this, 
+                                                                 arguments);
+        }
+    },
+    
+    /**
+     * Method: display
+     * Call the display method of the appropriate parent class. 
+     */
+    display: function() {
+        if(this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.display.apply(this, 
+                                                                arguments);
+        } else {
+            OpenLayers.Layer.Markers.prototype.display.apply(this, 
+                                                                 arguments);
+        }
+    },
+    
+    /**
+     * APIMethod: mergeNewParams
+     * Modify parameters for the layer and redraw.
+     * 
+     * Parameters:
+     * newParams - {Object}
+     */
+    mergeNewParams:function(newParams) {
+        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
+        var newArguments = [upperParams];
+        return OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this, 
+                                                                 newArguments);
+    },
+
+    /**
+     * APIMethod: clone
+     *
+     * Parameters:
+     * obj - {Object} 
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.WFS>} An exact clone of this OpenLayers.Layer.WFS
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.WFS(this.name,
+                                           this.url,
+                                           this.params,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        if (this.vectorMode) {
+            obj = OpenLayers.Layer.Vector.prototype.clone.apply(this, [obj]);
+        } else {
+            obj = OpenLayers.Layer.Markers.prototype.clone.apply(this, [obj]);
+        }    
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+
+    /** 
+     * APIMethod: getFullRequestString
+     * combine the layer's url with its params and these newParams. 
+     *   
+     *    Add the SRS parameter from 'projection' -- this is probably
+     *     more eloquently done via a setProjection() method, but this 
+     *     works for now and always.
+     *
+     * Parameters:
+     * newParams - {Object} 
+     * altUrl - {String} Use this as the url instead of the layer's url
+     */
+    getFullRequestString:function(newParams, altUrl) {
+        var projectionCode = this.projection.getCode() || this.map.getProjection();
+        this.params.SRS = (projectionCode == "none") ? null : projectionCode;
+
+        return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
+                                                    this, arguments);
+    },
+   
+    /**
+     * APIMethod: commit
+     * Write out the data to a WFS server.
+     */
+    commit: function() {
+        if (!this.writer) {
+            var options = {};
+            if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
+                options.externalProjection = this.projection;
+                options.internalProjection = this.map.getProjectionObject();
+            }    
+            
+            this.writer = new OpenLayers.Format.WFS(options,this);
+        }
+
+        var data = this.writer.write(this.features);
+
+        OpenLayers.Request.POST({
+            url: this.url,
+            data: data,
+            success: this.commitSuccess,
+            failure: this.commitFailure,
+            scope: this
+        });
+    },
+
+    /**
+     * Method: commitSuccess
+     * Called when the Ajax request returns a response
+     *
+     * Parameters:
+     * response - {XmlNode} from server
+     */
+    commitSuccess: function(request) {
+        var response = request.responseText;
+        if (response.indexOf('SUCCESS') != -1) {
+            this.commitReport(OpenLayers.i18n("commitSuccess", {'response':response}));
+            
+            for(var i = 0; i < this.features.length; i++) {
+                this.features[i].state = null;
+            }    
+            // TBD redraw the layer or reset the state of features
+            // foreach features: set state to null
+        } else if (response.indexOf('FAILED') != -1 ||
+            response.indexOf('Exception') != -1) {
+            this.commitReport(OpenLayers.i18n("commitFailed", {'response':response}));
+        }
+    },
+    
+    /**
+     * Method: commitFailure
+     * Called when the Ajax request fails
+     *
+     * Parameters:
+     * response - {XmlNode} from server
+     */
+    commitFailure: function(request) {},
+    
+    /**
+     * APIMethod: commitReport 
+     * Called with a 'success' message if the commit succeeded, otherwise
+     *     a failure message, and the full request text as a second parameter.
+     *     Override this function to provide custom transaction reporting.
+     *
+     * string - {String} reporting string
+     * response - {String} full XML response
+     */
+    commitReport: function(string, response) {
+        OpenLayers.Console.userError(string);
+    },
+
+    
+    /**
+     * APIMethod: refresh
+     * Refreshes all the features of the layer
+     */
+    refresh: function() {
+        if (this.tile) {
+            if (this.vectorMode) {
+                this.renderer.clear();
+                this.features.length = 0;
+            } else {   
+                this.clearMarkers();
+                this.markers.length = 0;
+            }    
+            this.tile.draw();
+        }
+    },
+    
+    /** 
+     * APIMethod: getDataExtent
+     * Calculates the max extent which includes all of the layer data.
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>}
+     */
+    getDataExtent: function () {
+        var extent; 
+        //get all additions from superclasses
+        if (this.vectorMode) {
+            extent = OpenLayers.Layer.Vector.prototype.getDataExtent.apply(this);
+        } else {
+            extent = OpenLayers.Layer.Markers.prototype.getDataExtent.apply(this);
+        }    
+
+        return extent;
+    },
+    
+    /** 
+     * APIMethod: setOpacity 
+     * Call the setOpacity method of the appropriate parent class to set the
+     *     opacity.  
+     * 
+     * Parameter: 
+     * opacity - {Float} 
+     */
+    setOpacity: function (opacity) {
+        if (this.vectorMode) {
+            OpenLayers.Layer.Vector.prototype.setOpacity.apply(this, [opacity]);
+        } else {
+            OpenLayers.Layer.Markers.prototype.setOpacity.apply(this, [opacity]);
+        }    
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.WFS"
+});
+/* ======================================================================
+    OpenLayers/Control/LayerSwitcher.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/** 
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Lang.js
+ * @requires Rico/Corner.js
+ */
+
+/**
+ * Class: OpenLayers.Control.LayerSwitcher
+ * The LayerSwitcher control displays a table of contents for the map. This 
+ * allows the user interface to switch between BaseLasyers and to show or hide
+ * Overlays. By default the switcher is shown minimized on the right edge of 
+ * the map, the user may expand it by clicking on the handle.
+ *
+ * To create the LayerSwitcher outside of the map, pass the Id of a html div 
+ * as the first argument to the constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.LayerSwitcher = 
+  OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: roundedCorner
+     * {Boolean} If true the Rico library is used for rounding the corners
+     *     of the layer switcher div, defaults to true.
+     */
+    roundedCorner: true,
+
+    /**  
+     * APIProperty: roundedCornerColor
+     * {String} The color of the rounded corners, only applies if roundedCorner
+     *     is true, defaults to "darkblue".
+     */
+    roundedCornerColor: "darkblue",
+    
+    /**  
+     * Property: layerStates 
+     * {Array(Object)} Basically a copy of the "state" of the map's layers 
+     *     the last time the control was drawn. We have this in order to avoid
+     *     unnecessarily redrawing the control.
+     */
+    layerStates: null,
+    
+
+  // DOM Elements
+  
+    /**
+     * Property: layersDiv
+     * {DOMElement} 
+     */
+    layersDiv: null,
+    
+    /** 
+     * Property: baseLayersDiv
+     * {DOMElement}
+     */
+    baseLayersDiv: null,
+
+    /** 
+     * Property: baseLayers
+     * {Array(<OpenLayers.Layer>)}
+     */
+    baseLayers: null,
+    
+    
+    /** 
+     * Property: dataLbl
+     * {DOMElement} 
+     */
+    dataLbl: null,
+    
+    /** 
+     * Property: dataLayersDiv
+     * {DOMElement} 
+     */
+    dataLayersDiv: null,
+
+    /** 
+     * Property: dataLayers
+     * {Array(<OpenLayers.Layer>)} 
+     */
+    dataLayers: null,
+
+
+    /** 
+     * Property: minimizeDiv
+     * {DOMElement} 
+     */
+    minimizeDiv: null,
+
+    /** 
+     * Property: maximizeDiv
+     * {DOMElement} 
+     */
+    maximizeDiv: null,
+    
+    /**
+     * APIProperty: ascending
+     * {Boolean} 
+     */
+    ascending: true,
+ 
+    /**
+     * Constructor: OpenLayers.Control.LayerSwitcher
+     * 
+     * Parameters:
+     * options - {Object}
+     */
+    initialize: function(options) {
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+        this.layerStates = [];
+    },
+
+    /**
+     * APIMethod: destroy 
+     */    
+    destroy: function() {
+        
+        OpenLayers.Event.stopObservingElement(this.div);
+
+        OpenLayers.Event.stopObservingElement(this.minimizeDiv);
+        OpenLayers.Event.stopObservingElement(this.maximizeDiv);
+
+        //clear out layers info and unregister their events 
+        this.clearLayersArray("base");
+        this.clearLayersArray("data");
+        
+        this.map.events.un({
+            "addlayer": this.redraw,
+            "changelayer": this.redraw,
+            "removelayer": this.redraw,
+            "changebaselayer": this.redraw,
+            scope: this
+        });
+        
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    /** 
+     * Method: setMap
+     *
+     * Properties:
+     * map - {<OpenLayers.Map>} 
+     */
+    setMap: function(map) {
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+
+        this.map.events.on({
+            "addlayer": this.redraw,
+            "changelayer": this.redraw,
+            "removelayer": this.redraw,
+            "changebaselayer": this.redraw,
+            scope: this
+        });
+    },
+
+    /**
+     * Method: draw
+     *
+     * Returns:
+     * {DOMElement} A reference to the DIV DOMElement containing the 
+     *     switcher tabs.
+     */  
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this);
+
+        // create layout divs
+        this.loadContents();
+
+        // set mode to minimize
+        if(!this.outsideViewport) {
+            this.minimizeControl();
+        }
+
+        // populate div with current info
+        this.redraw();    
+
+        return this.div;
+    },
+
+    /** 
+     * Method: clearLayersArray
+     * User specifies either "base" or "data". we then clear all the
+     *     corresponding listeners, the div, and reinitialize a new array.
+     * 
+     * Parameters:
+     * layersType - {String}  
+     */
+    clearLayersArray: function(layersType) {
+        var layers = this[layersType + "Layers"];
+        if (layers) {
+            for(var i=0, len=layers.length; i<len ; i++) {
+                var layer = layers[i];
+                OpenLayers.Event.stopObservingElement(layer.inputElem);
+                OpenLayers.Event.stopObservingElement(layer.labelSpan);
+            }
+        }
+        this[layersType + "LayersDiv"].innerHTML = "";
+        this[layersType + "Layers"] = [];
+    },
+
+
+    /**
+     * Method: checkRedraw
+     * Checks if the layer state has changed since the last redraw() call.
+     * 
+     * Returns:
+     * {Boolean} The layer state changed since the last redraw() call. 
+     */
+    checkRedraw: function() {
+        var redraw = false;
+        if ( !this.layerStates.length ||
+             (this.map.layers.length != this.layerStates.length) ) {
+            redraw = true;
+        } else {
+            for (var i=0, len=this.layerStates.length; i<len; i++) {
+                var layerState = this.layerStates[i];
+                var layer = this.map.layers[i];
+                if ( (layerState.name != layer.name) || 
+                     (layerState.inRange != layer.inRange) || 
+                     (layerState.id != layer.id) || 
+                     (layerState.visibility != layer.visibility) ) {
+                    redraw = true;
+                    break;
+                }    
+            }
+        }    
+        return redraw;
+    },
+    
+    /** 
+     * Method: redraw
+     * Goes through and takes the current state of the Map and rebuilds the
+     *     control to display that state. Groups base layers into a 
+     *     radio-button group and lists each data layer with a checkbox.
+     *
+     * Returns: 
+     * {DOMElement} A reference to the DIV DOMElement containing the control
+     */  
+    redraw: function() {
+        //if the state hasn't changed since last redraw, no need 
+        // to do anything. Just return the existing div.
+        if (!this.checkRedraw()) { 
+            return this.div; 
+        } 
+
+        //clear out previous layers 
+        this.clearLayersArray("base");
+        this.clearLayersArray("data");
+        
+        var containsOverlays = false;
+        var containsBaseLayers = false;
+        
+        // Save state -- for checking layer if the map state changed.
+        // We save this before redrawing, because in the process of redrawing
+        // we will trigger more visibility changes, and we want to not redraw
+        // and enter an infinite loop.
+        var len = this.map.layers.length;
+        this.layerStates = new Array(len);
+        for (var i=0; i <len; i++) {
+            var layer = this.map.layers[i];
+            this.layerStates[i] = {
+                'name': layer.name, 
+                'visibility': layer.visibility,
+                'inRange': layer.inRange,
+                'id': layer.id
+            };
+        }    
+
+        var layers = this.map.layers.slice();
+        if (!this.ascending) { layers.reverse(); }
+        for(var i=0, len=layers.length; i<len; i++) {
+            var layer = layers[i];
+            var baseLayer = layer.isBaseLayer;
+
+            if (layer.displayInLayerSwitcher) {
+
+                if (baseLayer) {
+                    containsBaseLayers = true;
+                } else {
+                    containsOverlays = true;
+                }    
+
+                // only check a baselayer if it is *the* baselayer, check data
+                //  layers if they are visible
+                var checked = (baseLayer) ? (layer == this.map.baseLayer)
+                                          : layer.getVisibility();
+    
+                // create input element
+                var inputElem = document.createElement("input");
+                inputElem.id = this.id + "_input_" + layer.name;
+                inputElem.name = (baseLayer) ? this.id + "_baseLayers" : layer.name;
+                inputElem.type = (baseLayer) ? "radio" : "checkbox";
+                inputElem.value = layer.name;
+                inputElem.checked = checked;
+                inputElem.defaultChecked = checked;
+
+                if (!baseLayer && !layer.inRange) {
+                    inputElem.disabled = true;
+                }
+                var context = {
+                    'inputElem': inputElem,
+                    'layer': layer,
+                    'layerSwitcher': this
+                };
+                OpenLayers.Event.observe(inputElem, "mouseup", 
+                    OpenLayers.Function.bindAsEventListener(this.onInputClick,
+                                                            context)
+                );
+                
+                // create span
+                var labelSpan = document.createElement("span");
+                OpenLayers.Element.addClass(labelSpan, "labelSpan");
+                if (!baseLayer && !layer.inRange) {
+                    labelSpan.style.color = "gray";
+                }
+                labelSpan.innerHTML = layer.name;
+                labelSpan.style.verticalAlign = (baseLayer) ? "bottom" 
+                                                            : "baseline";
+                OpenLayers.Event.observe(labelSpan, "click", 
+                    OpenLayers.Function.bindAsEventListener(this.onInputClick,
+                                                            context)
+                );
+                // create line break
+                var br = document.createElement("br");
+    
+                
+                var groupArray = (baseLayer) ? this.baseLayers
+                                             : this.dataLayers;
+                groupArray.push({
+                    'layer': layer,
+                    'inputElem': inputElem,
+                    'labelSpan': labelSpan
+                });
+                                                     
+    
+                var groupDiv = (baseLayer) ? this.baseLayersDiv
+                                           : this.dataLayersDiv;
+                groupDiv.appendChild(inputElem);
+                groupDiv.appendChild(labelSpan);
+                groupDiv.appendChild(br);
+            }
+        }
+
+        // if no overlays, dont display the overlay label
+        this.dataLbl.style.display = (containsOverlays) ? "" : "none";        
+        
+        // if no baselayers, dont display the baselayer label
+        this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";        
+
+        return this.div;
+    },
+
+    /** 
+     * Method:
+     * A label has been clicked, check or uncheck its corresponding input
+     * 
+     * Parameters:
+     * e - {Event} 
+     *
+     * Context:  
+     *  - {DOMElement} inputElem
+     *  - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
+     *  - {<OpenLayers.Layer>} layer
+     */
+
+    onInputClick: function(e) {
+
+        if (!this.inputElem.disabled) {
+            if (this.inputElem.type == "radio") {
+                this.inputElem.checked = true;
+                this.layer.map.setBaseLayer(this.layer);
+            } else {
+                this.inputElem.checked = !this.inputElem.checked;
+                this.layerSwitcher.updateMap();
+            }
+        }
+        OpenLayers.Event.stop(e);
+    },
+    
+    /**
+     * Method: onLayerClick
+     * Need to update the map accordingly whenever user clicks in either of
+     *     the layers.
+     * 
+     * Parameters: 
+     * e - {Event} 
+     */
+    onLayerClick: function(e) {
+        this.updateMap();
+    },
+
+
+    /** 
+     * Method: updateMap
+     * Cycles through the loaded data and base layer input arrays and makes
+     *     the necessary calls to the Map object such that that the map's 
+     *     visual state corresponds to what the user has selected in 
+     *     the control.
+     */
+    updateMap: function() {
+
+        // set the newly selected base layer        
+        for(var i=0, len=this.baseLayers.length; i<len; i++) {
+            var layerEntry = this.baseLayers[i];
+            if (layerEntry.inputElem.checked) {
+                this.map.setBaseLayer(layerEntry.layer, false);
+            }
+        }
+
+        // set the correct visibilities for the overlays
+        for(var i=0, len=this.dataLayers.length; i<len; i++) {
+            var layerEntry = this.dataLayers[i];   
+            layerEntry.layer.setVisibility(layerEntry.inputElem.checked);
+        }
+
+    },
+
+    /** 
+     * Method: maximizeControl
+     * Set up the labels and divs for the control
+     * 
+     * Parameters:
+     * e - {Event} 
+     */
+    maximizeControl: function(e) {
+
+        // set the div's width and height to empty values, so
+        // the div dimensions can be controlled by CSS
+        this.div.style.width = "";
+        this.div.style.height = "";
+
+        this.showControls(false);
+
+        if (e != null) {
+            OpenLayers.Event.stop(e);                                            
+        }
+    },
+    
+    /** 
+     * Method: minimizeControl
+     * Hide all the contents of the control, shrink the size, 
+     *     add the maximize icon
+     *
+     * Parameters:
+     * e - {Event} 
+     */
+    minimizeControl: function(e) {
+
+        // to minimize the control we set its div's width
+        // and height to 0px, we cannot just set "display"
+        // to "none" because it would hide the maximize
+        // div
+        this.div.style.width = "0px";
+        this.div.style.height = "0px";
+
+        this.showControls(true);
+
+        if (e != null) {
+            OpenLayers.Event.stop(e);                                            
+        }
+    },
+
+    /**
+     * Method: showControls
+     * Hide/Show all LayerSwitcher controls depending on whether we are
+     *     minimized or not
+     * 
+     * Parameters:
+     * minimize - {Boolean}
+     */
+    showControls: function(minimize) {
+
+        this.maximizeDiv.style.display = minimize ? "" : "none";
+        this.minimizeDiv.style.display = minimize ? "none" : "";
+
+        this.layersDiv.style.display = minimize ? "none" : "";
+    },
+    
+    /** 
+     * Method: loadContents
+     * Set up the labels and divs for the control
+     */
+    loadContents: function() {
+
+        //configure main div
+
+        OpenLayers.Event.observe(this.div, "mouseup", 
+            OpenLayers.Function.bindAsEventListener(this.mouseUp, this));
+        OpenLayers.Event.observe(this.div, "click",
+                      this.ignoreEvent);
+        OpenLayers.Event.observe(this.div, "mousedown",
+            OpenLayers.Function.bindAsEventListener(this.mouseDown, this));
+        OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent);
+
+        // layers list div        
+        this.layersDiv = document.createElement("div");
+        this.layersDiv.id = this.id + "_layersDiv";
+        OpenLayers.Element.addClass(this.layersDiv, "layersDiv");
+
+        this.baseLbl = document.createElement("div");
+        this.baseLbl.innerHTML = OpenLayers.i18n("Base Layer");
+        OpenLayers.Element.addClass(this.baseLbl, "baseLbl");
+        
+        this.baseLayersDiv = document.createElement("div");
+        OpenLayers.Element.addClass(this.baseLayersDiv, "baseLayersDiv");
+
+        this.dataLbl = document.createElement("div");
+        this.dataLbl.innerHTML = OpenLayers.i18n("Overlays");
+        OpenLayers.Element.addClass(this.dataLbl, "dataLbl");
+        
+        this.dataLayersDiv = document.createElement("div");
+        OpenLayers.Element.addClass(this.dataLayersDiv, "dataLayersDiv");
+
+        if (this.ascending) {
+            this.layersDiv.appendChild(this.baseLbl);
+            this.layersDiv.appendChild(this.baseLayersDiv);
+            this.layersDiv.appendChild(this.dataLbl);
+            this.layersDiv.appendChild(this.dataLayersDiv);
+        } else {
+            this.layersDiv.appendChild(this.dataLbl);
+            this.layersDiv.appendChild(this.dataLayersDiv);
+            this.layersDiv.appendChild(this.baseLbl);
+            this.layersDiv.appendChild(this.baseLayersDiv);
+        }    
+ 
+        this.div.appendChild(this.layersDiv);
+
+        if(this.roundedCorner) {
+            OpenLayers.Rico.Corner.round(this.div, {
+                corners: "tl bl",
+                bgColor: "transparent",
+                color: this.roundedCornerColor,
+                blend: false
+            });
+            OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
+        }
+
+        var imgLocation = OpenLayers.Util.getImagesLocation();
+        var sz = new OpenLayers.Size(18,18);        
+
+        // maximize button div
+        var img = imgLocation + 'layer-switcher-maximize.png';
+        this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
+                                    "OpenLayers_Control_MaximizeDiv", 
+                                    null, 
+                                    sz, 
+                                    img, 
+                                    "absolute");
+        OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv");
+        this.maximizeDiv.style.display = "none";
+        OpenLayers.Event.observe(this.maximizeDiv, "click", 
+            OpenLayers.Function.bindAsEventListener(this.maximizeControl, this)
+        );
+        
+        this.div.appendChild(this.maximizeDiv);
+
+        // minimize button div
+        var img = imgLocation + 'layer-switcher-minimize.png';
+        var sz = new OpenLayers.Size(18,18);        
+        this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
+                                    "OpenLayers_Control_MinimizeDiv", 
+                                    null, 
+                                    sz, 
+                                    img, 
+                                    "absolute");
+        OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv");
+        this.minimizeDiv.style.display = "none";
+        OpenLayers.Event.observe(this.minimizeDiv, "click", 
+            OpenLayers.Function.bindAsEventListener(this.minimizeControl, this)
+        );
+
+        this.div.appendChild(this.minimizeDiv);
+    },
+    
+    /** 
+     * Method: ignoreEvent
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    ignoreEvent: function(evt) {
+        OpenLayers.Event.stop(evt);
+    },
+
+    /** 
+     * Method: mouseDown
+     * Register a local 'mouseDown' flag so that we'll know whether or not
+     *     to ignore a mouseUp event
+     * 
+     * Parameters:
+     * evt - {Event}
+     */
+    mouseDown: function(evt) {
+        this.isMouseDown = true;
+        this.ignoreEvent(evt);
+    },
+
+    /** 
+     * Method: mouseUp
+     * If the 'isMouseDown' flag has been set, that means that the drag was 
+     *     started from within the LayerSwitcher control, and thus we can 
+     *     ignore the mouseup. Otherwise, let the Event continue.
+     *  
+     * Parameters:
+     * evt - {Event} 
+     */
+    mouseUp: function(evt) {
+        if (this.isMouseDown) {
+            this.isMouseDown = false;
+            this.ignoreEvent(evt);
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.LayerSwitcher"
+});
+/* ======================================================================
+    OpenLayers/Strategy/Filter.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Strategy.js
+ * @requires OpenLayers/Filter.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Filter
+ * Strategy for limiting features that get added to a layer by 
+ *     evaluating a filter.  The strategy maintains a cache of
+ *     all features until removeFeatures is called on the layer.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Filter = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * APIProperty: filter
+     * {<OpenLayers.Filter>}  Filter for limiting features sent to the layer.
+     *     Use the <setFilter> method to update this filter after construction.
+     */
+    filter: null,
+    
+    /**
+     * Property: cache
+     * {Array(<OpenLayers.Feature.Vector>)} List of currently cached
+     *     features.
+     */
+    cache: null,
+    
+    /**
+     * Property: caching
+     * {Boolean} The filter is currently caching features.
+     */
+    caching: false,
+    
+    /**
+     * Constructor: OpenLayers.Strategy.Filter
+     * Create a new filter strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+
+    /**
+     * APIMethod: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     *     By default, this strategy automatically activates itself when a layer
+     *     is added to a map.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated or false if
+     *      the strategy was already active.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.apply(this, arguments);
+        if (activated) {
+            this.cache = [];
+            this.layer.events.on({
+                "beforefeaturesadded": this.handleAdd,
+                "beforefeaturesremoved": this.handleRemove,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy.  Clear the feature cache.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully deactivated or false if
+     *      the strategy was already inactive.
+     */
+    deactivate: function() {
+        this.cache = null;
+        if (this.layer && this.layer.events) {
+            this.layer.events.un({
+                "beforefeaturesadded": this.handleAdd,
+                "beforefeaturesremoved": this.handleRemove,
+                scope: this
+            });            
+        }
+        return OpenLayers.Strategy.prototype.deactivate.apply(this, arguments);
+    },
+    
+    /**
+     * Method: handleAdd
+     */
+    handleAdd: function(event) {
+        if (!this.caching && this.filter) {
+            var features = event.features;
+            event.features = [];
+            var feature;
+            for (var i=0, ii=features.length; i<ii; ++i) {
+                feature = features[i];
+                if (this.filter.evaluate(feature)) {
+                    event.features.push(feature);
+                } else {
+                    this.cache.push(feature);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: handleRemove
+     */
+    handleRemove: function(event) {
+        if (!this.caching) {
+            this.cache = [];
+        }
+    },
+
+    /** 
+     * APIMethod: setFilter
+     * Update the filter for this strategy.  This will re-evaluate
+     *     any features on the layer and in the cache.  Only features
+     *     for which filter.evalute(feature) returns true will be
+     *     added to the layer.  Others will be cached by the strategy.
+     *
+     * Parameters:
+     * filter - <OpenLayers.Filter> A filter for evaluating features.
+     */
+    setFilter: function(filter) {
+        this.filter = filter;
+        var previousCache = this.cache;
+        this.cache = [];
+        // look through layer for features to remove from layer
+        this.handleAdd({features: this.layer.features});
+        // cache now contains features to remove from layer
+        if (this.cache.length > 0) {
+            this.caching = true;
+            this.layer.removeFeatures(this.cache.slice());
+            this.caching = false;
+        }
+        // now look through previous cache for features to add to layer
+        if (previousCache.length > 0) {
+            var event = {features: previousCache};
+            this.handleAdd(event);
+            if (event.features.length > 0) {
+                // event has features to add to layer
+                this.caching = true;
+                this.layer.addFeatures(event.features);
+                this.caching = false;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Strategy.Filter"
+
+});
+/* ======================================================================
+    OpenLayers/Format/Atom.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Atom
+ * Read/write Atom feeds. Create a new instance with the
+ *     <OpenLayers.Format.AtomFeed> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Atom = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.  Properties
+     *     of this object should not be set individually.  Read-only.  All
+     *     XML subclasses should have their own namespaces object.  Use
+     *     <setNamespace> to add or set a namespace alias after construction.
+     */
+    namespaces: {
+        atom: "http://www.w3.org/2005/Atom",
+        georss: "http://www.georss.org/georss"
+    },
+    
+    /**
+     * APIProperty: feedTitle
+     * {String} Atom feed elements require a title.  Default is "untitled".
+     */
+    feedTitle: "untitled",
+
+    /**
+     * APIProperty: defaultEntryTitle
+     * {String} Atom entry elements require a title.  In cases where one is
+     *     not provided in the feature attributes, this will be used.  Default
+     *     is "untitled".
+     */
+    defaultEntryTitle: "untitled",
+
+    /**
+     * Property: gmlParse
+     * {Object} GML Format object for parsing features
+     * Non-API and only created if necessary
+     */
+    gmlParser: null,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x)
+     * For GeoRSS the default is (y,x), therefore: false
+     */
+    xy: false,
+    
+    /**
+     * Constructor: OpenLayers.Format.AtomEntry
+     * Create a new parser for Atom.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from an Atom feed or entry document.
+     
+     * Parameters:
+     * doc - {Element} or {String}
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(doc) {
+        if (typeof doc == "string") {
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+        return this.parseFeatures(doc);
+    },
+    
+    /**
+     * APIMethod: write
+     * Serialize or more feature nodes to Atom documents.
+     *
+     * Parameters:
+     * features - a single {<OpenLayers.Feature.Vector>} or an
+     * Array({<OpenLayers.Feature.Vector>}).
+     *
+     * Returns:
+     * {String} an Atom entry document if passed one feature node, or a feed
+     * document if passed an array of feature nodes.
+     */
+    write: function(features) {
+        var doc;
+        if (OpenLayers.Util.isArray(features)) {
+            doc = this.createElementNSPlus("atom:feed");
+            doc.appendChild(
+                this.createElementNSPlus("atom:title", {
+                    value: this.feedTitle
+                })
+            );
+            for (var i=0, ii=features.length; i<ii; i++) {
+                doc.appendChild(this.buildEntryNode(features[i]));
+            }
+        }
+        else {
+            doc = this.buildEntryNode(features);
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [doc]);
+    },
+    
+    /**
+     * Method: buildContentNode
+     *
+     * Parameters:
+     * content - {Object}
+     *
+     * Returns:
+     * {DOMElement} an Atom content node.
+     *
+     * TODO: types other than text.
+     */
+    buildContentNode: function(content) {
+        var node = this.createElementNSPlus("atom:content", {
+            attributes: {
+                type: content.type || null
+            }
+        });
+        if (content.src) {
+            node.setAttribute("src", content.src);
+        } else {
+            if (content.type == "text" || content.type == null) {
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            } else if (content.type == "html") {
+                if (typeof content.value != "string") {
+                    throw "HTML content must be in form of an escaped string";
+                }
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            } else if (content.type == "xhtml") {
+                node.appendChild(content.value);
+            } else if (content.type == "xhtml" ||
+                           content.type.match(/(\+|\/)xml$/)) {
+                node.appendChild(content.value);
+            }
+            else { // MUST be a valid Base64 encoding
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            }
+        }
+        return node;
+    },
+    
+    /**
+     * Method: buildEntryNode
+     * Build an Atom entry node from a feature object.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     *
+     * Returns:
+     * {DOMElement} an Atom entry node.
+     *
+     * These entries are geared for publication using AtomPub.
+     *
+     * TODO: support extension elements
+     */
+    buildEntryNode: function(feature) {
+        var attrib = feature.attributes;
+        var atomAttrib = attrib.atom || {};
+        var entryNode = this.createElementNSPlus("atom:entry");
+        
+        // atom:author
+        if (atomAttrib.authors) {
+            var authors = OpenLayers.Util.isArray(atomAttrib.authors) ?
+                atomAttrib.authors : [atomAttrib.authors];
+            for (var i=0, ii=authors.length; i<ii; i++) {
+                entryNode.appendChild(
+                    this.buildPersonConstructNode(
+                        "author", authors[i]
+                    )
+                );
+            }
+        }
+        
+        // atom:category
+        if (atomAttrib.categories) {
+            var categories = OpenLayers.Util.isArray(atomAttrib.categories) ?
+                atomAttrib.categories : [atomAttrib.categories];
+            var category;
+            for (var i=0, ii=categories.length; i<ii; i++) {
+                category = categories[i];
+                entryNode.appendChild(
+                    this.createElementNSPlus("atom:category", {
+                        attributes: {
+                            term: category.term,
+                            scheme: category.scheme || null,
+                            label: category.label || null
+                        }
+                    })
+                );
+            }
+        }
+        
+        // atom:content
+        if (atomAttrib.content) {
+            entryNode.appendChild(this.buildContentNode(atomAttrib.content));
+        }
+        
+        // atom:contributor
+        if (atomAttrib.contributors) {
+            var contributors = OpenLayers.Util.isArray(atomAttrib.contributors) ?
+                atomAttrib.contributors : [atomAttrib.contributors];
+            for (var i=0, ii=contributors.length; i<ii; i++) {
+                entryNode.appendChild(
+                    this.buildPersonConstructNode(
+                        "contributor",
+                        contributors[i]
+                        )
+                    );
+            }
+        }
+        
+        // atom:id
+        if (feature.fid) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:id", {
+                    value: feature.fid
+                })
+            );
+        }
+        
+        // atom:link
+        if (atomAttrib.links) {
+            var links = OpenLayers.Util.isArray(atomAttrib.links) ?
+                atomAttrib.links : [atomAttrib.links];
+            var link;
+            for (var i=0, ii=links.length; i<ii; i++) {
+                link = links[i];
+                entryNode.appendChild(
+                    this.createElementNSPlus("atom:link", {
+                        attributes: {
+                            href: link.href,
+                            rel: link.rel || null,
+                            type: link.type || null,
+                            hreflang: link.hreflang || null,
+                            title: link.title || null,
+                            length: link.length || null
+                        }
+                    })
+                );
+            }
+        }
+        
+        // atom:published
+        if (atomAttrib.published) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:published", {
+                    value: atomAttrib.published
+                })
+            );
+        }
+        
+        // atom:rights
+        if (atomAttrib.rights) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:rights", {
+                    value: atomAttrib.rights
+                })
+            );
+        }
+        
+        // atom:source not implemented
+        
+        // atom:summary
+        if (atomAttrib.summary || attrib.description) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:summary", {
+                    value: atomAttrib.summary || attrib.description
+                })
+            );
+        }
+        
+        // atom:title
+        entryNode.appendChild(
+            this.createElementNSPlus("atom:title", {
+                value: atomAttrib.title || attrib.title || this.defaultEntryTitle
+            })
+        );
+        
+        // atom:updated
+        if (atomAttrib.updated) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:updated", {
+                    value: atomAttrib.updated
+                })
+            );
+        }
+        
+        // georss:where
+        if (feature.geometry) {
+            var whereNode = this.createElementNSPlus("georss:where");
+            whereNode.appendChild(
+                this.buildGeometryNode(feature.geometry)
+            );
+            entryNode.appendChild(whereNode);
+        }
+        
+        return entryNode;
+    },
+    
+    /**
+     * Method: initGmlParser
+     * Creates a GML parser.
+     */
+    initGmlParser: function() {
+        this.gmlParser = new OpenLayers.Format.GML.v3({
+            xy: this.xy,
+            featureNS: "http://example.com#feature",
+            internalProjection: this.internalProjection,
+            externalProjection: this.externalProjection
+        });
+    },
+    
+    /**
+     * Method: buildGeometryNode
+     * builds a GeoRSS node with a given geometry
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {DOMElement} A gml node.
+     */
+    buildGeometryNode: function(geometry) {
+        if (!this.gmlParser) {
+            this.initGmlParser();
+        }
+        var node = this.gmlParser.writeNode("feature:_geometry", geometry);
+        return node.firstChild;
+    },
+    
+    /**
+     * Method: buildPersonConstructNode
+     *
+     * Parameters:
+     * name - {String}
+     * value - {Object}
+     *
+     * Returns:
+     * {DOMElement} an Atom person construct node.
+     *
+     * Example:
+     * >>> buildPersonConstructNode("author", {name: "John Smith"})
+     * {<author><name>John Smith</name></author>}
+     *
+     * TODO: how to specify extension elements? Add to the oNames array?
+     */
+    buildPersonConstructNode: function(name, value) {
+        var oNames = ["uri", "email"];
+        var personNode = this.createElementNSPlus("atom:" + name);
+        personNode.appendChild(
+            this.createElementNSPlus("atom:name", {
+                value: value.name
+            })
+        );
+        for (var i=0, ii=oNames.length; i<ii; i++) {
+            if (value[oNames[i]]) {
+                personNode.appendChild(
+                    this.createElementNSPlus("atom:" + oNames[i], {
+                        value: value[oNames[i]]
+                    })
+                );
+            }
+        }
+        return personNode;
+    },
+    
+    /**
+     * Method: getFirstChildValue
+     *
+     * Parameters:
+     * node - {DOMElement}
+     * nsuri - {String} Child node namespace uri ("*" for any).
+     * name - {String} Child node name.
+     * def - {String} Optional string default to return if no child found.
+     *
+     * Returns:
+     * {String} The value of the first child with the given tag name.  Returns
+     *     default value or empty string if none found.
+     */
+    getFirstChildValue: function(node, nsuri, name, def) {
+        var value;
+        var nodes = this.getElementsByTagNameNS(node, nsuri, name);
+        if (nodes && nodes.length > 0) {
+            value = this.getChildValue(nodes[0], def);
+        } else {
+            value = def;
+        }
+        return value;
+    },
+    
+    /**
+     * Method: parseFeature
+     * Parse feature from an Atom entry node..
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An <OpenLayers.Feature.Vector>.
+     */
+    parseFeature: function(node) {
+        var atomAttrib = {};
+        var value = null;
+        var nodes = null;
+        var attval = null;
+        var atomns = this.namespaces.atom;
+        
+        // atomAuthor*
+        this.parsePersonConstructs(node, "author", atomAttrib);
+        
+        // atomCategory*
+        nodes = this.getElementsByTagNameNS(node, atomns, "category");
+        if (nodes.length > 0) {
+            atomAttrib.categories = [];
+        }
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            value = {};
+            value.term = nodes[i].getAttribute("term");
+            attval = nodes[i].getAttribute("scheme");
+            if (attval) { value.scheme = attval; }
+            attval = nodes[i].getAttribute("label");
+            if (attval) { value.label = attval; }
+            atomAttrib.categories.push(value);
+        }
+        
+        // atomContent?
+        nodes = this.getElementsByTagNameNS(node, atomns, "content");
+        if (nodes.length > 0) {
+            value = {};
+            attval = nodes[0].getAttribute("type");
+            if (attval) {
+                value.type = attval;
+            }
+            attval = nodes[0].getAttribute("src");
+            if (attval) {
+                value.src = attval;
+            } else {
+                if (value.type == "text" || 
+                    value.type == "html" || 
+                    value.type == null ) {
+                    value.value = this.getFirstChildValue(
+                                        node,
+                                        atomns,
+                                        "content",
+                                        null
+                                        );
+                } else if (value.type == "xhtml" ||
+                           value.type.match(/(\+|\/)xml$/)) {
+                    value.value = this.getChildEl(nodes[0]);
+                } else { // MUST be base64 encoded
+                    value.value = this.getFirstChildValue(
+                                        node,
+                                        atomns,
+                                        "content",
+                                        null
+                                        );
+                }
+                atomAttrib.content = value;
+            }
+        }
+        
+        // atomContributor*
+        this.parsePersonConstructs(node, "contributor", atomAttrib);
+        
+        // atomId
+        atomAttrib.id = this.getFirstChildValue(node, atomns, "id", null);
+        
+        // atomLink*
+        nodes = this.getElementsByTagNameNS(node, atomns, "link");
+        if (nodes.length > 0) {
+            atomAttrib.links = new Array(nodes.length);
+        }
+        var oAtts = ["rel", "type", "hreflang", "title", "length"];
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            value = {};
+            value.href = nodes[i].getAttribute("href");
+            for (var j=0, jj=oAtts.length; j<jj; j++) {
+                attval = nodes[i].getAttribute(oAtts[j]);
+                if (attval) {
+                    value[oAtts[j]] = attval;
+                }
+            }
+            atomAttrib.links[i] = value;
+        }
+        
+        // atomPublished?
+        value = this.getFirstChildValue(node, atomns, "published", null);
+        if (value) {
+            atomAttrib.published = value;
+        }
+        
+        // atomRights?
+        value = this.getFirstChildValue(node, atomns, "rights", null);
+        if (value) {
+            atomAttrib.rights = value;
+        }
+        
+        // atomSource? -- not implemented
+        
+        // atomSummary?
+        value = this.getFirstChildValue(node, atomns, "summary", null);
+        if (value) {
+            atomAttrib.summary = value;
+        }
+        
+        // atomTitle
+        atomAttrib.title = this.getFirstChildValue(
+                                node, atomns, "title", null
+                                );
+        
+        // atomUpdated
+        atomAttrib.updated = this.getFirstChildValue(
+                                node, atomns, "updated", null
+                                );
+        
+        var featureAttrib = {
+            title: atomAttrib.title,
+            description: atomAttrib.summary,
+            atom: atomAttrib
+        };
+        var geometry = this.parseLocations(node)[0];
+        var feature = new OpenLayers.Feature.Vector(geometry, featureAttrib);
+        feature.fid = atomAttrib.id;
+        return feature;
+    },
+    
+    /**
+     * Method: parseFeatures
+     * Return features from an Atom entry or feed.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s.
+     */
+    parseFeatures: function(node) {
+        var features = [];
+        var entries = this.getElementsByTagNameNS(
+            node, this.namespaces.atom, "entry"
+        );
+        if (entries.length == 0) {
+            entries = [node];
+        }
+        for (var i=0, ii=entries.length; i<ii; i++) {
+            features.push(this.parseFeature(entries[i]));
+        }
+        return features;
+    },
+    
+    /**
+     * Method: parseLocations
+     * Parse the locations from an Atom entry or feed.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An Array of <OpenLayers.Geometry>s.
+     */
+    parseLocations: function(node) {
+        var georssns = this.namespaces.georss;
+
+        var locations = {components: []};
+        var where = this.getElementsByTagNameNS(node, georssns, "where");
+        if (where && where.length > 0) {
+            if (!this.gmlParser) {
+                this.initGmlParser();
+            }
+            for (var i=0, ii=where.length; i<ii; i++) {
+                this.gmlParser.readChildNodes(where[i], locations);
+            }
+        }
+        
+        var components = locations.components;
+        var point = this.getElementsByTagNameNS(node, georssns, "point");
+        if (point && point.length > 0) {
+            for (var i=0, ii=point.length; i<ii; i++) {
+                var xy = OpenLayers.String.trim(
+                            point[i].firstChild.nodeValue
+                            ).split(/\s+/);
+                if (xy.length !=2) {
+                    xy = OpenLayers.String.trim(
+                                point[i].firstChild.nodeValue
+                                ).split(/\s*,\s*/);
+                }
+                components.push(
+                    new OpenLayers.Geometry.Point(
+                        parseFloat(xy[1]),
+                        parseFloat(xy[0])
+                    )
+                );
+            }
+        }
+
+        var line = this.getElementsByTagNameNS(node, georssns, "line");
+        if (line && line.length > 0) {
+            var coords;
+            var p;
+            var points;
+            for (var i=0, ii=line.length; i<ii; i++) {
+                coords = OpenLayers.String.trim(
+                                line[i].firstChild.nodeValue
+                                ).split(/\s+/);
+                points = [];
+                for (var j=0, jj=coords.length; j<jj; j+=2) {
+                    p = new OpenLayers.Geometry.Point(
+                        parseFloat(coords[j+1]),
+                        parseFloat(coords[j])
+                    );
+                    points.push(p);
+                }
+                components.push(
+                    new OpenLayers.Geometry.LineString(points)
+                );
+            }
+        }        
+
+        var polygon = this.getElementsByTagNameNS(node, georssns, "polygon");
+        if (polygon && polygon.length > 0) {
+            var coords;
+            var p;
+            var points;
+            for (var i=0, ii=polygon.length; i<ii; i++) {
+                coords = OpenLayers.String.trim(
+                            polygon[i].firstChild.nodeValue
+                            ).split(/\s+/);
+                points = [];
+                for (var j=0, jj=coords.length; j<jj; j+=2) {
+                    p = new OpenLayers.Geometry.Point(
+                        parseFloat(coords[j+1]),
+                        parseFloat(coords[j])
+                    );
+                    points.push(p);
+                }
+                components.push(
+                    new OpenLayers.Geometry.Polygon(
+                        [new OpenLayers.Geometry.LinearRing(components)]
+                    )
+                );
+            }
+        }
+        
+        if (this.internalProjection && this.externalProjection) {
+            for (var i=0, ii=components.length; i<ii; i++) {
+                if (components[i]) {
+                    components[i].transform(
+                        this.externalProjection,
+                        this.internalProjection
+                    );
+                }
+            }
+        }
+        
+        return components;
+    },
+    
+    /**
+     * Method: parsePersonConstruct
+     * Parse Atom person constructs from an Atom entry node.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     * name - {String} Construcy name ("author" or "contributor")
+     * data = {Object} Object in which to put parsed persons.
+     *
+     * Returns:
+     * An {Object}.
+     */
+    parsePersonConstructs: function(node, name, data) {
+        var persons = [];
+        var atomns = this.namespaces.atom;
+        var nodes = this.getElementsByTagNameNS(node, atomns, name);
+        var oAtts = ["uri", "email"];
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            var value = {};
+            value.name = this.getFirstChildValue(
+                            nodes[i],
+                            atomns,
+                            "name",
+                            null
+                            );
+            for (var j=0, jj=oAtts.length; j<jj; j++) {
+                var attval = this.getFirstChildValue(
+                            nodes[i],
+                            atomns,
+                            oAtts[j],
+                            null);
+                if (attval) {
+                    value[oAtts[j]] = attval;
+                }
+            }
+            persons.push(value);
+        }
+        if (persons.length > 0) {
+            data[name + "s"] = persons;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Atom"
+});
+/* ======================================================================
+    OpenLayers/Control/KeyboardDefaults.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for 
+ * full list of contributors). Published under the Clear BSD license.  
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Keyboard.js
+ */
+
+/**
+ * Class: OpenLayers.Control.KeyboardDefaults
+ * The KeyboardDefaults control adds panning and zooming functions, controlled
+ * with the keyboard. By default arrow keys pan, +/- keys zoom & Page Up/Page
+ * Down/Home/End scroll by three quarters of a page.
+ * 
+ * This control has no visible appearance.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.KeyboardDefaults = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
+     * APIProperty: slideFactor
+     * Pixels to slide by.
+     */
+    slideFactor: 75,
+
+    /**
+     * Constructor: OpenLayers.Control.KeyboardDefaults
+     */
+        
+    /**
+     * Method: draw
+     * Create handler.
+     */
+    draw: function() {
+        this.handler = new OpenLayers.Handler.Keyboard( this, { 
+                                "keydown": this.defaultKeyPress });
+    },
+    
+    /**
+     * Method: defaultKeyPress
+     * When handling the key event, we only use evt.keyCode. This holds 
+     * some drawbacks, though we get around them below. When interpretting
+     * the keycodes below (including the comments associated with them),
+     * consult the URL below. For instance, the Safari browser returns
+     * "IE keycodes", and so is supported by any keycode labeled "IE".
+     * 
+     * Very informative URL:
+     *    http://unixpapa.com/js/key.html
+     *
+     * Parameters:
+     * code - {Integer} 
+     */
+    defaultKeyPress: function (evt) {
+        switch(evt.keyCode) {
+            case OpenLayers.Event.KEY_LEFT:
+                this.map.pan(-this.slideFactor, 0);
+                break;
+            case OpenLayers.Event.KEY_RIGHT: 
+                this.map.pan(this.slideFactor, 0);
+                break;
+            case OpenLayers.Event.KEY_UP:
+                this.map.pan(0, -this.slideFactor);
+                break;
+            case OpenLayers.Event.KEY_DOWN:
+                this.map.pan(0, this.slideFactor);
+                break;
+            
+            case 33: // Page Up. Same in all browsers.
+                var size = this.map.getSize();
+                this.map.pan(0, -0.75*size.h);
+                break;
+            case 34: // Page Down. Same in all browsers.
+                var size = this.map.getSize();
+                this.map.pan(0, 0.75*size.h);
+                break; 
+            case 35: // End. Same in all browsers.
+                var size = this.map.getSize();
+                this.map.pan(0.75*size.w, 0);
+                break; 
+            case 36: // Home. Same in all browsers.
+                var size = this.map.getSize();
+                this.map.pan(-0.75*size.w, 0);
+                break; 
+
+            case 43:  // +/= (ASCII), keypad + (ASCII, Opera)
+            case 61:  // +/= (Mozilla, Opera, some ASCII)
+            case 187: // +/= (IE)
+            case 107: // keypad + (IE, Mozilla)
+                this.map.zoomIn();
+                break; 
+            case 45:  // -/_ (ASCII, Opera), keypad - (ASCII, Opera)
+            case 109: // -/_ (Mozilla), keypad - (Mozilla, IE)
+            case 189: // -/_ (IE)
+            case 95:  // -/_ (some ASCII)
+                this.map.zoomOut();
+                break; 
+        } 
+    },
+
+    CLASS_NAME: "OpenLayers.Control.KeyboardDefaults"
+});
diff --git a/src/main/webapp/lib/openlayers/OpenLayers_min.js b/src/main/webapp/lib/openlayers/OpenLayers_min.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ca978c7dcd91547f7dc03a115bf876ad32ffb17
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/OpenLayers_min.js
@@ -0,0 +1,2963 @@
+/*
+
+  OpenLayers.js -- OpenLayers Map Viewer Library
+
+  Copyright 2005-2011 OpenLayers Contributors, released under the FreeBSD
+  license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt
+  for the full text of the license.
+
+  Includes compressed code under the following licenses:
+
+  (For uncompressed versions of the code used please see the
+  OpenLayers SVN repository: <http://openlayers.org/>)
+
+*/
+
+/* Contains portions of Prototype.js:
+ *
+ * Prototype JavaScript framework, version 1.4.0
+ *  (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+ *--------------------------------------------------------------------------*/
+
+/**  
+*  
+*  Contains portions of Rico <http://openrico.org/>
+* 
+*  Copyright 2005 Sabre Airline Solutions  
+*  
+*  Licensed under the Apache License, Version 2.0 (the "License"); you
+*  may not use this file except in compliance with the License. You
+*  may obtain a copy of the License at
+*  
+*         http://www.apache.org/licenses/LICENSE-2.0  
+*  
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+*  implied. See the License for the specific language governing
+*  permissions and limitations under the License. 
+*
+**/
+
+/**
+ * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
+ * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/**
+ * Contains portions of Gears <http://code.google.com/apis/gears/>
+ *
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. Neither the name of Google Inc. nor the names of its contributors may be
+ *     used to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sets up google.gears.*, which is *the only* supported way to access Gears.
+ *
+ * Circumvent this file at your own risk!
+ *
+ * In the future, Gears may automatically define google.gears.* without this
+ * file. Gears may use these objects to transparently fix bugs and compatibility
+ * issues. Applications that use the code below will continue to work seamlessly
+ * when that happens.
+ */
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */(function(){if(window.google&&google.gears){return;}
+var factory=null;if(typeof GearsFactory!='undefined'){factory=new GearsFactory();}else{try{factory=new ActiveXObject('Gears.Factory');if(factory.getBuildInfo().indexOf('ie_mobile')!=-1){factory.privateSetGlobalObject(this);}}catch(e){if((typeof navigator.mimeTypes!='undefined')&&navigator.mimeTypes["application/x-googlegears"]){factory=document.createElement("object");factory.style.display="none";factory.width=0;factory.height=0;factory.type="application/x-googlegears";document.documentElement.appendChild(factory);}}}
+if(!factory){return;}
+if(!window.google){google={};}
+if(!google.gears){google.gears={factory:factory};}})();var OpenLayers={VERSION_NUMBER:"Release 2.11",singleFile:true,_getScriptLocation:(function(){var r=new RegExp("(^|(.*?\\/))(OpenLayers\.js)(\\?|$)"),s=document.getElementsByTagName('script'),src,m,l="";for(var i=0,len=s.length;i<len;i++){src=s[i].getAttribute('src');if(src){var m=src.match(r);if(m){l=m[1];break;}}}
+return(function(){return l;});})()};OpenLayers.Class=function(){var len=arguments.length;var P=arguments[0];var F=arguments[len-1];var C=typeof F.initialize=="function"?F.initialize:function(){P.prototype.initialize.apply(this,arguments);};if(len>1){var newArgs=[C,P].concat(Array.prototype.slice.call(arguments).slice(1,len-1),F);OpenLayers.inherit.apply(null,newArgs);}else{C.prototype=F;}
+return C;};OpenLayers.Class.isPrototype=function(){};OpenLayers.Class.create=function(){return function(){if(arguments&&arguments[0]!=OpenLayers.Class.isPrototype){this.initialize.apply(this,arguments);}};};OpenLayers.Class.inherit=function(P){var C=function(){P.call(this);};var newArgs=[C].concat(Array.prototype.slice.call(arguments));OpenLayers.inherit.apply(null,newArgs);return C.prototype;};OpenLayers.inherit=function(C,P){var F=function(){};F.prototype=P.prototype;C.prototype=new F;var i,l,o;for(i=2,l=arguments.length;i<l;i++){o=arguments[i];if(typeof o==="function"){o=o.prototype;}
+OpenLayers.Util.extend(C.prototype,o);}};OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.extend=function(destination,source){destination=destination||{};if(source){for(var property in source){var value=source[property];if(value!==undefined){destination[property]=value;}}
+var sourceIsEvt=typeof window.Event=="function"&&source instanceof window.Event;if(!sourceIsEvt&&source.hasOwnProperty&&source.hasOwnProperty("toString")){destination.toString=source.toString;}}
+return destination;};OpenLayers.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:true,defaultFilter:null,initialize:function(options){options=options||{};OpenLayers.Util.extend(this,options);this.options=options;},mergeWithDefaultFilter:function(filter){var merged;if(filter&&this.defaultFilter){merged=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,filter]});}else{merged=filter||this.defaultFilter||undefined;}
+return merged;},destroy:function(){this.options=null;this.format=null;},read:function(options){options=options||{};options.filter=this.mergeWithDefaultFilter(options.filter);},create:function(){},update:function(){},"delete":function(){},commit:function(){},abort:function(response){},createCallback:function(method,response,options){return OpenLayers.Function.bind(function(){method.apply(this,[response,options]);},this);},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:true,features:null,reqFeatures:null,priv:null,error:null,initialize:function(options){OpenLayers.Util.extend(this,options);},success:function(){return this.code>0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Protocol.SQL=OpenLayers.Class(OpenLayers.Protocol,{databaseName:'ol',tableName:"ol_vector_features",postReadFiltering:true,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);},destroy:function(){OpenLayers.Protocol.prototype.destroy.apply(this);},supported:function(){return false;},evaluateFilter:function(feature,filter){return filter&&this.postReadFiltering?filter.evaluate(feature):true;},CLASS_NAME:"OpenLayers.Protocol.SQL"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(error){alert(error);},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){},CLASS_NAME:"OpenLayers.Console"};(function(){var scripts=document.getElementsByTagName("script");for(var i=0,len=scripts.length;i<len;++i){if(scripts[i].src.indexOf("firebug.js")!=-1){if(console){OpenLayers.Util.extend(OpenLayers.Console,console);break;}}}})();OpenLayers.Lang={code:null,defaultCode:"en",getCode:function(){if(!OpenLayers.Lang.code){OpenLayers.Lang.setCode();}
+return OpenLayers.Lang.code;},setCode:function(code){var lang;if(!code){code=(OpenLayers.BROWSER_NAME=="msie")?navigator.userLanguage:navigator.language;}
+var parts=code.split('-');parts[0]=parts[0].toLowerCase();if(typeof OpenLayers.Lang[parts[0]]=="object"){lang=parts[0];}
+if(parts[1]){var testLang=parts[0]+'-'+parts[1].toUpperCase();if(typeof OpenLayers.Lang[testLang]=="object"){lang=testLang;}}
+if(!lang){OpenLayers.Console.warn('Failed to find OpenLayers.Lang.'+parts.join("-")+' dictionary, falling back to default language');lang=OpenLayers.Lang.defaultCode;}
+OpenLayers.Lang.code=lang;},translate:function(key,context){var dictionary=OpenLayers.Lang[OpenLayers.Lang.getCode()];var message=dictionary&&dictionary[key];if(!message){message=key;}
+if(context){message=OpenLayers.String.format(message,context);}
+return message;}};OpenLayers.i18n=OpenLayers.Lang.translate;OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
+return camelizedString;},format:function(template,context,args){if(!context){context=window;}
+var replacer=function(str,match){var replacement;var subs=match.split(/\.+/);for(var i=0;i<subs.length;i++){if(i==0){replacement=context;}
+replacement=replacement[subs[i]];}
+if(typeof replacement=="function"){replacement=args?replacement.apply(null,args):replacement();}
+if(typeof replacement=='undefined'){return'undefined';}else{return replacement;}};return template.replace(OpenLayers.String.tokenRegEx,replacer);},tokenRegEx:/\$\{([\w.]+?)\}/g,numberRegEx:/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,isNumeric:function(value){return OpenLayers.String.numberRegEx.test(value);},numericIf:function(value){return OpenLayers.String.isNumeric(value)?parseFloat(value):value;}};if(!String.prototype.startsWith){String.prototype.startsWith=function(sStart){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.startsWith'}));return OpenLayers.String.startsWith(this,sStart);};}
+if(!String.prototype.contains){String.prototype.contains=function(str){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.contains'}));return OpenLayers.String.contains(this,str);};}
+if(!String.prototype.trim){String.prototype.trim=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.trim'}));return OpenLayers.String.trim(this);};}
+if(!String.prototype.camelize){String.prototype.camelize=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.camelize'}));return OpenLayers.String.camelize(this);};}
+OpenLayers.Number={decimalSeparator:".",thousandsSeparator:",",limitSigDigs:function(num,sig){var fig=0;if(sig>0){fig=parseFloat(num.toPrecision(sig));}
+return fig;},format:function(num,dec,tsep,dsep){dec=(typeof dec!="undefined")?dec:0;tsep=(typeof tsep!="undefined")?tsep:OpenLayers.Number.thousandsSeparator;dsep=(typeof dsep!="undefined")?dsep:OpenLayers.Number.decimalSeparator;if(dec!=null){num=parseFloat(num.toFixed(dec));}
+var parts=num.toString().split(".");if(parts.length==1&&dec==null){dec=0;}
+var integer=parts[0];if(tsep){var thousands=/(-?[0-9]+)([0-9]{3})/;while(thousands.test(integer)){integer=integer.replace(thousands,"$1"+tsep+"$2");}}
+var str;if(dec==0){str=integer;}else{var rem=parts.length>1?parts[1]:"0";if(dec!=null){rem=rem+new Array(dec-rem.length+1).join("0");}
+str=integer+dsep+rem;}
+return str;}};if(!Number.prototype.limitSigDigs){Number.prototype.limitSigDigs=function(sig){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Number.limitSigDigs'}));return OpenLayers.Number.limitSigDigs(this,sig);};}
+OpenLayers.Function={bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},bindAsEventListener:function(func,object){return function(event){return func.call(object,event||window.event);};},False:function(){return false;},True:function(){return true;},Void:function(){}};if(!Function.prototype.bind){Function.prototype.bind=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bind'}));Array.prototype.unshift.apply(arguments,[this]);return OpenLayers.Function.bind.apply(null,arguments);};}
+if(!Function.prototype.bindAsEventListener){Function.prototype.bindAsEventListener=function(object){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bindAsEventListener'}));return OpenLayers.Function.bindAsEventListener(this,object);};}
+OpenLayers.Array={filter:function(array,callback,caller){var selected=[];if(Array.prototype.filter){selected=array.filter(callback,caller);}else{var len=array.length;if(typeof callback!="function"){throw new TypeError();}
+for(var i=0;i<len;i++){if(i in array){var val=array[i];if(callback.call(caller,val,i,array)){selected.push(val);}}}}
+return selected;}};OpenLayers.Bounds=OpenLayers.Class({left:null,bottom:null,right:null,top:null,centerLonLat:null,initialize:function(left,bottom,right,top){if(left!=null){this.left=OpenLayers.Util.toFloat(left);}
+if(bottom!=null){this.bottom=OpenLayers.Util.toFloat(bottom);}
+if(right!=null){this.right=OpenLayers.Util.toFloat(right);}
+if(top!=null){this.top=OpenLayers.Util.toFloat(top);}},clone:function(){return new OpenLayers.Bounds(this.left,this.bottom,this.right,this.top);},equals:function(bounds){var equals=false;if(bounds!=null){equals=((this.left==bounds.left)&&(this.right==bounds.right)&&(this.top==bounds.top)&&(this.bottom==bounds.bottom));}
+return equals;},toString:function(){return[this.left,this.bottom,this.right,this.top].join(",");},toArray:function(reverseAxisOrder){if(reverseAxisOrder===true){return[this.bottom,this.left,this.top,this.right];}else{return[this.left,this.bottom,this.right,this.top];}},toBBOX:function(decimal,reverseAxisOrder){if(decimal==null){decimal=6;}
+var mult=Math.pow(10,decimal);var xmin=Math.round(this.left*mult)/mult;var ymin=Math.round(this.bottom*mult)/mult;var xmax=Math.round(this.right*mult)/mult;var ymax=Math.round(this.top*mult)/mult;if(reverseAxisOrder===true){return ymin+","+xmin+","+ymax+","+xmax;}else{return xmin+","+ymin+","+xmax+","+ymax;}},toGeometry:function(){return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(this.left,this.bottom),new OpenLayers.Geometry.Point(this.right,this.bottom),new OpenLayers.Geometry.Point(this.right,this.top),new OpenLayers.Geometry.Point(this.left,this.top)])]);},getWidth:function(){return(this.right-this.left);},getHeight:function(){return(this.top-this.bottom);},getSize:function(){return new OpenLayers.Size(this.getWidth(),this.getHeight());},getCenterPixel:function(){return new OpenLayers.Pixel((this.left+this.right)/2,(this.bottom+this.top)/2);},getCenterLonLat:function(){if(!this.centerLonLat){this.centerLonLat=new OpenLayers.LonLat((this.left+this.right)/2,(this.bottom+this.top)/2);}
+return this.centerLonLat;},scale:function(ratio,origin){if(origin==null){origin=this.getCenterLonLat();}
+var origx,origy;if(origin.CLASS_NAME=="OpenLayers.LonLat"){origx=origin.lon;origy=origin.lat;}else{origx=origin.x;origy=origin.y;}
+var left=(this.left-origx)*ratio+origx;var bottom=(this.bottom-origy)*ratio+origy;var right=(this.right-origx)*ratio+origx;var top=(this.top-origy)*ratio+origy;return new OpenLayers.Bounds(left,bottom,right,top);},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("boundsAddError");OpenLayers.Console.error(msg);return null;}
+return new OpenLayers.Bounds(this.left+x,this.bottom+y,this.right+x,this.top+y);},extend:function(object){var bounds=null;if(object){switch(object.CLASS_NAME){case"OpenLayers.LonLat":bounds=new OpenLayers.Bounds(object.lon,object.lat,object.lon,object.lat);break;case"OpenLayers.Geometry.Point":bounds=new OpenLayers.Bounds(object.x,object.y,object.x,object.y);break;case"OpenLayers.Bounds":bounds=object;break;}
+if(bounds){this.centerLonLat=null;if((this.left==null)||(bounds.left<this.left)){this.left=bounds.left;}
+if((this.bottom==null)||(bounds.bottom<this.bottom)){this.bottom=bounds.bottom;}
+if((this.right==null)||(bounds.right>this.right)){this.right=bounds.right;}
+if((this.top==null)||(bounds.top>this.top)){this.top=bounds.top;}}}},containsLonLat:function(ll,inclusive){return this.contains(ll.lon,ll.lat,inclusive);},containsPixel:function(px,inclusive){return this.contains(px.x,px.y,inclusive);},contains:function(x,y,inclusive){if(inclusive==null){inclusive=true;}
+if(x==null||y==null){return false;}
+x=OpenLayers.Util.toFloat(x);y=OpenLayers.Util.toFloat(y);var contains=false;if(inclusive){contains=((x>=this.left)&&(x<=this.right)&&(y>=this.bottom)&&(y<=this.top));}else{contains=((x>this.left)&&(x<this.right)&&(y>this.bottom)&&(y<this.top));}
+return contains;},intersectsBounds:function(bounds,inclusive){if(inclusive==null){inclusive=true;}
+var intersects=false;var mightTouch=(this.left==bounds.right||this.right==bounds.left||this.top==bounds.bottom||this.bottom==bounds.top);if(inclusive||!mightTouch){var inBottom=(((bounds.bottom>=this.bottom)&&(bounds.bottom<=this.top))||((this.bottom>=bounds.bottom)&&(this.bottom<=bounds.top)));var inTop=(((bounds.top>=this.bottom)&&(bounds.top<=this.top))||((this.top>bounds.bottom)&&(this.top<bounds.top)));var inLeft=(((bounds.left>=this.left)&&(bounds.left<=this.right))||((this.left>=bounds.left)&&(this.left<=bounds.right)));var inRight=(((bounds.right>=this.left)&&(bounds.right<=this.right))||((this.right>=bounds.left)&&(this.right<=bounds.right)));intersects=((inBottom||inTop)&&(inLeft||inRight));}
+return intersects;},containsBounds:function(bounds,partial,inclusive){if(partial==null){partial=false;}
+if(inclusive==null){inclusive=true;}
+var bottomLeft=this.contains(bounds.left,bounds.bottom,inclusive);var bottomRight=this.contains(bounds.right,bounds.bottom,inclusive);var topLeft=this.contains(bounds.left,bounds.top,inclusive);var topRight=this.contains(bounds.right,bounds.top,inclusive);return(partial)?(bottomLeft||bottomRight||topLeft||topRight):(bottomLeft&&bottomRight&&topLeft&&topRight);},determineQuadrant:function(lonlat){var quadrant="";var center=this.getCenterLonLat();quadrant+=(lonlat.lat<center.lat)?"b":"t";quadrant+=(lonlat.lon<center.lon)?"l":"r";return quadrant;},transform:function(source,dest){this.centerLonLat=null;var ll=OpenLayers.Projection.transform({'x':this.left,'y':this.bottom},source,dest);var lr=OpenLayers.Projection.transform({'x':this.right,'y':this.bottom},source,dest);var ul=OpenLayers.Projection.transform({'x':this.left,'y':this.top},source,dest);var ur=OpenLayers.Projection.transform({'x':this.right,'y':this.top},source,dest);this.left=Math.min(ll.x,ul.x);this.bottom=Math.min(ll.y,lr.y);this.right=Math.max(lr.x,ur.x);this.top=Math.max(ul.y,ur.y);return this;},wrapDateLine:function(maxExtent,options){options=options||{};var leftTolerance=options.leftTolerance||0;var rightTolerance=options.rightTolerance||0;var newBounds=this.clone();if(maxExtent){while(newBounds.left<maxExtent.left&&(newBounds.right-rightTolerance)<=maxExtent.left){newBounds=newBounds.add(maxExtent.getWidth(),0);}
+while((newBounds.left+leftTolerance)>=maxExtent.right&&newBounds.right>maxExtent.right){newBounds=newBounds.add(-maxExtent.getWidth(),0);}}
+return newBounds;},CLASS_NAME:"OpenLayers.Bounds"});OpenLayers.Bounds.fromString=function(str,reverseAxisOrder){var bounds=str.split(",");return OpenLayers.Bounds.fromArray(bounds,reverseAxisOrder);};OpenLayers.Bounds.fromArray=function(bbox,reverseAxisOrder){return reverseAxisOrder===true?new OpenLayers.Bounds(parseFloat(bbox[1]),parseFloat(bbox[0]),parseFloat(bbox[3]),parseFloat(bbox[2])):new OpenLayers.Bounds(parseFloat(bbox[0]),parseFloat(bbox[1]),parseFloat(bbox[2]),parseFloat(bbox[3]));};OpenLayers.Bounds.fromSize=function(size){return new OpenLayers.Bounds(0,size.h,size.w,0);};OpenLayers.Bounds.oppositeQuadrant=function(quadrant){var opp="";opp+=(quadrant.charAt(0)=='t')?'b':'t';opp+=(quadrant.charAt(1)=='l')?'r':'l';return opp;};OpenLayers.Element={visible:function(element){return OpenLayers.Util.getElement(element).style.display!='none';},toggle:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);var display=OpenLayers.Element.visible(element)?'hide':'show';OpenLayers.Element[display](element);}},hide:function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{newMethod:"element.style.display = 'none';"}));for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='none';}}},show:function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{newMethod:"element.style.display = '';"}));for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='';}}},remove:function(element){element=OpenLayers.Util.getElement(element);element.parentNode.removeChild(element);},getHeight:function(element){element=OpenLayers.Util.getElement(element);return element.offsetHeight;},getDimensions:function(element){element=OpenLayers.Util.getElement(element);if(OpenLayers.Element.getStyle(element,'display')!='none'){return{width:element.offsetWidth,height:element.offsetHeight};}
+var els=element.style;var originalVisibility=els.visibility;var originalPosition=els.position;var originalDisplay=els.display;els.visibility='hidden';els.position='absolute';els.display='';var originalWidth=element.clientWidth;var originalHeight=element.clientHeight;els.display=originalDisplay;els.position=originalPosition;els.visibility=originalVisibility;return{width:originalWidth,height:originalHeight};},hasClass:function(element,name){var names=element.className;return(!!names&&new RegExp("(^|\\s)"+name+"(\\s|$)").test(names));},addClass:function(element,name){if(!OpenLayers.Element.hasClass(element,name)){element.className+=(element.className?" ":"")+name;}
+return element;},removeClass:function(element,name){var names=element.className;if(names){element.className=OpenLayers.String.trim(names.replace(new RegExp("(^|\\s+)"+name+"(\\s+|$)")," "));}
+return element;},toggleClass:function(element,name){if(OpenLayers.Element.hasClass(element,name)){OpenLayers.Element.removeClass(element,name);}else{OpenLayers.Element.addClass(element,name);}
+return element;},getStyle:function(element,style){element=OpenLayers.Util.getElement(element);var value=null;if(element&&element.style){value=element.style[OpenLayers.String.camelize(style)];if(!value){if(document.defaultView&&document.defaultView.getComputedStyle){var css=document.defaultView.getComputedStyle(element,null);value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){value=element.currentStyle[OpenLayers.String.camelize(style)];}}
+var positions=['left','top','right','bottom'];if(window.opera&&(OpenLayers.Util.indexOf(positions,style)!=-1)&&(OpenLayers.Element.getStyle(element,'position')=='static')){value='auto';}}
+return value=='auto'?null:value;}};OpenLayers.LonLat=OpenLayers.Class({lon:0.0,lat:0.0,initialize:function(lon,lat){this.lon=OpenLayers.Util.toFloat(lon);this.lat=OpenLayers.Util.toFloat(lat);},toString:function(){return("lon="+this.lon+",lat="+this.lat);},toShortString:function(){return(this.lon+", "+this.lat);},clone:function(){return new OpenLayers.LonLat(this.lon,this.lat);},add:function(lon,lat){if((lon==null)||(lat==null)){var msg=OpenLayers.i18n("lonlatAddError");OpenLayers.Console.error(msg);return null;}
+return new OpenLayers.LonLat(this.lon+OpenLayers.Util.toFloat(lon),this.lat+OpenLayers.Util.toFloat(lat));},equals:function(ll){var equals=false;if(ll!=null){equals=((this.lon==ll.lon&&this.lat==ll.lat)||(isNaN(this.lon)&&isNaN(this.lat)&&isNaN(ll.lon)&&isNaN(ll.lat)));}
+return equals;},transform:function(source,dest){var point=OpenLayers.Projection.transform({'x':this.lon,'y':this.lat},source,dest);this.lon=point.x;this.lat=point.y;return this;},wrapDateLine:function(maxExtent){var newLonLat=this.clone();if(maxExtent){while(newLonLat.lon<maxExtent.left){newLonLat.lon+=maxExtent.getWidth();}
+while(newLonLat.lon>maxExtent.right){newLonLat.lon-=maxExtent.getWidth();}}
+return newLonLat;},CLASS_NAME:"OpenLayers.LonLat"});OpenLayers.LonLat.fromString=function(str){var pair=str.split(",");return new OpenLayers.LonLat(pair[0],pair[1]);};OpenLayers.LonLat.fromArray=function(arr){var gotArr=OpenLayers.Util.isArray(arr),lon=gotArr&&arr[0],lat=gotArr&&arr[1];return new OpenLayers.LonLat(lon,lat);};OpenLayers.Pixel=OpenLayers.Class({x:0.0,y:0.0,initialize:function(x,y){this.x=parseFloat(x);this.y=parseFloat(y);},toString:function(){return("x="+this.x+",y="+this.y);},clone:function(){return new OpenLayers.Pixel(this.x,this.y);},equals:function(px){var equals=false;if(px!=null){equals=((this.x==px.x&&this.y==px.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(px.x)&&isNaN(px.y)));}
+return equals;},distanceTo:function(px){return Math.sqrt(Math.pow(this.x-px.x,2)+
+Math.pow(this.y-px.y,2));},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("pixelAddError");OpenLayers.Console.error(msg);return null;}
+return new OpenLayers.Pixel(this.x+x,this.y+y);},offset:function(px){var newPx=this.clone();if(px){newPx=this.add(px.x,px.y);}
+return newPx;},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Size=OpenLayers.Class({w:0.0,h:0.0,initialize:function(w,h){this.w=parseFloat(w);this.h=parseFloat(h);},toString:function(){return("w="+this.w+",h="+this.h);},clone:function(){return new OpenLayers.Size(this.w,this.h);},equals:function(sz){var equals=false;if(sz!=null){equals=((this.w==sz.w&&this.h==sz.h)||(isNaN(this.w)&&isNaN(this.h)&&isNaN(sz.w)&&isNaN(sz.h)));}
+return equals;},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.getElement=function(){var elements=[];for(var i=0,len=arguments.length;i<len;i++){var element=arguments[i];if(typeof element=='string'){element=document.getElementById(element);}
+if(arguments.length==1){return element;}
+elements.push(element);}
+return elements;};OpenLayers.Util.isElement=function(o){return!!(o&&o.nodeType===1);};OpenLayers.Util.isArray=function(a){return(Object.prototype.toString.call(a)==='[object Array]');};if(typeof window.$==="undefined"){window.$=OpenLayers.Util.getElement;}
+OpenLayers.Util.removeItem=function(array,item){for(var i=array.length-1;i>=0;i--){if(array[i]==item){array.splice(i,1);}}
+return array;};OpenLayers.Util.clearArray=function(array){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'array = []'}));array.length=0;};OpenLayers.Util.indexOf=function(array,obj){if(typeof array.indexOf=="function"){return array.indexOf(obj);}else{for(var i=0,len=array.length;i<len;i++){if(array[i]==obj){return i;}}
+return-1;}};OpenLayers.Util.modifyDOMElement=function(element,id,px,sz,position,border,overflow,opacity){if(id){element.id=id;}
+if(px){element.style.left=px.x+"px";element.style.top=px.y+"px";}
+if(sz){element.style.width=sz.w+"px";element.style.height=sz.h+"px";}
+if(position){element.style.position=position;}
+if(border){element.style.border=border;}
+if(overflow){element.style.overflow=overflow;}
+if(parseFloat(opacity)>=0.0&&parseFloat(opacity)<1.0){element.style.filter='alpha(opacity='+(opacity*100)+')';element.style.opacity=opacity;}else if(parseFloat(opacity)==1.0){element.style.filter='';element.style.opacity='';}};OpenLayers.Util.createDiv=function(id,px,sz,imgURL,position,border,overflow,opacity){var dom=document.createElement('div');if(imgURL){dom.style.backgroundImage='url('+imgURL+')';}
+if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="absolute";}
+OpenLayers.Util.modifyDOMElement(dom,id,px,sz,position,border,overflow,opacity);return dom;};OpenLayers.Util.createImage=function(id,px,sz,imgURL,position,border,opacity,delayDisplay){var image=document.createElement("img");if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="relative";}
+OpenLayers.Util.modifyDOMElement(image,id,px,sz,position,border,null,opacity);if(delayDisplay){image.style.display="none";OpenLayers.Event.observe(image,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,image));OpenLayers.Event.observe(image,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,image));}
+image.style.alt=id;image.galleryImg="no";if(imgURL){image.src=imgURL;}
+return image;};OpenLayers.Util.setOpacity=function(element,opacity){OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);};OpenLayers.Util.onImageLoad=function(){if(!this.viewRequestID||(this.map&&this.viewRequestID==this.map.viewRequestID)){this.style.display="";}
+OpenLayers.Element.removeClass(this,"olImageLoadError");};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;OpenLayers.Util.onImageLoadError=function(){this._attempts=(this._attempts)?(this._attempts+1):1;if(this._attempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS){var urls=this.urls;if(urls&&OpenLayers.Util.isArray(urls)&&urls.length>1){var src=this.src.toString();var current_url,k;for(k=0;current_url=urls[k];k++){if(src.indexOf(current_url)!=-1){break;}}
+var guess=Math.floor(urls.length*Math.random());var new_url=urls[guess];k=0;while(new_url==current_url&&k++<4){guess=Math.floor(urls.length*Math.random());new_url=urls[guess];}
+this.src=src.replace(current_url,new_url);}else{this.src=this.src;}}else{OpenLayers.Element.addClass(this,"olImageLoadError");}
+this.style.display="";};OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(OpenLayers.Util.alphaHackNeeded==null){var arVersion=navigator.appVersion.split("MSIE");var version=parseFloat(arVersion[1]);var filter=false;try{filter=!!(document.body.filters);}catch(e){}
+OpenLayers.Util.alphaHackNeeded=(filter&&(version>=5.5)&&(version<7));}
+return OpenLayers.Util.alphaHackNeeded;};OpenLayers.Util.modifyAlphaImageDiv=function(div,id,px,sz,imgURL,position,border,sizing,opacity){OpenLayers.Util.modifyDOMElement(div,id,px,sz,position,null,null,opacity);var img=div.childNodes[0];if(imgURL){img.src=imgURL;}
+OpenLayers.Util.modifyDOMElement(img,div.id+"_innerImage",null,sz,"relative",border);if(OpenLayers.Util.alphaHack()){if(div.style.display!="none"){div.style.display="inline-block";}
+if(sizing==null){sizing="scale";}
+div.style.filter="progid:DXImageTransform.Microsoft"+".AlphaImageLoader(src='"+img.src+"', "+"sizingMethod='"+sizing+"')";if(parseFloat(div.style.opacity)>=0.0&&parseFloat(div.style.opacity)<1.0){div.style.filter+=" alpha(opacity="+div.style.opacity*100+")";}
+img.style.filter="alpha(opacity=0)";}};OpenLayers.Util.createAlphaImageDiv=function(id,px,sz,imgURL,position,border,sizing,opacity,delayDisplay){var div=OpenLayers.Util.createDiv();var img=OpenLayers.Util.createImage(null,null,null,null,null,null,null,false);div.appendChild(img);if(delayDisplay){img.style.display="none";OpenLayers.Event.observe(img,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,div));OpenLayers.Event.observe(img,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,div));}
+OpenLayers.Util.modifyAlphaImageDiv(div,id,px,sz,imgURL,position,border,sizing,opacity);return div;};OpenLayers.Util.upperCaseObject=function(object){var uObject={};for(var key in object){uObject[key.toUpperCase()]=object[key];}
+return uObject;};OpenLayers.Util.applyDefaults=function(to,from){to=to||{};var fromIsEvt=typeof window.Event=="function"&&from instanceof window.Event;for(var key in from){if(to[key]===undefined||(!fromIsEvt&&from.hasOwnProperty&&from.hasOwnProperty(key)&&!to.hasOwnProperty(key))){to[key]=from[key];}}
+if(!fromIsEvt&&from&&from.hasOwnProperty&&from.hasOwnProperty('toString')&&!to.hasOwnProperty('toString')){to.toString=from.toString;}
+return to;};OpenLayers.Util.getParameterString=function(params){var paramsArray=[];for(var key in params){var value=params[key];if((value!=null)&&(typeof value!='function')){var encodedValue;if(typeof value=='object'&&value.constructor==Array){var encodedItemArray=[];var item;for(var itemIndex=0,len=value.length;itemIndex<len;itemIndex++){item=value[itemIndex];encodedItemArray.push(encodeURIComponent((item===null||item===undefined)?"":item));}
+encodedValue=encodedItemArray.join(",");}
+else{encodedValue=encodeURIComponent(value);}
+paramsArray.push(encodeURIComponent(key)+"="+encodedValue);}}
+return paramsArray.join("&");};OpenLayers.Util.urlAppend=function(url,paramStr){var newUrl=url;if(paramStr){var parts=(url+" ").split(/[?&]/);newUrl+=(parts.pop()===" "?paramStr:parts.length?"&"+paramStr:"?"+paramStr);}
+return newUrl;};OpenLayers.ImgPath='';OpenLayers.Util.getImagesLocation=function(){return OpenLayers.ImgPath||(OpenLayers._getScriptLocation()+"img/");};OpenLayers.Util.Try=function(){var returnValue=null;for(var i=0,len=arguments.length;i<len;i++){var lambda=arguments[i];try{returnValue=lambda();break;}catch(e){}}
+return returnValue;};OpenLayers.Util.getXmlNodeValue=function(node){var val=null;OpenLayers.Util.Try(function(){val=node.text;if(!val){val=node.textContent;}
+if(!val){val=node.firstChild.nodeValue;}},function(){val=node.textContent;});return val;};OpenLayers.Util.mouseLeft=function(evt,div){var target=(evt.relatedTarget)?evt.relatedTarget:evt.toElement;while(target!=div&&target!=null){target=target.parentNode;}
+return(target!=div);};OpenLayers.Util.DEFAULT_PRECISION=14;OpenLayers.Util.toFloat=function(number,precision){if(precision==null){precision=OpenLayers.Util.DEFAULT_PRECISION;}
+if(typeof number!=="number"){number=parseFloat(number);}
+return precision===0?number:parseFloat(number.toPrecision(precision));};OpenLayers.Util.rad=function(x){return x*Math.PI/180;};OpenLayers.Util.deg=function(x){return x*180/Math.PI;};OpenLayers.Util.VincentyConstants={a:6378137,b:6356752.3142,f:1/298.257223563};OpenLayers.Util.distVincenty=function(p1,p2){var ct=OpenLayers.Util.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var L=OpenLayers.Util.rad(p2.lon-p1.lon);var U1=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p1.lat)));var U2=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p2.lat)));var sinU1=Math.sin(U1),cosU1=Math.cos(U1);var sinU2=Math.sin(U2),cosU2=Math.cos(U2);var lambda=L,lambdaP=2*Math.PI;var iterLimit=20;while(Math.abs(lambda-lambdaP)>1e-12&&--iterLimit>0){var sinLambda=Math.sin(lambda),cosLambda=Math.cos(lambda);var sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)+
+(cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));if(sinSigma==0){return 0;}
+var cosSigma=sinU1*sinU2+cosU1*cosU2*cosLambda;var sigma=Math.atan2(sinSigma,cosSigma);var alpha=Math.asin(cosU1*cosU2*sinLambda/sinSigma);var cosSqAlpha=Math.cos(alpha)*Math.cos(alpha);var cos2SigmaM=cosSigma-2*sinU1*sinU2/cosSqAlpha;var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));lambdaP=lambda;lambda=L+(1-C)*f*Math.sin(alpha)*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));}
+if(iterLimit==0){return NaN;}
+var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));var s=b*A*(sigma-deltaSigma);var d=s.toFixed(3)/1000;return d;};OpenLayers.Util.destinationVincenty=function(lonlat,brng,dist){var u=OpenLayers.Util;var ct=u.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var lon1=lonlat.lon;var lat1=lonlat.lat;var s=dist;var alpha1=u.rad(brng);var sinAlpha1=Math.sin(alpha1);var cosAlpha1=Math.cos(alpha1);var tanU1=(1-f)*Math.tan(u.rad(lat1));var cosU1=1/Math.sqrt((1+tanU1*tanU1)),sinU1=tanU1*cosU1;var sigma1=Math.atan2(tanU1,cosAlpha1);var sinAlpha=cosU1*sinAlpha1;var cosSqAlpha=1-sinAlpha*sinAlpha;var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var sigma=s/(b*A),sigmaP=2*Math.PI;while(Math.abs(sigma-sigmaP)>1e-12){var cos2SigmaM=Math.cos(2*sigma1+sigma);var sinSigma=Math.sin(sigma);var cosSigma=Math.cos(sigma);var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));sigmaP=sigma;sigma=s/(b*A)+deltaSigma;}
+var tmp=sinU1*sinSigma-cosU1*cosSigma*cosAlpha1;var lat2=Math.atan2(sinU1*cosSigma+cosU1*sinSigma*cosAlpha1,(1-f)*Math.sqrt(sinAlpha*sinAlpha+tmp*tmp));var lambda=Math.atan2(sinSigma*sinAlpha1,cosU1*cosSigma-sinU1*sinSigma*cosAlpha1);var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));var L=lambda-(1-C)*f*sinAlpha*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));var revAz=Math.atan2(sinAlpha,-tmp);return new OpenLayers.LonLat(lon1+u.deg(L),u.deg(lat2));};OpenLayers.Util.getParameters=function(url){url=(url===null||url===undefined)?window.location.href:url;var paramsString="";if(OpenLayers.String.contains(url,'?')){var start=url.indexOf('?')+1;var end=OpenLayers.String.contains(url,"#")?url.indexOf('#'):url.length;paramsString=url.substring(start,end);}
+var parameters={};var pairs=paramsString.split(/[&;]/);for(var i=0,len=pairs.length;i<len;++i){var keyValue=pairs[i].split('=');if(keyValue[0]){var key=keyValue[0];try{key=decodeURIComponent(key);}catch(err){key=unescape(key);}
+var value=(keyValue[1]||'').replace(/\+/g," ");try{value=decodeURIComponent(value);}catch(err){value=unescape(value);}
+value=value.split(",");if(value.length==1){value=value[0];}
+parameters[key]=value;}}
+return parameters;};OpenLayers.Util.getArgs=function(url){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Util.getParameters'}));return OpenLayers.Util.getParameters(url);};OpenLayers.Util.lastSeqID=0;OpenLayers.Util.createUniqueID=function(prefix){if(prefix==null){prefix="id_";}
+OpenLayers.Util.lastSeqID+=1;return prefix+OpenLayers.Util.lastSeqID;};OpenLayers.INCHES_PER_UNIT={'inches':1.0,'ft':12.0,'mi':63360.0,'m':39.3701,'km':39370.1,'dd':4374754,'yd':36};OpenLayers.INCHES_PER_UNIT["in"]=OpenLayers.INCHES_PER_UNIT.inches;OpenLayers.INCHES_PER_UNIT["degrees"]=OpenLayers.INCHES_PER_UNIT.dd;OpenLayers.INCHES_PER_UNIT["nmi"]=1852*OpenLayers.INCHES_PER_UNIT.m;OpenLayers.METERS_PER_INCH=0.02540005080010160020;OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"Inch":OpenLayers.INCHES_PER_UNIT.inches,"Meter":1.0/OpenLayers.METERS_PER_INCH,"Foot":0.30480060960121920243/OpenLayers.METERS_PER_INCH,"IFoot":0.30480000000000000000/OpenLayers.METERS_PER_INCH,"ClarkeFoot":0.3047972651151/OpenLayers.METERS_PER_INCH,"SearsFoot":0.30479947153867624624/OpenLayers.METERS_PER_INCH,"GoldCoastFoot":0.30479971018150881758/OpenLayers.METERS_PER_INCH,"IInch":0.02540000000000000000/OpenLayers.METERS_PER_INCH,"MicroInch":0.00002540000000000000/OpenLayers.METERS_PER_INCH,"Mil":0.00000002540000000000/OpenLayers.METERS_PER_INCH,"Centimeter":0.01000000000000000000/OpenLayers.METERS_PER_INCH,"Kilometer":1000.00000000000000000000/OpenLayers.METERS_PER_INCH,"Yard":0.91440182880365760731/OpenLayers.METERS_PER_INCH,"SearsYard":0.914398414616029/OpenLayers.METERS_PER_INCH,"IndianYard":0.91439853074444079983/OpenLayers.METERS_PER_INCH,"IndianYd37":0.91439523/OpenLayers.METERS_PER_INCH,"IndianYd62":0.9143988/OpenLayers.METERS_PER_INCH,"IndianYd75":0.9143985/OpenLayers.METERS_PER_INCH,"IndianFoot":0.30479951/OpenLayers.METERS_PER_INCH,"IndianFt37":0.30479841/OpenLayers.METERS_PER_INCH,"IndianFt62":0.3047996/OpenLayers.METERS_PER_INCH,"IndianFt75":0.3047995/OpenLayers.METERS_PER_INCH,"Mile":1609.34721869443738887477/OpenLayers.METERS_PER_INCH,"IYard":0.91440000000000000000/OpenLayers.METERS_PER_INCH,"IMile":1609.34400000000000000000/OpenLayers.METERS_PER_INCH,"NautM":1852.00000000000000000000/OpenLayers.METERS_PER_INCH,"Lat-66":110943.316488932731/OpenLayers.METERS_PER_INCH,"Lat-83":110946.25736872234125/OpenLayers.METERS_PER_INCH,"Decimeter":0.10000000000000000000/OpenLayers.METERS_PER_INCH,"Millimeter":0.00100000000000000000/OpenLayers.METERS_PER_INCH,"Dekameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Decameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Hectometer":100.00000000000000000000/OpenLayers.METERS_PER_INCH,"GermanMeter":1.0000135965/OpenLayers.METERS_PER_INCH,"CaGrid":0.999738/OpenLayers.METERS_PER_INCH,"ClarkeChain":20.1166194976/OpenLayers.METERS_PER_INCH,"GunterChain":20.11684023368047/OpenLayers.METERS_PER_INCH,"BenoitChain":20.116782494375872/OpenLayers.METERS_PER_INCH,"SearsChain":20.11676512155/OpenLayers.METERS_PER_INCH,"ClarkeLink":0.201166194976/OpenLayers.METERS_PER_INCH,"GunterLink":0.2011684023368047/OpenLayers.METERS_PER_INCH,"BenoitLink":0.20116782494375872/OpenLayers.METERS_PER_INCH,"SearsLink":0.2011676512155/OpenLayers.METERS_PER_INCH,"Rod":5.02921005842012/OpenLayers.METERS_PER_INCH,"IntnlChain":20.1168/OpenLayers.METERS_PER_INCH,"IntnlLink":0.201168/OpenLayers.METERS_PER_INCH,"Perch":5.02921005842012/OpenLayers.METERS_PER_INCH,"Pole":5.02921005842012/OpenLayers.METERS_PER_INCH,"Furlong":201.1684023368046/OpenLayers.METERS_PER_INCH,"Rood":3.778266898/OpenLayers.METERS_PER_INCH,"CapeFoot":0.3047972615/OpenLayers.METERS_PER_INCH,"Brealey":375.00000000000000000000/OpenLayers.METERS_PER_INCH,"ModAmFt":0.304812252984505969011938/OpenLayers.METERS_PER_INCH,"Fathom":1.8288/OpenLayers.METERS_PER_INCH,"NautM-UK":1853.184/OpenLayers.METERS_PER_INCH,"50kilometers":50000.0/OpenLayers.METERS_PER_INCH,"150kilometers":150000.0/OpenLayers.METERS_PER_INCH});OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"mm":OpenLayers.INCHES_PER_UNIT["Meter"]/1000.0,"cm":OpenLayers.INCHES_PER_UNIT["Meter"]/100.0,"dm":OpenLayers.INCHES_PER_UNIT["Meter"]*100.0,"km":OpenLayers.INCHES_PER_UNIT["Meter"]*1000.0,"kmi":OpenLayers.INCHES_PER_UNIT["nmi"],"fath":OpenLayers.INCHES_PER_UNIT["Fathom"],"ch":OpenLayers.INCHES_PER_UNIT["IntnlChain"],"link":OpenLayers.INCHES_PER_UNIT["IntnlLink"],"us-in":OpenLayers.INCHES_PER_UNIT["inches"],"us-ft":OpenLayers.INCHES_PER_UNIT["Foot"],"us-yd":OpenLayers.INCHES_PER_UNIT["Yard"],"us-ch":OpenLayers.INCHES_PER_UNIT["GunterChain"],"us-mi":OpenLayers.INCHES_PER_UNIT["Mile"],"ind-yd":OpenLayers.INCHES_PER_UNIT["IndianYd37"],"ind-ft":OpenLayers.INCHES_PER_UNIT["IndianFt37"],"ind-ch":20.11669506/OpenLayers.METERS_PER_INCH});OpenLayers.DOTS_PER_INCH=72;OpenLayers.Util.normalizeScale=function(scale){var normScale=(scale>1.0)?(1.0/scale):scale;return normScale;};OpenLayers.Util.getResolutionFromScale=function(scale,units){var resolution;if(scale){if(units==null){units="degrees";}
+var normScale=OpenLayers.Util.normalizeScale(scale);resolution=1/(normScale*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH);}
+return resolution;};OpenLayers.Util.getScaleFromResolution=function(resolution,units){if(units==null){units="degrees";}
+var scale=resolution*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH;return scale;};OpenLayers.Util.safeStopPropagation=function(evt){OpenLayers.Event.stop(evt,true);};OpenLayers.Util.pagePosition=function(forElement){var pos=[0,0];var viewportElement=OpenLayers.Util.getViewportElement();if(!forElement||forElement==window||forElement==viewportElement){return pos;}
+var BUGGY_GECKO_BOX_OBJECT=OpenLayers.IS_GECKO&&document.getBoxObjectFor&&OpenLayers.Element.getStyle(forElement,'position')=='absolute'&&(forElement.style.top==''||forElement.style.left=='');var parent=null;var box;if(forElement.getBoundingClientRect){box=forElement.getBoundingClientRect();var scrollTop=viewportElement.scrollTop;var scrollLeft=viewportElement.scrollLeft;pos[0]=box.left+scrollLeft;pos[1]=box.top+scrollTop;}else if(document.getBoxObjectFor&&!BUGGY_GECKO_BOX_OBJECT){box=document.getBoxObjectFor(forElement);var vpBox=document.getBoxObjectFor(viewportElement);pos[0]=box.screenX-vpBox.screenX;pos[1]=box.screenY-vpBox.screenY;}else{pos[0]=forElement.offsetLeft;pos[1]=forElement.offsetTop;parent=forElement.offsetParent;if(parent!=forElement){while(parent){pos[0]+=parent.offsetLeft;pos[1]+=parent.offsetTop;parent=parent.offsetParent;}}
+var browser=OpenLayers.BROWSER_NAME;if(browser=="opera"||(browser=="safari"&&OpenLayers.Element.getStyle(forElement,'position')=='absolute')){pos[1]-=document.body.offsetTop;}
+parent=forElement.offsetParent;while(parent&&parent!=document.body){pos[0]-=parent.scrollLeft;if(browser!="opera"||parent.tagName!='TR'){pos[1]-=parent.scrollTop;}
+parent=parent.offsetParent;}}
+return pos;};OpenLayers.Util.getViewportElement=function(){var viewportElement=arguments.callee.viewportElement;if(viewportElement==undefined){viewportElement=(OpenLayers.BROWSER_NAME=="msie"&&document.compatMode!='CSS1Compat')?document.body:document.documentElement;arguments.callee.viewportElement=viewportElement;}
+return viewportElement;};OpenLayers.Util.isEquivalentUrl=function(url1,url2,options){options=options||{};OpenLayers.Util.applyDefaults(options,{ignoreCase:true,ignorePort80:true,ignoreHash:true});var urlObj1=OpenLayers.Util.createUrlObject(url1,options);var urlObj2=OpenLayers.Util.createUrlObject(url2,options);for(var key in urlObj1){if(key!=="args"){if(urlObj1[key]!=urlObj2[key]){return false;}}}
+for(var key in urlObj1.args){if(urlObj1.args[key]!=urlObj2.args[key]){return false;}
+delete urlObj2.args[key];}
+for(var key in urlObj2.args){return false;}
+return true;};OpenLayers.Util.createUrlObject=function(url,options){options=options||{};if(!(/^\w+:\/\//).test(url)){var loc=window.location;var port=loc.port?":"+loc.port:"";var fullUrl=loc.protocol+"//"+loc.host.split(":").shift()+port;if(url.indexOf("/")===0){url=fullUrl+url;}else{var parts=loc.pathname.split("/");parts.pop();url=fullUrl+parts.join("/")+"/"+url;}}
+if(options.ignoreCase){url=url.toLowerCase();}
+var a=document.createElement('a');a.href=url;var urlObject={};urlObject.host=a.host.split(":").shift();urlObject.protocol=a.protocol;if(options.ignorePort80){urlObject.port=(a.port=="80"||a.port=="0")?"":a.port;}else{urlObject.port=(a.port==""||a.port=="0")?"80":a.port;}
+urlObject.hash=(options.ignoreHash||a.hash==="#")?"":a.hash;var queryString=a.search;if(!queryString){var qMark=url.indexOf("?");queryString=(qMark!=-1)?url.substr(qMark):"";}
+urlObject.args=OpenLayers.Util.getParameters(queryString);urlObject.pathname=(a.pathname.charAt(0)=="/")?a.pathname:"/"+a.pathname;return urlObject;};OpenLayers.Util.removeTail=function(url){var head=null;var qMark=url.indexOf("?");var hashMark=url.indexOf("#");if(qMark==-1){head=(hashMark!=-1)?url.substr(0,hashMark):url;}else{head=(hashMark!=-1)?url.substr(0,Math.min(qMark,hashMark)):url.substr(0,qMark);}
+return head;};OpenLayers.IS_GECKO=(function(){var ua=navigator.userAgent.toLowerCase();return ua.indexOf("webkit")==-1&&ua.indexOf("gecko")!=-1;})();OpenLayers.BROWSER_NAME=(function(){var name="";var ua=navigator.userAgent.toLowerCase();if(ua.indexOf("opera")!=-1){name="opera";}else if(ua.indexOf("msie")!=-1){name="msie";}else if(ua.indexOf("safari")!=-1){name="safari";}else if(ua.indexOf("mozilla")!=-1){if(ua.indexOf("firefox")!=-1){name="firefox";}else{name="mozilla";}}
+return name;})();OpenLayers.Util.getBrowserName=function(){return OpenLayers.BROWSER_NAME;};OpenLayers.Util.getRenderedDimensions=function(contentHTML,size,options){var w,h;var container=document.createElement("div");container.style.visibility="hidden";var containerElement=(options&&options.containerElement)?options.containerElement:document.body;if(size){if(size.w){w=size.w;container.style.width=w+"px";}else if(size.h){h=size.h;container.style.height=h+"px";}}
+if(options&&options.displayClass){container.className=options.displayClass;}
+var content=document.createElement("div");content.innerHTML=contentHTML;content.style.overflow="visible";if(content.childNodes){for(var i=0,l=content.childNodes.length;i<l;i++){if(!content.childNodes[i].style)continue;content.childNodes[i].style.overflow="visible";}}
+container.appendChild(content);containerElement.appendChild(container);var parentHasPositionAbsolute=false;var parent=container.parentNode;while(parent&&parent.tagName.toLowerCase()!="body"){var parentPosition=OpenLayers.Element.getStyle(parent,"position");if(parentPosition=="absolute"){parentHasPositionAbsolute=true;break;}else if(parentPosition&&parentPosition!="static"){break;}
+parent=parent.parentNode;}
+if(!parentHasPositionAbsolute){container.style.position="absolute";}
+if(!w){w=parseInt(content.scrollWidth);container.style.width=w+"px";}
+if(!h){h=parseInt(content.scrollHeight);}
+container.removeChild(content);containerElement.removeChild(container);return new OpenLayers.Size(w,h);};OpenLayers.Util.getScrollbarWidth=function(){var scrollbarWidth=OpenLayers.Util._scrollbarWidth;if(scrollbarWidth==null){var scr=null;var inn=null;var wNoScroll=0;var wScroll=0;scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='scroll';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);OpenLayers.Util._scrollbarWidth=(wNoScroll-wScroll);scrollbarWidth=OpenLayers.Util._scrollbarWidth;}
+return scrollbarWidth;};OpenLayers.Util.getFormattedLonLat=function(coordinate,axis,dmsOption){if(!dmsOption){dmsOption='dms';}
+coordinate=(coordinate+540)%360-180;var abscoordinate=Math.abs(coordinate);var coordinatedegrees=Math.floor(abscoordinate);var coordinateminutes=(abscoordinate-coordinatedegrees)/(1/60);var tempcoordinateminutes=coordinateminutes;coordinateminutes=Math.floor(coordinateminutes);var coordinateseconds=(tempcoordinateminutes-coordinateminutes)/(1/60);coordinateseconds=Math.round(coordinateseconds*10);coordinateseconds/=10;if(coordinateseconds>=60){coordinateseconds-=60;coordinateminutes+=1;if(coordinateminutes>=60){coordinateminutes-=60;coordinatedegrees+=1;}}
+if(coordinatedegrees<10){coordinatedegrees="0"+coordinatedegrees;}
+var str=coordinatedegrees+"\u00B0";if(dmsOption.indexOf('dm')>=0){if(coordinateminutes<10){coordinateminutes="0"+coordinateminutes;}
+str+=coordinateminutes+"'";if(dmsOption.indexOf('dms')>=0){if(coordinateseconds<10){coordinateseconds="0"+coordinateseconds;}
+str+=coordinateseconds+'"';}}
+if(axis=="lon"){str+=coordinate<0?OpenLayers.i18n("W"):OpenLayers.i18n("E");}else{str+=coordinate<0?OpenLayers.i18n("S"):OpenLayers.i18n("N");}
+return str;};OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:false,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},destroy:function(){},read:function(data){OpenLayers.Console.userError(OpenLayers.i18n("readNotImplemented"));},write:function(object){OpenLayers.Console.userError(OpenLayers.i18n("writeNotImplemented"));},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:"    ",space:" ",newline:"\n",level:0,pretty:false,nativeJSON:(function(){return!!(window.JSON&&typeof JSON.parse=="function"&&typeof JSON.stringify=="function");})(),read:function(json,filter){var object;if(this.nativeJSON){object=JSON.parse(json,filter);}else try{if(/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){object=eval('('+json+')');if(typeof filter==='function'){function walk(k,v){if(v&&typeof v==='object'){for(var i in v){if(v.hasOwnProperty(i)){v[i]=walk(i,v[i]);}}}
+return filter(k,v);}
+object=walk('',object);}}}catch(e){}
+if(this.keepData){this.data=object;}
+return object;},write:function(value,pretty){this.pretty=!!pretty;var json=null;var type=typeof value;if(this.serialize[type]){try{json=(!this.pretty&&this.nativeJSON)?JSON.stringify(value):this.serialize[type].apply(this,[value]);}catch(err){OpenLayers.Console.error("Trouble serializing: "+err);}}
+return json;},writeIndent:function(){var pieces=[];if(this.pretty){for(var i=0;i<this.level;++i){pieces.push(this.indent);}}
+return pieces.join('');},writeNewline:function(){return(this.pretty)?this.newline:'';},writeSpace:function(){return(this.pretty)?this.space:'';},serialize:{'object':function(object){if(object==null){return"null";}
+if(object.constructor==Date){return this.serialize.date.apply(this,[object]);}
+if(object.constructor==Array){return this.serialize.array.apply(this,[object]);}
+var pieces=['{'];this.level+=1;var key,keyJSON,valueJSON;var addComma=false;for(key in object){if(object.hasOwnProperty(key)){keyJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[key,this.pretty]);valueJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[object[key],this.pretty]);if(keyJSON!=null&&valueJSON!=null){if(addComma){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),keyJSON,':',this.writeSpace(),valueJSON);addComma=true;}}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),'}');return pieces.join('');},'array':function(array){var json;var pieces=['['];this.level+=1;for(var i=0,len=array.length;i<len;++i){json=OpenLayers.Format.JSON.prototype.write.apply(this,[array[i],this.pretty]);if(json!=null){if(i>0){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),json);}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),']');return pieces.join('');},'string':function(string){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};if(/["\\\x00-\x1f]/.test(string)){return'"'+string.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;}
+c=b.charCodeAt();return'\\u00'+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+string+'"';},'number':function(number){return isFinite(number)?String(number):"null";},'boolean':function(bool){return String(bool);},'date':function(date){function format(number){return(number<10)?'0'+number:number;}
+return'"'+date.getFullYear()+'-'+
+format(date.getMonth()+1)+'-'+
+format(date.getDate())+'T'+
+format(date.getHours())+':'+
+format(date.getMinutes())+':'+
+format(date.getSeconds())+'"';}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Feature=OpenLayers.Class({layer:null,id:null,lonlat:null,data:null,marker:null,popupClass:null,popup:null,initialize:function(layer,lonlat,data){this.layer=layer;this.lonlat=lonlat;this.data=(data!=null)?data:{};this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){if((this.layer!=null)&&(this.layer.map!=null)){if(this.popup!=null){this.layer.map.removePopup(this.popup);}}
+if(this.layer!=null&&this.marker!=null){this.layer.removeMarker(this.marker);}
+this.layer=null;this.id=null;this.lonlat=null;this.data=null;if(this.marker!=null){this.destroyMarker(this.marker);this.marker=null;}
+if(this.popup!=null){this.destroyPopup(this.popup);this.popup=null;}},onScreen:function(){var onScreen=false;if((this.layer!=null)&&(this.layer.map!=null)){var screenBounds=this.layer.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
+return onScreen;},createMarker:function(){if(this.lonlat!=null){this.marker=new OpenLayers.Marker(this.lonlat,this.data.icon);}
+return this.marker;},destroyMarker:function(){this.marker.destroy();},createPopup:function(closeBox){if(this.lonlat!=null){if(!this.popup){var anchor=(this.marker)?this.marker.icon:null;var popupClass=this.popupClass?this.popupClass:OpenLayers.Popup.AnchoredBubble;this.popup=new popupClass(this.id+"_popup",this.lonlat,this.data.popupSize,this.data.popupContentHTML,anchor,closeBox);}
+if(this.data.overflow!=null){this.popup.contentDiv.style.overflow=this.data.overflow;}
+this.popup.feature=this;}
+return this.popup;},destroyPopup:function(){if(this.popup){this.popup.feature=null;this.popup.destroy();this.popup=null;}},CLASS_NAME:"OpenLayers.Feature"});OpenLayers.State={UNKNOWN:'Unknown',INSERT:'Insert',UPDATE:'Update',DELETE:'Delete'};OpenLayers.Feature.Vector=OpenLayers.Class(OpenLayers.Feature,{fid:null,geometry:null,attributes:null,bounds:null,state:null,style:null,url:null,renderIntent:"default",modified:null,initialize:function(geometry,attributes,style){OpenLayers.Feature.prototype.initialize.apply(this,[null,null,attributes]);this.lonlat=null;this.geometry=geometry?geometry:null;this.state=null;this.attributes={};if(attributes){this.attributes=OpenLayers.Util.extend(this.attributes,attributes);}
+this.style=style?style:null;},destroy:function(){if(this.layer){this.layer.removeFeatures(this);this.layer=null;}
+this.geometry=null;this.modified=null;OpenLayers.Feature.prototype.destroy.apply(this,arguments);},clone:function(){return new OpenLayers.Feature.Vector(this.geometry?this.geometry.clone():null,this.attributes,this.style);},onScreen:function(boundsOnly){var onScreen=false;if(this.layer&&this.layer.map){var screenBounds=this.layer.map.getExtent();if(boundsOnly){var featureBounds=this.geometry.getBounds();onScreen=screenBounds.intersectsBounds(featureBounds);}else{var screenPoly=screenBounds.toGeometry();onScreen=screenPoly.intersects(this.geometry);}}
+return onScreen;},getVisibility:function(){return!(this.style&&this.style.display=='none'||!this.layer||this.layer&&this.layer.styleMap&&this.layer.styleMap.createSymbolizer(this,this.renderIntent).display=='none'||this.layer&&!this.layer.getVisibility());},createMarker:function(){return null;},destroyMarker:function(){},createPopup:function(){return null;},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;if(this.geometry){atPoint=this.geometry.atPoint(lonlat,toleranceLon,toleranceLat);}
+return atPoint;},destroyPopup:function(){},move:function(location){if(!this.layer||!this.geometry.move){return undefined;}
+var pixel;if(location.CLASS_NAME=="OpenLayers.LonLat"){pixel=this.layer.getViewPortPxFromLonLat(location);}else{pixel=location;}
+var lastPixel=this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());var res=this.layer.map.getResolution();this.geometry.move(res*(pixel.x-lastPixel.x),res*(lastPixel.y-pixel.y));this.layer.drawFeature(this);return lastPixel;},toState:function(state){if(state==OpenLayers.State.UPDATE){switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.DELETE:this.state=state;break;case OpenLayers.State.UPDATE:case OpenLayers.State.INSERT:break;}}else if(state==OpenLayers.State.INSERT){switch(this.state){case OpenLayers.State.UNKNOWN:break;default:this.state=state;break;}}else if(state==OpenLayers.State.DELETE){switch(this.state){case OpenLayers.State.INSERT:break;case OpenLayers.State.DELETE:break;case OpenLayers.State.UNKNOWN:case OpenLayers.State.UPDATE:this.state=state;break;}}else if(state==OpenLayers.State.UNKNOWN){this.state=state;}},CLASS_NAME:"OpenLayers.Feature.Vector"});OpenLayers.Feature.Vector.style={'default':{fillColor:"#ee9900",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#ee9900",strokeOpacity:1,strokeWidth:1,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit"},'select':{fillColor:"blue",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"blue",strokeOpacity:1,strokeWidth:2,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"pointer"},'temporary':{fillColor:"#66cccc",fillOpacity:0.2,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#66cccc",strokeOpacity:1,strokeLinecap:"round",strokeWidth:2,strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit"},'delete':{display:"none"}};OpenLayers.Format.WKT=OpenLayers.Class(OpenLayers.Format,{initialize:function(options){this.regExes={'typeStr':/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,'spaces':/\s+/,'parenComma':/\)\s*,\s*\(/,'doubleParenComma':/\)\s*\)\s*,\s*\(\s*\(/,'trimParens':/^\s*\(?(.*?)\)?\s*$/};OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(wkt){var features,type,str;wkt=wkt.replace(/[\n\r]/g," ");var matches=this.regExes.typeStr.exec(wkt);if(matches){type=matches[1].toLowerCase();str=matches[2];if(this.parse[type]){features=this.parse[type].apply(this,[str]);}
+if(this.internalProjection&&this.externalProjection){if(features&&features.CLASS_NAME=="OpenLayers.Feature.Vector"){features.geometry.transform(this.externalProjection,this.internalProjection);}else if(features&&type!="geometrycollection"&&typeof features=="object"){for(var i=0,len=features.length;i<len;i++){var component=features[i];component.geometry.transform(this.externalProjection,this.internalProjection);}}}}
+return features;},write:function(features){var collection,geometry,type,data,isCollection;if(features.constructor==Array){collection=features;isCollection=true;}else{collection=[features];isCollection=false;}
+var pieces=[];if(isCollection){pieces.push('GEOMETRYCOLLECTION(');}
+for(var i=0,len=collection.length;i<len;++i){if(isCollection&&i>0){pieces.push(',');}
+geometry=collection[i].geometry;pieces.push(this.extractGeometry(geometry));}
+if(isCollection){pieces.push(')');}
+return pieces.join('');},extractGeometry:function(geometry){var type=geometry.CLASS_NAME.split('.')[2].toLowerCase();if(!this.extract[type]){return null;}
+if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var wktType=type=='collection'?'GEOMETRYCOLLECTION':type.toUpperCase();var data=wktType+'('+this.extract[type].apply(this,[geometry])+')';return data;},extract:{'point':function(point){return point.x+' '+point.y;},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push('('+
+this.extract.point.apply(this,[multipoint.components[i]])+')');}
+return array.join(',');},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
+return array.join(',');},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push('('+
+this.extract.linestring.apply(this,[multilinestring.components[i]])+')');}
+return array.join(',');},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push('('+
+this.extract.linestring.apply(this,[polygon.components[i]])+')');}
+return array.join(',');},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push('('+
+this.extract.polygon.apply(this,[multipolygon.components[i]])+')');}
+return array.join(',');},'collection':function(collection){var array=[];for(var i=0,len=collection.components.length;i<len;++i){array.push(this.extractGeometry.apply(this,[collection.components[i]]));}
+return array.join(',');}},parse:{'point':function(str){var coords=OpenLayers.String.trim(str).split(this.regExes.spaces);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(coords[0],coords[1]));},'multipoint':function(str){var point;var points=OpenLayers.String.trim(str).split(',');var components=[];for(var i=0,len=points.length;i<len;++i){point=points[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.point.apply(this,[point]).geometry);}
+return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPoint(components));},'linestring':function(str){var points=OpenLayers.String.trim(str).split(',');var components=[];for(var i=0,len=points.length;i<len;++i){components.push(this.parse.point.apply(this,[points[i]]).geometry);}
+return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(components));},'multilinestring':function(str){var line;var lines=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=lines.length;i<len;++i){line=lines[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.linestring.apply(this,[line]).geometry);}
+return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiLineString(components));},'polygon':function(str){var ring,linestring,linearring;var rings=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=rings.length;i<len;++i){ring=rings[i].replace(this.regExes.trimParens,'$1');linestring=this.parse.linestring.apply(this,[ring]).geometry;linearring=new OpenLayers.Geometry.LinearRing(linestring.components);components.push(linearring);}
+return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon(components));},'multipolygon':function(str){var polygon;var polygons=OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);var components=[];for(var i=0,len=polygons.length;i<len;++i){polygon=polygons[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.polygon.apply(this,[polygon]).geometry);}
+return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(components));},'geometrycollection':function(str){str=str.replace(/,\s*([A-Za-z])/g,'|$1');var wktArray=OpenLayers.String.trim(str).split('|');var components=[];for(var i=0,len=wktArray.length;i<len;++i){components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));}
+return components;}},CLASS_NAME:"OpenLayers.Format.WKT"});OpenLayers.Protocol.SQL.Gears=OpenLayers.Class(OpenLayers.Protocol.SQL,{FID_PREFIX:'__gears_fid__',NULL_GEOMETRY:'__gears_null_geometry__',NULL_FEATURE_STATE:'__gears_null_feature_state__',jsonParser:null,wktParser:null,fidRegExp:null,saveFeatureState:true,typeOfFid:"string",db:null,initialize:function(options){if(!this.supported()){return;}
+OpenLayers.Protocol.SQL.prototype.initialize.apply(this,[options]);this.jsonParser=new OpenLayers.Format.JSON();this.wktParser=new OpenLayers.Format.WKT();this.fidRegExp=new RegExp('^'+this.FID_PREFIX);this.initializeDatabase();},initializeDatabase:function(){this.db=google.gears.factory.create('beta.database');this.db.open(this.databaseName);this.db.execute("CREATE TABLE IF NOT EXISTS "+this.tableName+" (fid TEXT UNIQUE, geometry TEXT, properties TEXT,"+"  state TEXT)");},destroy:function(){this.db.close();this.db=null;this.jsonParser=null;this.wktParser=null;OpenLayers.Protocol.SQL.prototype.destroy.apply(this);},supported:function(){return!!(window.google&&google.gears);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);var feature,features=[];var rs=this.db.execute("SELECT * FROM "+this.tableName);while(rs.isValidRow()){feature=this.unfreezeFeature(rs);if(this.evaluateFilter(feature,options.filter)){if(!options.noFeatureStateReset){feature.state=null;}
+features.push(feature);}
+rs.next();}
+rs.close();var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"read",features:features});if(options&&options.callback){options.callback.call(options.scope,resp);}
+return resp;},unfreezeFeature:function(row){var feature;var wkt=row.fieldByName('geometry');if(wkt==this.NULL_GEOMETRY){feature=new OpenLayers.Feature.Vector();}else{feature=this.wktParser.read(wkt);}
+feature.attributes=this.jsonParser.read(row.fieldByName('properties'));feature.fid=this.extractFidFromField(row.fieldByName('fid'));var state=row.fieldByName('state');if(state==this.NULL_FEATURE_STATE){state=null;}
+feature.state=state;return feature;},extractFidFromField:function(field){if(!field.match(this.fidRegExp)&&this.typeOfFid=="number"){field=parseFloat(field);}
+return field;},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="create";if(options&&options.callback){options.callback.call(options.scope,resp);}
+return resp;},update:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="update";if(options&&options.callback){options.callback.call(options.scope,resp);}
+return resp;},createOrUpdate:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var i,len=features.length,feature;var insertedFeatures=new Array(len);for(i=0;i<len;i++){feature=features[i];var params=this.freezeFeature(feature);this.db.execute("REPLACE INTO "+this.tableName+" (fid, geometry, properties, state)"+" VALUES (?, ?, ?, ?)",params);var clone=feature.clone();clone.fid=this.extractFidFromField(params[0]);insertedFeatures[i]=clone;}
+return new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,features:insertedFeatures,reqFeatures:features});},freezeFeature:function(feature){feature.fid=feature.fid!=null?""+feature.fid:OpenLayers.Util.createUniqueID(this.FID_PREFIX);var geometry=feature.geometry!=null?feature.geometry.toString():this.NULL_GEOMETRY;var properties=this.jsonParser.write(feature.attributes);var state=this.getFeatureStateForFreeze(feature);return[feature.fid,geometry,properties,state];},getFeatureStateForFreeze:function(feature){var state;if(!this.saveFeatureState){state=this.NULL_FEATURE_STATE;}else if(this.createdOffline(feature)){state=OpenLayers.State.INSERT;}else{state=feature.state;}
+return state;},"delete":function(features,options){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+options=OpenLayers.Util.applyDefaults(options,this.options);var i,len,feature;for(i=0,len=features.length;i<len;i++){feature=features[i];if(this.saveFeatureState&&!this.createdOffline(feature)){var toDelete=feature.clone();toDelete.fid=feature.fid;if(toDelete.geometry){toDelete.geometry.destroy();toDelete.geometry=null;}
+toDelete.state=feature.state;this.createOrUpdate(toDelete);}else{this.db.execute("DELETE FROM "+this.tableName+" WHERE fid = ?",[feature.fid]);}}
+var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"delete",reqFeatures:features});if(options&&options.callback){options.callback.call(options.scope,resp);}
+return resp;},createdOffline:function(feature){return(typeof feature.fid=="string"&&!!(feature.fid.match(this.fidRegExp)));},commit:function(features,options){var opt,resp=[],nRequests=0,nResponses=0;function callback(resp){if(++nResponses<nRequests){resp.last=false;}
+this.callUserCallback(options,resp);}
+var feature,toCreate=[],toUpdate=[],toDelete=[];for(var i=features.length-1;i>=0;i--){feature=features[i];switch(feature.state){case OpenLayers.State.INSERT:toCreate.push(feature);break;case OpenLayers.State.UPDATE:toUpdate.push(feature);break;case OpenLayers.State.DELETE:toDelete.push(feature);break;}}
+if(toCreate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.create);resp.push(this.create(toCreate,opt));}
+if(toUpdate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.update);resp.push(this.update(toUpdate,opt));}
+if(toDelete.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options["delete"]);resp.push(this["delete"](toDelete,opt));}
+return resp;},clear:function(){this.db.execute("DELETE FROM "+this.tableName);},callUserCallback:function(options,resp){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}
+if(resp.last&&options.callback){options.callback.call(options.scope);}},CLASS_NAME:"OpenLayers.Protocol.SQL.Gears"});OpenLayers.Format.CSWGetRecords=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetRecords.DEFAULTS);var cls=OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetRecords version: "+options.version;}
+return new cls(options);};OpenLayers.Format.CSWGetRecords.DEFAULTS={"version":"2.0.2"};OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:false,displayClass:"",title:"",autoActivate:false,active:null,handler:null,eventListeners:null,events:null,EVENT_TYPES:["activate","deactivate"],initialize:function(options){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,options);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
+if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}},destroy:function(){if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
+this.events.destroy();this.events=null;}
+this.eventListeners=null;if(this.handler){this.handler.destroy();this.handler=null;}
+if(this.handlers){for(var key in this.handlers){if(this.handlers.hasOwnProperty(key)&&typeof this.handlers[key].destroy=="function"){this.handlers[key].destroy();}}
+this.handlers=null;}
+if(this.map){this.map.removeControl(this);this.map=null;}
+this.div=null;},setMap:function(map){this.map=map;if(this.handler){this.handler.setMap(map);}},draw:function(px){if(this.div==null){this.div=OpenLayers.Util.createDiv(this.id);this.div.className=this.displayClass;if(!this.allowSelection){this.div.className+=" olControlNoSelect";this.div.setAttribute("unselectable","on",0);this.div.onselectstart=OpenLayers.Function.False;}
+if(this.title!=""){this.div.title=this.title;}}
+if(px!=null){this.position=px.clone();}
+this.moveTo(this.position);return this.div;},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},activate:function(){if(this.active){return false;}
+if(this.handler){this.handler.activate();}
+this.active=true;if(this.map){OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
+this.events.triggerEvent("activate");return true;},deactivate:function(){if(this.active){if(this.handler){this.handler.deactivate();}
+this.active=false;if(this.map){OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
+this.events.triggerEvent("deactivate");return true;}
+return false;},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Event={observers:false,KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(event){return event.target||event.srcElement;},isSingleTouch:function(event){return event.touches&&event.touches.length==1;},isMultiTouch:function(event){return event.touches&&event.touches.length>1;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},isRightClick:function(event){return(((event.which)&&(event.which==3))||((event.button)&&(event.button==2)));},stop:function(event,allowDefault){if(!allowDefault){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}}
+if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble=true;}},findElement:function(event,tagName){var element=OpenLayers.Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){element=element.parentNode;}
+return element;},observe:function(elementParam,name,observer,useCapture){var element=OpenLayers.Util.getElement(elementParam);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){name='keydown';}
+if(!this.observers){this.observers={};}
+if(!element._eventCacheID){var idPrefix="eventCacheID_";if(element.id){idPrefix=element.id+"_"+idPrefix;}
+element._eventCacheID=OpenLayers.Util.createUniqueID(idPrefix);}
+var cacheID=element._eventCacheID;if(!this.observers[cacheID]){this.observers[cacheID]=[];}
+this.observers[cacheID].push({'element':element,'name':name,'observer':observer,'useCapture':useCapture});if(element.addEventListener){element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}},stopObservingElement:function(elementParam){var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[cacheID]);},_removeElementObservers:function(elementObservers){if(elementObservers){for(var i=elementObservers.length-1;i>=0;i--){var entry=elementObservers[i];var args=new Array(entry.element,entry.name,entry.observer,entry.useCapture);var removed=OpenLayers.Event.stopObserving.apply(this,args);}}},stopObserving:function(elementParam,name,observer,useCapture){useCapture=useCapture||false;var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;if(name=='keypress'){if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent){name='keydown';}}
+var foundEntry=false;var elementObservers=OpenLayers.Event.observers[cacheID];if(elementObservers){var i=0;while(!foundEntry&&i<elementObservers.length){var cacheEntry=elementObservers[i];if((cacheEntry.name==name)&&(cacheEntry.observer==observer)&&(cacheEntry.useCapture==useCapture)){elementObservers.splice(i,1);if(elementObservers.length==0){delete OpenLayers.Event.observers[cacheID];}
+foundEntry=true;break;}
+i++;}}
+if(foundEntry){if(element.removeEventListener){element.removeEventListener(name,observer,useCapture);}else if(element&&element.detachEvent){element.detachEvent('on'+name,observer);}}
+return foundEntry;},unloadCache:function(){if(OpenLayers.Event&&OpenLayers.Event.observers){for(var cacheID in OpenLayers.Event.observers){var elementObservers=OpenLayers.Event.observers[cacheID];OpenLayers.Event._removeElementObservers.apply(this,[elementObservers]);}
+OpenLayers.Event.observers=false;}},CLASS_NAME:"OpenLayers.Event"};OpenLayers.Event.observe(window,'unload',OpenLayers.Event.unloadCache,false);if(window.Event){OpenLayers.Util.applyDefaults(window.Event,OpenLayers.Event);}else{var Event=OpenLayers.Event;}
+OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:["mouseover","mouseout","mousedown","mouseup","mousemove","click","dblclick","rightclick","dblrightclick","resize","focus","blur","touchstart","touchmove","touchend"],listeners:null,object:null,element:null,eventTypes:null,eventHandler:null,fallThrough:null,includeXY:false,clearMouseListener:null,initialize:function(object,element,eventTypes,fallThrough,options){OpenLayers.Util.extend(this,options);this.object=object;this.fallThrough=fallThrough;this.listeners={};this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this);this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this);this.eventTypes=[];if(eventTypes!=null){for(var i=0,len=eventTypes.length;i<len;i++){this.addEventType(eventTypes[i]);}}
+if(element!=null){this.attachToElement(element);}},destroy:function(){if(this.element){OpenLayers.Event.stopObservingElement(this.element);if(this.element.hasScrollEvent){OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener);}}
+this.element=null;this.listeners=null;this.object=null;this.eventTypes=null;this.fallThrough=null;this.eventHandler=null;},addEventType:function(eventName){if(!this.listeners[eventName]){this.eventTypes.push(eventName);this.listeners[eventName]=[];}},attachToElement:function(element){if(this.element){OpenLayers.Event.stopObservingElement(this.element);}
+this.element=element;for(var i=0,len=this.BROWSER_EVENTS.length;i<len;i++){var eventType=this.BROWSER_EVENTS[i];this.addEventType(eventType);OpenLayers.Event.observe(element,eventType,this.eventHandler);}
+OpenLayers.Event.observe(element,"dragstart",OpenLayers.Event.stop);},on:function(object){for(var type in object){if(type!="scope"){this.register(type,object.scope,object[type]);}}},register:function(type,obj,func){if((func!=null)&&(OpenLayers.Util.indexOf(this.eventTypes,type)!=-1)){if(obj==null){obj=this.object;}
+var listeners=this.listeners[type];listeners.push({obj:obj,func:func});}},registerPriority:function(type,obj,func){if(func!=null){if(obj==null){obj=this.object;}
+var listeners=this.listeners[type];if(listeners!=null){listeners.unshift({obj:obj,func:func});}}},un:function(object){for(var type in object){if(type!="scope"){this.unregister(type,object.scope,object[type]);}}},unregister:function(type,obj,func){if(obj==null){obj=this.object;}
+var listeners=this.listeners[type];if(listeners!=null){for(var i=0,len=listeners.length;i<len;i++){if(listeners[i].obj==obj&&listeners[i].func==func){listeners.splice(i,1);break;}}}},remove:function(type){if(this.listeners[type]!=null){this.listeners[type]=[];}},triggerEvent:function(type,evt){var listeners=this.listeners[type];if(!listeners||listeners.length==0){return undefined;}
+if(evt==null){evt={};}
+evt.object=this.object;evt.element=this.element;if(!evt.type){evt.type=type;}
+listeners=listeners.slice();var continueChain;for(var i=0,len=listeners.length;i<len;i++){var callback=listeners[i];continueChain=callback.func.apply(callback.obj,[evt]);if((continueChain!=undefined)&&(continueChain==false)){break;}}
+if(!this.fallThrough){OpenLayers.Event.stop(evt,true);}
+return continueChain;},handleBrowserEvent:function(evt){var type=evt.type,listeners=this.listeners[type];if(!listeners||listeners.length==0){return;}
+var touches=evt.touches;if(touches&&touches[0]){var x=0;var y=0;var num=touches.length;var touch;for(var i=0;i<num;++i){touch=touches[i];x+=touch.clientX;y+=touch.clientY;}
+evt.clientX=x/num;evt.clientY=y/num;}
+if(this.includeXY){evt.xy=this.getMousePosition(evt);}
+this.triggerEvent(type,evt);},clearMouseCache:function(){this.element.scrolls=null;this.element.lefttop=null;var body=document.body;if(body&&!((body.scrollTop!=0||body.scrollLeft!=0)&&navigator.userAgent.match(/iPhone/i))){this.element.offsets=null;}},getMousePosition:function(evt){if(!this.includeXY){this.clearMouseCache();}else if(!this.element.hasScrollEvent){OpenLayers.Event.observe(window,"scroll",this.clearMouseListener);this.element.hasScrollEvent=true;}
+if(!this.element.scrolls){var viewportElement=OpenLayers.Util.getViewportElement();this.element.scrolls=[viewportElement.scrollLeft,viewportElement.scrollTop];}
+if(!this.element.lefttop){this.element.lefttop=[(document.documentElement.clientLeft||0),(document.documentElement.clientTop||0)];}
+if(!this.element.offsets){this.element.offsets=OpenLayers.Util.pagePosition(this.element);}
+return new OpenLayers.Pixel((evt.clientX+this.element.scrolls[0])-this.element.offsets[0]
+-this.element.lefttop[0],(evt.clientY+this.element.scrolls[1])-this.element.offsets[1]
+-this.element.lefttop[1]);},CLASS_NAME:"OpenLayers.Events"});OpenLayers.Control.OverviewMap=OpenLayers.Class(OpenLayers.Control,{element:null,ovmap:null,size:new OpenLayers.Size(180,90),layers:null,minRectSize:15,minRectDisplayClass:"RectReplacement",minRatio:8,maxRatio:32,mapOptions:null,autoPan:false,handlers:null,resolutionFactor:1,maximized:false,initialize:function(options){this.layers=[];this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,[options]);},destroy:function(){if(!this.mapDiv){return;}
+if(this.handlers.click){this.handlers.click.destroy();}
+if(this.handlers.drag){this.handlers.drag.destroy();}
+this.ovmap&&this.ovmap.eventsDiv.removeChild(this.extentRectangle);this.extentRectangle=null;if(this.rectEvents){this.rectEvents.destroy();this.rectEvents=null;}
+if(this.ovmap){this.ovmap.destroy();this.ovmap=null;}
+this.element.removeChild(this.mapDiv);this.mapDiv=null;this.div.removeChild(this.element);this.element=null;if(this.maximizeDiv){OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.div.removeChild(this.maximizeDiv);this.maximizeDiv=null;}
+if(this.minimizeDiv){OpenLayers.Event.stopObservingElement(this.minimizeDiv);this.div.removeChild(this.minimizeDiv);this.minimizeDiv=null;}
+this.map.events.un({"moveend":this.update,"changebaselayer":this.baseLayerDraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!(this.layers.length>0)){if(this.map.baseLayer){var layer=this.map.baseLayer.clone();this.layers=[layer];}else{this.map.events.register("changebaselayer",this,this.baseLayerDraw);return this.div;}}
+this.element=document.createElement('div');this.element.className=this.displayClass+'Element';this.element.style.display='none';this.mapDiv=document.createElement('div');this.mapDiv.style.width=this.size.w+'px';this.mapDiv.style.height=this.size.h+'px';this.mapDiv.style.position='relative';this.mapDiv.style.overflow='hidden';this.mapDiv.id=OpenLayers.Util.createUniqueID('overviewMap');this.extentRectangle=document.createElement('div');this.extentRectangle.style.position='absolute';this.extentRectangle.style.zIndex=1000;this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.element.appendChild(this.mapDiv);this.div.appendChild(this.element);if(!this.outsideViewport){this.div.className+=" "+this.displayClass+'Container';var imgLocation=OpenLayers.Util.getImagesLocation();var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv(this.displayClass+'MaximizeButton',null,new OpenLayers.Size(18,18),img,'absolute');this.maximizeDiv.style.display='none';this.maximizeDiv.className=this.displayClass+'MaximizeButton';OpenLayers.Event.observe(this.maximizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv('OpenLayers_Control_minimizeDiv',null,new OpenLayers.Size(18,18),img,'absolute');this.minimizeDiv.style.display='none';this.minimizeDiv.className=this.displayClass+'MinimizeButton';OpenLayers.Event.observe(this.minimizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);var eventsToStop=['dblclick','mousedown'];for(var i=0,len=eventsToStop.length;i<len;i++){OpenLayers.Event.observe(this.maximizeDiv,eventsToStop[i],OpenLayers.Event.stop);OpenLayers.Event.observe(this.minimizeDiv,eventsToStop[i],OpenLayers.Event.stop);}
+this.minimizeControl();}else{this.element.style.display='';}
+if(this.map.getExtent()){this.update();}
+this.map.events.register('moveend',this,this.update);if(this.maximized){this.maximizeControl();}
+return this.div;},baseLayerDraw:function(){this.draw();this.map.events.unregister("changebaselayer",this,this.baseLayerDraw);},rectDrag:function(px){var deltaX=this.handlers.drag.last.x-px.x;var deltaY=this.handlers.drag.last.y-px.y;if(deltaX!=0||deltaY!=0){var rectTop=this.rectPxBounds.top;var rectLeft=this.rectPxBounds.left;var rectHeight=Math.abs(this.rectPxBounds.getHeight());var rectWidth=this.rectPxBounds.getWidth();var newTop=Math.max(0,(rectTop-deltaY));newTop=Math.min(newTop,this.ovmap.size.h-this.hComp-rectHeight);var newLeft=Math.max(0,(rectLeft-deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-this.wComp-rectWidth);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+rectHeight,newLeft+rectWidth,newTop));}},mapDivClick:function(evt){var pxCenter=this.rectPxBounds.getCenterPixel();var deltaX=evt.xy.x-pxCenter.x;var deltaY=evt.xy.y-pxCenter.y;var top=this.rectPxBounds.top;var left=this.rectPxBounds.left;var height=Math.abs(this.rectPxBounds.getHeight());var width=this.rectPxBounds.getWidth();var newTop=Math.max(0,(top+deltaY));newTop=Math.min(newTop,this.ovmap.size.h-height);var newLeft=Math.max(0,(left+deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-width);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+height,newLeft+width,newTop));this.updateMapToRect();},maximizeControl:function(e){this.element.style.display='';this.showToggle(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.element.style.display='none';this.showToggle(true);if(e!=null){OpenLayers.Event.stop(e);}},showToggle:function(minimize){this.maximizeDiv.style.display=minimize?'':'none';this.minimizeDiv.style.display=minimize?'none':'';},update:function(){if(this.ovmap==null){this.createMap();}
+if(this.autoPan||!this.isSuitableOverview()){this.updateOverview();}
+this.updateRectToMap();},isSuitableOverview:function(){var mapExtent=this.map.getExtent();var maxExtent=this.map.maxExtent;var testExtent=new OpenLayers.Bounds(Math.max(mapExtent.left,maxExtent.left),Math.max(mapExtent.bottom,maxExtent.bottom),Math.min(mapExtent.right,maxExtent.right),Math.min(mapExtent.top,maxExtent.top));if(this.ovmap.getProjection()!=this.map.getProjection()){testExtent=testExtent.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}
+var resRatio=this.ovmap.getResolution()/this.map.getResolution();return((resRatio>this.minRatio)&&(resRatio<=this.maxRatio)&&(this.ovmap.getExtent().containsBounds(testExtent)));},updateOverview:function(){var mapRes=this.map.getResolution();var targetRes=this.ovmap.getResolution();var resRatio=targetRes/mapRes;if(resRatio>this.maxRatio){targetRes=this.minRatio*mapRes;}else if(resRatio<=this.minRatio){targetRes=this.maxRatio*mapRes;}
+var center;if(this.ovmap.getProjection()!=this.map.getProjection()){center=this.map.center.clone();center.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{center=this.map.center;}
+this.ovmap.setCenter(center,this.ovmap.getZoomForResolution(targetRes*this.resolutionFactor));this.updateRectToMap();},createMap:function(){var options=OpenLayers.Util.extend({controls:[],maxResolution:'auto',fallThrough:false},this.mapOptions);this.ovmap=new OpenLayers.Map(this.mapDiv,options);this.ovmap.eventsDiv.appendChild(this.extentRectangle);OpenLayers.Event.stopObserving(window,'unload',this.ovmap.unloadDestroy);this.ovmap.addLayers(this.layers);this.ovmap.zoomToMaxExtent();this.wComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-left-width'))+
+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-right-width'));this.wComp=(this.wComp)?this.wComp:2;this.hComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-top-width'))+
+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-bottom-width'));this.hComp=(this.hComp)?this.hComp:2;this.handlers.drag=new OpenLayers.Handler.Drag(this,{move:this.rectDrag,done:this.updateMapToRect},{map:this.ovmap});this.handlers.click=new OpenLayers.Handler.Click(this,{"click":this.mapDivClick},{"single":true,"double":false,"stopSingle":true,"stopDouble":true,"pixelTolerance":1,map:this.ovmap});this.handlers.click.activate();this.rectEvents=new OpenLayers.Events(this,this.extentRectangle,null,true);this.rectEvents.register("mouseover",this,function(e){if(!this.handlers.drag.active&&!this.map.dragging){this.handlers.drag.activate();}});this.rectEvents.register("mouseout",this,function(e){if(!this.handlers.drag.dragging){this.handlers.drag.deactivate();}});if(this.ovmap.getProjection()!=this.map.getProjection()){var sourceUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var targetUnits=this.ovmap.getProjectionObject().getUnits()||this.ovmap.units||this.ovmap.baseLayer.units;this.resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;}},updateRectToMap:function(){var bounds;if(this.ovmap.getProjection()!=this.map.getProjection()){bounds=this.map.getExtent().transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{bounds=this.map.getExtent();}
+var pxBounds=this.getRectBoundsFromMapBounds(bounds);if(pxBounds){this.setRectPxBounds(pxBounds);}},updateMapToRect:function(){var lonLatBounds=this.getMapBoundsFromRectBounds(this.rectPxBounds);if(this.ovmap.getProjection()!=this.map.getProjection()){lonLatBounds=lonLatBounds.transform(this.ovmap.getProjectionObject(),this.map.getProjectionObject());}
+this.map.panTo(lonLatBounds.getCenterLonLat());},setRectPxBounds:function(pxBounds){var top=Math.max(pxBounds.top,0);var left=Math.max(pxBounds.left,0);var bottom=Math.min(pxBounds.top+Math.abs(pxBounds.getHeight()),this.ovmap.size.h-this.hComp);var right=Math.min(pxBounds.left+pxBounds.getWidth(),this.ovmap.size.w-this.wComp);var width=Math.max(right-left,0);var height=Math.max(bottom-top,0);if(width<this.minRectSize||height<this.minRectSize){this.extentRectangle.className=this.displayClass+
+this.minRectDisplayClass;var rLeft=left+(width/2)-(this.minRectSize/2);var rTop=top+(height/2)-(this.minRectSize/2);this.extentRectangle.style.top=Math.round(rTop)+'px';this.extentRectangle.style.left=Math.round(rLeft)+'px';this.extentRectangle.style.height=this.minRectSize+'px';this.extentRectangle.style.width=this.minRectSize+'px';}else{this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.extentRectangle.style.top=Math.round(top)+'px';this.extentRectangle.style.left=Math.round(left)+'px';this.extentRectangle.style.height=Math.round(height)+'px';this.extentRectangle.style.width=Math.round(width)+'px';}
+this.rectPxBounds=new OpenLayers.Bounds(Math.round(left),Math.round(bottom),Math.round(right),Math.round(top));},getRectBoundsFromMapBounds:function(lonLatBounds){var leftBottomLonLat=new OpenLayers.LonLat(lonLatBounds.left,lonLatBounds.bottom);var rightTopLonLat=new OpenLayers.LonLat(lonLatBounds.right,lonLatBounds.top);var leftBottomPx=this.getOverviewPxFromLonLat(leftBottomLonLat);var rightTopPx=this.getOverviewPxFromLonLat(rightTopLonLat);var bounds=null;if(leftBottomPx&&rightTopPx){bounds=new OpenLayers.Bounds(leftBottomPx.x,leftBottomPx.y,rightTopPx.x,rightTopPx.y);}
+return bounds;},getMapBoundsFromRectBounds:function(pxBounds){var leftBottomPx=new OpenLayers.Pixel(pxBounds.left,pxBounds.bottom);var rightTopPx=new OpenLayers.Pixel(pxBounds.right,pxBounds.top);var leftBottomLonLat=this.getLonLatFromOverviewPx(leftBottomPx);var rightTopLonLat=this.getLonLatFromOverviewPx(rightTopPx);return new OpenLayers.Bounds(leftBottomLonLat.lon,leftBottomLonLat.lat,rightTopLonLat.lon,rightTopLonLat.lat);},getLonLatFromOverviewPx:function(overviewMapPx){var size=this.ovmap.size;var res=this.ovmap.getResolution();var center=this.ovmap.getExtent().getCenterLonLat();var delta_x=overviewMapPx.x-(size.w/2);var delta_y=overviewMapPx.y-(size.h/2);return new OpenLayers.LonLat(center.lon+delta_x*res,center.lat-delta_y*res);},getOverviewPxFromLonLat:function(lonlat){var res=this.ovmap.getResolution();var extent=this.ovmap.getExtent();var px=null;if(extent){px=new OpenLayers.Pixel(Math.round(1/res*(lonlat.lon-extent.left)),Math.round(1/res*(extent.top-lonlat.lat)));}
+return px;},CLASS_NAME:'OpenLayers.Control.OverviewMap'});OpenLayers.Tween=OpenLayers.Class({INTERVAL:10,easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,interval:null,playing:false,initialize:function(easing){this.easing=(easing)?easing:OpenLayers.Easing.Expo.easeOut;},start:function(begin,finish,duration,options){this.playing=true;this.begin=begin;this.finish=finish;this.duration=duration;this.callbacks=options.callbacks;this.time=0;if(this.interval){window.clearInterval(this.interval);this.interval=null;}
+if(this.callbacks&&this.callbacks.start){this.callbacks.start.call(this,this.begin);}
+this.interval=window.setInterval(OpenLayers.Function.bind(this.play,this),this.INTERVAL);},stop:function(){if(!this.playing){return;}
+if(this.callbacks&&this.callbacks.done){this.callbacks.done.call(this,this.finish);}
+window.clearInterval(this.interval);this.interval=null;this.playing=false;},play:function(){var value={};for(var i in this.begin){var b=this.begin[i];var f=this.finish[i];if(b==null||f==null||isNaN(b)||isNaN(f)){OpenLayers.Console.error('invalid value for Tween');}
+var c=f-b;value[i]=this.easing.apply(this,[this.time,b,c,this.duration]);}
+this.time++;if(this.callbacks&&this.callbacks.eachStep){this.callbacks.eachStep.call(this,value);}
+if(this.time>this.duration){this.stop();}},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(t,b,c,d){return c*t/d+b;},easeOut:function(t,b,c,d){return c*t/d+b;},easeInOut:function(t,b,c,d){return c*t/d+b;},CLASS_NAME:"OpenLayers.Easing.Linear"};OpenLayers.Easing.Expo={easeIn:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOut:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOut:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},CLASS_NAME:"OpenLayers.Easing.Expo"};OpenLayers.Easing.Quad={easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOut:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1000},EVENT_TYPES:["preaddlayer","addlayer","preremovelayer","removelayer","changelayer","movestart","move","moveend","zoomend","popupopen","popupclose","addmarker","removemarker","clearmarkers","mouseover","mouseout","mousemove","dragstart","drag","dragend","changebaselayer"],id:null,fractionalZoom:false,events:null,allOverlays:false,div:null,dragging:false,size:null,viewPortDiv:null,layerContainerOrigin:null,layerContainerDiv:null,layers:null,controls:null,popups:null,baseLayer:null,center:null,resolution:null,zoom:0,panRatio:1.5,viewRequestID:0,tileSize:null,projection:"EPSG:4326",units:'degrees',resolutions:null,maxResolution:1.40625,minResolution:null,maxScale:null,minScale:null,maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:true,panTween:null,eventListeners:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,paddingForPopups:null,minPx:null,maxPx:null,initialize:function(div,options){if(arguments.length===1&&typeof div==="object"){options=div;div=options&&options.div;}
+this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,OpenLayers.Map.TILE_HEIGHT);this.maxExtent=new OpenLayers.Bounds(-180,-90,180,90);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()+'theme/default/style.css';OpenLayers.Util.extend(this,options);this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(div);if(!this.div){this.div=document.createElement("div");this.div.style.height="1px";this.div.style.width="1px";}
+OpenLayers.Element.addClass(this.div,'olMap');var id=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(id,null,null,null,"relative",null,"hidden");this.viewPortDiv.style.width="100%";this.viewPortDiv.style.height="100%";this.viewPortDiv.className="olMapViewport";this.div.appendChild(this.viewPortDiv);var eventsDiv=document.createElement("div");eventsDiv.id=this.id+"_events";eventsDiv.style.position="absolute";eventsDiv.style.width="100%";eventsDiv.style.height="100%";eventsDiv.style.zIndex=this.Z_INDEX_BASE.Control-1;this.viewPortDiv.appendChild(eventsDiv);this.eventsDiv=eventsDiv;this.events=new OpenLayers.Events(this,this.eventsDiv,this.EVENT_TYPES,this.fallThrough,{includeXY:true});id=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(id);this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;this.eventsDiv.appendChild(this.layerContainerDiv);this.updateSize();if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
+this.events.register("movestart",this,this.updateSize);if(OpenLayers.String.contains(navigator.appName,"Microsoft")){this.events.register("resize",this,this.updateSize);}else{this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this);OpenLayers.Event.observe(window,'resize',this.updateSizeDestroy);}
+if(this.theme){var addNode=true;var nodes=document.getElementsByTagName('link');for(var i=0,len=nodes.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,this.theme)){addNode=false;break;}}
+if(addNode){var cssNode=document.createElement('link');cssNode.setAttribute('rel','stylesheet');cssNode.setAttribute('type','text/css');cssNode.setAttribute('href',this.theme);document.getElementsByTagName('head')[0].appendChild(cssNode);}}
+if(this.controls==null){if(OpenLayers.Control!=null){this.controls=[new OpenLayers.Control.Navigation(),new OpenLayers.Control.PanZoom(),new OpenLayers.Control.ArgParser(),new OpenLayers.Control.Attribution()];}else{this.controls=[];}}
+for(var i=0,len=this.controls.length;i<len;i++){this.addControlToMap(this.controls[i]);}
+this.popups=[];this.unloadDestroy=OpenLayers.Function.bind(this.destroy,this);OpenLayers.Event.observe(window,'unload',this.unloadDestroy);if(options&&options.layers){delete this.center;this.addLayers(options.layers);if(options.center){this.setCenter(options.center,options.zoom);}}},render:function(div){this.div=OpenLayers.Util.getElement(div);OpenLayers.Element.addClass(this.div,'olMap');this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);this.div.appendChild(this.viewPortDiv);this.updateSize();},unloadDestroy:null,updateSizeDestroy:null,destroy:function(){if(!this.unloadDestroy){return false;}
+if(this.panTween){this.panTween.stop();this.panTween=null;}
+OpenLayers.Event.stopObserving(window,'unload',this.unloadDestroy);this.unloadDestroy=null;if(this.updateSizeDestroy){OpenLayers.Event.stopObserving(window,'resize',this.updateSizeDestroy);}else{this.events.unregister("resize",this,this.updateSize);}
+this.paddingForPopups=null;if(this.controls!=null){for(var i=this.controls.length-1;i>=0;--i){this.controls[i].destroy();}
+this.controls=null;}
+if(this.layers!=null){for(var i=this.layers.length-1;i>=0;--i){this.layers[i].destroy(false);}
+this.layers=null;}
+if(this.viewPortDiv){this.div.removeChild(this.viewPortDiv);}
+this.viewPortDiv=null;if(this.eventListeners){this.events.un(this.eventListeners);this.eventListeners=null;}
+this.events.destroy();this.events=null;},setOptions:function(options){var updatePxExtent=this.minPx&&options.restrictedExtent!=this.restrictedExtent;OpenLayers.Util.extend(this,options);updatePxExtent&&this.moveTo(this.getCachedCenter(),this.zoom,{forceZoomChange:true});},getTileSize:function(){return this.tileSize;},getBy:function(array,property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this[array],function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getLayersBy:function(property,match){return this.getBy("layers",property,match);},getLayersByName:function(match){return this.getLayersBy("name",match);},getLayersByClass:function(match){return this.getLayersBy("CLASS_NAME",match);},getControlsBy:function(property,match){return this.getBy("controls",property,match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},getLayer:function(id){var foundLayer=null;for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer.id==id){foundLayer=layer;break;}}
+return foundLayer;},setLayerZIndex:function(layer,zIdx){layer.setZIndex(this.Z_INDEX_BASE[layer.isBaseLayer?'BaseLayer':'Overlay']
++zIdx*5);},resetLayersZIndex:function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];this.setLayerZIndex(layer,i);}},addLayer:function(layer){for(var i=0,len=this.layers.length;i<len;i++){if(this.layers[i]==layer){var msg=OpenLayers.i18n('layerAlreadyAdded',{'layerName':layer.name});OpenLayers.Console.warn(msg);return false;}}
+if(this.events.triggerEvent("preaddlayer",{layer:layer})===false){return;}
+if(this.allOverlays){layer.isBaseLayer=false;}
+layer.div.className="olLayerDiv";layer.div.style.overflow="";this.setLayerZIndex(layer,this.layers.length);if(layer.isFixed){this.viewPortDiv.appendChild(layer.div);}else{this.layerContainerDiv.appendChild(layer.div);}
+this.layers.push(layer);layer.setMap(this);if(layer.isBaseLayer||(this.allOverlays&&!this.baseLayer)){if(this.baseLayer==null){this.setBaseLayer(layer);}else{layer.setVisibility(false);}}else{layer.redraw();}
+this.events.triggerEvent("addlayer",{layer:layer});layer.events.triggerEvent("added",{map:this,layer:layer});layer.afterAdd();},addLayers:function(layers){for(var i=0,len=layers.length;i<len;i++){this.addLayer(layers[i]);}},removeLayer:function(layer,setNewBaseLayer){if(this.events.triggerEvent("preremovelayer",{layer:layer})===false){return;}
+if(setNewBaseLayer==null){setNewBaseLayer=true;}
+if(layer.isFixed){this.viewPortDiv.removeChild(layer.div);}else{this.layerContainerDiv.removeChild(layer.div);}
+OpenLayers.Util.removeItem(this.layers,layer);layer.removeMap(this);layer.map=null;if(this.baseLayer==layer){this.baseLayer=null;if(setNewBaseLayer){for(var i=0,len=this.layers.length;i<len;i++){var iLayer=this.layers[i];if(iLayer.isBaseLayer||this.allOverlays){this.setBaseLayer(iLayer);break;}}}}
+this.resetLayersZIndex();this.events.triggerEvent("removelayer",{layer:layer});layer.events.triggerEvent("removed",{map:this,layer:layer});},getNumLayers:function(){return this.layers.length;},getLayerIndex:function(layer){return OpenLayers.Util.indexOf(this.layers,layer);},setLayerIndex:function(layer,idx){var base=this.getLayerIndex(layer);if(idx<0){idx=0;}else if(idx>this.layers.length){idx=this.layers.length;}
+if(base!=idx){this.layers.splice(base,1);this.layers.splice(idx,0,layer);for(var i=0,len=this.layers.length;i<len;i++){this.setLayerZIndex(this.layers[i],i);}
+this.events.triggerEvent("changelayer",{layer:layer,property:"order"});if(this.allOverlays){if(idx===0){this.setBaseLayer(layer);}else if(this.baseLayer!==this.layers[0]){this.setBaseLayer(this.layers[0]);}}}},raiseLayer:function(layer,delta){var idx=this.getLayerIndex(layer)+delta;this.setLayerIndex(layer,idx);},setBaseLayer:function(newBaseLayer){if(newBaseLayer!=this.baseLayer){if(OpenLayers.Util.indexOf(this.layers,newBaseLayer)!=-1){var center=this.getCachedCenter();var newResolution=OpenLayers.Util.getResolutionFromScale(this.getScale(),newBaseLayer.units);if(this.baseLayer!=null&&!this.allOverlays){this.baseLayer.setVisibility(false);}
+this.baseLayer=newBaseLayer;this.viewRequestID++;if(!this.allOverlays||this.baseLayer.visibility){this.baseLayer.setVisibility(true);}
+if(center!=null){var newZoom=this.getZoomForResolution(newResolution||this.resolution,true);this.setCenter(center,newZoom,false,true);}
+this.events.triggerEvent("changebaselayer",{layer:this.baseLayer});}}},addControl:function(control,px){this.controls.push(control);this.addControlToMap(control,px);},addControls:function(controls,pixels){var pxs=(arguments.length===1)?[]:pixels;for(var i=0,len=controls.length;i<len;i++){var ctrl=controls[i];var px=(pxs[i])?pxs[i]:null;this.addControl(ctrl,px);}},addControlToMap:function(control,px){control.outsideViewport=(control.div!=null);if(this.displayProjection&&!control.displayProjection){control.displayProjection=this.displayProjection;}
+control.setMap(this);var div=control.draw(px);if(div){if(!control.outsideViewport){div.style.zIndex=this.Z_INDEX_BASE['Control']+
+this.controls.length;this.viewPortDiv.appendChild(div);}}
+if(control.autoActivate){control.activate();}},getControl:function(id){var returnControl=null;for(var i=0,len=this.controls.length;i<len;i++){var control=this.controls[i];if(control.id==id){returnControl=control;break;}}
+return returnControl;},removeControl:function(control){if((control)&&(control==this.getControl(control.id))){if(control.div&&(control.div.parentNode==this.viewPortDiv)){this.viewPortDiv.removeChild(control.div);}
+OpenLayers.Util.removeItem(this.controls,control);}},addPopup:function(popup,exclusive){if(exclusive){for(var i=this.popups.length-1;i>=0;--i){this.removePopup(this.popups[i]);}}
+popup.map=this;this.popups.push(popup);var popupDiv=popup.draw();if(popupDiv){popupDiv.style.zIndex=this.Z_INDEX_BASE['Popup']+
+this.popups.length;this.layerContainerDiv.appendChild(popupDiv);}},removePopup:function(popup){OpenLayers.Util.removeItem(this.popups,popup);if(popup.div){try{this.layerContainerDiv.removeChild(popup.div);}
+catch(e){}}
+popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();}
+return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;}
+if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i<len;i++){this.layers[i].onMapResize();}
+var center=this.getCachedCenter();if(this.baseLayer!=null&&center!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=this.div.offsetWidth;size.h=this.div.offsetHeight;}
+if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);}
+return size;},calculateBounds:function(center,resolution){var extent=null;if(center==null){center=this.getCachedCenter();}
+if(resolution==null){resolution=this.getResolution();}
+if((center!=null)&&(resolution!=null)){var size=this.getSize();var w_deg=size.w*resolution;var h_deg=size.h*resolution;extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);}
+return extent;},getCenter:function(){var center=null;var cachedCenter=this.getCachedCenter();if(cachedCenter){center=cachedCenter.clone();}
+return center;},getCachedCenter:function(){if(!this.center&&this.size){this.center=this.getLonLatFromViewPortPx(new OpenLayers.Pixel(this.size.w/2,this.size.h/2));}
+return this.center;},getZoom:function(){return this.zoom;},pan:function(dx,dy,options){options=OpenLayers.Util.applyDefaults(options,{animate:true,dragging:false});if(options.dragging){if(dx!=0||dy!=0){this.moveByPx(dx,dy);}}else{var centerPx=this.getViewPortPxFromLonLat(this.getCachedCenter());var newCenterPx=centerPx.add(dx,dy);if(this.dragging||!newCenterPx.equals(centerPx)){var newCenterLonLat=this.getLonLatFromViewPortPx(newCenterPx);if(options.animate){this.panTo(newCenterLonLat);}else{this.moveTo(newCenterLonLat);this.dragging=false;this.events.triggerEvent("moveend");}}}},panTo:function(lonlat){if(this.panMethod&&this.getExtent().scale(this.panRatio).containsLonLat(lonlat)){if(!this.panTween){this.panTween=new OpenLayers.Tween(this.panMethod);}
+var center=this.getCachedCenter();if(lonlat.equals(center)){return;}
+var from=this.getPixelFromLonLat(center);var to=this.getPixelFromLonLat(lonlat);var vector={x:to.x-from.x,y:to.y-from.y};var last={x:0,y:0};this.panTween.start({x:0,y:0},vector,this.panDuration,{callbacks:{eachStep:OpenLayers.Function.bind(function(px){var x=px.x-last.x,y=px.y-last.y;this.moveByPx(x,y);last.x=Math.round(px.x);last.y=Math.round(px.y);},this),done:OpenLayers.Function.bind(function(px){this.moveTo(lonlat);this.dragging=false;this.events.triggerEvent("moveend");},this)}});}else{this.setCenter(lonlat);}},setCenter:function(lonlat,zoom,dragging,forceZoomChange){this.panTween&&this.panTween.stop();this.moveTo(lonlat,zoom,{'dragging':dragging,'forceZoomChange':forceZoomChange});},moveByPx:function(dx,dy){var hw=this.size.w/2;var hh=this.size.h/2;var x=hw+dx;var y=hh+dy;var wrapDateLine=this.baseLayer.wrapDateLine;var xRestriction=0;var yRestriction=0;if(this.restrictedExtent){xRestriction=hw;yRestriction=hh;wrapDateLine=false;}
+dx=wrapDateLine||x<=this.maxPx.x-xRestriction&&x>=this.minPx.x+xRestriction?Math.round(dx):0;dy=y<=this.maxPx.y-yRestriction&&y>=this.minPx.y+yRestriction?Math.round(dy):0;var minX=this.minPx.x,maxX=this.maxPx.x;if(dx||dy){if(!this.dragging){this.dragging=true;this.events.triggerEvent("movestart");}
+this.center=null;if(dx){this.layerContainerDiv.style.left=parseInt(this.layerContainerDiv.style.left)-dx+"px";this.minPx.x-=dx;this.maxPx.x-=dx;if(wrapDateLine){if(this.maxPx.x>maxX){this.maxPx.x-=(maxX-minX);}
+if(this.minPx.x<minX){this.minPx.x+=(maxX-minX);}}}
+if(dy){this.layerContainerDiv.style.top=parseInt(this.layerContainerDiv.style.top)-dy+"px";this.minPx.y-=dy;this.maxPx.y-=dy;}
+var layer,i,len;for(i=0,len=this.layers.length;i<len;++i){layer=this.layers[i];if(layer.visibility&&(layer===this.baseLayer||layer.inRange)){layer.moveByPx(dx,dy);layer.events.triggerEvent("move");}}
+this.events.triggerEvent("move");}},moveTo:function(lonlat,zoom,options){if(!options){options={};}
+if(zoom!=null){zoom=parseFloat(zoom);if(!this.fractionalZoom){zoom=Math.round(zoom);}}
+var dragging=options.dragging||this.dragging;var forceZoomChange=options.forceZoomChange;if(!this.getCachedCenter()&&!this.isValidLonLat(lonlat)){lonlat=this.maxExtent.getCenterLonLat();this.center=lonlat.clone();}
+if(this.restrictedExtent!=null){if(lonlat==null){lonlat=this.center;}
+if(zoom==null){zoom=this.getZoom();}
+var resolution=this.getResolutionForZoom(zoom);var extent=this.calculateBounds(lonlat,resolution);if(!this.restrictedExtent.containsBounds(extent)){var maxCenter=this.restrictedExtent.getCenterLonLat();if(extent.getWidth()>this.restrictedExtent.getWidth()){lonlat=new OpenLayers.LonLat(maxCenter.lon,lonlat.lat);}else if(extent.left<this.restrictedExtent.left){lonlat=lonlat.add(this.restrictedExtent.left-
+extent.left,0);}else if(extent.right>this.restrictedExtent.right){lonlat=lonlat.add(this.restrictedExtent.right-
+extent.right,0);}
+if(extent.getHeight()>this.restrictedExtent.getHeight()){lonlat=new OpenLayers.LonLat(lonlat.lon,maxCenter.lat);}else if(extent.bottom<this.restrictedExtent.bottom){lonlat=lonlat.add(0,this.restrictedExtent.bottom-
+extent.bottom);}
+else if(extent.top>this.restrictedExtent.top){lonlat=lonlat.add(0,this.restrictedExtent.top-
+extent.top);}}}
+var zoomChanged=forceZoomChange||((this.isValidZoomLevel(zoom))&&(zoom!=this.getZoom()));var centerChanged=(this.isValidLonLat(lonlat))&&(!lonlat.equals(this.center));if(zoomChanged||centerChanged||dragging){dragging||this.events.triggerEvent("movestart");if(centerChanged){if(!zoomChanged&&this.center){this.centerLayerContainer(lonlat);}
+this.center=lonlat.clone();}
+var res=zoomChanged?this.getResolutionForZoom(zoom):this.getResolution();if(zoomChanged||this.layerContainerOrigin==null){this.layerContainerOrigin=this.getCachedCenter();this.layerContainerDiv.style.left="0px";this.layerContainerDiv.style.top="0px";var maxExtent=this.getMaxExtent({restricted:true});var maxExtentCenter=maxExtent.getCenterLonLat();var lonDelta=this.center.lon-maxExtentCenter.lon;var latDelta=maxExtentCenter.lat-this.center.lat;var extentWidth=Math.round(maxExtent.getWidth()/res);var extentHeight=Math.round(maxExtent.getHeight()/res);var left=(this.size.w-extentWidth)/2-lonDelta/res;var top=(this.size.h-extentHeight)/2-latDelta/res;this.minPx=new OpenLayers.Pixel(left,top);this.maxPx=new OpenLayers.Pixel(left+extentWidth,top+extentHeight);}
+if(zoomChanged){this.zoom=zoom;this.resolution=res;this.viewRequestID++;}
+var bounds=this.getExtent();if(this.baseLayer.visibility){this.baseLayer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||this.baseLayer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}
+bounds=this.baseLayer.getExtent();for(var i=this.layers.length-1;i>=0;--i){var layer=this.layers[i];if(layer!==this.baseLayer&&!layer.isBaseLayer){var inRange=layer.calculateInRange();if(layer.inRange!=inRange){layer.inRange=inRange;if(!inRange){layer.display(false);}
+this.events.triggerEvent("changelayer",{layer:layer,property:"visibility"});}
+if(inRange&&layer.visibility){layer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||layer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}}}
+this.events.triggerEvent("move");dragging||this.events.triggerEvent("moveend");if(zoomChanged){for(var i=0,len=this.popups.length;i<len;i++){this.popups[i].updatePosition();}
+this.events.triggerEvent("zoomend");}}},centerLayerContainer:function(lonlat){var originPx=this.getViewPortPxFromLonLat(this.layerContainerOrigin);var newPx=this.getViewPortPxFromLonLat(lonlat);if((originPx!=null)&&(newPx!=null)){var oldLeft=parseInt(this.layerContainerDiv.style.left);var oldTop=parseInt(this.layerContainerDiv.style.top);var newLeft=Math.round(originPx.x-newPx.x);var newTop=Math.round(originPx.y-newPx.y);this.layerContainerDiv.style.left=newLeft+"px";this.layerContainerDiv.style.top=newTop+"px";var dx=oldLeft-newLeft;var dy=oldTop-newTop;this.minPx.x-=dx;this.maxPx.x-=dx;this.minPx.y-=dy;this.maxPx.y-=dy;}},isValidZoomLevel:function(zoomLevel){return((zoomLevel!=null)&&(zoomLevel>=0)&&(zoomLevel<this.getNumZoomLevels()));},isValidLonLat:function(lonlat){var valid=false;if(lonlat!=null){var maxExtent=this.getMaxExtent();valid=maxExtent.containsLonLat(lonlat);}
+return valid;},getProjection:function(){var projection=this.getProjectionObject();return projection?projection.getCode():null;},getProjectionObject:function(){var projection=null;if(this.baseLayer!=null){projection=this.baseLayer.projection;}
+return projection;},getMaxResolution:function(){var maxResolution=null;if(this.baseLayer!=null){maxResolution=this.baseLayer.maxResolution;}
+return maxResolution;},getMaxExtent:function(options){var maxExtent=null;if(options&&options.restricted&&this.restrictedExtent){maxExtent=this.restrictedExtent;}else if(this.baseLayer!=null){maxExtent=this.baseLayer.maxExtent;}
+return maxExtent;},getNumZoomLevels:function(){var numZoomLevels=null;if(this.baseLayer!=null){numZoomLevels=this.baseLayer.numZoomLevels;}
+return numZoomLevels;},getExtent:function(){var extent=null;if(this.baseLayer!=null){extent=this.baseLayer.getExtent();}
+return extent;},getResolution:function(){var resolution=null;if(this.baseLayer!=null){resolution=this.baseLayer.getResolution();}else if(this.allOverlays===true&&this.layers.length>0){resolution=this.layers[0].getResolution();}
+return resolution;},getUnits:function(){var units=null;if(this.baseLayer!=null){units=this.baseLayer.units;}
+return units;},getScale:function(){var scale=null;if(this.baseLayer!=null){var res=this.getResolution();var units=this.baseLayer.units;scale=OpenLayers.Util.getScaleFromResolution(res,units);}
+return scale;},getZoomForExtent:function(bounds,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForExtent(bounds,closest);}
+return zoom;},getResolutionForZoom:function(zoom){var resolution=null;if(this.baseLayer){resolution=this.baseLayer.getResolutionForZoom(zoom);}
+return resolution;},getZoomForResolution:function(resolution,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForResolution(resolution,closest);}
+return zoom;},zoomTo:function(zoom){if(this.isValidZoomLevel(zoom)){this.setCenter(null,zoom);}},zoomIn:function(){this.zoomTo(this.getZoom()+1);},zoomOut:function(){this.zoomTo(this.getZoom()-1);},zoomToExtent:function(bounds,closest){var center=bounds.getCenterLonLat();if(this.baseLayer.wrapDateLine){var maxExtent=this.getMaxExtent();bounds=bounds.clone();while(bounds.right<bounds.left){bounds.right+=maxExtent.getWidth();}
+center=bounds.getCenterLonLat().wrapDateLine(maxExtent);}
+this.setCenter(center,this.getZoomForExtent(bounds,closest));},zoomToMaxExtent:function(options){var restricted=(options)?options.restricted:true;var maxExtent=this.getMaxExtent({'restricted':restricted});this.zoomToExtent(maxExtent);},zoomToScale:function(scale,closest){var res=OpenLayers.Util.getResolutionFromScale(scale,this.baseLayer.units);var size=this.getSize();var w_deg=size.w*res;var h_deg=size.h*res;var center=this.getCachedCenter();var extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);this.zoomToExtent(extent,closest);},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(this.baseLayer!=null){lonlat=this.baseLayer.getLonLatFromViewPortPx(viewPortPx);}
+return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(this.baseLayer!=null){px=this.baseLayer.getViewPortPxFromLonLat(lonlat);}
+return px;},getLonLatFromPixel:function(px){return this.getLonLatFromViewPortPx(px);},getPixelFromLonLat:function(lonlat){var px=this.getViewPortPxFromLonLat(lonlat);px.x=Math.round(px.x);px.y=Math.round(px.y);return px;},getGeodesicPixelSize:function(px){var lonlat=px?this.getLonLatFromPixel(px):(this.getCachedCenter()||new OpenLayers.LonLat(0,0));var res=this.getResolution();var left=lonlat.add(-res/2,0);var right=lonlat.add(res/2,0);var bottom=lonlat.add(0,-res/2);var top=lonlat.add(0,res/2);var dest=new OpenLayers.Projection("EPSG:4326");var source=this.getProjectionObject()||dest;if(!source.equals(dest)){left.transform(source,dest);right.transform(source,dest);bottom.transform(source,dest);top.transform(source,dest);}
+return new OpenLayers.Size(OpenLayers.Util.distVincenty(left,right),OpenLayers.Util.distVincenty(bottom,top));},getViewPortPxFromLayerPx:function(layerPx){var viewPortPx=null;if(layerPx!=null){var dX=parseInt(this.layerContainerDiv.style.left);var dY=parseInt(this.layerContainerDiv.style.top);viewPortPx=layerPx.add(dX,dY);}
+return viewPortPx;},getLayerPxFromViewPortPx:function(viewPortPx){var layerPx=null;if(viewPortPx!=null){var dX=-parseInt(this.layerContainerDiv.style.left);var dY=-parseInt(this.layerContainerDiv.style.top);layerPx=viewPortPx.add(dX,dY);if(isNaN(layerPx.x)||isNaN(layerPx.y)){layerPx=null;}}
+return layerPx;},getLonLatFromLayerPx:function(px){px=this.getViewPortPxFromLayerPx(px);return this.getLonLatFromViewPortPx(px);},getLayerPxFromLonLat:function(lonlat){var px=this.getPixelFromLonLat(lonlat);return this.getLayerPxFromViewPortPx(px);},CLASS_NAME:"OpenLayers.Map"});OpenLayers.Map.TILE_WIDTH=256;OpenLayers.Map.TILE_HEIGHT=256;OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,titleRegEx:/\+title=[^\+]*/,initialize:function(projCode,options){OpenLayers.Util.extend(this,options);this.projCode=projCode;if(window.Proj4js){this.proj=new Proj4js.Proj(projCode);}},getCode:function(){return this.proj?this.proj.srsCode:this.projCode;},getUnits:function(){return this.proj?this.proj.units:null;},toString:function(){return this.getCode();},equals:function(projection){var p=projection,equals=false;if(p){if(window.Proj4js&&this.proj.defData&&p.proj.defData){equals=this.proj.defData.replace(this.titleRegEx,"")==p.proj.defData.replace(this.titleRegEx,"");}else if(p.getCode){var source=this.getCode(),target=p.getCode();equals=source==target||!!OpenLayers.Projection.transforms[source]&&OpenLayers.Projection.transforms[source][target]===OpenLayers.Projection.nullTransform;}}
+return equals;},destroy:function(){delete this.proj;delete this.projCode;},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};OpenLayers.Projection.addTransform=function(from,to,method){if(!OpenLayers.Projection.transforms[from]){OpenLayers.Projection.transforms[from]={};}
+OpenLayers.Projection.transforms[from][to]=method;};OpenLayers.Projection.transform=function(point,source,dest){if(source.proj&&dest.proj){point=Proj4js.transform(source.proj,dest.proj,point);}else if(source&&dest&&OpenLayers.Projection.transforms[source.getCode()]&&OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]){OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point);}
+return point;};OpenLayers.Projection.nullTransform=function(point){return point;};OpenLayers.Layer=OpenLayers.Class({id:null,name:null,div:null,opacity:null,alwaysInRange:null,EVENT_TYPES:["loadstart","loadend","loadcancel","visibilitychanged","move","moveend","added","removed"],RESOLUTION_PROPERTIES:['scales','resolutions','maxScale','minScale','maxResolution','minResolution','numZoomLevels','maxZoomLevel'],events:null,map:null,isBaseLayer:false,alpha:false,displayInLayerSwitcher:true,visibility:true,attribution:null,inRange:false,imageSize:null,imageOffset:null,options:null,eventListeners:null,gutter:0,projection:null,units:null,scales:null,resolutions:null,maxExtent:null,minExtent:null,maxResolution:null,minResolution:null,numZoomLevels:null,minScale:null,maxScale:null,displayOutsideMaxExtent:false,wrapDateLine:false,transitionEffect:null,SUPPORTED_TRANSITIONS:['resize'],metadata:{},initialize:function(name,options){this.addOptions(options);this.name=name;if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");this.div=OpenLayers.Util.createDiv(this.id);this.div.style.width="100%";this.div.style.height="100%";this.div.dir="ltr";this.events=new OpenLayers.Events(this,this.div,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}}
+if(this.wrapDateLine){this.displayOutsideMaxExtent=true;}},destroy:function(setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;}
+if(this.map!=null){this.map.removeLayer(this,setNewBaseLayer);}
+this.projection=null;this.map=null;this.name=null;this.div=null;this.options=null;if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
+this.events.destroy();}
+this.eventListeners=null;this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer(this.name,this.getOptions());}
+OpenLayers.Util.applyDefaults(obj,this);obj.map=null;return obj;},getOptions:function(){var options={};for(var o in this.options){options[o]=this[o];}
+return options;},setName:function(newName){if(newName!=this.name){this.name=newName;if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"name"});}}},addOptions:function(newOptions,reinitialize){if(this.options==null){this.options={};}
+OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
+if(this.projection&&this.projection.getUnits()){this.units=this.projection.getUnits();}
+if(this.map){var resolution=this.map.getResolution();var properties=this.RESOLUTION_PROPERTIES.concat(["projection","units","minExtent","maxExtent"]);for(var o in newOptions){if(newOptions.hasOwnProperty(o)&&OpenLayers.Util.indexOf(properties,o)>=0){this.initResolutions();if(reinitialize&&this.map.baseLayer===this){this.map.setCenter(this.map.getCenter(),this.map.getZoomForResolution(resolution),false,true);this.map.events.triggerEvent("changebaselayer",{layer:this});}
+break;}}}},onMapResize:function(){},redraw:function(){var redrawn=false;if(this.map){this.inRange=this.calculateInRange();var extent=this.getExtent();if(extent&&this.inRange&&this.visibility){var zoomChanged=true;this.moveTo(extent,zoomChanged,false);this.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});redrawn=true;}}
+return redrawn;},moveTo:function(bounds,zoomChanged,dragging){var display=this.visibility;if(!this.isBaseLayer){display=display&&this.inRange;}
+this.display(display);},moveByPx:function(dx,dy){},setMap:function(map){if(this.map==null){this.map=map;this.maxExtent=this.maxExtent||this.map.maxExtent;this.minExtent=this.minExtent||this.map.minExtent;this.projection=this.projection||this.map.projection;if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
+this.units=this.projection.getUnits()||this.units||this.map.units;this.initResolutions();if(!this.isBaseLayer){this.inRange=this.calculateInRange();var show=((this.visibility)&&(this.inRange));this.div.style.display=show?"":"none";}
+this.setTileSize();}},afterAdd:function(){},removeMap:function(map){},getImageSize:function(bounds){return(this.imageSize||this.tileSize);},setTileSize:function(size){var tileSize=(size)?size:((this.tileSize)?this.tileSize:this.map.getTileSize());this.tileSize=tileSize;if(this.gutter){this.imageOffset=new OpenLayers.Pixel(-this.gutter,-this.gutter);this.imageSize=new OpenLayers.Size(tileSize.w+(2*this.gutter),tileSize.h+(2*this.gutter));}},getVisibility:function(){return this.visibility;},setVisibility:function(visibility){if(visibility!=this.visibility){this.visibility=visibility;this.display(visibility);this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"});}
+this.events.triggerEvent("visibilitychanged");}},display:function(display){if(display!=(this.div.style.display!="none")){this.div.style.display=(display&&this.calculateInRange())?"block":"none";}},calculateInRange:function(){var inRange=false;if(this.alwaysInRange){inRange=true;}else{if(this.map){var resolution=this.map.getResolution();inRange=((resolution>=this.minResolution)&&(resolution<=this.maxResolution));}}
+return inRange;},setIsBaseLayer:function(isBaseLayer){if(isBaseLayer!=this.isBaseLayer){this.isBaseLayer=isBaseLayer;if(this.map!=null){this.map.events.triggerEvent("changebaselayer",{layer:this});}}},initResolutions:function(){var i,len,p;var props={},alwaysInRange=true;for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p];if(alwaysInRange&&this.options[p]){alwaysInRange=false;}}
+if(this.alwaysInRange==null){this.alwaysInRange=alwaysInRange;}
+if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
+if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}
+if(props.resolutions==null){for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p]!=null?this.options[p]:this.map[p];}
+if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
+if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}}
+var maxResolution;if(this.options.maxResolution&&this.options.maxResolution!=="auto"){maxResolution=this.options.maxResolution;}
+if(this.options.minScale){maxResolution=OpenLayers.Util.getResolutionFromScale(this.options.minScale,this.units);}
+var minResolution;if(this.options.minResolution&&this.options.minResolution!=="auto"){minResolution=this.options.minResolution;}
+if(this.options.maxScale){minResolution=OpenLayers.Util.getResolutionFromScale(this.options.maxScale,this.units);}
+if(props.resolutions){props.resolutions.sort(function(a,b){return(b-a);});if(!maxResolution){maxResolution=props.resolutions[0];}
+if(!minResolution){var lastIdx=props.resolutions.length-1;minResolution=props.resolutions[lastIdx];}}
+this.resolutions=props.resolutions;if(this.resolutions){len=this.resolutions.length;this.scales=new Array(len);for(i=0;i<len;i++){this.scales[i]=OpenLayers.Util.getScaleFromResolution(this.resolutions[i],this.units);}
+this.numZoomLevels=len;}
+this.minResolution=minResolution;if(minResolution){this.maxScale=OpenLayers.Util.getScaleFromResolution(minResolution,this.units);}
+this.maxResolution=maxResolution;if(maxResolution){this.minScale=OpenLayers.Util.getScaleFromResolution(maxResolution,this.units);}},resolutionsFromScales:function(scales){if(scales==null){return;}
+var resolutions,i,len;len=scales.length;resolutions=new Array(len);for(i=0;i<len;i++){resolutions[i]=OpenLayers.Util.getResolutionFromScale(scales[i],this.units);}
+return resolutions;},calculateResolutions:function(props){var viewSize,wRes,hRes;var maxResolution=props.maxResolution;if(props.minScale!=null){maxResolution=OpenLayers.Util.getResolutionFromScale(props.minScale,this.units);}else if(maxResolution=="auto"&&this.maxExtent!=null){viewSize=this.map.getSize();wRes=this.maxExtent.getWidth()/viewSize.w;hRes=this.maxExtent.getHeight()/viewSize.h;maxResolution=Math.max(wRes,hRes);}
+var minResolution=props.minResolution;if(props.maxScale!=null){minResolution=OpenLayers.Util.getResolutionFromScale(props.maxScale,this.units);}else if(props.minResolution=="auto"&&this.minExtent!=null){viewSize=this.map.getSize();wRes=this.minExtent.getWidth()/viewSize.w;hRes=this.minExtent.getHeight()/viewSize.h;minResolution=Math.max(wRes,hRes);}
+var maxZoomLevel=props.maxZoomLevel;var numZoomLevels=props.numZoomLevels;if(typeof minResolution==="number"&&typeof maxResolution==="number"&&numZoomLevels===undefined){var ratio=maxResolution/minResolution;numZoomLevels=Math.floor(Math.log(ratio)/Math.log(2))+1;}else if(numZoomLevels===undefined&&maxZoomLevel!=null){numZoomLevels=maxZoomLevel+1;}
+if(typeof numZoomLevels!=="number"||numZoomLevels<=0||(typeof maxResolution!=="number"&&typeof minResolution!=="number")){return;}
+var resolutions=new Array(numZoomLevels);var base=2;if(typeof minResolution=="number"&&typeof maxResolution=="number"){base=Math.pow((maxResolution/minResolution),(1/(numZoomLevels-1)));}
+var i;if(typeof maxResolution==="number"){for(i=0;i<numZoomLevels;i++){resolutions[i]=maxResolution/Math.pow(base,i);}}else{for(i=0;i<numZoomLevels;i++){resolutions[numZoomLevels-1-i]=minResolution*Math.pow(base,i);}}
+return resolutions;},getResolution:function(){var zoom=this.map.getZoom();return this.getResolutionForZoom(zoom);},getExtent:function(){return this.map.calculateBounds();},getZoomForExtent:function(extent,closest){var viewSize=this.map.getSize();var idealResolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);return this.getZoomForResolution(idealResolution,closest);},getDataExtent:function(){},getResolutionForZoom:function(zoom){zoom=Math.max(0,Math.min(zoom,this.resolutions.length-1));var resolution;if(this.map.fractionalZoom){var low=Math.floor(zoom);var high=Math.ceil(zoom);resolution=this.resolutions[low]-
+((zoom-low)*(this.resolutions[low]-this.resolutions[high]));}else{resolution=this.resolutions[Math.round(zoom)];}
+return resolution;},getZoomForResolution:function(resolution,closest){var zoom,i,len;if(this.map.fractionalZoom){var lowZoom=0;var highZoom=this.resolutions.length-1;var highRes=this.resolutions[lowZoom];var lowRes=this.resolutions[highZoom];var res;for(i=0,len=this.resolutions.length;i<len;++i){res=this.resolutions[i];if(res>=resolution){highRes=res;lowZoom=i;}
+if(res<=resolution){lowRes=res;highZoom=i;break;}}
+var dRes=highRes-lowRes;if(dRes>0){zoom=lowZoom+((highRes-resolution)/dRes);}else{zoom=lowZoom;}}else{var diff;var minDiff=Number.POSITIVE_INFINITY;for(i=0,len=this.resolutions.length;i<len;i++){if(closest){diff=Math.abs(this.resolutions[i]-resolution);if(diff>minDiff){break;}
+minDiff=diff;}else{if(this.resolutions[i]<resolution){break;}}}
+zoom=Math.max(0,i-1);}
+return zoom;},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;var map=this.map;if(viewPortPx!=null&&map.minPx){var res=map.getResolution();var maxExtent=map.getMaxExtent({restricted:true});var lon=(viewPortPx.x-map.minPx.x)*res+maxExtent.left;var lat=(map.minPx.y-viewPortPx.y)*res+maxExtent.top;lonlat=new OpenLayers.LonLat(lon,lat);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}}
+return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(lonlat!=null){var resolution=this.map.getResolution();var extent=this.map.getExtent();px=new OpenLayers.Pixel((1/resolution*(lonlat.lon-extent.left)),(1/resolution*(extent.top-lonlat.lat)));}
+return px;},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.div.childNodes.length;i<len;++i){var element=this.div.childNodes[i].firstChild;OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);}
+if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}}},getZIndex:function(){return this.div.style.zIndex;},setZIndex:function(zIndex){this.div.style.zIndex=zIndex;},adjustBounds:function(bounds){if(this.gutter){var mapGutter=this.gutter*this.map.getResolution();bounds=new OpenLayers.Bounds(bounds.left-mapGutter,bounds.bottom-mapGutter,bounds.right+mapGutter,bounds.top+mapGutter);}
+if(this.wrapDateLine){var wrappingOptions={'rightTolerance':this.getResolution(),'leftTolerance':this.getResolution()};bounds=bounds.wrapDateLine(this.maxExtent,wrappingOptions);}
+return bounds;},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);}
+return extent;},getLonLatFromViewPortPx:function(viewPortPx){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments);},getViewPortPxFromLonLat:function(lonlat){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments);},initMercatorParameters:function(){this.RESOLUTIONS=[];var maxResolution=156543.03390625;for(var zoom=0;zoom<=this.MAX_ZOOM_LEVEL;++zoom){this.RESOLUTIONS[zoom]=maxResolution/Math.pow(2,zoom);}
+this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:function(lon,lat){var x=lon*20037508.34/180;var y=Math.log(Math.tan((90+lat)*Math.PI/360))/(Math.PI/180);y=y*20037508.34/180;return new OpenLayers.LonLat(x,y);},inverseMercator:function(x,y){var lon=(x/20037508.34)*180;var lat=(y/20037508.34)*180;lat=180/Math.PI*(2*Math.atan(Math.exp(lat*Math.PI/180))-Math.PI/2);return new OpenLayers.LonLat(lon,lat);},projectForward:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.forwardMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;},projectInverse:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.inverseMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;}};(function(){var codes=["EPSG:900913","EPSG:3857","EPSG:102113","EPSG:102100"];var add=OpenLayers.Projection.addTransform;var merc=OpenLayers.Layer.SphericalMercator;var same=OpenLayers.Projection.nullTransform;var i,len,code,other,j;for(i=0,len=codes.length;i<len;++i){code=codes[i];add("EPSG:4326",code,merc.projectForward);add(code,"EPSG:4326",merc.projectInverse);for(j=i+1;j<len;++j){other=codes[j];add(code,other,same);add(other,code,same);}}})();OpenLayers.Layer.EventPane=OpenLayers.Class(OpenLayers.Layer,{smoothDragPan:true,isBaseLayer:true,isFixed:true,pane:null,mapObject:null,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(this.pane==null){this.pane=OpenLayers.Util.createDiv(this.div.id+"_EventPane");}},destroy:function(){this.mapObject=null;this.pane=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;this.pane.style.display=this.div.style.display;this.pane.style.width="100%";this.pane.style.height="100%";if(OpenLayers.BROWSER_NAME=="msie"){this.pane.style.background="url("+OpenLayers.Util.getImagesLocation()+"blank.gif)";}
+if(this.isFixed){this.map.eventsDiv.appendChild(this.pane);}else{this.map.layerContainerDiv.appendChild(this.pane);}
+this.loadMapObject();if(this.mapObject==null){this.loadWarningMessage();}},removeMap:function(map){if(this.pane&&this.pane.parentNode){this.pane.parentNode.removeChild(this.pane);}
+OpenLayers.Layer.prototype.removeMap.apply(this,arguments);},loadWarningMessage:function(){this.div.style.backgroundColor="darkblue";var viewSize=this.map.getSize();var msgW=Math.min(viewSize.w,300);var msgH=Math.min(viewSize.h,200);var size=new OpenLayers.Size(msgW,msgH);var centerPx=new OpenLayers.Pixel(viewSize.w/2,viewSize.h/2);var topLeft=centerPx.add(-size.w/2,-size.h/2);var div=OpenLayers.Util.createDiv(this.name+"_warning",topLeft,size,null,null,null,"auto");div.style.padding="7px";div.style.backgroundColor="yellow";div.innerHTML=this.getWarningHTML();this.div.appendChild(div);},getWarningHTML:function(){return"";},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);this.pane.style.display=this.div.style.display;},setZIndex:function(zIndex){OpenLayers.Layer.prototype.setZIndex.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;},moveByPx:function(dx,dy){OpenLayers.Layer.prototype.moveByPx.apply(this,arguments);if(this.dragPanMapObject){this.dragPanMapObject(dx,-dy);}else{this.moveTo(this.map.getCachedCenter());}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(this.mapObject!=null){var newCenter=this.map.getCenter();var newZoom=this.map.getZoom();if(newCenter!=null){var moOldCenter=this.getMapObjectCenter();var oldCenter=this.getOLLonLatFromMapObjectLonLat(moOldCenter);var moOldZoom=this.getMapObjectZoom();var oldZoom=this.getOLZoomFromMapObjectZoom(moOldZoom);if(!(newCenter.equals(oldCenter))||!(newZoom==oldZoom)){if(!zoomChanged&&oldCenter&&this.dragPanMapObject&&this.smoothDragPan){var oldPx=this.map.getViewPortPxFromLonLat(oldCenter);var newPx=this.map.getViewPortPxFromLonLat(newCenter);this.dragPanMapObject(newPx.x-oldPx.x,oldPx.y-newPx.y);}else{var center=this.getMapObjectLonLatFromOLLonLat(newCenter);var zoom=this.getMapObjectZoomFromOLZoom(newZoom);this.setMapObjectCenter(center,zoom,dragging);}}}}},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moPixel=this.getMapObjectPixelFromOLPixel(viewPortPx);var moLonLat=this.getMapObjectLonLatFromMapObjectPixel(moPixel);lonlat=this.getOLLonLatFromMapObjectLonLat(moLonLat);}
+return lonlat;},getViewPortPxFromLonLat:function(lonlat){var viewPortPx=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moLonLat=this.getMapObjectLonLatFromOLLonLat(lonlat);var moPixel=this.getMapObjectPixelFromMapObjectLonLat(moLonLat);viewPortPx=this.getOLPixelFromMapObjectPixel(moPixel);}
+return viewPortPx;},getOLLonLatFromMapObjectLonLat:function(moLonLat){var olLonLat=null;if(moLonLat!=null){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);olLonLat=new OpenLayers.LonLat(lon,lat);}
+return olLonLat;},getMapObjectLonLatFromOLLonLat:function(olLonLat){var moLatLng=null;if(olLonLat!=null){moLatLng=this.getMapObjectLonLatFromLonLat(olLonLat.lon,olLonLat.lat);}
+return moLatLng;},getOLPixelFromMapObjectPixel:function(moPixel){var olPixel=null;if(moPixel!=null){var x=this.getXFromMapObjectPixel(moPixel);var y=this.getYFromMapObjectPixel(moPixel);olPixel=new OpenLayers.Pixel(x,y);}
+return olPixel;},getMapObjectPixelFromOLPixel:function(olPixel){var moPixel=null;if(olPixel!=null){moPixel=this.getMapObjectPixelFromXY(olPixel.x,olPixel.y);}
+return moPixel;},CLASS_NAME:"OpenLayers.Layer.EventPane"});OpenLayers.Layer.FixedZoomLevels=OpenLayers.Class({initialize:function(){},initResolutions:function(){var props=new Array('minZoomLevel','maxZoomLevel','numZoomLevels');for(var i=0,len=props.length;i<len;i++){var property=props[i];this[property]=(this.options[property]!=null)?this.options[property]:this.map[property];}
+if((this.minZoomLevel==null)||(this.minZoomLevel<this.MIN_ZOOM_LEVEL)){this.minZoomLevel=this.MIN_ZOOM_LEVEL;}
+var desiredZoomLevels;var limitZoomLevels=this.MAX_ZOOM_LEVEL-this.minZoomLevel+1;if(((this.options.numZoomLevels==null)&&(this.options.maxZoomLevel!=null))||((this.numZoomLevels==null)&&(this.maxZoomLevel!=null))){desiredZoomLevels=this.maxZoomLevel-this.minZoomLevel+1;}else{desiredZoomLevels=this.numZoomLevels;}
+if(desiredZoomLevels!=null){this.numZoomLevels=Math.min(desiredZoomLevels,limitZoomLevels);}else{this.numZoomLevels=limitZoomLevels;}
+this.maxZoomLevel=this.minZoomLevel+this.numZoomLevels-1;if(this.RESOLUTIONS!=null){var resolutionsIndex=0;this.resolutions=[];for(var i=this.minZoomLevel;i<=this.maxZoomLevel;i++){this.resolutions[resolutionsIndex++]=this.RESOLUTIONS[i];}
+this.maxResolution=this.resolutions[0];this.minResolution=this.resolutions[this.resolutions.length-1];}},getResolution:function(){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getResolution.apply(this,arguments);}else{var resolution=null;var viewSize=this.map.getSize();var extent=this.getExtent();if((viewSize!=null)&&(extent!=null)){resolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);}
+return resolution;}},getExtent:function(){var extent=null;var size=this.map.getSize();var tlPx=new OpenLayers.Pixel(0,0);var tlLL=this.getLonLatFromViewPortPx(tlPx);var brPx=new OpenLayers.Pixel(size.w,size.h);var brLL=this.getLonLatFromViewPortPx(brPx);if((tlLL!=null)&&(brLL!=null)){extent=new OpenLayers.Bounds(tlLL.lon,brLL.lat,brLL.lon,tlLL.lat);}
+return extent;},getZoomForResolution:function(resolution){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getZoomForResolution.apply(this,arguments);}else{var extent=OpenLayers.Layer.prototype.getExtent.apply(this,[]);return this.getZoomForExtent(extent);}},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=moZoom-this.minZoomLevel;if(this.map.baseLayer!==this){zoom=this.map.baseLayer.getZoomForResolution(this.getResolutionForZoom(zoom))}}
+return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=olZoom+this.minZoomLevel;if(this.map.baseLayer!==this){zoom=this.getZoomForResolution(this.map.baseLayer.getResolutionForZoom(zoom));}}
+return zoom;},CLASS_NAME:"OpenLayers.Layer.FixedZoomLevels"});OpenLayers.Layer.Google=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:21,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515,0.00000268220901489257,0.0000013411045074462891,0.00000067055225372314453],type:null,wrapDateLine:true,sphericalMercator:false,version:null,initialize:function(name,options){options=options||{};if(!options.version){options.version=typeof GMap2==="function"?"2":"3";}
+var mixin=OpenLayers.Layer.Google["v"+
+options.version.replace(/\./g,"_")];if(mixin){OpenLayers.Util.applyDefaults(options,mixin);}else{throw"Unsupported Google Maps API version: "+options.version;}
+OpenLayers.Util.applyDefaults(options,mixin.DEFAULTS);if(options.maxExtent){options.maxExtent=options.maxExtent.clone();}
+OpenLayers.Layer.EventPane.prototype.initialize.apply(this,[name,options]);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,[name,options]);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},clone:function(){return new OpenLayers.Layer.Google(this.name,this.getOptions());},setVisibility:function(visible){var opacity=this.opacity==null?1:this.opacity;OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this,arguments);this.setOpacity(opacity);},display:function(visible){if(!this._dragging){this.setGMapVisibility(visible);}
+OpenLayers.Layer.EventPane.prototype.display.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){this._dragging=dragging;OpenLayers.Layer.EventPane.prototype.moveTo.apply(this,arguments);delete this._dragging;},setOpacity:function(opacity){if(opacity!==this.opacity){if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}
+this.opacity=opacity;}
+if(this.getVisibility()){var container=this.getMapContainer();OpenLayers.Util.modifyDOMElement(container,null,null,null,null,null,null,opacity);}},destroy:function(){if(this.map){this.setGMapVisibility(false);var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache&&cache.count<=1){this.removeGMapElements();}}
+OpenLayers.Layer.EventPane.prototype.destroy.apply(this,arguments);},removeGMapElements:function(){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject&&this.getMapContainer();if(container&&container.parentNode){container.parentNode.removeChild(container);}
+var termsOfUse=cache.termsOfUse;if(termsOfUse&&termsOfUse.parentNode){termsOfUse.parentNode.removeChild(termsOfUse);}
+var poweredBy=cache.poweredBy;if(poweredBy&&poweredBy.parentNode){poweredBy.parentNode.removeChild(poweredBy);}}},removeMap:function(map){if(this.visibility&&this.mapObject){this.setGMapVisibility(false);}
+var cache=OpenLayers.Layer.Google.cache[map.id];if(cache){if(cache.count<=1){this.removeGMapElements();delete OpenLayers.Layer.Google.cache[map.id];}else{--cache.count;}}
+delete this.termsOfUse;delete this.poweredBy;delete this.mapObject;delete this.dragObject;OpenLayers.Layer.EventPane.prototype.removeMap.apply(this,arguments);},getOLBoundsFromMapObjectBounds:function(moBounds){var olBounds=null;if(moBounds!=null){var sw=moBounds.getSouthWest();var ne=moBounds.getNorthEast();if(this.sphericalMercator){sw=this.forwardMercator(sw.lng(),sw.lat());ne=this.forwardMercator(ne.lng(),ne.lat());}else{sw=new OpenLayers.LonLat(sw.lng(),sw.lat());ne=new OpenLayers.LonLat(ne.lng(),ne.lat());}
+olBounds=new OpenLayers.Bounds(sw.lon,sw.lat,ne.lon,ne.lat);}
+return olBounds;},getWarningHTML:function(){return OpenLayers.i18n("googleWarning");},getMapObjectCenter:function(){return this.mapObject.getCenter();},getMapObjectZoom:function(){return this.mapObject.getZoom();},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lon:moLonLat.lng();},getLatitudeFromMapObjectLonLat:function(moLonLat){var lat=this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lat:moLonLat.lat();return lat;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},CLASS_NAME:"OpenLayers.Layer.Google"});OpenLayers.Layer.Google.cache={};OpenLayers.Layer.Google.v2={termsOfUse:null,poweredBy:null,dragObject:null,loadMapObject:function(){if(!this.type){this.type=G_NORMAL_MAP;}
+var mapObject,termsOfUse,poweredBy;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;termsOfUse=cache.termsOfUse;poweredBy=cache.poweredBy;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMap2Container";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);try{mapObject=new GMap2(div);termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.right="";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright";poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.right="";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy gmnoprint";}catch(e){throw(e);}
+OpenLayers.Layer.Google.cache[this.map.id]={mapObject:mapObject,termsOfUse:termsOfUse,poweredBy:poweredBy,count:1};}
+this.mapObject=mapObject;this.termsOfUse=termsOfUse;this.poweredBy=poweredBy;if(OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),this.type)===-1){this.mapObject.addMapType(this.type);}
+if(typeof mapObject.getDragObject=="function"){this.dragObject=mapObject.getDragObject();}else{this.dragPanMapObject=null;}
+if(this.isBaseLayer===false){this.setGMapVisibility(this.div.style.display!=="none");}},onMapResize:function(){if(this.visibility&&this.mapObject.isLoaded()){this.mapObject.checkResize();}else{if(!this._resized){var layer=this;var handle=GEvent.addListener(this.mapObject,"load",function(){GEvent.removeListener(handle);delete layer._resized;layer.mapObject.checkResize();layer.moveTo(layer.map.getCenter(),layer.map.getZoom());});}
+this._resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject.getContainer();if(visible===true){this.mapObject.setMapType(this.type);container.style.display="";this.termsOfUse.style.left="";this.termsOfUse.style.display="";this.poweredBy.style.display="";cache.displayed=this.id;}else{if(cache.displayed===this.id){delete cache.displayed;}
+if(!cache.displayed){container.style.display="none";this.termsOfUse.style.display="none";this.termsOfUse.style.left="-9999px";this.poweredBy.style.display="none";}}}},getMapContainer:function(){return this.mapObject.getContainer();},getMapObjectBoundsFromOLBounds:function(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new GLatLngBounds(new GLatLng(sw.lat,sw.lon),new GLatLng(ne.lat,ne.lon));}
+return moBounds;},setMapObjectCenter:function(center,zoom){this.mapObject.setCenter(center,zoom);},dragPanMapObject:function(dX,dY){this.dragObject.moveBy(new GSize(-dX,dY));},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.fromContainerPixelToLatLng(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.fromLatLngToContainerPixel(moLonLat);},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new GLatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new GLatLng(lat,lon);}
+return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new GPoint(x,y);}};OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);}
+this.setDefaultStyle(style||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();this.rules[i]=null;}
+this.rules=null;this.defaultStyle=null;},createSymbolizer:function(feature){var style=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),feature);var rules=this.rules;var rule,context;var elseRules=[];var appliedRules=false;for(var i=0,len=rules.length;i<len;i++){rule=rules[i];var applies=rule.evaluate(feature);if(applies){if(rule instanceof OpenLayers.Rule&&rule.elseFilter){elseRules.push(rule);}else{appliedRules=true;this.applySymbolizer(rule,style,feature);}}}
+if(appliedRules==false&&elseRules.length>0){appliedRules=true;for(var i=0,len=elseRules.length;i<len;i++){this.applySymbolizer(elseRules[i],style,feature);}}
+if(rules.length>0&&appliedRules==false){style.display="none";}
+if(style.label&&typeof style.label!=="string"){style.label=String(style.label);}
+return style;},applySymbolizer:function(rule,style,feature){var symbolizerPrefix=feature.geometry?this.getSymbolizerPrefix(feature.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];var symbolizer=rule.symbolizer[symbolizerPrefix]||rule.symbolizer;if(this.defaultsPerSymbolizer===true){var defaults=this.defaultStyle;OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:defaults.pointRadius});if(symbolizer.stroke===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{strokeWidth:defaults.strokeWidth,strokeColor:defaults.strokeColor,strokeOpacity:defaults.strokeOpacity,strokeDashstyle:defaults.strokeDashstyle,strokeLinecap:defaults.strokeLinecap});}
+if(symbolizer.fill===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{fillColor:defaults.fillColor,fillOpacity:defaults.fillOpacity});}
+if(symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:this.defaultStyle.pointRadius,externalGraphic:this.defaultStyle.externalGraphic,graphicName:this.defaultStyle.graphicName,graphicOpacity:this.defaultStyle.graphicOpacity,graphicWidth:this.defaultStyle.graphicWidth,graphicHeight:this.defaultStyle.graphicHeight,graphicXOffset:this.defaultStyle.graphicXOffset,graphicYOffset:this.defaultStyle.graphicYOffset});}}
+return this.createLiterals(OpenLayers.Util.extend(style,symbolizer),feature);},createLiterals:function(style,feature){var context=OpenLayers.Util.extend({},feature.attributes||feature.data);OpenLayers.Util.extend(context,this.context);for(var i in this.propertyStyles){style[i]=OpenLayers.Style.createLiteral(style[i],context,feature,i);}
+return style;},findPropertyStyles:function(){var propertyStyles={};var style=this.defaultStyle;this.addPropertyStyles(propertyStyles,style);var rules=this.rules;var symbolizer,value;for(var i=0,len=rules.length;i<len;i++){symbolizer=rules[i].symbolizer;for(var key in symbolizer){value=symbolizer[key];if(typeof value=="object"){this.addPropertyStyles(propertyStyles,value);}else{this.addPropertyStyles(propertyStyles,symbolizer);break;}}}
+return propertyStyles;},addPropertyStyles:function(propertyStyles,symbolizer){var property;for(var key in symbolizer){property=symbolizer[key];if(typeof property=="string"&&property.match(/\$\{\w+\}/)){propertyStyles[key]=true;}}
+return propertyStyles;},addRules:function(rules){Array.prototype.push.apply(this.rules,rules);this.propertyStyles=this.findPropertyStyles();},setDefaultStyle:function(style){this.defaultStyle=style;this.propertyStyles=this.findPropertyStyles();},getSymbolizerPrefix:function(geometry){var prefixes=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=prefixes.length;i<len;i++){if(geometry.CLASS_NAME.indexOf(prefixes[i])!=-1){return prefixes[i];}}},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.rules){options.rules=[];for(var i=0,len=this.rules.length;i<len;++i){options.rules.push(this.rules[i].clone());}}
+options.context=this.context&&OpenLayers.Util.extend({},this.context);var defaultStyle=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(defaultStyle,options);},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(value,context,feature,property){if(typeof value=="string"&&value.indexOf("${")!=-1){value=OpenLayers.String.format(value,context,[feature,property]);value=(isNaN(value)||!value)?value:parseFloat(value);}
+return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.Symbolizer=OpenLayers.Class({zIndex:0,initialize:function(config){OpenLayers.Util.extend(this,config);},clone:function(){var Type=eval(this.CLASS_NAME);return new Type(OpenLayers.Util.extend({},this));},CLASS_NAME:"OpenLayers.Symbolizer"});OpenLayers.Symbolizer.Point=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Point"});OpenLayers.Symbolizer.Line=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Line"});OpenLayers.Symbolizer.Polygon=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Polygon"});OpenLayers.Symbolizer.Text=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Text"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:false,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(options){this.symbolizer={};OpenLayers.Util.extend(this,options);if(this.symbolizers){delete this.symbolizer;}
+this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i in this.symbolizer){this.symbolizer[i]=null;}
+this.symbolizer=null;delete this.symbolizers;},evaluate:function(feature){var context=this.getContext(feature);var applies=true;if(this.minScaleDenominator||this.maxScaleDenominator){var scale=feature.layer.map.getScale();}
+if(this.minScaleDenominator){applies=scale>=OpenLayers.Style.createLiteral(this.minScaleDenominator,context);}
+if(applies&&this.maxScaleDenominator){applies=scale<OpenLayers.Style.createLiteral(this.maxScaleDenominator,context);}
+if(applies&&this.filter){if(this.filter.CLASS_NAME=="OpenLayers.Filter.FeatureId"){applies=this.filter.evaluate(feature);}else{applies=this.filter.evaluate(context);}}
+return applies;},getContext:function(feature){var context=this.context;if(!context){context=feature.attributes||feature.data;}
+if(typeof this.context=="function"){context=this.context(feature);}
+return context;},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.symbolizers){var len=this.symbolizers.length;options.symbolizers=new Array(len);for(var i=0;i<len;++i){options.symbolizers[i]=this.symbolizers[i].clone();}}else{options.symbolizer={};var value,type;for(var key in this.symbolizer){value=this.symbolizer[key];type=typeof value;if(type==="object"){options.symbolizer[key]=OpenLayers.Util.extend({},value);}else if(type==="string"){options.symbolizer[key]=value;}}}
+options.filter=this.filter&&this.filter.clone();options.context=this.context&&OpenLayers.Util.extend({},this.context);return new OpenLayers.Rule(options);},CLASS_NAME:"OpenLayers.Rule"});OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(options){if(window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}
+OpenLayers.Format.prototype.initialize.apply(this,[options]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var alias in this.namespaces){this.namespaceAlias[this.namespaces[alias]]=alias;}},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,arguments);},setNamespace:function(alias,uri){this.namespaces[alias]=uri;this.namespaceAlias[uri]=alias;},read:function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
+var node=OpenLayers.Util.Try(OpenLayers.Function.bind((function(){var xmldom;if(window.ActiveXObject&&!this.xmldom){xmldom=new ActiveXObject("Microsoft.XMLDOM");}else{xmldom=this.xmldom;}
+xmldom.loadXML(text);return xmldom;}),this),function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
+req.send(null);return req.responseXML;});if(this.keepData){this.data=node;}
+return node;},write:function(node){var data;if(this.xmldom){data=node.xml;}else{var serializer=new XMLSerializer();if(node.nodeType==1){var doc=document.implementation.createDocument("","",null);if(doc.importNode){node=doc.importNode(node,true);}
+doc.appendChild(node);data=serializer.serializeToString(doc);}else{data=serializer.serializeToString(node);}}
+return data;},createElementNS:function(uri,name){var element;if(this.xmldom){if(typeof uri=="string"){element=this.xmldom.createNode(1,name,uri);}else{element=this.xmldom.createNode(1,name,"");}}else{element=document.createElementNS(uri,name);}
+return element;},createTextNode:function(text){var node;if(typeof text!=="string"){text=String(text);}
+if(this.xmldom){node=this.xmldom.createTextNode(text);}else{node=document.createTextNode(text);}
+return node;},getElementsByTagNameNS:function(node,uri,name){var elements=[];if(node.getElementsByTagNameNS){elements=node.getElementsByTagNameNS(uri,name);}else{var allNodes=node.getElementsByTagName("*");var potentialNode,fullName;for(var i=0,len=allNodes.length;i<len;++i){potentialNode=allNodes[i];fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if((name=="*")||(fullName==potentialNode.nodeName)){if((uri=="*")||(uri==potentialNode.namespaceURI)){elements.push(potentialNode);}}}}
+return elements;},getAttributeNodeNS:function(node,uri,name){var attributeNode=null;if(node.getAttributeNodeNS){attributeNode=node.getAttributeNodeNS(uri,name);}else{var attributes=node.attributes;var potentialNode,fullName;for(var i=0,len=attributes.length;i<len;++i){potentialNode=attributes[i];if(potentialNode.namespaceURI==uri){fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if(fullName==potentialNode.nodeName){attributeNode=potentialNode;break;}}}}
+return attributeNode;},getAttributeNS:function(node,uri,name){var attributeValue="";if(node.getAttributeNS){attributeValue=node.getAttributeNS(uri,name)||"";}else{var attributeNode=this.getAttributeNodeNS(node,uri,name);if(attributeNode){attributeValue=attributeNode.nodeValue;}}
+return attributeValue;},getChildValue:function(node,def){var value=def||"";if(node){for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 3:case 4:value+=child.nodeValue;}}}
+return value;},concatChildValues:function(node,def){var value="";var child=node.firstChild;var childValue;while(child){childValue=child.nodeValue;if(childValue){value+=childValue;}
+child=child.nextSibling;}
+if(value==""&&def!=undefined){value=def;}
+return value;},isSimpleContent:function(node){var simple=true;for(var child=node.firstChild;child;child=child.nextSibling){if(child.nodeType===1){simple=false;break;}}
+return simple;},contentType:function(node){var simple=false,complex=false;var type=OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 1:complex=true;break;case 8:break;default:simple=true;}
+if(complex&&simple){break;}}
+if(complex&&simple){type=OpenLayers.Format.XML.CONTENT_TYPE.MIXED;}else if(complex){return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;}else if(simple){return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;}
+return type;},hasAttributeNS:function(node,uri,name){var found=false;if(node.hasAttributeNS){found=node.hasAttributeNS(uri,name);}else{found=!!this.getAttributeNodeNS(node,uri,name);}
+return found;},setAttributeNS:function(node,uri,name,value){if(node.setAttributeNS){node.setAttributeNS(uri,name,value);}else{if(this.xmldom){if(uri){var attribute=node.ownerDocument.createNode(2,name,uri);attribute.nodeValue=value;node.setAttributeNode(attribute);}else{node.setAttribute(name,value);}}else{throw"setAttributeNS not implemented";}}},createElementNSPlus:function(name,options){options=options||{};var uri=options.uri||this.namespaces[options.prefix];if(!uri){var loc=name.indexOf(":");uri=this.namespaces[name.substring(0,loc)];}
+if(!uri){uri=this.namespaces[this.defaultPrefix];}
+var node=this.createElementNS(uri,name);if(options.attributes){this.setAttributes(node,options.attributes);}
+var value=options.value;if(value!=null){node.appendChild(this.createTextNode(value));}
+return node;},setAttributes:function(node,obj){var value,uri;for(var name in obj){if(obj[name]!=null&&obj[name].toString){value=obj[name].toString();uri=this.namespaces[name.substring(0,name.indexOf(":"))]||null;this.setAttributeNS(node,uri,name,value);}}},readNode:function(node,obj){if(!obj){obj={};}
+var group=this.readers[node.namespaceURI?this.namespaceAlias[node.namespaceURI]:this.defaultPrefix];if(group){var local=node.localName||node.nodeName.split(":").pop();var reader=group[local]||group["*"];if(reader){reader.apply(this,[node,obj]);}}
+return obj;},readChildNodes:function(node,obj){if(!obj){obj={};}
+var children=node.childNodes;var child;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){this.readNode(child,obj);}}
+return obj;},writeNode:function(name,obj,parent){var prefix,local;var split=name.indexOf(":");if(split>0){prefix=name.substring(0,split);local=name.substring(split+1);}else{if(parent){prefix=this.namespaceAlias[parent.namespaceURI];}else{prefix=this.defaultPrefix;}
+local=name;}
+var child=this.writers[prefix][local].apply(this,[obj]);if(parent){parent.appendChild(child);}
+return child;},getChildEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.firstChild,name,uri);},getNextEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.nextSibling,name,uri);},getThisOrNextEl:function(node,name,uri){outer:for(var sibling=node;sibling;sibling=sibling.nextSibling){switch(sibling.nodeType){case 1:if((!name||name===(sibling.localName||sibling.nodeName.split(":").pop()))&&(!uri||uri===sibling.namespaceURI)){break outer;}
+sibling=null;break outer;case 3:if(/^\s*$/.test(sibling.nodeValue)){break;}
+case 4:case 6:case 12:case 10:case 11:sibling=null;break outer;}}
+return sibling||null;},lookupNamespaceURI:function(node,prefix){var uri=null;if(node){if(node.lookupNamespaceURI){uri=node.lookupNamespaceURI(prefix);}else{outer:switch(node.nodeType){case 1:if(node.namespaceURI!==null&&node.prefix===prefix){uri=node.namespaceURI;break outer;}
+var len=node.attributes.length;if(len){var attr;for(var i=0;i<len;++i){attr=node.attributes[i];if(attr.prefix==="xmlns"&&attr.name==="xmlns:"+prefix){uri=attr.value||null;break outer;}else if(attr.name==="xmlns"&&prefix===null){uri=attr.value||null;break outer;}}}
+uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;case 2:uri=this.lookupNamespaceURI(node.ownerElement,prefix);break outer;case 9:uri=this.lookupNamespaceURI(node.documentElement,prefix);break outer;case 6:case 12:case 10:case 11:break outer;default:uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;}}}
+return uri;},getXMLDoc:function(){if(!OpenLayers.Format.XML.document&&!this.xmldom){if(document.implementation&&document.implementation.createDocument){OpenLayers.Format.XML.document=document.implementation.createDocument("","",null);}else if(!this.xmldom&&window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}}
+return OpenLayers.Format.XML.document||this.xmldom;},CLASS_NAME:"OpenLayers.Format.XML"});OpenLayers.Format.XML.CONTENT_TYPE={EMPTY:0,SIMPLE:1,COMPLEX:2,MIXED:3};OpenLayers.Format.XML.lookupNamespaceURI=OpenLayers.Function.bind(OpenLayers.Format.XML.prototype.lookupNamespaceURI,OpenLayers.Format.XML.prototype);OpenLayers.Format.XML.document=null;OpenLayers.Format.OGCExceptionReport=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},defaultPrefix:"ogc",read:function(data){var result;if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var root=data.documentElement;var exceptionInfo={exceptionReport:null};if(root){this.readChildNodes(data,exceptionInfo);if(exceptionInfo.exceptionReport===null){exceptionInfo=new OpenLayers.Format.OWSCommon().read(data);}}
+return exceptionInfo;},readers:{"ogc":{"ServiceExceptionReport":function(node,obj){obj.exceptionReport={exceptions:[]};this.readChildNodes(node,obj.exceptionReport);},"ServiceException":function(node,exceptionReport){var exception={code:node.getAttribute("code"),locator:node.getAttribute("locator"),text:this.getChildValue(node)};exceptionReport.exceptions.push(exception);}}},CLASS_NAME:"OpenLayers.Format.OGCExceptionReport"});OpenLayers.Format.XML.VersionedOGC=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:null,version:null,profile:null,errorProperty:null,name:null,stringifyOutput:false,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);var className=this.CLASS_NAME;this.name=className.substring(className.lastIndexOf(".")+1);},getVersion:function(root,options){var version;if(root){version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}}}else{version=(options&&options.version)||this.version||this.defaultVersion;}
+return version;},getParser:function(version){version=version||this.defaultVersion;var profile=this.profile?"_"+this.profile:"";if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format[this.name]["v"+version.replace(/\./g,"_")+profile];if(!format){throw"Can't find a "+this.name+" parser for version "+
+version+profile;}
+this.parser=new format(this.options);}
+return this.parser;},write:function(obj,options){var version=this.getVersion(null,options);this.parser=this.getParser(version);var root=this.parser.write(obj,options);if(this.stringifyOutput===false){return root;}else{return OpenLayers.Format.XML.prototype.write.apply(this,[root]);}},read:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var root=data.documentElement;var version=this.getVersion(root);this.parser=this.getParser(version);var obj=this.parser.read(data,options);if(this.errorProperty!==null&&obj[this.errorProperty]===undefined){var format=new OpenLayers.Format.OGCExceptionReport();obj.error=format.read(data);}
+obj.version=version;return obj;},CLASS_NAME:"OpenLayers.Format.XML.VersionedOGC"});OpenLayers.Filter=OpenLayers.Class({initialize:function(options){OpenLayers.Util.extend(this,options);},destroy:function(){},evaluate:function(context){return true;},clone:function(){return null;},CLASS_NAME:"OpenLayers.Filter"});OpenLayers.Filter.FeatureId=OpenLayers.Class(OpenLayers.Filter,{fids:null,type:"FID",initialize:function(options){this.fids=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){for(var i=0,len=this.fids.length;i<len;i++){var fid=feature.fid||feature.id;if(fid==this.fids[i]){return true;}}
+return false;},clone:function(){var filter=new OpenLayers.Filter.FeatureId();OpenLayers.Util.extend(filter,this);filter.fids=this.fids.slice();return filter;},CLASS_NAME:"OpenLayers.Filter.FeatureId"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(options){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this);},evaluate:function(context){var i,len;switch(this.type){case OpenLayers.Filter.Logical.AND:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==false){return false;}}
+return true;case OpenLayers.Filter.Logical.OR:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==true){return true;}}
+return false;case OpenLayers.Filter.Logical.NOT:return(!this.filters[0].evaluate(context));}
+return undefined;},clone:function(){var filters=[];for(var i=0,len=this.filters.length;i<len;++i){filters.push(this.filters[i].clone());}
+return new OpenLayers.Filter.Logical({type:this.type,filters:filters});},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:true,lowerBoundary:null,upperBoundary:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);if(this.type===OpenLayers.Filter.Comparison.LIKE&&options.matchCase===undefined){this.matchCase=null;}},evaluate:function(context){if(context instanceof OpenLayers.Feature.Vector){context=context.attributes;}
+var result=false;var got=context[this.property];var exp;switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()==exp.toUpperCase());}else{result=(got==exp);}
+break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()!=exp.toUpperCase());}else{result=(got!=exp);}
+break;case OpenLayers.Filter.Comparison.LESS_THAN:result=got<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:result=got>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;}
+return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){var msg="'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison";OpenLayers.Console.error(msg);return null;}
+wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(),this);},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){var intersect=false;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(feature.geometry){var geom=this.value;if(this.value.CLASS_NAME=="OpenLayers.Bounds"){geom=this.value.toGeometry();}
+if(feature.geometry.intersects(geom)){intersect=true;}}
+break;default:OpenLayers.Console.error(OpenLayers.i18n("filterEvaluateNotImplemented"));break;}
+return intersect;},clone:function(){var options=OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(options);},CLASS_NAME:"OpenLayers.Filter.Spatial"});OpenLayers.Filter.Spatial.BBOX="BBOX";OpenLayers.Filter.Spatial.INTERSECTS="INTERSECTS";OpenLayers.Filter.Spatial.DWITHIN="DWITHIN";OpenLayers.Filter.Spatial.WITHIN="WITHIN";OpenLayers.Filter.Spatial.CONTAINS="CONTAINS";OpenLayers.Format.SLD=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",stringifyOutput:true,namedLayersAsArray:false,CLASS_NAME:"OpenLayers.Format.SLD"});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){this.id=null;this.bounds=null;},clone:function(){return new OpenLayers.Geometry();},setBounds:function(bounds){if(bounds){this.bounds=bounds.clone();}},clearBounds:function(){this.bounds=null;if(this.parent){this.parent.clearBounds();}},extendBounds:function(newBounds){var bounds=this.getBounds();if(!bounds){this.setBounds(newBounds);}else{this.bounds.extend(newBounds);}},getBounds:function(){if(this.bounds==null){this.calculateBounds();}
+return this.bounds;},calculateBounds:function(){},distanceTo:function(geometry,options){},getVertices:function(nodes){},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;var bounds=this.getBounds();if((bounds!=null)&&(lonlat!=null)){var dX=(toleranceLon!=null)?toleranceLon:0;var dY=(toleranceLat!=null)?toleranceLat:0;var toleranceBounds=new OpenLayers.Bounds(this.bounds.left-dX,this.bounds.bottom-dY,this.bounds.right+dX,this.bounds.top+dY);atPoint=toleranceBounds.containsLonLat(lonlat);}
+return atPoint;},getLength:function(){return 0.0;},getArea:function(){return 0.0;},getCentroid:function(){return null;},toString:function(){return OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this));},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(wkt){var format=arguments.callee.format;if(!format){format=new OpenLayers.Format.WKT();arguments.callee.format=format;}
+var geom;var result=format.read(wkt);if(result instanceof OpenLayers.Feature.Vector){geom=result.geometry;}else if(OpenLayers.Util.isArray(result)){var len=result.length;var components=new Array(len);for(var i=0;i<len;++i){components[i]=result[i].geometry;}
+geom=new OpenLayers.Geometry.Collection(components);}
+return geom;};OpenLayers.Geometry.segmentsIntersect=function(seg1,seg2,options){var point=options&&options.point;var tolerance=options&&options.tolerance;var intersection=false;var x11_21=seg1.x1-seg2.x1;var y11_21=seg1.y1-seg2.y1;var x12_11=seg1.x2-seg1.x1;var y12_11=seg1.y2-seg1.y1;var y22_21=seg2.y2-seg2.y1;var x22_21=seg2.x2-seg2.x1;var d=(y22_21*x12_11)-(x22_21*y12_11);var n1=(x22_21*y11_21)-(y22_21*x11_21);var n2=(x12_11*y11_21)-(y12_11*x11_21);if(d==0){if(n1==0&&n2==0){intersection=true;}}else{var along1=n1/d;var along2=n2/d;if(along1>=0&&along1<=1&&along2>=0&&along2<=1){if(!point){intersection=true;}else{var x=seg1.x1+(along1*x12_11);var y=seg1.y1+(along1*y12_11);intersection=new OpenLayers.Geometry.Point(x,y);}}}
+if(tolerance){var dist;if(intersection){if(point){var segs=[seg1,seg2];var seg,x,y;outer:for(var i=0;i<2;++i){seg=segs[i];for(var j=1;j<3;++j){x=seg["x"+j];y=seg["y"+j];dist=Math.sqrt(Math.pow(x-intersection.x,2)+
+Math.pow(y-intersection.y,2));if(dist<tolerance){intersection.x=x;intersection.y=y;break outer;}}}}}else{var segs=[seg1,seg2];var source,target,x,y,p,result;outer:for(var i=0;i<2;++i){source=segs[i];target=segs[(i+1)%2];for(var j=1;j<3;++j){p={x:source["x"+j],y:source["y"+j]};result=OpenLayers.Geometry.distanceToSegment(p,target);if(result.distance<tolerance){if(point){intersection=new OpenLayers.Geometry.Point(p.x,p.y);}else{intersection=true;}
+break outer;}}}}}
+return intersection;};OpenLayers.Geometry.distanceToSegment=function(point,segment){var x0=point.x;var y0=point.y;var x1=segment.x1;var y1=segment.y1;var x2=segment.x2;var y2=segment.y2;var dx=x2-x1;var dy=y2-y1;var along=((dx*(x0-x1))+(dy*(y0-y1)))/(Math.pow(dx,2)+Math.pow(dy,2));var x,y;if(along<=0.0){x=x1;y=y1;}else if(along>=1.0){x=x2;y=y2;}else{x=x1+along*dx;y=y1+along*dy;}
+return{distance:Math.sqrt(Math.pow(x-x0,2)+Math.pow(y-y0,2)),x:x,y:y};};OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(x,y){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(x);this.y=parseFloat(y);},clone:function(obj){if(obj==null){obj=new OpenLayers.Geometry.Point(this.x,this.y);}
+OpenLayers.Util.applyDefaults(obj,this);return obj;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y);},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var distance,x0,y0,x1,y1,result;if(geometry instanceof OpenLayers.Geometry.Point){x0=this.x;y0=this.y;x1=geometry.x;y1=geometry.y;distance=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));result=!details?distance:{x0:x0,y0:y0,x1:x1,y1:y1,distance:distance};}else{result=geometry.distanceTo(this,options);if(details){result={x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0,distance:result.distance};}}
+return result;},equals:function(geom){var equals=false;if(geom!=null){equals=((this.x==geom.x&&this.y==geom.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(geom.x)&&isNaN(geom.y)));}
+return equals;},toShortString:function(){return(this.x+", "+this.y);},move:function(x,y){this.x=this.x+x;this.y=this.y+y;this.clearBounds();},rotate:function(angle,origin){angle*=Math.PI/180;var radius=this.distanceTo(origin);var theta=angle+Math.atan2(this.y-origin.y,this.x-origin.x);this.x=origin.x+(radius*Math.cos(theta));this.y=origin.y+(radius*Math.sin(theta));this.clearBounds();},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y);},resize:function(scale,origin,ratio){ratio=(ratio==undefined)?1:ratio;this.x=origin.x+(scale*ratio*(this.x-origin.x));this.y=origin.y+(scale*(this.y-origin.y));this.clearBounds();return this;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.equals(geometry);}else{intersect=geometry.intersects(this);}
+return intersect;},transform:function(source,dest){if((source&&dest)){OpenLayers.Projection.transform(this,source,dest);this.bounds=null;}
+return this;},getVertices:function(nodes){return[this];},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(components){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];if(components!=null){this.addComponents(components);}},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments);},clone:function(){var geometry=eval("new "+this.CLASS_NAME+"()");for(var i=0,len=this.components.length;i<len;i++){geometry.addComponent(this.components[i].clone());}
+OpenLayers.Util.applyDefaults(geometry,this);return geometry;},getComponentsString:function(){var strings=[];for(var i=0,len=this.components.length;i<len;i++){strings.push(this.components[i].toShortString());}
+return strings.join(",");},calculateBounds:function(){this.bounds=null;var bounds=new OpenLayers.Bounds();var components=this.components;if(components){for(var i=0,len=components.length;i<len;i++){bounds.extend(components[i].getBounds());}}
+if(bounds.left!=null&&bounds.bottom!=null&&bounds.right!=null&&bounds.top!=null){this.setBounds(bounds);}},addComponents:function(components){if(!(OpenLayers.Util.isArray(components))){components=[components];}
+for(var i=0,len=components.length;i<len;i++){this.addComponent(components[i]);}},addComponent:function(component,index){var added=false;if(component){if(this.componentTypes==null||(OpenLayers.Util.indexOf(this.componentTypes,component.CLASS_NAME)>-1)){if(index!=null&&(index<this.components.length)){var components1=this.components.slice(0,index);var components2=this.components.slice(index,this.components.length);components1.push(component);this.components=components1.concat(components2);}else{this.components.push(component);}
+component.parent=this;this.clearBounds();added=true;}}
+return added;},removeComponents:function(components){var removed=false;if(!(OpenLayers.Util.isArray(components))){components=[components];}
+for(var i=components.length-1;i>=0;--i){removed=this.removeComponent(components[i])||removed;}
+return removed;},removeComponent:function(component){OpenLayers.Util.removeItem(this.components,component);this.clearBounds();return true;},getLength:function(){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getLength();}
+return length;},getArea:function(){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getArea();}
+return area;},getGeodesicArea:function(projection){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getGeodesicArea(projection);}
+return area;},getCentroid:function(weighted){if(!weighted){return this.components.length&&this.components[0].getCentroid();}
+var len=this.components.length;if(!len){return false;}
+var areas=[];var centroids=[];var areaSum=0;var minArea=Number.MAX_VALUE;var component;for(var i=0;i<len;++i){component=this.components[i];var area=component.getArea();var centroid=component.getCentroid(true);if(isNaN(area)||isNaN(centroid.x)||isNaN(centroid.y)){continue;}
+areas.push(area);areaSum+=area;minArea=(area<minArea&&area>0)?area:minArea;centroids.push(centroid);}
+len=areas.length;if(areaSum===0){for(var i=0;i<len;++i){areas[i]=1;}
+areaSum=areas.length;}else{for(var i=0;i<len;++i){areas[i]/=minArea;}
+areaSum/=minArea;}
+var xSum=0,ySum=0,centroid,area;for(var i=0;i<len;++i){centroid=centroids[i];area=areas[i];xSum+=centroid.x*area;ySum+=centroid.y*area;}
+return new OpenLayers.Geometry.Point(xSum/areaSum,ySum/areaSum);},getGeodesicLength:function(projection){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getGeodesicLength(projection);}
+return length;},move:function(x,y){for(var i=0,len=this.components.length;i<len;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0;i<this.components.length;++i){this.components[i].resize(scale,origin,ratio);}
+return this;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best,distance;var min=Number.POSITIVE_INFINITY;for(var i=0,len=this.components.length;i<len;++i){result=this.components[i].distanceTo(geometry,options);distance=details?result.distance:result;if(distance<min){min=distance;best=result;if(min==0){break;}}}
+return best;},equals:function(geometry){var equivalent=true;if(!geometry||!geometry.CLASS_NAME||(this.CLASS_NAME!=geometry.CLASS_NAME)){equivalent=false;}else if(!(OpenLayers.Util.isArray(geometry.components))||(geometry.components.length!=this.components.length)){equivalent=false;}else{for(var i=0,len=this.components.length;i<len;++i){if(!this.components[i].equals(geometry.components[i])){equivalent=false;break;}}}
+return equivalent;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len;i++){var component=this.components[i];component.transform(source,dest);}
+this.bounds=null;}
+return this;},intersects:function(geometry){var intersect=false;for(var i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
+return intersect;},getVertices:function(nodes){var vertices=[];for(var i=0,len=this.components.length;i<len;++i){Array.prototype.push.apply(vertices,this.components[i].getVertices(nodes));}
+return vertices;},CLASS_NAME:"OpenLayers.Geometry.Collection"});OpenLayers.Geometry.MultiPoint=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},addPoint:function(point,index){this.addComponent(point,index);},removePoint:function(point){this.removeComponent(point);},CLASS_NAME:"OpenLayers.Geometry.MultiPoint"});OpenLayers.Geometry.Curve=OpenLayers.Class(OpenLayers.Geometry.MultiPoint,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.MultiPoint.prototype.initialize.apply(this,arguments);},getLength:function(){var length=0.0;if(this.components&&(this.components.length>1)){for(var i=1,len=this.components.length;i<len;i++){length+=this.components[i-1].distanceTo(this.components[i]);}}
+return length;},getGeodesicLength:function(projection){var geom=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){geom=this.clone().transform(projection,gg);}}
+var length=0.0;if(geom.components&&(geom.components.length>1)){var p1,p2;for(var i=1,len=geom.components.length;i<len;i++){p1=geom.components[i-1];p2=geom.components[i];length+=OpenLayers.Util.distVincenty({lon:p1.x,lat:p1.y},{lon:p2.x,lat:p2.y});}}
+return length*1000;},CLASS_NAME:"OpenLayers.Geometry.Curve"});OpenLayers.Geometry.LineString=OpenLayers.Class(OpenLayers.Geometry.Curve,{initialize:function(points){OpenLayers.Geometry.Curve.prototype.initialize.apply(this,arguments);},removeComponent:function(point){var removed=this.components&&(this.components.length>2);if(removed){OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);}
+return removed;},intersects:function(geometry){var intersect=false;var type=geometry.CLASS_NAME;if(type=="OpenLayers.Geometry.LineString"||type=="OpenLayers.Geometry.LinearRing"||type=="OpenLayers.Geometry.Point"){var segs1=this.getSortedSegments();var segs2;if(type=="OpenLayers.Geometry.Point"){segs2=[{x1:geometry.x,y1:geometry.y,x2:geometry.x,y2:geometry.y}];}else{segs2=geometry.getSortedSegments();}
+var seg1,seg1x1,seg1x2,seg1y1,seg1y2,seg2,seg2y1,seg2y2;outer:for(var i=0,len=segs1.length;i<len;++i){seg1=segs1[i];seg1x1=seg1.x1;seg1x2=seg1.x2;seg1y1=seg1.y1;seg1y2=seg1.y2;inner:for(var j=0,jlen=segs2.length;j<jlen;++j){seg2=segs2[j];if(seg2.x1>seg1x2){break;}
+if(seg2.x2<seg1x1){continue;}
+seg2y1=seg2.y1;seg2y2=seg2.y2;if(Math.min(seg2y1,seg2y2)>Math.max(seg1y1,seg1y2)){continue;}
+if(Math.max(seg2y1,seg2y2)<Math.min(seg1y1,seg1y2)){continue;}
+if(OpenLayers.Geometry.segmentsIntersect(seg1,seg2)){intersect=true;break outer;}}}}else{intersect=geometry.intersects(this);}
+return intersect;},getSortedSegments:function(){var numSeg=this.components.length-1;var segments=new Array(numSeg),point1,point2;for(var i=0;i<numSeg;++i){point1=this.components[i];point2=this.components[i+1];if(point1.x<point2.x){segments[i]={x1:point1.x,y1:point1.y,x2:point2.x,y2:point2.y};}else{segments[i]={x1:point2.x,y1:point2.y,x2:point1.x,y2:point1.y};}}
+function byX1(seg1,seg2){return seg1.x1-seg2.x1;}
+return segments.sort(byX1);},splitWithSegment:function(seg,options){var edge=!(options&&options.edge===false);var tolerance=options&&options.tolerance;var lines=[];var verts=this.getVertices();var points=[];var intersections=[];var split=false;var vert1,vert2,point;var node,vertex,target;var interOptions={point:true,tolerance:tolerance};var result=null;for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];points.push(vert1.clone());vert2=verts[i+1];target={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};point=OpenLayers.Geometry.segmentsIntersect(seg,target,interOptions);if(point instanceof OpenLayers.Geometry.Point){if((point.x===seg.x1&&point.y===seg.y1)||(point.x===seg.x2&&point.y===seg.y2)||point.equals(vert1)||point.equals(vert2)){vertex=true;}else{vertex=false;}
+if(vertex||edge){if(!point.equals(intersections[intersections.length-1])){intersections.push(point.clone());}
+if(i===0){if(point.equals(vert1)){continue;}}
+if(point.equals(vert2)){continue;}
+split=true;if(!point.equals(vert1)){points.push(point);}
+lines.push(new OpenLayers.Geometry.LineString(points));points=[point.clone()];}}}
+if(split){points.push(vert2.clone());lines.push(new OpenLayers.Geometry.LineString(points));}
+if(intersections.length>0){var xDir=seg.x1<seg.x2?1:-1;var yDir=seg.y1<seg.y2?1:-1;result={lines:lines,points:intersections.sort(function(p1,p2){return(xDir*p1.x-xDir*p2.x)||(yDir*p1.y-yDir*p2.y);})};}
+return result;},split:function(target,options){var results=null;var mutual=options&&options.mutual;var sourceSplit,targetSplit,sourceParts,targetParts;if(target instanceof OpenLayers.Geometry.LineString){var verts=this.getVertices();var vert1,vert2,seg,splits,lines,point;var points=[];sourceParts=[];for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];vert2=verts[i+1];seg={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};targetParts=targetParts||[target];if(mutual){points.push(vert1.clone());}
+for(var j=0;j<targetParts.length;++j){splits=targetParts[j].splitWithSegment(seg,options);if(splits){lines=splits.lines;if(lines.length>0){lines.unshift(j,1);Array.prototype.splice.apply(targetParts,lines);j+=lines.length-2;}
+if(mutual){for(var k=0,len=splits.points.length;k<len;++k){point=splits.points[k];if(!point.equals(vert1)){points.push(point);sourceParts.push(new OpenLayers.Geometry.LineString(points));if(point.equals(vert2)){points=[];}else{points=[point.clone()];}}}}}}}
+if(mutual&&sourceParts.length>0&&points.length>0){points.push(vert2.clone());sourceParts.push(new OpenLayers.Geometry.LineString(points));}}else{results=target.splitWith(this,options);}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetSplit||sourceSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){return geometry.split(this,options);},getVertices:function(nodes){var vertices;if(nodes===true){vertices=[this.components[0],this.components[this.components.length-1]];}else if(nodes===false){vertices=this.components.slice(1,this.components.length-1);}else{vertices=this.components.slice();}
+return vertices;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best={};var min=Number.POSITIVE_INFINITY;if(geometry instanceof OpenLayers.Geometry.Point){var segs=this.getSortedSegments();var x=geometry.x;var y=geometry.y;var seg;for(var i=0,len=segs.length;i<len;++i){seg=segs[i];result=OpenLayers.Geometry.distanceToSegment(geometry,seg);if(result.distance<min){min=result.distance;best=result;if(min===0){break;}}else{if(seg.x2>x&&((y>seg.y1&&y<seg.y2)||(y<seg.y1&&y>seg.y2))){break;}}}
+if(details){best={distance:best.distance,x0:best.x,y0:best.y,x1:x,y1:y};}else{best=best.distance;}}else if(geometry instanceof OpenLayers.Geometry.LineString){var segs0=this.getSortedSegments();var segs1=geometry.getSortedSegments();var seg0,seg1,intersection,x0,y0;var len1=segs1.length;var interOptions={point:true};outer:for(var i=0,len=segs0.length;i<len;++i){seg0=segs0[i];x0=seg0.x1;y0=seg0.y1;for(var j=0;j<len1;++j){seg1=segs1[j];intersection=OpenLayers.Geometry.segmentsIntersect(seg0,seg1,interOptions);if(intersection){min=0;best={distance:0,x0:intersection.x,y0:intersection.y,x1:intersection.x,y1:intersection.y};break outer;}else{result=OpenLayers.Geometry.distanceToSegment({x:x0,y:y0},seg1);if(result.distance<min){min=result.distance;best={distance:min,x0:x0,y0:y0,x1:result.x,y1:result.y};}}}}
+if(!details){best=best.distance;}
+if(min!==0){if(seg0){result=geometry.distanceTo(new OpenLayers.Geometry.Point(seg0.x2,seg0.y2),options);var dist=details?result.distance:result;if(dist<min){if(details){best={distance:min,x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0};}else{best=dist;}}}}}else{best=geometry.distanceTo(this,options);if(details){best={distance:best.distance,x0:best.x1,y0:best.y1,x1:best.x0,y1:best.y0};}}
+return best;},simplify:function(tolerance){if(this&&this!==null){var points=this.getVertices();if(points.length<3){return this;}
+var compareNumbers=function(a,b){return(a-b);};var douglasPeuckerReduction=function(points,firstPoint,lastPoint,tolerance){var maxDistance=0;var indexFarthest=0;for(var index=firstPoint,distance;index<lastPoint;index++){distance=perpendicularDistance(points[firstPoint],points[lastPoint],points[index]);if(distance>maxDistance){maxDistance=distance;indexFarthest=index;}}
+if(maxDistance>tolerance&&indexFarthest!=firstPoint){pointIndexsToKeep.push(indexFarthest);douglasPeuckerReduction(points,firstPoint,indexFarthest,tolerance);douglasPeuckerReduction(points,indexFarthest,lastPoint,tolerance);}};var perpendicularDistance=function(point1,point2,point){var area=Math.abs(0.5*(point1.x*point2.y+point2.x*point.y+point.x*point1.y-point2.x*point1.y-point.x*point2.y-point1.x*point.y));var bottom=Math.sqrt(Math.pow(point1.x-point2.x,2)+Math.pow(point1.y-point2.y,2));var height=area/bottom*2;return height;};var firstPoint=0;var lastPoint=points.length-1;var pointIndexsToKeep=[];pointIndexsToKeep.push(firstPoint);pointIndexsToKeep.push(lastPoint);while(points[firstPoint].equals(points[lastPoint])){lastPoint--;pointIndexsToKeep.push(lastPoint);}
+douglasPeuckerReduction(points,firstPoint,lastPoint,tolerance);var returnPoints=[];pointIndexsToKeep.sort(compareNumbers);for(var index=0;index<pointIndexsToKeep.length;index++){returnPoints.push(points[pointIndexsToKeep[index]]);}
+return new OpenLayers.Geometry.LineString(returnPoints);}
+else{return this;}},CLASS_NAME:"OpenLayers.Geometry.LineString"});OpenLayers.Geometry.MultiLineString=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LineString"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},split:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,sourceLine,sourceLines,sourceSplit,targetSplit;var sourceParts=[];var targetParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){sourceLine=this.components[i];sourceSplit=false;for(var j=0;j<targetParts.length;++j){splits=sourceLine.split(targetParts[j],options);if(splits){if(mutual){sourceLines=splits[0];for(var k=0,klen=sourceLines.length;k<klen;++k){if(k===0&&sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLines[k]);}else{sourceParts.push(new OpenLayers.Geometry.MultiLineString([sourceLines[k]]));}}
+sourceSplit=true;splits=splits[1];}
+if(splits.length){splits.unshift(j,1);Array.prototype.splice.apply(targetParts,splits);break;}}}
+if(!sourceSplit){if(sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLine.clone());}else{sourceParts=[new OpenLayers.Geometry.MultiLineString(sourceLine.clone())];}}}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,targetLine,sourceLines,sourceSplit,targetSplit,sourceParts,targetParts;if(geometry instanceof OpenLayers.Geometry.LineString){targetParts=[];sourceParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){targetSplit=false;targetLine=this.components[i];for(var j=0;j<sourceParts.length;++j){splits=sourceParts[j].split(targetLine,options);if(splits){if(mutual){sourceLines=splits[0];if(sourceLines.length){sourceLines.unshift(j,1);Array.prototype.splice.apply(sourceParts,sourceLines);j+=sourceLines.length-2;}
+splits=splits[1];if(splits.length===0){splits=[targetLine.clone()];}}
+for(var k=0,klen=splits.length;k<klen;++k){if(k===0&&targetParts.length){targetParts[targetParts.length-1].addComponent(splits[k]);}else{targetParts.push(new OpenLayers.Geometry.MultiLineString([splits[k]]));}}
+targetSplit=true;}}
+if(!targetSplit){if(targetParts.length){targetParts[targetParts.length-1].addComponent(targetLine.clone());}else{targetParts=[new OpenLayers.Geometry.MultiLineString([targetLine.clone()])];}}}}else{results=geometry.split(this);}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.LineString.prototype.initialize.apply(this,arguments);},addComponent:function(point,index){var added=false;var lastPoint=this.components.pop();if(index!=null||!point.equals(lastPoint)){added=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments);}
+var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);return added;},removeComponent:function(point){var removed=this.components&&(this.components.length>3);if(removed){this.components.pop();OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);}
+return removed;},move:function(x,y){for(var i=0,len=this.components.length;i<len-1;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].resize(scale,origin,ratio);}
+return this;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len-1;i++){var component=this.components[i];component.transform(source,dest);}
+this.bounds=null;}
+return this;},getCentroid:function(){if(this.components&&(this.components.length>2)){var sumX=0.0;var sumY=0.0;for(var i=0;i<this.components.length-1;i++){var b=this.components[i];var c=this.components[i+1];sumX+=(b.x+c.x)*(b.x*c.y-c.x*b.y);sumY+=(b.y+c.y)*(b.x*c.y-c.x*b.y);}
+var area=-1*this.getArea();var x=sumX/(6*area);var y=sumY/(6*area);return new OpenLayers.Geometry.Point(x,y);}else{return null;}},getArea:function(){var area=0.0;if(this.components&&(this.components.length>2)){var sum=0.0;for(var i=0,len=this.components.length;i<len-1;i++){var b=this.components[i];var c=this.components[i+1];sum+=(b.x+c.x)*(c.y-b.y);}
+area=-sum/2.0;}
+return area;},getGeodesicArea:function(projection){var ring=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){ring=this.clone().transform(projection,gg);}}
+var area=0.0;var len=ring.components&&ring.components.length;if(len>2){var p1,p2;for(var i=0;i<len-1;i++){p1=ring.components[i];p2=ring.components[i+1];area+=OpenLayers.Util.rad(p2.x-p1.x)*(2+Math.sin(OpenLayers.Util.rad(p1.y))+
+Math.sin(OpenLayers.Util.rad(p2.y)));}
+area=area*6378137.0*6378137.0/2.0;}
+return area;},containsPoint:function(point){var approx=OpenLayers.Number.limitSigDigs;var digs=14;var px=approx(point.x,digs);var py=approx(point.y,digs);function getX(y,x1,y1,x2,y2){return(((x1-x2)*y)+((x2*y1)-(x1*y2)))/(y1-y2);}
+var numSeg=this.components.length-1;var start,end,x1,y1,x2,y2,cx,cy;var crosses=0;for(var i=0;i<numSeg;++i){start=this.components[i];x1=approx(start.x,digs);y1=approx(start.y,digs);end=this.components[i+1];x2=approx(end.x,digs);y2=approx(end.y,digs);if(y1==y2){if(py==y1){if(x1<=x2&&(px>=x1&&px<=x2)||x1>=x2&&(px<=x1&&px>=x2)){crosses=-1;break;}}
+continue;}
+cx=approx(getX(py,x1,y1,x2,y2),digs);if(cx==px){if(y1<y2&&(py>=y1&&py<=y2)||y1>y2&&(py<=y1&&py>=y2)){crosses=-1;break;}}
+if(cx<=px){continue;}
+if(x1!=x2&&(cx<Math.min(x1,x2)||cx>Math.max(x1,x2))){continue;}
+if(y1<y2&&(py>=y1&&py<y2)||y1>y2&&(py<y1&&py>=y2)){++crosses;}}
+var contained=(crosses==-1)?1:!!(crosses&1);return contained;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){intersect=geometry.intersects(this);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){intersect=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[geometry]);}else{for(var i=0,len=geometry.components.length;i<len;++i){intersect=geometry.components[i].intersects(this);if(intersect){break;}}}
+return intersect;},getVertices:function(nodes){return(nodes===true)?[]:this.components.slice(0,this.components.length-1);},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},getArea:function(){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getArea());for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getArea());}}
+return area;},getGeodesicArea:function(projection){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getGeodesicArea(projection));for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getGeodesicArea(projection));}}
+return area;},containsPoint:function(point){var numRings=this.components.length;var contained=false;if(numRings>0){contained=this.components[0].containsPoint(point);if(contained!==1){if(contained&&numRings>1){var hole;for(var i=1;i<numRings;++i){hole=this.components[i].containsPoint(point);if(hole){if(hole===1){contained=1;}else{contained=false;}
+break;}}}}}
+return contained;},intersects:function(geometry){var intersect=false;var i,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"||geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){for(i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
+if(!intersect){for(i=0,len=geometry.components.length;i<len;++i){intersect=this.containsPoint(geometry.components[i]);if(intersect){break;}}}}else{for(i=0,len=geometry.components.length;i<len;++i){intersect=this.intersects(geometry.components[i]);if(intersect){break;}}}
+if(!intersect&&geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){var ring=this.components[0];for(i=0,len=ring.components.length;i<len;++i){intersect=geometry.containsPoint(ring.components[i]);if(intersect){break;}}}
+return intersect;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var result;if(!edge&&this.intersects(geometry)){result=0;}else{result=OpenLayers.Geometry.Collection.prototype.distanceTo.apply(this,[geometry,options]);}
+return result;},CLASS_NAME:"OpenLayers.Geometry.Polygon"});OpenLayers.Geometry.Polygon.createRegularPolygon=function(origin,radius,sides,rotation){var angle=Math.PI*((1/sides)-(1/2));if(rotation){angle+=(rotation/180)*Math.PI;}
+var rotatedAngle,x,y;var points=[];for(var i=0;i<sides;++i){rotatedAngle=angle+(i*2*Math.PI/sides);x=origin.x+(radius*Math.cos(rotatedAngle));y=origin.y+(radius*Math.sin(rotatedAngle));points.push(new OpenLayers.Geometry.Point(x,y));}
+var ring=new OpenLayers.Geometry.LinearRing(points);return new OpenLayers.Geometry.Polygon([ring]);};OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Format.GML=OpenLayers.Class(OpenLayers.Format.XML,{featureNS:"http://mapserver.gis.umn.edu/mapserver",featurePrefix:"feature",featureName:"featureMember",layerName:"features",geometryName:"geometry",collectionName:"FeatureCollection",gmlns:"http://www.opengis.net/gml",extractAttributes:true,xy:true,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)};OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var featureNodes=this.getElementsByTagNameNS(data.documentElement,this.gmlns,this.featureName);var features=[];for(var i=0;i<featureNodes.length;i++){var feature=this.parseFeature(featureNodes[i]);if(feature){features.push(feature);}}
+return features;},parseFeature:function(node){var order=["MultiPolygon","Polygon","MultiLineString","LineString","MultiPoint","Point","Envelope"];var type,nodeList,geometry,parser;for(var i=0;i<order.length;++i){type=order[i];nodeList=this.getElementsByTagNameNS(node,this.gmlns,type);if(nodeList.length>0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));}
+break;}}
+var bounds;var boxNodes=this.getElementsByTagNameNS(node,this.gmlns,"Box");for(i=0;i<boxNodes.length;++i){var boxNode=boxNodes[i];var box=this.parseGeometry["box"].apply(this,[boxNode]);var parentNode=boxNode.parentNode;var parentName=parentNode.localName||parentNode.nodeName.split(":").pop();if(parentName==="boundedBy"){bounds=box;}else{geometry=box.toGeometry();}}
+var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);}
+var feature=new OpenLayers.Feature.Vector(geometry,attributes);feature.bounds=bounds;feature.gml={featureType:node.firstChild.nodeName.split(":")[1],featureNS:node.firstChild.namespaceURI,featureNSPrefix:node.firstChild.prefix};var childNode=node.firstChild;var fid;while(childNode){if(childNode.nodeType==1){fid=childNode.getAttribute("fid")||childNode.getAttribute("id");if(fid){break;}}
+childNode=childNode.nextSibling;}
+feature.fid=fid;return feature;},parseGeometry:{point:function(node){var nodeList,coordString;var coords=[];var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"pos");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}}
+if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coord");if(nodeList.length>0){var xList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"X");var yList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"Y");if(xList.length>0&&yList.length>0){coords=[xList[0].firstChild.nodeValue,yList[0].firstChild.nodeValue];}}}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){return new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}
+else{return new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}},multipoint:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Point");var components=[];if(nodeList.length>0){var point;for(var i=0;i<nodeList.length;++i){point=this.parseGeometry.point.apply(this,[nodeList[i]]);if(point){components.push(point);}}}
+return new OpenLayers.Geometry.MultiPoint(components);},linestring:function(node,ring){var nodeList,coordString;var coords=[];var points=[];nodeList=this.getElementsByTagNameNS(node,this.gmlns,"posList");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);var dim=parseInt(nodeList[0].getAttribute("dimension"));var j,x,y,z;for(var i=0;i<coords.length/dim;++i){j=i*dim;x=coords[j];y=coords[j+1];z=(dim==2)?null:coords[j+2];if(this.xy){points.push(new OpenLayers.Geometry.Point(x,y,z));}else{points.push(new OpenLayers.Geometry.Point(y,x,z));}}}
+if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);for(var i=0;i<pointList.length;++i){coords=pointList[i].split(",");if(coords.length==2){coords[2]=null;}
+if(this.xy){points.push(new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]));}else{points.push(new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]));}}}}
+var line=null;if(points.length!=0){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}}
+return line;},multilinestring:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LineString");var components=[];if(nodeList.length>0){var line;for(var i=0;i<nodeList.length;++i){line=this.parseGeometry.linestring.apply(this,[nodeList[i]]);if(line){components.push(line);}}}
+return new OpenLayers.Geometry.MultiLineString(components);},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LinearRing");var components=[];if(nodeList.length>0){var ring;for(var i=0;i<nodeList.length;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components.push(ring);}}}
+return new OpenLayers.Geometry.Polygon(components);},multipolygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Polygon");var components=[];if(nodeList.length>0){var polygon;for(var i=0;i<nodeList.length;++i){polygon=this.parseGeometry.polygon.apply(this,[nodeList[i]]);if(polygon){components.push(polygon);}}}
+return new OpenLayers.Geometry.MultiPolygon(components);},envelope:function(node){var components=[];var coordString;var envelope;var lpoint=this.getElementsByTagNameNS(node,this.gmlns,"lowerCorner");if(lpoint.length>0){var coords=[];if(lpoint.length>0){coordString=lpoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){var lowerPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var lowerPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+var upoint=this.getElementsByTagNameNS(node,this.gmlns,"upperCorner");if(upoint.length>0){var coords=[];if(upoint.length>0){coordString=upoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){var upperPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var upperPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+if(lowerPoint&&upperPoint){components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));var ring=new OpenLayers.Geometry.LinearRing(components);envelope=new OpenLayers.Geometry.Polygon([ring]);}
+return envelope;},box:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");var coordString;var coords,beginPoint=null,endPoint=null;if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coords=coordString.split(" ");if(coords.length==2){beginPoint=coords[0].split(",");endPoint=coords[1].split(",");}}
+if(beginPoint!==null&&endPoint!==null){return new OpenLayers.Bounds(parseFloat(beginPoint[0]),parseFloat(beginPoint[1]),parseFloat(endPoint[0]),parseFloat(endPoint[1]));}}},parseAttributes:function(node){var attributes={};var childNode=node.firstChild;var children,i,child,grandchildren,grandchild,name,value;while(childNode){if(childNode.nodeType==1){children=childNode.childNodes;for(i=0;i<children.length;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length==1){grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}else{attributes[child.nodeName.split(":").pop()]=null;}}}
+break;}
+childNode=childNode.nextSibling;}
+return attributes;},write:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var gml=this.createElementNS("http://www.opengis.net/wfs","wfs:"+this.collectionName);for(var i=0;i<features.length;i++){gml.appendChild(this.createFeatureXML(features[i]));}
+return OpenLayers.Format.XML.prototype.write.apply(this,[gml]);},createFeatureXML:function(feature){var geometry=feature.geometry;var geometryNode=this.buildGeometryNode(geometry);var geomContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
+this.geometryName);geomContainer.appendChild(geometryNode);var featureNode=this.createElementNS(this.gmlns,"gml:"+this.featureName);var featureContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
+this.layerName);var fid=feature.fid||feature.id;featureContainer.setAttribute("fid",fid);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr.substring(attr.lastIndexOf(":")+1);var attrContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
+nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);}
+featureNode.appendChild(featureContainer);return featureNode;},buildGeometryNode:function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];return builder.apply(this,[geometry]);},buildGeometry:{point:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Point");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multipoint:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPoint");var points=geometry.components;var pointMember,pointGeom;for(var i=0;i<points.length;i++){pointMember=this.createElementNS(this.gmlns,"gml:pointMember");pointGeom=this.buildGeometry.point.apply(this,[points[i]]);pointMember.appendChild(pointGeom);gml.appendChild(pointMember);}
+return gml;},linestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LineString");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multilinestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiLineString");var lines=geometry.components;var lineMember,lineGeom;for(var i=0;i<lines.length;++i){lineMember=this.createElementNS(this.gmlns,"gml:lineStringMember");lineGeom=this.buildGeometry.linestring.apply(this,[lines[i]]);lineMember.appendChild(lineGeom);gml.appendChild(lineMember);}
+return gml;},linearring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LinearRing");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},polygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0;i<rings.length;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.gmlns,"gml:"+type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);gml.appendChild(ringMember);}
+return gml;},multipolygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPolygon");var polys=geometry.components;var polyMember,polyGeom;for(var i=0;i<polys.length;++i){polyMember=this.createElementNS(this.gmlns,"gml:polygonMember");polyGeom=this.buildGeometry.polygon.apply(this,[polys[i]]);polyMember.appendChild(polyGeom);gml.appendChild(polyMember);}
+return gml;},bounds:function(bounds){var gml=this.createElementNS(this.gmlns,"gml:Box");gml.appendChild(this.buildCoordinatesNode(bounds));return gml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.gmlns,"gml:coordinates");coordinatesNode.setAttribute("decimal",".");coordinatesNode.setAttribute("cs",",");coordinatesNode.setAttribute("ts"," ");var parts=[];if(geometry instanceof OpenLayers.Bounds){parts.push(geometry.left+","+geometry.bottom);parts.push(geometry.right+","+geometry.top);}else{var points=(geometry.components)?geometry.components:[geometry];for(var i=0;i<points.length;i++){parts.push(points[i].x+","+points[i].y);}}
+var txtNode=this.createTextNode(parts.join(" "));coordinatesNode.appendChild(txtNode);return coordinatesNode;},CLASS_NAME:"OpenLayers.Format.GML"});if(!OpenLayers.Format.GML){OpenLayers.Format.GML={};}
+OpenLayers.Format.GML.Base=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs"},defaultPrefix:"gml",schemaLocation:null,featureType:null,featureNS:null,geometryName:"geometry",extractAttributes:true,srsName:null,xy:true,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g),featureMember:(/^(.*:)?featureMembers?$/)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.setGeometryTypes();if(options&&options.featureNS){this.setNamespace("feature",options.featureNS);}
+this.singleFeatureType=!options||(typeof options.featureType==="string");},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var features=[];this.readNode(data,{features:features},true);if(features.length==0){var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMember");if(elements.length){for(var i=0,len=elements.length;i<len;++i){this.readNode(elements[i],{features:features},true);}}else{var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMembers");if(elements.length){this.readNode(elements[0],{features:features},true);}}}
+return features;},readNode:function(node,obj,first){if(first===true&&this.autoConfig===true){this.featureType=null;delete this.namespaceAlias[this.featureNS];delete this.namespaces["feature"];this.featureNS=null;}
+if(!this.featureNS&&(!(node.prefix in this.namespaces)&&node.parentNode.namespaceURI==this.namespaces["gml"]&&this.regExes.featureMember.test(node.parentNode.nodeName))){this.featureType=node.nodeName.split(":").pop();this.setNamespace("feature",node.namespaceURI);this.featureNS=node.namespaceURI;this.autoConfig=true;}
+return OpenLayers.Format.XML.prototype.readNode.apply(this,[node,obj]);},readers:{"gml":{"featureMember":function(node,obj){this.readChildNodes(node,obj);},"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"name":function(node,obj){obj.name=this.getChildValue(node);},"boundedBy":function(node,obj){var container={};this.readChildNodes(node,container);if(container.components&&container.components.length>0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");if(this.xy){points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{points[i]=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+obj.points=points;},"coord":function(node,obj){var coord={};this.readChildNodes(node,coord);if(!obj.points){obj.points=[];}
+obj.points.push(new OpenLayers.Geometry.Point(coord.x,coord.y,coord.z));},"X":function(node,coord){coord.x=this.getChildValue(node);},"Y":function(node,coord){coord.y=this.getChildValue(node);},"Z":function(node,coord){coord.z=this.getChildValue(node);},"MultiPoint":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPoint(obj.components)];},"pointMember":function(node,obj){this.readChildNodes(node,obj);},"LineString":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"MultiLineString":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];},"lineStringMember":function(node,obj){this.readChildNodes(node,obj);},"Polygon":function(node,container){var obj={outer:null,inner:[]};this.readChildNodes(node,obj);obj.inner.unshift(obj.outer);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.Polygon(obj.inner));},"LinearRing":function(node,obj){var container={};this.readChildNodes(node,container);obj.components=[new OpenLayers.Geometry.LinearRing(container.points)];},"MultiPolygon":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];},"polygonMember":function(node,obj){this.readChildNodes(node,obj);},"GeometryCollection":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.Collection(obj.components)];},"geometryMember":function(node,obj){this.readChildNodes(node,obj);}},"feature":{"*":function(node,obj){var name;var local=node.localName||node.nodeName.split(":").pop();if(obj.features){if(!this.singleFeatureType&&(OpenLayers.Util.indexOf(this.featureType,local)!==-1)){name="_typeName";}else if(local===this.featureType){name="_typeName";}}else{if(node.childNodes.length==0||(node.childNodes.length==1&&node.firstChild.nodeType==3)){if(this.extractAttributes){name="_attribute";}}else{name="_geometry";}}
+if(name){this.readers.feature[name].apply(this,[node,obj]);}},"_typeName":function(node,obj){var container={components:[],attributes:{}};this.readChildNodes(node,container);if(container.name){container.attributes.name=container.name;}
+var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);if(!this.singleFeatureType){feature.type=node.nodeName.split(":").pop();feature.namespace=node.namespaceURI;}
+var fid=node.getAttribute("fid")||this.getAttributeNS(node,this.namespaces["gml"],"id");if(fid){feature.fid=fid;}
+if(this.internalProjection&&this.externalProjection&&feature.geometry){feature.geometry.transform(this.externalProjection,this.internalProjection);}
+if(container.bounds){feature.bounds=container.bounds;}
+obj.features.push(feature);},"_geometry":function(node,obj){if(!this.geometryName){this.geometryName=node.nodeName.split(":").pop();}
+for(var child=node.firstChild;child;child=child.nextSibling){if(null!=child.attributes&&child.attributes.length>0&&null!=child.attributes[0].name){if(child.attributes[0].name.indexOf("xmlns")!=-1){var pref=child.prefix;var URI=child.namespaceURI;if(!OpenLayers.Format.WFST.v1.prototype.namespaces[pref]&&!OpenLayers.Format.WFST.v1_1_0.prototype.readers[pref]){OpenLayers.Format.WFST.v1.prototype.namespaces[pref]=URI;OpenLayers.Format.WFST.v1_1_0.prototype.readers[pref]=OpenLayers.Format.GML.v3.prototype.readers["feature"];this.namespaceAlias[URI]=pref;}}}}
+this.readChildNodes(node,obj);},"_attribute":function(node,obj){var local=node.localName||node.nodeName.split(":").pop();var value=this.getChildValue(node);if(!obj.attributes[local]){obj.attributes[local]=value;}else{obj.attributes[local]=obj.attributes[local]+", "+value;}}},"wfs":{"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);}},},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":{"featureMember":function(feature){var node=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",feature,node);return node;},"MultiPoint":function(geometry){var node=this.createElementNSPlus("gml:MultiPoint");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("pointMember",components[i],node);}
+return node;},"pointMember":function(geometry){var node=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",geometry,node);return node;},"MultiLineString":function(geometry){var node=this.createElementNSPlus("gml:MultiLineString");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("lineStringMember",components[i],node);}
+return node;},"lineStringMember":function(geometry){var node=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",geometry,node);return node;},"MultiPolygon":function(geometry){var node=this.createElementNSPlus("gml:MultiPolygon");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("polygonMember",components[i],node);}
+return node;},"polygonMember":function(geometry){var node=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",geometry,node);return node;},"GeometryCollection":function(geometry){var node=this.createElementNSPlus("gml:GeometryCollection");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("geometryMember",geometry.components[i],node);}
+return node;},"geometryMember":function(geometry){var node=this.createElementNSPlus("gml:geometryMember");var child=this.writeNode("feature:_geometry",geometry);node.appendChild(child.firstChild);return node;}},"feature":{"_typeName":function(feature){var node=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:feature.fid}});if(feature.geometry){this.writeNode("feature:_geometry",feature.geometry,node);}
+for(var name in feature.attributes){var value=feature.attributes[name];if(value!=null){this.writeNode("feature:_attribute",{name:name,value:value},node);}}
+return node;},"_geometry":function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone().transform(this.internalProjection,this.externalProjection);}
+var node=this.createElementNSPlus("feature:"+this.geometryName);var type=this.geometryTypes[geometry.CLASS_NAME];var child=this.writeNode("gml:"+type,geometry,node);if(this.srsName){child.setAttribute("srsName",this.srsName);}
+return node;},"_attribute":function(obj){return this.createElementNSPlus("feature:"+obj.name,{value:obj.value});}},"wfs":{"FeatureCollection":function(features){var node=this.createElementNSPlus("wfs:FeatureCollection");for(var i=0,len=features.length;i<len;++i){this.writeNode("gml:featureMember",features[i],node);}
+return node;}}},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":"LineString","OpenLayers.Geometry.MultiLineString":"MultiLineString","OpenLayers.Geometry.Polygon":"Polygon","OpenLayers.Geometry.MultiPolygon":"MultiPolygon","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.Base"});OpenLayers.Format.GML.v2=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"outerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"innerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"Box":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.readers["wfs"]},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="wfs:FeatureCollection";}else{name="gml:featureMember";}
+var root=this.writeNode(name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("coordinates",[geometry],node);return node;},"coordinates":function(points){var numPoints=points.length;var parts=new Array(numPoints);var point;for(var i=0;i<numPoints;++i){point=points[i];if(this.xy){parts[i]=point.x+","+point.y;}else{parts[i]=point.y+","+point.x;}
+if(point.z!=undefined){parts[i]+=","+point.z;}}
+return this.createElementNSPlus("gml:coordinates",{attributes:{decimal:".",cs:",",ts:" "},value:(numPoints==1)?parts[0]:parts.join(" ")});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("coordinates",geometry.components,node);return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("outerBoundaryIs",geometry.components[0],node);for(var i=1;i<geometry.components.length;++i){this.writeNode("innerBoundaryIs",geometry.components[i],node);}
+return node;},"outerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:outerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"innerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:innerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("coordinates",ring.components,node);return node;},"Box":function(bounds){var node=this.createElementNSPlus("gml:Box");this.writeNode("coordinates",[{x:bounds.left,y:bounds.bottom},{x:bounds.right,y:bounds.top}],node);if(this.srsName){node.setAttribute("srsName",this.srsName);}
+return node;}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},CLASS_NAME:"OpenLayers.Format.GML.v2"});OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Filter.Function=OpenLayers.Class(OpenLayers.Filter,{name:null,params:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Filter.Function"});OpenLayers.Format.Filter.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"ogc",schemaLocation:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var obj={};this.readers.ogc["Filter"].apply(this,[data,obj]);return obj.filter;},readers:{"ogc":{"Filter":function(node,parent){var obj={fids:[],filters:[]};this.readChildNodes(node,obj);if(obj.fids.length>0){parent.filter=new OpenLayers.Filter.FeatureId({fids:obj.fids});}else if(obj.filters.length>0){parent.filter=obj.filters[0];}},"FeatureId":function(node,obj){var fid=node.getAttribute("fid");if(fid){obj.fids.push(fid);}},"And":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND});this.readChildNodes(node,filter);obj.filters.push(filter);},"Or":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.OR});this.readChildNodes(node,filter);obj.filters.push(filter);},"Not":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.NOT});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsBetween":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.BETWEEN});this.readChildNodes(node,filter);obj.filters.push(filter);},"Literal":function(node,obj){obj.value=OpenLayers.String.numericIf(this.getChildValue(node));},"PropertyName":function(node,filter){filter.property=this.getChildValue(node);},"LowerBoundary":function(node,filter){filter.lowerBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"UpperBoundary":function(node,filter){filter.upperBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"Intersects":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.INTERSECTS);},"Within":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.WITHIN);},"Contains":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.CONTAINS);},"DWithin":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.DWITHIN);},"Distance":function(node,obj){obj.distance=parseInt(this.getChildValue(node));obj.distanceUnits=node.getAttribute("units");},"Function":function(node,obj){return;}}},readSpatial:function(node,obj,type){var filter=new OpenLayers.Filter.Spatial({type:type});this.readChildNodes(node,filter);filter.value=filter.components[0];delete filter.components;obj.filters.push(filter);},readOgcExpression:function(node){var obj={};this.readChildNodes(node,obj);var value=obj.value;if(value===undefined){value=this.getChildValue(node);}
+return value;},writeOgcExpression:function(value,node){if(value instanceof OpenLayers.Filter.Function){var child=this.writeNode("Function",value,node);node.appendChild(child);}else{this.writeNode("Literal",value,node);}
+return node;},write:function(filter){return this.writers.ogc["Filter"].apply(this,[filter]);},writeFeatureIdNodes:function(filter,node){for(var i=0,ii=filter.fids.length;i<ii;++i){this.writeNode("FeatureId",filter.fids[i],node);}},writers:{"ogc":{"Filter":function(filter){var node=this.createElementNSPlus("ogc:Filter");if(filter.type==="FID"){this.writeFeatureIdNodes(filter,node);}else{this.writeNode(this.getFilterType(filter),filter,node);}
+return node;},"FeatureId":function(fid){return this.createElementNSPlus("ogc:FeatureId",{attributes:{fid:fid}});},"And":function(filter){var node=this.createElementNSPlus("ogc:And");var childFilter;for(var i=0,ii=filter.filters.length;i<ii;++i){childFilter=filter.filters[i];if(childFilter.type==="FID"){this.writeFeatureIdNodes(childFilter,node);}else{this.writeNode(this.getFilterType(childFilter),childFilter,node);}}
+return node;},"Or":function(filter){var node=this.createElementNSPlus("ogc:Or");var childFilter;for(var i=0,ii=filter.filters.length;i<ii;++i){childFilter=filter.filters[i];if(childFilter.type==="FID"){this.writeFeatureIdNodes(childFilter,node);}else{this.writeNode(this.getFilterType(childFilter),childFilter,node);}}
+return node;},"Not":function(filter){var node=this.createElementNSPlus("ogc:Not");var childFilter=filter.filters[0];if(childFilter.type==="FID"){this.writeFeatureIdNodes(childFilter,node);}else{this.writeNode(this.getFilterType(childFilter),childFilter,node);}
+return node;},"PropertyIsLessThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThan");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsGreaterThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThan");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsLessThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsGreaterThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsBetween":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsBetween");this.writeNode("PropertyName",filter,node);this.writeNode("LowerBoundary",filter,node);this.writeNode("UpperBoundary",filter,node);return node;},"PropertyName":function(filter){return this.createElementNSPlus("ogc:PropertyName",{value:filter.property});},"Literal":function(value){return this.createElementNSPlus("ogc:Literal",{value:value});},"LowerBoundary":function(filter){var node=this.createElementNSPlus("ogc:LowerBoundary");this.writeOgcExpression(filter.lowerBoundary,node);return node;},"UpperBoundary":function(filter){var node=this.createElementNSPlus("ogc:UpperBoundary");this.writeNode("Literal",filter.upperBoundary,node);return node;},"INTERSECTS":function(filter){return this.writeSpatial(filter,"Intersects");},"WITHIN":function(filter){return this.writeSpatial(filter,"Within");},"CONTAINS":function(filter){return this.writeSpatial(filter,"Contains");},"DWITHIN":function(filter){var node=this.writeSpatial(filter,"DWithin");this.writeNode("Distance",filter,node);return node;},"Distance":function(filter){return this.createElementNSPlus("ogc:Distance",{attributes:{units:filter.distanceUnits},value:filter.distance});},"Function":function(filter){var node=this.createElementNSPlus("ogc:Function",{attributes:{name:filter.name}});var params=filter.params;for(var i=0,len=params.length;i<len;i++){this.writeOgcExpression(params[i],node);}
+return node;}}},getFilterType:function(filter){var filterType=this.filterMap[filter.type];if(!filterType){throw"Filter writing not supported for rule type: "+filter.type;}
+return filterType;},filterMap:{"&&":"And","||":"Or","!":"Not","==":"PropertyIsEqualTo","!=":"PropertyIsNotEqualTo","<":"PropertyIsLessThan",">":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike","BBOX":"BBOX","DWITHIN":"DWITHIN","WITHIN":"WITHIN","CONTAINS":"CONTAINS","INTERSECTS":"INTERSECTS","FID":"FeatureId"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Format.Filter.v1_0_0=OpenLayers.Class(OpenLayers.Format.GML.v2,OpenLayers.Format.Filter.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.0.0/filter.xsd",initialize:function(options){OpenLayers.Format.GML.v2.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escape");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.readers["feature"]},writers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo");this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{wildCard:"*",singleChar:".",escape:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");filter.property&&this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Box",filter.value,node);if(filter.projection){box.setAttribute("srsName",filter.projection);}
+return node;}},OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.writers["feature"]},writeSpatial:function(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);if(filter.value instanceof OpenLayers.Filter.Function){this.writeNode("Function",filter.value,node);}else{var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Box",filter.value);}
+if(filter.projection){child.setAttribute("srsName",filter.projection);}
+node.appendChild(child);}
+return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_0_0"});OpenLayers.Format.SLD.v1=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,{namespaces:{sld:"http://www.opengis.net/sld",ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"sld",schemaLocation:null,multipleSymbolizers:false,featureTypeCounter:null,defaultSymbolizer:{fillColor:"#808080",fillOpacity:1,strokeColor:"#000000",strokeOpacity:1,strokeWidth:1,strokeDashstyle:"solid",pointRadius:3,graphicName:"square"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);},read:function(data,options){options=OpenLayers.Util.applyDefaults(options,this.options);var sld={namedLayers:options.namedLayersAsArray===true?[]:{}};this.readChildNodes(data,sld);return sld;},readers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(node,sld){sld.version=node.getAttribute("version");this.readChildNodes(node,sld);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj.description=this.getChildValue(node);},"NamedLayer":function(node,sld){var layer={userStyles:[],namedStyles:[]};this.readChildNodes(node,layer);for(var i=0,len=layer.userStyles.length;i<len;++i){layer.userStyles[i].layerName=layer.name;}
+if(OpenLayers.Util.isArray(sld.namedLayers)){sld.namedLayers.push(layer);}else{sld.namedLayers[layer.name]=layer;}},"NamedStyle":function(node,layer){layer.namedStyles.push(this.getChildName(node.firstChild));},"UserStyle":function(node,layer){var obj={defaultsPerSymbolizer:true,rules:[]};this.featureTypeCounter=-1;this.readChildNodes(node,obj);var style;if(this.multipleSymbolizers){delete obj.defaultsPerSymbolizer;style=new OpenLayers.Style2(obj);}else{style=new OpenLayers.Style(this.defaultSymbolizer,obj);}
+layer.userStyles.push(style);},"IsDefault":function(node,style){if(this.getChildValue(node)=="1"){style.isDefault=true;}},"FeatureTypeStyle":function(node,style){++this.featureTypeCounter;var obj={rules:this.multipleSymbolizers?style.rules:[]};this.readChildNodes(node,obj);if(!this.multipleSymbolizers){style.rules=obj.rules;}},"Rule":function(node,obj){var config;if(this.multipleSymbolizers){config={symbolizers:[]};}
+var rule=new OpenLayers.Rule(config);this.readChildNodes(node,rule);obj.rules.push(rule);},"ElseFilter":function(node,rule){rule.elseFilter=true;},"MinScaleDenominator":function(node,rule){rule.minScaleDenominator=parseFloat(this.getChildValue(node));},"MaxScaleDenominator":function(node,rule){rule.maxScaleDenominator=parseFloat(this.getChildValue(node));},"TextSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Text(config));}else{rule.symbolizer["Text"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Text"]);}},"Label":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);if(obj.property){symbolizer.label="${"+obj.property+"}";}else{var value=this.readOgcExpression(node);if(value){symbolizer.label=value;}}},"Font":function(node,symbolizer){this.readChildNodes(node,symbolizer);},"Halo":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);symbolizer.haloRadius=obj.haloRadius;symbolizer.haloColor=obj.fillColor;symbolizer.haloOpacity=obj.fillOpacity;},"Radius":function(node,symbolizer){var radius=this.readOgcExpression(node);if(radius!=null){symbolizer.haloRadius=radius;}},"RasterSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Raster(config));}else{rule.symbolizer["Raster"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Raster"]);}},"Geometry":function(node,obj){obj.geometry={};this.readChildNodes(node,obj.geometry);},"ColorMap":function(node,symbolizer){symbolizer.colorMap=[];this.readChildNodes(node,symbolizer.colorMap);},"ColorMapEntry":function(node,colorMap){var q=node.getAttribute("quantity");var o=node.getAttribute("opacity");colorMap.push({color:node.getAttribute("color"),quantity:q!==null?parseFloat(q):undefined,label:node.getAttribute("label")||undefined,opacity:o!==null?parseFloat(o):undefined});},"LineSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Line(config));}else{rule.symbolizer["Line"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Line"]);}},"PolygonSymbolizer":function(node,rule){var config={fill:false,stroke:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Polygon"]||config;}
+this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Polygon(config));}else{rule.symbolizer["Polygon"]=config;}},"PointSymbolizer":function(node,rule){var config={fill:false,stroke:false,graphic:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Point"]||config;}
+this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Point(config));}else{rule.symbolizer["Point"]=config;}},"Stroke":function(node,symbolizer){symbolizer.stroke=true;this.readChildNodes(node,symbolizer);},"Fill":function(node,symbolizer){symbolizer.fill=true;this.readChildNodes(node,symbolizer);},"CssParameter":function(node,symbolizer){var cssProperty=node.getAttribute("name");var symProperty=this.cssMap[cssProperty];if(symProperty){var value=this.readOgcExpression(node);if(value){symbolizer[symProperty]=value;}}},"Graphic":function(node,symbolizer){symbolizer.graphic=true;var graphic={};this.readChildNodes(node,graphic);var properties=["stroke","strokeColor","strokeWidth","strokeOpacity","strokeLinecap","fill","fillColor","fillOpacity","graphicName","rotation","graphicFormat"];var prop,value;for(var i=0,len=properties.length;i<len;++i){prop=properties[i];value=graphic[prop];if(value!=undefined){symbolizer[prop]=value;}}
+if(graphic.opacity!=undefined){symbolizer.graphicOpacity=graphic.opacity;}
+if(graphic.size!=undefined){symbolizer.pointRadius=graphic.size/2;}
+if(graphic.href!=undefined){symbolizer.externalGraphic=graphic.href;}
+if(graphic.rotation!=undefined){symbolizer.rotation=graphic.rotation;}},"ExternalGraphic":function(node,graphic){this.readChildNodes(node,graphic);},"Mark":function(node,graphic){this.readChildNodes(node,graphic);},"WellKnownName":function(node,graphic){graphic.graphicName=this.getChildValue(node);},"Opacity":function(node,obj){var opacity=this.readOgcExpression(node);if(opacity){obj.opacity=opacity;}},"Size":function(node,obj){var size=this.readOgcExpression(node);if(size){obj.size=size;}},"Rotation":function(node,obj){var rotation=this.readOgcExpression(node);if(rotation){obj.rotation=rotation;}},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Format":function(node,graphic){graphic.graphicFormat=this.getChildValue(node);}}},OpenLayers.Format.Filter.v1_0_0.prototype.readers),cssMap:{"stroke":"strokeColor","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-dasharray":"strokeDashstyle","fill":"fillColor","fill-opacity":"fillOpacity","font-family":"fontFamily","font-size":"fontSize","font-weight":"fontWeight","font-style":"fontStyle"},getCssProperty:function(sym){var css=null;for(var prop in this.cssMap){if(this.cssMap[prop]==sym){css=prop;break;}}
+return css;},getGraphicFormat:function(href){var format,regex;for(var key in this.graphicFormats){if(this.graphicFormats[key].test(href)){format=key;break;}}
+return format||this.defautlGraphicFormat;},defaultGraphicFormat:"image/png",graphicFormats:{"image/jpeg":/\.jpe?g$/i,"image/gif":/\.gif$/i,"image/png":/\.png$/i},write:function(sld){return this.writers.sld.StyledLayerDescriptor.apply(this,[sld]);},writers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(sld){var root=this.createElementNSPlus("sld:StyledLayerDescriptor",{attributes:{"version":this.VERSION,"xsi:schemaLocation":this.schemaLocation}});root.setAttribute("xmlns:ogc",this.namespaces.ogc);root.setAttribute("xmlns:gml",this.namespaces.gml);if(sld.name){this.writeNode("Name",sld.name,root);}
+if(sld.title){this.writeNode("Title",sld.title,root);}
+if(sld.description){this.writeNode("Abstract",sld.description,root);}
+if(OpenLayers.Util.isArray(sld.namedLayers)){for(var i=0,len=sld.namedLayers.length;i<len;++i){this.writeNode("NamedLayer",sld.namedLayers[i],root);}}else{for(var name in sld.namedLayers){this.writeNode("NamedLayer",sld.namedLayers[name],root);}}
+return root;},"Name":function(name){return this.createElementNSPlus("sld:Name",{value:name});},"Title":function(title){return this.createElementNSPlus("sld:Title",{value:title});},"Abstract":function(description){return this.createElementNSPlus("sld:Abstract",{value:description});},"NamedLayer":function(layer){var node=this.createElementNSPlus("sld:NamedLayer");this.writeNode("Name",layer.name,node);if(layer.namedStyles){for(var i=0,len=layer.namedStyles.length;i<len;++i){this.writeNode("NamedStyle",layer.namedStyles[i],node);}}
+if(layer.userStyles){for(var i=0,len=layer.userStyles.length;i<len;++i){this.writeNode("UserStyle",layer.userStyles[i],node);}}
+return node;},"NamedStyle":function(name){var node=this.createElementNSPlus("sld:NamedStyle");this.writeNode("Name",name,node);return node;},"UserStyle":function(style){var node=this.createElementNSPlus("sld:UserStyle");if(style.name){this.writeNode("Name",style.name,node);}
+if(style.title){this.writeNode("Title",style.title,node);}
+if(style.description){this.writeNode("Abstract",style.description,node);}
+if(style.isDefault){this.writeNode("IsDefault",style.isDefault,node);}
+if(this.multipleSymbolizers&&style.rules){var rulesByZ={0:[]};var zValues=[0];var rule,ruleMap,symbolizer,zIndex,clone;for(var i=0,ii=style.rules.length;i<ii;++i){rule=style.rules[i];if(rule.symbolizers){ruleMap={};for(var j=0,jj=rule.symbolizers.length;j<jj;++j){symbolizer=rule.symbolizers[j];zIndex=symbolizer.zIndex;if(!(zIndex in ruleMap)){clone=rule.clone();clone.symbolizers=[];ruleMap[zIndex]=clone;}
+ruleMap[zIndex].symbolizers.push(symbolizer.clone());}
+for(zIndex in ruleMap){if(!(zIndex in rulesByZ)){zValues.push(zIndex);rulesByZ[zIndex]=[];}
+rulesByZ[zIndex].push(ruleMap[zIndex]);}}else{rulesByZ[0].push(rule.clone());}}
+zValues.sort();var rules;for(var i=0,ii=zValues.length;i<ii;++i){rules=rulesByZ[zValues[i]];if(rules.length>0){clone=style.clone();clone.rules=rulesByZ[zValues[i]];this.writeNode("FeatureTypeStyle",clone,node);}}}else{this.writeNode("FeatureTypeStyle",style,node);}
+return node;},"IsDefault":function(bool){return this.createElementNSPlus("sld:IsDefault",{value:(bool)?"1":"0"});},"FeatureTypeStyle":function(style){var node=this.createElementNSPlus("sld:FeatureTypeStyle");for(var i=0,len=style.rules.length;i<len;++i){this.writeNode("Rule",style.rules[i],node);}
+return node;},"Rule":function(rule){var node=this.createElementNSPlus("sld:Rule");if(rule.name){this.writeNode("Name",rule.name,node);}
+if(rule.title){this.writeNode("Title",rule.title,node);}
+if(rule.description){this.writeNode("Abstract",rule.description,node);}
+if(rule.elseFilter){this.writeNode("ElseFilter",null,node);}else if(rule.filter){this.writeNode("ogc:Filter",rule.filter,node);}
+if(rule.minScaleDenominator!=undefined){this.writeNode("MinScaleDenominator",rule.minScaleDenominator,node);}
+if(rule.maxScaleDenominator!=undefined){this.writeNode("MaxScaleDenominator",rule.maxScaleDenominator,node);}
+var type,symbolizer;if(this.multipleSymbolizers&&rule.symbolizers){var symbolizer;for(var i=0,ii=rule.symbolizers.length;i<ii;++i){symbolizer=rule.symbolizers[i];type=symbolizer.CLASS_NAME.split(".").pop();this.writeNode(type+"Symbolizer",symbolizer,node);}}else{var types=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=types.length;i<len;++i){type=types[i];symbolizer=rule.symbolizer[type];if(symbolizer){this.writeNode(type+"Symbolizer",symbolizer,node);}}}
+return node;},"ElseFilter":function(){return this.createElementNSPlus("sld:ElseFilter");},"MinScaleDenominator":function(scale){return this.createElementNSPlus("sld:MinScaleDenominator",{value:scale});},"MaxScaleDenominator":function(scale){return this.createElementNSPlus("sld:MaxScaleDenominator",{value:scale});},"LineSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:LineSymbolizer");this.writeNode("Stroke",symbolizer,node);return node;},"Stroke":function(symbolizer){var node=this.createElementNSPlus("sld:Stroke");if(symbolizer.strokeColor!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeColor"},node);}
+if(symbolizer.strokeOpacity!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeOpacity"},node);}
+if(symbolizer.strokeWidth!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeWidth"},node);}
+if(symbolizer.strokeDashstyle!=undefined&&symbolizer.strokeDashstyle!=="solid"){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeDashstyle"},node);}
+if(symbolizer.strokeLinecap!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeLinecap"},node);}
+return node;},"CssParameter":function(obj){return this.createElementNSPlus("sld:CssParameter",{attributes:{name:this.getCssProperty(obj.key)},value:obj.symbolizer[obj.key]});},"TextSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:TextSymbolizer");if(symbolizer.label!=null){this.writeNode("Label",symbolizer.label,node);}
+if(symbolizer.fontFamily!=null||symbolizer.fontSize!=null||symbolizer.fontWeight!=null||symbolizer.fontStyle!=null){this.writeNode("Font",symbolizer,node);}
+if(symbolizer.haloRadius!=null||symbolizer.haloColor!=null||symbolizer.haloOpacity!=null){this.writeNode("Halo",symbolizer,node);}
+if(symbolizer.fillColor!=null||symbolizer.fillOpacity!=null){this.writeNode("Fill",symbolizer,node);}
+return node;},"Font":function(symbolizer){var node=this.createElementNSPlus("sld:Font");if(symbolizer.fontFamily){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontFamily"},node);}
+if(symbolizer.fontSize){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontSize"},node);}
+if(symbolizer.fontWeight){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontWeight"},node);}
+if(symbolizer.fontStyle){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontStyle"},node);}
+return node;},"Label":function(label){var node=this.createElementNSPlus("sld:Label");var tokens=label.split("${");node.appendChild(this.createTextNode(tokens[0]));var item,last;for(var i=1,len=tokens.length;i<len;i++){item=tokens[i];last=item.indexOf("}");if(last>0){this.writeNode("ogc:PropertyName",{property:item.substring(0,last)},node);node.appendChild(this.createTextNode(item.substring(++last)));}else{node.appendChild(this.createTextNode("${"+item));}}
+return node;},"Halo":function(symbolizer){var node=this.createElementNSPlus("sld:Halo");if(symbolizer.haloRadius){this.writeNode("Radius",symbolizer.haloRadius,node);}
+if(symbolizer.haloColor||symbolizer.haloOpacity){this.writeNode("Fill",{fillColor:symbolizer.haloColor,fillOpacity:symbolizer.haloOpacity},node);}
+return node;},"Radius":function(value){return this.createElementNSPlus("sld:Radius",{value:value});},"RasterSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:RasterSymbolizer");if(symbolizer.geometry){this.writeNode("Geometry",symbolizer.geometry,node);}
+if(symbolizer.opacity){this.writeNode("Opacity",symbolizer.opacity,node);}
+if(symbolizer.colorMap){this.writeNode("ColorMap",symbolizer.colorMap,node);}
+return node;},"Geometry":function(geometry){var node=this.createElementNSPlus("sld:Geometry");if(geometry.property){this.writeNode("ogc:PropertyName",geometry,node);}
+return node;},"ColorMap":function(colorMap){var node=this.createElementNSPlus("sld:ColorMap");for(var i=0,len=colorMap.length;i<len;++i){this.writeNode("ColorMapEntry",colorMap[i],node);}
+return node;},"ColorMapEntry":function(colorMapEntry){var node=this.createElementNSPlus("sld:ColorMapEntry");var a=colorMapEntry;node.setAttribute("color",a.color);a.opacity!==undefined&&node.setAttribute("opacity",parseFloat(a.opacity));a.quantity!==undefined&&node.setAttribute("quantity",parseFloat(a.quantity));a.label!==undefined&&node.setAttribute("label",a.label);return node;},"PolygonSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PolygonSymbolizer");if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);}
+if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);}
+return node;},"Fill":function(symbolizer){var node=this.createElementNSPlus("sld:Fill");if(symbolizer.fillColor){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillColor"},node);}
+if(symbolizer.fillOpacity!=null){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillOpacity"},node);}
+return node;},"PointSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PointSymbolizer");this.writeNode("Graphic",symbolizer,node);return node;},"Graphic":function(symbolizer){var node=this.createElementNSPlus("sld:Graphic");if(symbolizer.externalGraphic!=undefined){this.writeNode("ExternalGraphic",symbolizer,node);}else{this.writeNode("Mark",symbolizer,node);}
+if(symbolizer.graphicOpacity!=undefined){this.writeNode("Opacity",symbolizer.graphicOpacity,node);}
+if(symbolizer.pointRadius!=undefined){this.writeNode("Size",symbolizer.pointRadius*2,node);}
+if(symbolizer.rotation!=undefined){this.writeNode("Rotation",symbolizer.rotation,node);}
+return node;},"ExternalGraphic":function(symbolizer){var node=this.createElementNSPlus("sld:ExternalGraphic");this.writeNode("OnlineResource",symbolizer.externalGraphic,node);var format=symbolizer.graphicFormat||this.getGraphicFormat(symbolizer.externalGraphic);this.writeNode("Format",format,node);return node;},"Mark":function(symbolizer){var node=this.createElementNSPlus("sld:Mark");if(symbolizer.graphicName){this.writeNode("WellKnownName",symbolizer.graphicName,node);}
+if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);}
+if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);}
+return node;},"WellKnownName":function(name){return this.createElementNSPlus("sld:WellKnownName",{value:name});},"Opacity":function(value){return this.createElementNSPlus("sld:Opacity",{value:value});},"Size":function(value){return this.createElementNSPlus("sld:Size",{value:value});},"Rotation":function(value){return this.createElementNSPlus("sld:Rotation",{value:value});},"OnlineResource":function(href){return this.createElementNSPlus("sld:OnlineResource",{attributes:{"xlink:type":"simple","xlink:href":href}});},"Format":function(format){return this.createElementNSPlus("sld:Format",{value:format});}}},OpenLayers.Format.Filter.v1_0_0.prototype.writers),CLASS_NAME:"OpenLayers.Format.SLD.v1"});OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:false,size:null,resolution:null,map:null,initialize:function(containerID,options){this.container=OpenLayers.Util.getElement(containerID);OpenLayers.Util.extend(this,options);},destroy:function(){this.container=null;this.extent=null;this.size=null;this.resolution=null;this.map=null;},supported:function(){return false;},setExtent:function(extent,resolutionChanged){this.extent=extent.clone();if(resolutionChanged){this.resolution=null;}},setSize:function(size){this.size=size.clone();this.resolution=null;},getResolution:function(){this.resolution=this.resolution||this.map.getResolution();return this.resolution;},drawFeature:function(feature,style){if(style==null){style=feature.style;}
+if(feature.geometry){var bounds=feature.geometry.getBounds();if(bounds){if(!bounds.intersectsBounds(this.extent)){style={display:"none"};}
+var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(style.display!="none"&&style.label&&rendered!==false){var location=feature.geometry.getCentroid();if(style.labelXOffset||style.labelYOffset){var xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;var yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);}
+this.drawText(feature.id,style,location);}else{this.removeText(feature.id);}
+return rendered;}}},drawGeometry:function(geometry,style,featureId){},drawText:function(featureId,style,location){},removeText:function(featureId){},clear:function(){},getFeatureIdFromEvent:function(evt){},eraseFeatures:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+for(var i=0,len=features.length;i<len;++i){var feature=features[i];this.eraseGeometry(feature.geometry,feature.id);this.removeText(feature.id);}},eraseGeometry:function(geometry,featureId){},moveRoot:function(renderer){},getRenderLayerId:function(){return this.container.id;},applyDefaultSymbolizer:function(symbolizer){var result=OpenLayers.Util.extend({},OpenLayers.Renderer.defaultSymbolizer);if(symbolizer.stroke===false){delete result.strokeWidth;delete result.strokeColor;}
+if(symbolizer.fill===false){delete result.fillColor;}
+OpenLayers.Util.extend(result,symbolizer);return result;},CLASS_NAME:"OpenLayers.Renderer"});OpenLayers.Renderer.defaultSymbolizer={fillColor:"#000000",strokeColor:"#000000",strokeWidth:2,fillOpacity:1,strokeOpacity:1,pointRadius:0};OpenLayers.ElementsIndexer=OpenLayers.Class({maxZIndex:null,order:null,indices:null,compare:null,initialize:function(yOrdering){this.compare=yOrdering?OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER:OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;this.clear();},insert:function(newNode){if(this.exists(newNode)){this.remove(newNode);}
+var nodeId=newNode.id;this.determineZIndex(newNode);var leftIndex=-1;var rightIndex=this.order.length;var middle;while(rightIndex-leftIndex>1){middle=parseInt((leftIndex+rightIndex)/2);var placement=this.compare(this,newNode,OpenLayers.Util.getElement(this.order[middle]));if(placement>0){leftIndex=middle;}else{rightIndex=middle;}}
+this.order.splice(rightIndex,0,nodeId);this.indices[nodeId]=this.getZIndex(newNode);return this.getNextElement(rightIndex);},remove:function(node){var nodeId=node.id;var arrayIndex=OpenLayers.Util.indexOf(this.order,nodeId);if(arrayIndex>=0){this.order.splice(arrayIndex,1);delete this.indices[nodeId];if(this.order.length>0){var lastId=this.order[this.order.length-1];this.maxZIndex=this.indices[lastId];}else{this.maxZIndex=0;}}},clear:function(){this.order=[];this.indices={};this.maxZIndex=0;},exists:function(node){return(this.indices[node.id]!=null);},getZIndex:function(node){return node._style.graphicZIndex;},determineZIndex:function(node){var zIndex=node._style.graphicZIndex;if(zIndex==null){zIndex=this.maxZIndex;node._style.graphicZIndex=zIndex;}else if(zIndex>this.maxZIndex){this.maxZIndex=zIndex;}},getNextElement:function(index){var nextIndex=index+1;if(nextIndex<this.order.length){var nextElement=OpenLayers.Util.getElement(this.order[nextIndex]);if(nextElement==undefined){nextElement=this.getNextElement(nextIndex);}
+return nextElement;}else{return null;}},CLASS_NAME:"OpenLayers.ElementsIndexer"});OpenLayers.ElementsIndexer.IndexingMethods={Z_ORDER:function(indexer,newNode,nextNode){var newZIndex=indexer.getZIndex(newNode);var returnVal=0;if(nextNode){var nextZIndex=indexer.getZIndex(nextNode);returnVal=newZIndex-nextZIndex;}
+return returnVal;},Z_ORDER_DRAWING_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal==0){returnVal=1;}
+return returnVal;},Z_ORDER_Y_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal===0){var result=nextNode._boundsBottom-newNode._boundsBottom;returnVal=(result===0)?1:result;}
+return returnVal;}};OpenLayers.Renderer.Elements=OpenLayers.Class(OpenLayers.Renderer,{rendererRoot:null,root:null,vectorRoot:null,textRoot:null,xmlns:null,indexer:null,BACKGROUND_ID_SUFFIX:"_background",LABEL_ID_SUFFIX:"_label",initialize:function(containerID,options){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.rendererRoot=this.createRenderRoot();this.root=this.createRoot("_root");this.vectorRoot=this.createRoot("_vroot");this.textRoot=this.createRoot("_troot");this.root.appendChild(this.vectorRoot);this.root.appendChild(this.textRoot);this.rendererRoot.appendChild(this.root);this.container.appendChild(this.rendererRoot);if(options&&(options.zIndexing||options.yOrdering)){this.indexer=new OpenLayers.ElementsIndexer(options.yOrdering);}},destroy:function(){this.clear();this.rendererRoot=null;this.root=null;this.xmlns=null;OpenLayers.Renderer.prototype.destroy.apply(this,arguments);},clear:function(){var child;var root=this.vectorRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
+root=this.textRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
+if(this.indexer){this.indexer.clear();}},getNodeType:function(geometry,style){},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;var rendered=true;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0,len=geometry.components.length;i<len;i++){rendered=this.drawGeometry(geometry.components[i],style,featureId)&&rendered;}
+return rendered;};rendered=false;var removeBackground=false;if(style.display!="none"){if(style.backgroundGraphic){this.redrawBackgroundNode(geometry.id,geometry,style,featureId);}else{removeBackground=true;}
+rendered=this.redrawNode(geometry.id,geometry,style,featureId);}
+if(rendered==false){var node=document.getElementById(geometry.id);if(node){if(node._style.backgroundGraphic){removeBackground=true;}
+node.parentNode.removeChild(node);}}
+if(removeBackground){var node=document.getElementById(geometry.id+this.BACKGROUND_ID_SUFFIX);if(node){node.parentNode.removeChild(node);}}
+return rendered;},redrawNode:function(id,geometry,style,featureId){style=this.applyDefaultSymbolizer(style);var node=this.nodeFactory(id,this.getNodeType(geometry,style));node._featureId=featureId;node._boundsBottom=geometry.getBounds().bottom;node._geometryClass=geometry.CLASS_NAME;node._style=style;var drawResult=this.drawGeometryNode(node,geometry,style);if(drawResult===false){return false;}
+node=drawResult.node;if(this.indexer){var insert=this.indexer.insert(node);if(insert){this.vectorRoot.insertBefore(node,insert);}else{this.vectorRoot.appendChild(node);}}else{if(node.parentNode!==this.vectorRoot){this.vectorRoot.appendChild(node);}}
+this.postDraw(node);return drawResult.complete;},redrawBackgroundNode:function(id,geometry,style,featureId){var backgroundStyle=OpenLayers.Util.extend({},style);backgroundStyle.externalGraphic=backgroundStyle.backgroundGraphic;backgroundStyle.graphicXOffset=backgroundStyle.backgroundXOffset;backgroundStyle.graphicYOffset=backgroundStyle.backgroundYOffset;backgroundStyle.graphicZIndex=backgroundStyle.backgroundGraphicZIndex;backgroundStyle.graphicWidth=backgroundStyle.backgroundWidth||backgroundStyle.graphicWidth;backgroundStyle.graphicHeight=backgroundStyle.backgroundHeight||backgroundStyle.graphicHeight;backgroundStyle.backgroundGraphic=null;backgroundStyle.backgroundXOffset=null;backgroundStyle.backgroundYOffset=null;backgroundStyle.backgroundGraphicZIndex=null;return this.redrawNode(id+this.BACKGROUND_ID_SUFFIX,geometry,backgroundStyle,null);},drawGeometryNode:function(node,geometry,style){style=style||node._style;var options={'isFilled':style.fill===undefined?true:style.fill,'isStroked':style.stroke===undefined?!!style.strokeWidth:style.stroke};var drawn;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.graphic===false){options.isFilled=false;options.isStroked=false;}
+drawn=this.drawPoint(node,geometry);break;case"OpenLayers.Geometry.LineString":options.isFilled=false;drawn=this.drawLineString(node,geometry);break;case"OpenLayers.Geometry.LinearRing":drawn=this.drawLinearRing(node,geometry);break;case"OpenLayers.Geometry.Polygon":drawn=this.drawPolygon(node,geometry);break;case"OpenLayers.Geometry.Surface":drawn=this.drawSurface(node,geometry);break;case"OpenLayers.Geometry.Rectangle":drawn=this.drawRectangle(node,geometry);break;default:break;}
+node._options=options;if(drawn!=false){return{node:this.setStyle(node,style,options,geometry),complete:drawn};}else{return false;}},postDraw:function(node){},drawPoint:function(node,geometry){},drawLineString:function(node,geometry){},drawLinearRing:function(node,geometry){},drawPolygon:function(node,geometry){},drawRectangle:function(node,geometry){},drawCircle:function(node,geometry){},drawSurface:function(node,geometry){},removeText:function(featureId){var label=document.getElementById(featureId+this.LABEL_ID_SUFFIX);if(label){this.textRoot.removeChild(label);}},getFeatureIdFromEvent:function(evt){var target=evt.target;var useElement=target&&target.correspondingUseElement;var node=useElement?useElement:(target||evt.srcElement);var featureId=node._featureId;return featureId;},eraseGeometry:function(geometry,featureId){if((geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPoint")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiLineString")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPolygon")||(geometry.CLASS_NAME=="OpenLayers.Geometry.Collection")){for(var i=0,len=geometry.components.length;i<len;i++){this.eraseGeometry(geometry.components[i],featureId);}}else{var element=OpenLayers.Util.getElement(geometry.id);if(element&&element.parentNode){if(element.geometry){element.geometry.destroy();element.geometry=null;}
+element.parentNode.removeChild(element);if(this.indexer){this.indexer.remove(element);}
+if(element._style.backgroundGraphic){var backgroundId=geometry.id+this.BACKGROUND_ID_SUFFIX;var bElem=OpenLayers.Util.getElement(backgroundId);if(bElem&&bElem.parentNode){bElem.parentNode.removeChild(bElem);}}}}},nodeFactory:function(id,type){var node=OpenLayers.Util.getElement(id);if(node){if(!this.nodeTypeCompare(node,type)){node.parentNode.removeChild(node);node=this.nodeFactory(id,type);}}else{node=this.createNode(type,id);}
+return node;},nodeTypeCompare:function(node,type){},createNode:function(type,id){},moveRoot:function(renderer){var root=this.root;if(renderer.root.parentNode==this.rendererRoot){root=renderer.root;}
+root.parentNode.removeChild(root);renderer.rendererRoot.appendChild(root);},getRenderLayerId:function(){return this.root.parentNode.parentNode.id;},isComplexSymbol:function(graphicName){return(graphicName!="circle")&&!!graphicName;},CLASS_NAME:"OpenLayers.Renderer.Elements"});OpenLayers.Renderer.symbol={"star":[350,75,379,161,469,161,397,215,423,301,350,250,277,301,303,215,231,161,321,161,350,75],"cross":[4,0,6,0,6,4,10,4,10,6,6,6,6,10,4,10,4,6,0,6,0,4,4,4,4,0],"x":[0,0,25,0,50,35,75,0,100,0,65,50,100,100,75,100,50,65,25,100,0,100,35,50,0,0],"square":[0,0,0,1,1,1,1,0,0,0],"triangle":[0,10,10,10,5,0,0,10]};OpenLayers.Renderer.NG=OpenLayers.Class(OpenLayers.Renderer.Elements,{labelNodeType:null,updateDimensions:function(zoomChanged){var mapExtent=this.map.getExtent();var renderExtent=mapExtent.scale(3);this.setExtent(renderExtent,true);var res=this.getResolution();var div=this.rendererRoot.parentNode;var layerLeft=parseFloat(div.parentNode.style.left);var layerTop=parseFloat(div.parentNode.style.top);div.style.left=((renderExtent.left-mapExtent.left)/res-layerLeft)+"px";div.style.top=((mapExtent.top-renderExtent.top)/res-layerTop)+"px";},setSize:function(){this.map.getExtent()&&this.updateDimensions();},drawFeature:function(feature,style){if(style==null){style=feature.style;}
+if(feature.geometry){var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(rendered!==false&&style.label){var location=feature.geometry.getCentroid();this.drawText(feature.id,style,location);}else{this.removeText(feature.id);}
+return rendered;}},drawText:function(featureId,style,location){var label;if(typeof featureId!=="string"){label=featureId;}else{label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,this.labelNodeType);label._featureId=featureId;}
+label._style=style;label._x=location.x;label._y=location.y;if(style.labelXOffset||style.labelYOffset){var xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;var yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);}
+if(label.parentNode!==this.textRoot){this.textRoot.appendChild(label);}
+return label;},CLASS_NAME:"OpenLayers.Renderer.NG"});OpenLayers.Format.WFST=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.WFST.DEFAULTS);var cls=OpenLayers.Format.WFST["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFST version: "+options.version;}
+return new cls(options);};OpenLayers.Format.WFST.DEFAULTS={"version":"1.0.0"};OpenLayers.Format.WFST.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs",gml:"http://www.opengis.net/gml",gml32:"http://www.opengis.net/gml/3.2",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",},defaultPrefix:"wfs",version:null,schemaLocations:null,srsName:null,extractAttributes:true,xy:true,stateName:null,initialize:function(options){this.stateName={};this.stateName[OpenLayers.State.INSERT]="wfs:Insert";this.stateName[OpenLayers.State.UPDATE]="wfs:Update";this.stateName[OpenLayers.State.DELETE]="wfs:Delete";OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},getSrsName:function(feature,options){var srsName=options&&options.srsName;if(!srsName){if(feature&&feature.layer){srsName=feature.layer.projection.getCode();}else{srsName=this.srsName;}}
+return srsName;},read:function(data,options){options=options||{};OpenLayers.Util.applyDefaults(options,{output:"features"});if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var obj={};if(data){this.readNode(data,obj,true);}
+if(obj.features&&options.output==="features"){obj=obj.features;}
+return obj;},readers:{"wfs":{"FeatureCollection":function(node,obj){obj.features=[];this.readChildNodes(node,obj);}}},write:function(features,options){var node=this.writeNode("wfs:Transaction",{features:features,options:options});var value=this.schemaLocationAttr();if(value){this.setAttributeNS(node,this.namespaces["xsi"],"xsi:schemaLocation",value);}
+return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"wfs":{"GetFeature":function(options){var node=this.createElementNSPlus("wfs:GetFeature",{attributes:{service:"WFS",version:this.version,handle:options&&options.handle,outputFormat:options&&options.outputFormat,maxFeatures:options&&options.maxFeatures,"xsi:schemaLocation":this.schemaLocationAttr(options)}});if(typeof this.featureType=="string"){this.writeNode("Query",options,node);}else{for(var i=0,len=this.featureType.length;i<len;i++){options.featureType=this.featureType[i];this.writeNode("Query",options,node);}}
+return node;},"Transaction":function(obj){obj=obj||{};var options=obj.options||{};var node=this.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version,handle:options.handle}});var i,len;var features=obj.features;if(features){if(options.multi===true){OpenLayers.Util.extend(this.geometryTypes,{"OpenLayers.Geometry.Point":"MultiPoint","OpenLayers.Geometry.LineString":(this.multiCurve===true)?"MultiCurve":"MultiLineString","OpenLayers.Geometry.Polygon":(this.multiSurface===true)?"MultiSurface":"MultiPolygon"});}
+var name,feature;for(i=0,len=features.length;i<len;++i){feature=features[i];name=this.stateName[feature.state];if(name){this.writeNode(name,{feature:feature,options:options},node);}}
+if(options.multi===true){this.setGeometryTypes();}}
+if(options.nativeElements){for(i=0,len=options.nativeElements.length;i<len;++i){this.writeNode("wfs:Native",options.nativeElements[i],node);}}
+return node;},"Native":function(nativeElement){var node=this.createElementNSPlus("wfs:Native",{attributes:{vendorId:nativeElement.vendorId,safeToIgnore:nativeElement.safeToIgnore},value:nativeElement.value});return node;},"Insert":function(obj){var feature=obj.feature;var options=obj.options;var node=this.createElementNSPlus("wfs:Insert",{attributes:{handle:options&&options.handle}});this.srsName=this.getSrsName(feature);this.writeNode("feature:_typeName",feature,node);return node;},"Update":function(obj){var feature=obj.feature;var options=obj.options;var node=this.createElementNSPlus("wfs:Update",{attributes:{handle:options&&options.handle,typeName:(this.featureNS?this.featurePrefix+":":"")+
+this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);}
+var modified=feature.modified;if(this.geometryName!==null&&(!modified||modified.geometry!==undefined)){this.srsName=this.getSrsName(feature);this.writeNode("Property",{name:this.geometryName,value:feature.geometry},node);}
+for(var key in feature.attributes){if(feature.attributes[key]!==undefined&&(!modified||!modified.attributes||(modified.attributes&&modified.attributes[key]!==undefined))){this.writeNode("Property",{name:key,value:feature.attributes[key]},node);}}
+this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;},"Property":function(obj){var node=this.createElementNSPlus("wfs:Property");this.writeNode("Name",obj.name,node);if(obj.value!==null){this.writeNode("Value",obj.value,node);}
+return node;},"Name":function(name){return this.createElementNSPlus("wfs:Name",{value:name});},"Value":function(obj){var node;if(obj instanceof OpenLayers.Geometry){node=this.createElementNSPlus("wfs:Value");var geom=this.writeNode("feature:_geometry",obj).firstChild;node.appendChild(geom);}else{node=this.createElementNSPlus("wfs:Value",{value:obj});}
+return node;},"Delete":function(obj){var feature=obj.feature;var options=obj.options;var node=this.createElementNSPlus("wfs:Delete",{attributes:{handle:options&&options.handle,typeName:(this.featureNS?this.featurePrefix+":":"")+
+this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);}
+this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;}}},schemaLocationAttr:function(options){options=OpenLayers.Util.extend({featurePrefix:this.featurePrefix,schema:this.schema},options);var schemaLocations=OpenLayers.Util.extend({},this.schemaLocations);if(options.schema){schemaLocations[options.featurePrefix]=options.schema;}
+var parts=[];var uri;for(var key in schemaLocations){uri=this.namespaces[key];if(uri){parts.push(uri+" "+schemaLocations[key]);}}
+var value=parts.join(" ")||undefined;return value;},setFilterProperty:function(filter){if(filter.filters){for(var i=0,len=filter.filters.length;i<len;++i){this.setFilterProperty(filter.filters[i]);}}else{if(filter instanceof OpenLayers.Filter.Spatial){filter.property=this.geometryName;}}},CLASS_NAME:"OpenLayers.Format.WFST.v1"});OpenLayers.Format.GML.v3=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",curve:false,multiCurve:true,surface:false,multiSurface:true,initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"FeatureCollection":function(node,obj){obj.features=[];this.readChildNodes(node,obj);},"Curve":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"segments":function(node,obj){this.readChildNodes(node,obj);},"LineStringSegment":function(node,container){var obj={};this.readChildNodes(node,obj);if(obj.points){Array.prototype.push.apply(container.points,obj.points);}},"pos":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var point;if(this.xy){point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{point=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}
+obj.points=[point];},"posList":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var dim=parseInt(node.getAttribute("dimension"))||2;var j,x,y,z;var numPoints=coords.length/dim;var points=new Array(numPoints);for(var i=0,len=coords.length;i<len;i+=dim){x=coords[i];y=coords[i+1];z=(dim==2)?undefined:coords[i+2];if(this.xy){points[i/dim]=new OpenLayers.Geometry.Point(x,y,z);}else{points[i/dim]=new OpenLayers.Geometry.Point(y,x,z);}}
+obj.points=points;},"Surface":function(node,obj){this.readChildNodes(node,obj);},"patches":function(node,obj){this.readChildNodes(node,obj);},"PolygonPatch":function(node,obj){this.readers.gml.Polygon.apply(this,[node,obj]);},"exterior":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"interior":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"MultiCurve":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];}},"curveMember":function(node,obj){this.readChildNodes(node,obj);},"MultiSurface":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];}},"surfaceMember":function(node,obj){this.readChildNodes(node,obj);},"surfaceMembers":function(node,obj){this.readChildNodes(node,obj);},"pointMembers":function(node,obj){this.readChildNodes(node,obj);},"lineStringMembers":function(node,obj){this.readChildNodes(node,obj);},"polygonMembers":function(node,obj){this.readChildNodes(node,obj);},"geometryMembers":function(node,obj){this.readChildNodes(node,obj);},"Envelope":function(node,container){var obj={points:new Array(2)};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));},"lowerCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[0]=obj.points[0];},"upperCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[1]=obj.points[0];}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.readers["wfs"]},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(features){var node=this.createElementNSPlus("gml:featureMembers");for(var i=0,len=features.length;i<len;++i){this.writeNode("feature:_typeName",features[i],node);}
+return node;},"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("pos",geometry,node);return node;},"pos":function(point){var pos=(this.xy)?(point.x+" "+point.y):(point.y+" "+point.x);return this.createElementNSPlus("gml:pos",{value:pos});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("posList",geometry.components,node);return node;},"Curve":function(geometry){var node=this.createElementNSPlus("gml:Curve");this.writeNode("segments",geometry,node);return node;},"segments":function(geometry){var node=this.createElementNSPlus("gml:segments");this.writeNode("LineStringSegment",geometry,node);return node;},"LineStringSegment":function(geometry){var node=this.createElementNSPlus("gml:LineStringSegment");this.writeNode("posList",geometry.components,node);return node;},"posList":function(points){var len=points.length;var parts=new Array(len);var point;for(var i=0;i<len;++i){point=points[i];if(this.xy){parts[i]=point.x+" "+point.y;}else{parts[i]=point.y+" "+point.x;}}
+return this.createElementNSPlus("gml:posList",{value:parts.join(" ")});},"Surface":function(geometry){var node=this.createElementNSPlus("gml:Surface");this.writeNode("patches",geometry,node);return node;},"patches":function(geometry){var node=this.createElementNSPlus("gml:patches");this.writeNode("PolygonPatch",geometry,node);return node;},"PolygonPatch":function(geometry){var node=this.createElementNSPlus("gml:PolygonPatch",{attributes:{interpolation:"planar"}});this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
+return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
+return node;},"exterior":function(ring){var node=this.createElementNSPlus("gml:exterior");this.writeNode("LinearRing",ring,node);return node;},"interior":function(ring){var node=this.createElementNSPlus("gml:interior");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("posList",ring.components,node);return node;},"MultiCurve":function(geometry){var node=this.createElementNSPlus("gml:MultiCurve");var components=geometry.components||[geometry];for(var i=0,len=components.length;i<len;++i){this.writeNode("curveMember",components[i],node);}
+return node;},"curveMember":function(geometry){var node=this.createElementNSPlus("gml:curveMember");if(this.curve){this.writeNode("Curve",geometry,node);}else{this.writeNode("LineString",geometry,node);}
+return node;},"MultiSurface":function(geometry){var node=this.createElementNSPlus("gml:MultiSurface");var components=geometry.components||[geometry];for(var i=0,len=components.length;i<len;++i){this.writeNode("surfaceMember",components[i],node);}
+return node;},"surfaceMember":function(polygon){var node=this.createElementNSPlus("gml:surfaceMember");if(this.surface){this.writeNode("Surface",polygon,node);}else{this.writeNode("Polygon",polygon,node);}
+return node;},"Envelope":function(bounds){var node=this.createElementNSPlus("gml:Envelope");this.writeNode("lowerCorner",bounds,node);this.writeNode("upperCorner",bounds,node);if(this.srsName){node.setAttribute("srsName",this.srsName);}
+return node;},"lowerCorner":function(bounds){var pos=(this.xy)?(bounds.left+" "+bounds.bottom):(bounds.bottom+" "+bounds.left);return this.createElementNSPlus("gml:lowerCorner",{value:pos});},"upperCorner":function(bounds){var pos=(this.xy)?(bounds.right+" "+bounds.top):(bounds.top+" "+bounds.right);return this.createElementNSPlus("gml:upperCorner",{value:pos});}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":(this.curve===true)?"Curve":"LineString","OpenLayers.Geometry.MultiLineString":(this.multiCurve===false)?"MultiLineString":"MultiCurve","OpenLayers.Geometry.Polygon":(this.surface===true)?"Surface":"Polygon","OpenLayers.Geometry.MultiPolygon":(this.multiSurface===false)?"MultiPolygon":"MultiSurface","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.v3"});OpenLayers.Format.Filter.v1_1_0=OpenLayers.Class(OpenLayers.Format.GML.v3,OpenLayers.Format.Filter.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.1.0/filter.xsd",initialize:function(options){OpenLayers.Format.GML.v3.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escapeChar");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"]},writers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeOgcExpression(filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{matchCase:filter.matchCase,wildCard:"*",singleChar:".",escapeChar:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");filter.property&&this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Envelope",filter.value);if(filter.projection){box.setAttribute("srsName",filter.projection);}
+node.appendChild(box);return node;},"SortBy":function(sortProperties){var node=this.createElementNSPlus("ogc:SortBy");for(var i=0,l=sortProperties.length;i<l;i++){this.writeNode("ogc:SortProperty",sortProperties[i],node);}
+return node;},"SortProperty":function(sortProperty){var node=this.createElementNSPlus("ogc:SortProperty");this.writeNode("ogc:PropertyName",sortProperty,node);this.writeNode("ogc:SortOrder",(sortProperty.order=='DESC')?'DESC':'ASC',node);return node;},"SortOrder":function(value){var node=this.createElementNSPlus("ogc:SortOrder",{value:value});return node;}},OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),"gml":OpenLayers.Format.GML.v3.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.writers["feature"]},writeSpatial:function(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);if(filter.value instanceof OpenLayers.Filter.Function){this.writeNode("Function",filter.value,node);}else{var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Envelope",filter.value);}
+if(filter.projection){child.setAttribute("srsName",filter.projection);}
+node.appendChild(child);}
+return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_1_0"});OpenLayers.Format.OWSCommon=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",getVersion:function(root,options){var version=this.version;if(!version){var uri=root.getAttribute("xmlns:ows");if(uri&&uri.substring(uri.lastIndexOf("/")+1)==="1.1"){version="1.1.0";}
+if(!version){version=this.defaultVersion;}}
+return version;},CLASS_NAME:"OpenLayers.Format.OWSCommon"});OpenLayers.Format.OWSCommon.v1=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},read:function(data,options){options=OpenLayers.Util.applyDefaults(options,this.options);var ows={};this.readChildNodes(data,ows);return ows;},readers:{"ows":{"Exception":function(node,exceptionReport){var exception={code:node.getAttribute('exceptionCode'),locator:node.getAttribute('locator'),texts:[]};exceptionReport.exceptions.push(exception);this.readChildNodes(node,exception);},"ExceptionText":function(node,exception){var text=this.getChildValue(node);exception.texts.push(text);},"ServiceIdentification":function(node,obj){obj.serviceIdentification={};this.readChildNodes(node,obj.serviceIdentification);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,serviceIdentification){serviceIdentification["abstract"]=this.getChildValue(node);},"Keywords":function(node,serviceIdentification){serviceIdentification.keywords={};this.readChildNodes(node,serviceIdentification.keywords);},"Keyword":function(node,keywords){keywords[this.getChildValue(node)]=true;},"ServiceType":function(node,serviceIdentification){serviceIdentification.serviceType={codeSpace:node.getAttribute('codeSpace'),value:this.getChildValue(node)};},"ServiceTypeVersion":function(node,serviceIdentification){serviceIdentification.serviceTypeVersion=this.getChildValue(node);},"Fees":function(node,serviceIdentification){serviceIdentification.fees=this.getChildValue(node);},"AccessConstraints":function(node,serviceIdentification){serviceIdentification.accessConstraints=this.getChildValue(node);},"ServiceProvider":function(node,obj){obj.serviceProvider={};this.readChildNodes(node,obj.serviceProvider);},"ProviderName":function(node,serviceProvider){serviceProvider.providerName=this.getChildValue(node);},"ProviderSite":function(node,serviceProvider){serviceProvider.providerSite=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ServiceContact":function(node,serviceProvider){serviceProvider.serviceContact={};this.readChildNodes(node,serviceProvider.serviceContact);},"IndividualName":function(node,serviceContact){serviceContact.individualName=this.getChildValue(node);},"PositionName":function(node,serviceContact){serviceContact.positionName=this.getChildValue(node);},"ContactInfo":function(node,serviceContact){serviceContact.contactInfo={};this.readChildNodes(node,serviceContact.contactInfo);},"Phone":function(node,contactInfo){contactInfo.phone={};this.readChildNodes(node,contactInfo.phone);},"Voice":function(node,phone){phone.voice=this.getChildValue(node);},"Address":function(node,contactInfo){contactInfo.address={};this.readChildNodes(node,contactInfo.address);},"DeliveryPoint":function(node,address){address.deliveryPoint=this.getChildValue(node);},"City":function(node,address){address.city=this.getChildValue(node);},"AdministrativeArea":function(node,address){address.administrativeArea=this.getChildValue(node);},"PostalCode":function(node,address){address.postalCode=this.getChildValue(node);},"Country":function(node,address){address.country=this.getChildValue(node);},"ElectronicMailAddress":function(node,address){address.electronicMailAddress=this.getChildValue(node);},"Role":function(node,serviceContact){serviceContact.role=this.getChildValue(node);},"OperationsMetadata":function(node,obj){obj.operationsMetadata={};this.readChildNodes(node,obj.operationsMetadata);},"Operation":function(node,operationsMetadata){var name=node.getAttribute("name");operationsMetadata[name]={};this.readChildNodes(node,operationsMetadata[name]);},"DCP":function(node,operation){operation.dcp={};this.readChildNodes(node,operation.dcp);},"HTTP":function(node,dcp){dcp.http={};this.readChildNodes(node,dcp.http);},"Get":function(node,http){http.get=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Post":function(node,http){http.post=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Parameter":function(node,operation){if(!operation.parameters){operation.parameters={};}
+var name=node.getAttribute("name");operation.parameters[name]={};this.readChildNodes(node,operation.parameters[name]);},"Value":function(node,allowedValues){allowedValues[this.getChildValue(node)]=true;},"OutputFormat":function(node,obj){obj.formats.push({value:this.getChildValue(node)});this.readChildNodes(node,obj);},"WGS84BoundingBox":function(node,obj){var boundingBox={};boundingBox.crs=node.getAttribute("crs");if(obj.BoundingBox){obj.BoundingBox.push(boundingBox);}else{obj.projection=boundingBox.crs;boundingBox=obj;}
+this.readChildNodes(node,boundingBox);},"BoundingBox":function(node,obj){this.readers['ows']['WGS84BoundingBox'].apply(this,[node,obj]);},"LowerCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.left=pointList[0];obj.bottom=pointList[1];},"UpperCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.right=pointList[0];obj.top=pointList[1];obj.bounds=new OpenLayers.Bounds(obj.left,obj.bottom,obj.right,obj.top);delete obj.left;delete obj.bottom;delete obj.right;delete obj.top;},"Language":function(node,obj){obj.language=this.getChildValue(node);}}},writers:{"ows":{"BoundingBox":function(options){var node=this.createElementNSPlus("ows:BoundingBox",{attributes:{crs:options.projection}});this.writeNode("ows:LowerCorner",options,node);this.writeNode("ows:UpperCorner",options,node);return node;},"LowerCorner":function(options){var node=this.createElementNSPlus("ows:LowerCorner",{value:options.bounds.left+" "+options.bounds.bottom});return node;},"UpperCorner":function(options){var node=this.createElementNSPlus("ows:UpperCorner",{value:options.bounds.right+" "+options.bounds.top});return node;},"Identifier":function(identifier){var node=this.createElementNSPlus("ows:Identifier",{value:identifier});return node;},"Title":function(title){var node=this.createElementNSPlus("ows:Title",{value:title});return node;},"Abstract":function(abstractValue){var node=this.createElementNSPlus("ows:Abstract",{value:abstractValue});return node;},"OutputFormat":function(format){var node=this.createElementNSPlus("ows:OutputFormat",{value:format});return node;}}},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1"});OpenLayers.Format.OWSCommon.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows",xlink:"http://www.w3.org/1999/xlink"},readers:{"ows":OpenLayers.Util.applyDefaults({"ExceptionReport":function(node,obj){obj.success=false;obj.exceptionReport={version:node.getAttribute('version'),language:node.getAttribute('language'),exceptions:[]};this.readChildNodes(node,obj.exceptionReport);}},OpenLayers.Format.OWSCommon.v1.prototype.readers.ows)},writers:{"ows":OpenLayers.Format.OWSCommon.v1.prototype.writers.ows},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_0_0"});OpenLayers.Format.WFST.v1_1_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_1_0,OpenLayers.Format.WFST.v1,{version:"1.1.0",schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readNode:function(node,obj,first){return OpenLayers.Format.GML.v3.prototype.readNode.apply(this,[node,obj]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){obj.numberOfFeatures=parseInt(node.getAttribute("numberOfFeatures"));OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(this,arguments);},"member":function(node,obj){this.readChildNodes(node,obj);},"TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"TransactionSummary":function(node,obj){obj.success=true;},"InsertResults":function(node,obj){this.readChildNodes(node,obj);},"Feature":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"gml32":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"],"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"GetFeature":function(options){var node=OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this,arguments);options&&this.setAttributes(node,{resultType:options.resultType,startIndex:options.startIndex,count:options.count});return node;},"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName},options);var prefix=options.featurePrefix;var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(prefix?prefix+":":"")+
+options.featureType,srsName:options.srsName}});if(options.featureNS){node.setAttribute("xmlns:"+prefix,options.featureNS);node.setAttribute("xmlns:gn","urn:x-inspire:specification:gmlas:GeographicalNames:3.0");}
+if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("wfs:PropertyName",{property:options.propertyNames[i]},node);}}
+if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);}
+return node;},"PropertyName":function(obj){return this.createElementNSPlus("wfs:PropertyName",{value:obj.property});}},OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.writers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.WFST.v1_1_0"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:false,read:function(json,type,filter){type=(type)?type:"FeatureCollection";var results=null;var obj=null;if(typeof json=="string"){obj=OpenLayers.Format.JSON.prototype.read.apply(this,[json,filter]);}else{obj=json;}
+if(!obj){OpenLayers.Console.error("Bad JSON: "+json);}else if(typeof(obj.type)!="string"){OpenLayers.Console.error("Bad GeoJSON - no type: "+json);}else if(this.isValidType(obj,type)){switch(type){case"Geometry":try{results=this.parseGeometry(obj);}catch(err){OpenLayers.Console.error(err);}
+break;case"Feature":try{results=this.parseFeature(obj);results.type="Feature";}catch(err){OpenLayers.Console.error(err);}
+break;case"FeatureCollection":results=[];switch(obj.type){case"Feature":try{results.push(this.parseFeature(obj));}catch(err){results=null;OpenLayers.Console.error(err);}
+break;case"FeatureCollection":for(var i=0,len=obj.features.length;i<len;++i){try{results.push(this.parseFeature(obj.features[i]));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;default:try{var geom=this.parseGeometry(obj);results.push(new OpenLayers.Feature.Vector(geom));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;}}
+return results;},isValidType:function(obj,type){var valid=false;switch(type){case"Geometry":if(OpenLayers.Util.indexOf(["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","Box","GeometryCollection"],obj.type)==-1){OpenLayers.Console.error("Unsupported geometry type: "+
+obj.type);}else{valid=true;}
+break;case"FeatureCollection":valid=true;break;default:if(obj.type==type){valid=true;}else{OpenLayers.Console.error("Cannot convert types from "+
+obj.type+" to "+type);}}
+return valid;},parseFeature:function(obj){var feature,geometry,attributes,bbox;attributes=(obj.properties)?obj.properties:{};bbox=(obj.geometry&&obj.geometry.bbox)||obj.bbox;try{geometry=this.parseGeometry(obj.geometry);}catch(err){throw err;}
+feature=new OpenLayers.Feature.Vector(geometry,attributes);if(bbox){feature.bounds=OpenLayers.Bounds.fromArray(bbox);}
+if(obj.id){feature.fid=obj.id;}
+return feature;},parseGeometry:function(obj){if(obj==null){return null;}
+var geometry,collection=false;if(obj.type=="GeometryCollection"){if(!(OpenLayers.Util.isArray(obj.geometries))){throw"GeometryCollection must have geometries array: "+obj;}
+var numGeom=obj.geometries.length;var components=new Array(numGeom);for(var i=0;i<numGeom;++i){components[i]=this.parseGeometry.apply(this,[obj.geometries[i]]);}
+geometry=new OpenLayers.Geometry.Collection(components);collection=true;}else{if(!(OpenLayers.Util.isArray(obj.coordinates))){throw"Geometry must have coordinates array: "+obj;}
+if(!this.parseCoords[obj.type.toLowerCase()]){throw"Unsupported geometry type: "+obj.type;}
+try{geometry=this.parseCoords[obj.type.toLowerCase()].apply(this,[obj.coordinates]);}catch(err){throw err;}}
+if(this.internalProjection&&this.externalProjection&&!collection){geometry.transform(this.externalProjection,this.internalProjection);}
+return geometry;},parseCoords:{"point":function(array){if(this.ignoreExtraDims==false&&array.length!=2){throw"Only 2D points are supported: "+array;}
+return new OpenLayers.Geometry.Point(array[0],array[1]);},"multipoint":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.MultiPoint(points);},"linestring":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.LineString(points);},"multilinestring":function(array){var lines=[];var l=null;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+lines.push(l);}
+return new OpenLayers.Geometry.MultiLineString(lines);},"polygon":function(array){var rings=[];var r,l;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+r=new OpenLayers.Geometry.LinearRing(l.components);rings.push(r);}
+return new OpenLayers.Geometry.Polygon(rings);},"multipolygon":function(array){var polys=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["polygon"].apply(this,[array[i]]);}catch(err){throw err;}
+polys.push(p);}
+return new OpenLayers.Geometry.MultiPolygon(polys);},"box":function(array){if(array.length!=2){throw"GeoJSON box coordinates must have 2 elements";}
+return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(array[0][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[0][1])])]);}},write:function(obj,pretty){var geojson={"type":null};if(OpenLayers.Util.isArray(obj)){geojson.type="FeatureCollection";var numFeatures=obj.length;geojson.features=new Array(numFeatures);for(var i=0;i<numFeatures;++i){var element=obj[i];if(!element instanceof OpenLayers.Feature.Vector){var msg="FeatureCollection only supports collections "+"of features: "+element;throw msg;}
+geojson.features[i]=this.extract.feature.apply(this,[element]);}}else if(obj.CLASS_NAME.indexOf("OpenLayers.Geometry")==0){geojson=this.extract.geometry.apply(this,[obj]);}else if(obj instanceof OpenLayers.Feature.Vector){geojson=this.extract.feature.apply(this,[obj]);if(obj.layer&&obj.layer.projection){geojson.crs=this.createCRSObject(obj);}}
+return OpenLayers.Format.JSON.prototype.write.apply(this,[geojson,pretty]);},createCRSObject:function(object){var proj=object.layer.projection.toString();var crs={};if(proj.match(/epsg:/i)){var code=parseInt(proj.substring(proj.indexOf(":")+1));if(code==4326){crs={"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}};}else{crs={"type":"name","properties":{"name":"EPSG:"+code}};}}
+return crs;},extract:{'feature':function(feature){var geom=this.extract.geometry.apply(this,[feature.geometry]);var json={"type":"Feature","properties":feature.attributes,"geometry":geom};if(feature.fid!=null){json.id=feature.fid;}
+return json;},'geometry':function(geometry){if(geometry==null){return null;}
+if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var geometryType=geometry.CLASS_NAME.split('.')[2];var data=this.extract[geometryType.toLowerCase()].apply(this,[geometry]);var json;if(geometryType=="Collection"){json={"type":"GeometryCollection","geometries":data};}else{json={"type":geometryType,"coordinates":data};}
+return json;},'point':function(point){return[point.x,point.y];},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push(this.extract.point.apply(this,[multipoint.components[i]]));}
+return array;},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
+return array;},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[multilinestring.components[i]]));}
+return array;},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[polygon.components[i]]));}
+return array;},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push(this.extract.polygon.apply(this,[multipolygon.components[i]]));}
+return array;},'collection':function(collection){var len=collection.components.length;var array=new Array(len);for(var i=0;i<len;++i){array[i]=this.extract.geometry.apply(this,[collection.components[i]]);}
+return array;}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Protocol.Script=OpenLayers.Class(OpenLayers.Protocol,{url:null,params:null,callback:null,scope:null,format:null,callbackKey:"callback",callbackPrefix:"",pendingRequests:null,srsInBBOX:false,initialize:function(options){options=options||{};this.params={};this.pendingRequests={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);if(!this.format){this.format=new OpenLayers.Format.GeoJSON();}
+if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var format=new OpenLayers.Format.QueryStringFilter({srsInBBOX:this.srsInBBOX});this.filterToParams=function(filter,params){return format.write(filter,params);}}},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);if(options.filter&&this.filterToParams){options.params=this.filterToParams(options.filter,options.params);}
+var response=new OpenLayers.Protocol.Response({requestType:"read"});var request=this.createRequest(options.url,options.params,OpenLayers.Function.bind(function(data){response.data=data;this.handleRead(response,options);},this));response.priv=request;return response;},createRequest:function(url,params,callback){var id=OpenLayers.Protocol.Script.register(callback);var name="OpenLayers.Protocol.Script.registry["+id+"]";params=OpenLayers.Util.extend({},params);params[this.callbackKey]=this.callbackPrefix+name;url=OpenLayers.Util.urlAppend(url,OpenLayers.Util.getParameterString(params));var script=document.createElement("script");script.type="text/javascript";script.src=url;script.id="OpenLayers_Protocol_Script_"+id;this.pendingRequests[script.id]=script;var head=document.getElementsByTagName("head")[0];head.appendChild(script);return script;},destroyRequest:function(script){OpenLayers.Protocol.Script.unregister(script.id.split("_").pop());delete this.pendingRequests[script.id];if(script.parentNode){script.parentNode.removeChild(script);}},handleRead:function(response,options){this.handleResponse(response,options);},handleResponse:function(response,options){if(options.callback){if(response.data){response.features=this.parseFeatures(response.data);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
+this.destroyRequest(response.priv);options.callback.call(options.scope,response);}},parseFeatures:function(data){return this.format.read(data);},abort:function(response){if(response){this.destroyRequest(response.priv);}else{for(var key in this.pendingRequests){this.destroyRequest(this.pendingRequests[key]);}}},destroy:function(){this.abort();delete this.params;delete this.format;OpenLayers.Protocol.prototype.destroy.apply(this);},CLASS_NAME:"OpenLayers.Protocol.Script"});(function(){var o=OpenLayers.Protocol.Script;var counter=0;o.registry=[];o.register=function(callback){var id=++counter;o.registry[id]=function(){o.unregister(id);callback.apply(this,arguments);};return id;};o.unregister=function(id){delete o.registry[id];};})();OpenLayers.Layer.VirtualEarth=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:19,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515],type:null,wrapDateLine:true,sphericalMercator:false,animationEnabled:true,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){var veDiv=OpenLayers.Util.createDiv(this.name);var sz=this.map.getSize();veDiv.style.width=sz.w+"px";veDiv.style.height=sz.h+"px";this.div.appendChild(veDiv);try{this.mapObject=new VEMap(this.name);}catch(e){}
+if(this.mapObject!=null){try{this.mapObject.LoadMap(null,null,this.type,true);this.mapObject.AttachEvent("onmousedown",OpenLayers.Function.True);}catch(e){}
+this.mapObject.HideDashboard();if(typeof this.mapObject.SetAnimationEnabled=="function"){this.mapObject.SetAnimationEnabled(this.animationEnabled);}}
+if(!this.mapObject||!this.mapObject.vemapcontrol||!this.mapObject.vemapcontrol.PanMap||(typeof this.mapObject.vemapcontrol.PanMap!="function")){this.dragPanMapObject=null;}},onMapResize:function(){this.mapObject.Resize(this.map.size.w,this.map.size.h);},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'VE','layerLib':'VirtualEarth'});},setMapObjectCenter:function(center,zoom){this.mapObject.SetCenterAndZoom(center,zoom);},getMapObjectCenter:function(){return this.mapObject.GetCenter();},dragPanMapObject:function(dX,dY){this.mapObject.vemapcontrol.PanMap(dX,-dY);},getMapObjectZoom:function(){return this.mapObject.GetZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return(typeof VEPixel!='undefined')?this.mapObject.PixelToLatLong(moPixel):this.mapObject.PixelToLatLong(moPixel.x,moPixel.y);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.LatLongToPixel(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lon:moLonLat.Longitude;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lat:moLonLat.Latitude;},getMapObjectLonLatFromLonLat:function(lon,lat){var veLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);veLatLong=new VELatLong(lonlat.lat,lonlat.lon);}else{veLatLong=new VELatLong(lat,lon);}
+return veLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return(typeof VEPixel!='undefined')?new VEPixel(x,y):new Msn.VE.Pixel(x,y);},CLASS_NAME:"OpenLayers.Layer.VirtualEarth"});OpenLayers.Control.Panel=OpenLayers.Class(OpenLayers.Control,{controls:null,autoActivate:true,defaultControl:null,saveState:false,allowDepress:false,activeState:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.controls=[];this.activeState={};},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this,arguments);for(var ctl,i=this.controls.length-1;i>=0;i--){ctl=this.controls[i];if(ctl.events){ctl.events.un({activate:this.iconOn,deactivate:this.iconOff});}
+OpenLayers.Event.stopObservingElement(ctl.panel_div);ctl.panel_div=null;}
+this.activeState=null;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];if(control===this.defaultControl||(this.saveState&&this.activeState[control.id])){control.activate();}}
+if(this.saveState===true){this.defaultControl=null;}
+this.redraw();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];this.activeState[control.id]=control.deactivate();}
+this.redraw();return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.addControlsToMap(this.controls);return this.div;},redraw:function(){for(var l=this.div.childNodes.length,i=l-1;i>=0;i--){this.div.removeChild(this.div.childNodes[i]);}
+this.div.innerHTML="";if(this.active){for(var i=0,len=this.controls.length;i<len;i++){this.div.appendChild(this.controls[i].panel_div);}}},activateControl:function(control){if(!this.active){return false;}
+if(control.type==OpenLayers.Control.TYPE_BUTTON){control.trigger();return;}
+if(control.type==OpenLayers.Control.TYPE_TOGGLE){if(control.active){control.deactivate();}else{control.activate();}
+return;}
+if(this.allowDepress&&control.active){control.deactivate();}else{var c;for(var i=0,len=this.controls.length;i<len;i++){c=this.controls[i];if(c!=control&&(c.type===OpenLayers.Control.TYPE_TOOL||c.type==null)){c.deactivate();}}
+control.activate();}},addControls:function(controls){if(!(OpenLayers.Util.isArray(controls))){controls=[controls];}
+this.controls=this.controls.concat(controls);for(var i=0,len=controls.length;i<len;i++){var element=document.createElement("div");element.className=controls[i].displayClass+"ItemInactive";controls[i].panel_div=element;if(controls[i].title!=""){controls[i].panel_div.title=controls[i].title;}
+OpenLayers.Event.observe(controls[i].panel_div,"click",OpenLayers.Function.bind(this.onClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"dblclick",OpenLayers.Function.bind(this.onDoubleClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"mousedown",OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));}
+if(this.map){this.addControlsToMap(controls);this.redraw();}},addControlsToMap:function(controls){var control;for(var i=0,len=controls.length;i<len;i++){control=controls[i];if(control.autoActivate===true){control.autoActivate=false;this.map.addControl(control);control.autoActivate=true;}else{this.map.addControl(control);control.deactivate();}
+control.events.on({activate:this.iconOn,deactivate:this.iconOff});}},iconOn:function(){var d=this.panel_div;d.className=d.className.replace(/ItemInactive$/,"ItemActive");},iconOff:function(){var d=this.panel_div;d.className=d.className.replace(/ItemActive$/,"ItemInactive");},onClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);this.activateControl(ctrl);},onDoubleClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);},getControlsBy:function(property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this.controls,function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getControlsByName:function(match){return this.getControlsBy("name",match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},CLASS_NAME:"OpenLayers.Control.Panel"});OpenLayers.Control.ZoomIn=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomIn();},CLASS_NAME:"OpenLayers.Control.ZoomIn"});OpenLayers.Control.ZoomOut=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomOut();},CLASS_NAME:"OpenLayers.Control.ZoomOut"});OpenLayers.Control.ZoomToMaxExtent=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){if(this.map){this.map.zoomToMaxExtent();}},CLASS_NAME:"OpenLayers.Control.ZoomToMaxExtent"});OpenLayers.Control.ZoomPanel=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.ZoomIn(),new OpenLayers.Control.ZoomToMaxExtent(),new OpenLayers.Control.ZoomOut()]);},CLASS_NAME:"OpenLayers.Control.ZoomPanel"});OpenLayers.Layer.HTTPRequest=OpenLayers.Class(OpenLayers.Layer,{URL_HASH_FACTOR:(Math.sqrt(5)-1)/2,url:null,params:null,reproject:false,initialize:function(name,url,params,options){OpenLayers.Layer.prototype.initialize.apply(this,[name,options]);this.url=url;this.params=OpenLayers.Util.extend({},params);},destroy:function(){this.url=null;this.params=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.HTTPRequest(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setUrl:function(newUrl){this.url=newUrl;},mergeNewParams:function(newParams){this.params=OpenLayers.Util.extend(this.params,newParams);var ret=this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"params"});}
+return ret;},redraw:function(force){if(force){return this.mergeNewParams({"_olSalt":Math.random()});}else{return OpenLayers.Layer.prototype.redraw.apply(this,[]);}},selectUrl:function(paramString,urls){var product=1;for(var i=0,len=paramString.length;i<len;i++){product*=paramString.charCodeAt(i)*this.URL_HASH_FACTOR;product-=Math.floor(product);}
+return urls[Math.floor(product*urls.length)];},getFullRequestString:function(newParams,altUrl){var url=altUrl||this.url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(OpenLayers.Util.isArray(url)){url=this.selectUrl(paramsString,url);}
+var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
+paramsString=OpenLayers.Util.getParameterString(allParams);return OpenLayers.Util.urlAppend(url,paramsString);},CLASS_NAME:"OpenLayers.Layer.HTTPRequest"});OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,tileOriginCorner:"bl",tileOrigin:null,tileOptions:null,grid:null,singleTile:false,ratio:1.5,buffer:0,numLoadingTiles:0,tileLoadingDelay:100,timerId:null,initialize:function(name,url,params,options){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.events.addEventType("tileloaded");this.grid=[];this._moveGriddedTiles=OpenLayers.Function.bind(this.moveGriddedTiles,this);},removeMap:function(map){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}},destroy:function(){this.clearGrid();this.grid=null;this.tileSize=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments);},clearGrid:function(){if(this.grid){for(var iRow=0,len=this.grid.length;iRow<len;iRow++){var row=this.grid[iRow];for(var iCol=0,clen=row.length;iCol<clen;iCol++){var tile=row[iCol];this.removeTileMonitoringHooks(tile);tile.destroy();}}
+this.grid=[];}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Grid(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();}
+obj.grid=[];return obj;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this,arguments);bounds=bounds||this.map.getExtent();if(bounds!=null){var forceReTile=!this.grid.length||zoomChanged;var tilesBounds=this.getTilesBounds();if(this.singleTile){if(forceReTile||(!dragging&&!tilesBounds.containsBounds(bounds))){this.initSingleTile(bounds);}}else{if(forceReTile||!tilesBounds.containsBounds(bounds,true)){this.initGriddedTiles(bounds);}else{this.scheduleMoveGriddedTiles();}}}},moveByPx:function(dx,dy){if(!this.singleTile){this.scheduleMoveGriddedTiles();}},scheduleMoveGriddedTiles:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);}
+this.timerId=window.setTimeout(this._moveGriddedTiles,this.tileLoadingDelay);},setTileSize:function(size){if(this.singleTile){size=this.map.getSize();size.h=parseInt(size.h*this.ratio);size.w=parseInt(size.w*this.ratio);}
+OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this,[size]);},getGridBounds:function(){var msg="The getGridBounds() function is deprecated. It will be "+"removed in 3.0. Please use getTilesBounds() instead.";OpenLayers.Console.warn(msg);return this.getTilesBounds();},getTilesBounds:function(){var bounds=null;if(this.grid.length){var bottom=this.grid.length-1;var bottomLeftTile=this.grid[bottom][0];var right=this.grid[0].length-1;var topRightTile=this.grid[0][right];bounds=new OpenLayers.Bounds(bottomLeftTile.bounds.left,bottomLeftTile.bounds.bottom,topRightTile.bounds.right,topRightTile.bounds.top);}
+return bounds;},initSingleTile:function(bounds){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var px=this.map.getLayerPxFromLonLat(ul);if(!this.grid.length){this.grid[0]=[];}
+var tile=this.grid[0][0];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);tile.draw();this.grid[0][0]=tile;}else{tile.moveTo(tileBounds,px);}
+this.removeExcessTiles(1,1);},calculateGridLayout:function(bounds,origin,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-origin.lon;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=origin.lon+tilecol*tilelon;var offsetlat=bounds.top-(origin.lat+tilelat);var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-tilerowremain*this.tileSize.h;var tileoffsetlat=origin.lat+tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},getTileOrigin:function(){var origin=this.tileOrigin;if(!origin){var extent=this.getMaxExtent();var edges=({"tl":["left","top"],"tr":["right","top"],"bl":["left","bottom"],"br":["right","bottom"]})[this.tileOriginCorner];origin=new OpenLayers.LonLat(extent[edges[0]],extent[edges[1]]);}
+return origin;},initGriddedTiles:function(bounds){var viewSize=this.map.getSize();var minRows=Math.ceil(viewSize.h/this.tileSize.h)+
+Math.max(1,2*this.buffer);var minCols=Math.ceil(viewSize.w/this.tileSize.w)+
+Math.max(1,2*this.buffer);var origin=this.getTileOrigin();var resolution=this.map.getResolution();var tileLayout=this.calculateGridLayout(bounds,origin,resolution);var tileoffsetx=Math.round(tileLayout.tileoffsetx);var tileoffsety=Math.round(tileLayout.tileoffsety);var tileoffsetlon=tileLayout.tileoffsetlon;var tileoffsetlat=tileLayout.tileoffsetlat;var tilelon=tileLayout.tilelon;var tilelat=tileLayout.tilelat;this.origin=new OpenLayers.Pixel(tileoffsetx,tileoffsety);var startX=tileoffsetx;var startLon=tileoffsetlon;var rowidx=0;var layerContainerDivLeft=parseInt(this.map.layerContainerDiv.style.left);var layerContainerDivTop=parseInt(this.map.layerContainerDiv.style.top);do{var row=this.grid[rowidx++];if(!row){row=[];this.grid.push(row);}
+tileoffsetlon=startLon;tileoffsetx=startX;var colidx=0;do{var tileBounds=new OpenLayers.Bounds(tileoffsetlon,tileoffsetlat,tileoffsetlon+tilelon,tileoffsetlat+tilelat);var x=tileoffsetx;x-=layerContainerDivLeft;var y=tileoffsety;y-=layerContainerDivTop;var px=new OpenLayers.Pixel(x,y);var tile=row[colidx++];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);row.push(tile);}else{tile.moveTo(tileBounds,px,false);}
+tileoffsetlon+=tilelon;tileoffsetx+=this.tileSize.w;}while((tileoffsetlon<=bounds.right+tilelon*this.buffer)||colidx<minCols);tileoffsetlat-=tilelat;tileoffsety+=this.tileSize.h;}while((tileoffsetlat>=bounds.bottom-tilelat*this.buffer)||rowidx<minRows);this.removeExcessTiles(rowidx,colidx);this.spiralTileLoad();},getMaxExtent:function(){return this.maxExtent;},spiralTileLoad:function(){var tileQueue=[];var directions=["right","down","left","up"];var iRow=0;var iCell=-1;var direction=OpenLayers.Util.indexOf(directions,"right");var directionsTried=0;while(directionsTried<directions.length){var testRow=iRow;var testCell=iCell;switch(directions[direction]){case"right":testCell++;break;case"down":testRow++;break;case"left":testCell--;break;case"up":testRow--;break;}
+var tile=null;if((testRow<this.grid.length)&&(testRow>=0)&&(testCell<this.grid[0].length)&&(testCell>=0)){tile=this.grid[testRow][testCell];}
+if((tile!=null)&&(!tile.queued)){tileQueue.unshift(tile);tile.queued=true;directionsTried=0;iRow=testRow;iCell=testCell;}else{direction=(direction+1)%4;directionsTried++;}}
+for(var i=0,len=tileQueue.length;i<len;i++){var tile=tileQueue[i];tile.draw();tile.queued=false;}},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize,this.tileOptions);},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this.numLoadingTiles==0){this.events.triggerEvent("loadstart");}
+this.numLoadingTiles++;};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.numLoadingTiles--;this.events.triggerEvent("tileloaded");if(this.numLoadingTiles==0){this.events.triggerEvent("loadend");}};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},moveGriddedTiles:function(){var shifted=true;var buffer=this.buffer||1;var tlLayer=this.grid[0][0].position;var offsetX=parseInt(this.map.layerContainerDiv.style.left);var offsetY=parseInt(this.map.layerContainerDiv.style.top);var tlViewPort=tlLayer.add(offsetX,offsetY);if(tlViewPort.x>-this.tileSize.w*(buffer-1)){this.shiftColumn(true);}else if(tlViewPort.x<-this.tileSize.w*buffer){this.shiftColumn(false);}else if(tlViewPort.y>-this.tileSize.h*(buffer-1)){this.shiftRow(true);}else if(tlViewPort.y<-this.tileSize.h*buffer){this.shiftRow(false);}else{shifted=false;}
+if(shifted){this.timerId=window.setTimeout(this._moveGriddedTiles,0);}},shiftRow:function(prepend){var modelRowIndex=(prepend)?0:(this.grid.length-1);var grid=this.grid;var modelRow=grid[modelRowIndex];var resolution=this.map.getResolution();var deltaY=(prepend)?-this.tileSize.h:this.tileSize.h;var deltaLat=resolution*-deltaY;var row=(prepend)?grid.pop():grid.shift();for(var i=0,len=modelRow.length;i<len;i++){var modelTile=modelRow[i];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.bottom=bounds.bottom+deltaLat;bounds.top=bounds.top+deltaLat;position.y=position.y+deltaY;row[i].moveTo(bounds,position);}
+if(prepend){grid.unshift(row);}else{grid.push(row);}},shiftColumn:function(prepend){var deltaX=(prepend)?-this.tileSize.w:this.tileSize.w;var resolution=this.map.getResolution();var deltaLon=resolution*deltaX;for(var i=0,len=this.grid.length;i<len;i++){var row=this.grid[i];var modelTileIndex=(prepend)?0:(row.length-1);var modelTile=row[modelTileIndex];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.left=bounds.left+deltaLon;bounds.right=bounds.right+deltaLon;position.x=position.x+deltaX;var tile=prepend?this.grid[i].pop():this.grid[i].shift();tile.moveTo(bounds,position);if(prepend){row.unshift(tile);}else{row.push(tile);}}},removeExcessTiles:function(rows,columns){while(this.grid.length>rows){var row=this.grid.pop();for(var i=0,l=row.length;i<l;i++){var tile=row[i];this.removeTileMonitoringHooks(tile);tile.destroy();}}
+while(this.grid[0].length>columns){for(var i=0,l=this.grid.length;i<l;i++){var row=this.grid[i];var tile=row.pop();this.removeTileMonitoringHooks(tile);tile.destroy();}}},onMapResize:function(){if(this.singleTile){this.clearGrid();this.setTileSize();}},getTileBounds:function(viewPortPx){var maxExtent=this.maxExtent;var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=maxExtent.left+(tileMapWidth*Math.floor((mapPoint.lon-
+maxExtent.left)/tileMapWidth));var tileBottom=maxExtent.bottom+(tileMapHeight*Math.floor((mapPoint.lat-
+maxExtent.bottom)/tileMapHeight));return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Tile=OpenLayers.Class({EVENT_TYPES:["loadstart","loadend","reload","unload"],events:null,id:null,layer:null,url:null,bounds:null,size:null,position:null,isLoading:false,initialize:function(layer,position,bounds,url,size,options){this.layer=layer;this.position=position.clone();this.bounds=bounds.clone();this.url=url;if(size){this.size=size.clone();}
+this.id=OpenLayers.Util.createUniqueID("Tile_");this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);OpenLayers.Util.extend(this,options);},unload:function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("unload");}},destroy:function(){this.layer=null;this.bounds=null;this.size=null;this.position=null;this.events.destroy();this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile(this.layer,this.position,this.bounds,this.url,this.size);}
+OpenLayers.Util.applyDefaults(obj,this);return obj;},draw:function(){var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));this.shouldDraw=(withinMaxExtent||this.layer.displayOutsideMaxExtent);this.clear();return this.shouldDraw;},moveTo:function(bounds,position,redraw){if(redraw==null){redraw=true;}
+this.bounds=bounds.clone();this.position=position.clone();if(redraw){this.draw();}},clear:function(){},getBoundsFromBaseLayer:function(position){var msg=OpenLayers.i18n('reprojectDeprecated',{'layerName':this.layer.name});OpenLayers.Console.warn(msg);var topLeft=this.layer.map.getLonLatFromLayerPx(position);var bottomRightPx=position.clone();bottomRightPx.x+=this.size.w;bottomRightPx.y+=this.size.h;var bottomRight=this.layer.map.getLonLatFromLayerPx(bottomRightPx);if(topLeft.lon>bottomRight.lon){if(topLeft.lon<0){topLeft.lon=-180-(topLeft.lon+180);}else{bottomRight.lon=180+bottomRight.lon+180;}}
+var bounds=new OpenLayers.Bounds(topLeft.lon,bottomRight.lat,bottomRight.lon,topLeft.lat);return bounds;},showTile:function(){if(this.shouldDraw){this.show();}},show:function(){},hide:function(){},CLASS_NAME:"OpenLayers.Tile"});OpenLayers.Tile.Image=OpenLayers.Class(OpenLayers.Tile,{url:null,imgDiv:null,frame:null,layerAlphaHack:null,isBackBuffer:false,isFirstDraw:true,backBufferTile:null,maxGetUrlLength:null,initialize:function(layer,position,bounds,url,size,options){OpenLayers.Tile.prototype.initialize.apply(this,arguments);if(this.maxGetUrlLength!=null){OpenLayers.Util.extend(this,OpenLayers.Tile.Image.IFrame);}
+this.url=url;this.frame=document.createElement('div');this.frame.style.overflow='hidden';this.frame.style.position='absolute';this.layerAlphaHack=this.layer.alpha&&OpenLayers.Util.alphaHack();},destroy:function(){if(this.imgDiv!=null){this.removeImgDiv();}
+this.imgDiv=null;if((this.frame!=null)&&(this.frame.parentNode==this.layer.div)){this.layer.div.removeChild(this.frame);}
+this.frame=null;if(this.backBufferTile){this.backBufferTile.destroy();this.backBufferTile=null;}
+this.layer.events.unregister("loadend",this,this.resetBackBuffer);OpenLayers.Tile.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile.Image(this.layer,this.position,this.bounds,this.url,this.size);}
+obj=OpenLayers.Tile.prototype.clone.apply(this,[obj]);obj.imgDiv=null;return obj;},draw:function(){if(this.layer!=this.layer.map.baseLayer&&this.layer.reproject){this.bounds=this.getBoundsFromBaseLayer(this.position);}
+var drawTile=OpenLayers.Tile.prototype.draw.apply(this,arguments);if((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1)||this.layer.singleTile){if(drawTile){if(!this.backBufferTile){this.backBufferTile=this.clone();this.backBufferTile.hide();this.backBufferTile.isBackBuffer=true;this.events.register('loadend',this,this.resetBackBuffer);this.layer.events.register("loadend",this,this.resetBackBuffer);}
+this.startTransition();}else{if(this.backBufferTile){this.backBufferTile.clear();}}}else{if(drawTile&&this.isFirstDraw){this.events.register('loadend',this,this.showTile);this.isFirstDraw=false;}}
+if(!drawTile){return false;}
+if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");}
+return this.renderTile();},resetBackBuffer:function(){this.showTile();if(this.backBufferTile&&(this.isFirstDraw||!this.layer.numLoadingTiles)){this.isFirstDraw=false;var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));if(withinMaxExtent){this.backBufferTile.position=this.position;this.backBufferTile.bounds=this.bounds;this.backBufferTile.size=this.size;this.backBufferTile.imageSize=this.layer.getImageSize(this.bounds)||this.size;this.backBufferTile.imageOffset=this.layer.imageOffset;this.backBufferTile.resolution=this.layer.getResolution();this.backBufferTile.renderTile();}
+this.backBufferTile.hide();}},renderTile:function(){if(this.layer.async){this.initImgDiv();this.layer.getURLasync(this.bounds,this,"url",this.positionImage);}else{this.url=this.layer.getURL(this.bounds);this.initImgDiv();this.positionImage();}
+return true;},positionImage:function(){if(this.layer===null){return;}
+OpenLayers.Util.modifyDOMElement(this.frame,null,this.position,this.size);var imageSize=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,null,null,imageSize,this.url);}else{OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,imageSize);this.imgDiv.src=this.url;}},clear:function(){if(this.imgDiv){this.hide();if(OpenLayers.Tile.Image.useBlankTile){this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";}}},initImgDiv:function(){if(this.imgDiv==null){var offset=this.layer.imageOffset;var size=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){this.imgDiv=OpenLayers.Util.createAlphaImageDiv(null,offset,size,null,"relative",null,null,null,true);}else{this.imgDiv=OpenLayers.Util.createImage(null,offset,size,null,"relative",null,null,true);}
+if(OpenLayers.Util.isArray(this.layer.url)){this.imgDiv.urls=this.layer.url.slice();}
+this.imgDiv.className='olTileImage';this.frame.style.zIndex=this.isBackBuffer?0:1;this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);}
+this.imgDiv.map=this.layer.map;var onload=function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};if(this.layerAlphaHack){OpenLayers.Event.observe(this.imgDiv.childNodes[0],'load',OpenLayers.Function.bind(onload,this));}else{OpenLayers.Event.observe(this.imgDiv,'load',OpenLayers.Function.bind(onload,this));}
+var onerror=function(){if(this.imgDiv._attempts>OpenLayers.IMAGE_RELOAD_ATTEMPTS){onload.call(this);}};OpenLayers.Event.observe(this.imgDiv,"error",OpenLayers.Function.bind(onerror,this));}
+this.imgDiv.viewRequestID=this.layer.map.viewRequestID;},removeImgDiv:function(){OpenLayers.Event.stopObservingElement(this.imgDiv);if(this.imgDiv.parentNode==this.frame){this.frame.removeChild(this.imgDiv);this.imgDiv.map=null;}
+this.imgDiv.urls=null;var child=this.imgDiv.firstChild;if(child){OpenLayers.Event.stopObservingElement(child);this.imgDiv.removeChild(child);delete child;}else{this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";}},checkImgURL:function(){if(this.layer){var loaded=this.layerAlphaHack?this.imgDiv.firstChild.src:this.imgDiv.src;if(!OpenLayers.Util.isEquivalentUrl(loaded,this.url)){this.hide();}}},startTransition:function(){if(!this.backBufferTile||!this.backBufferTile.imgDiv){return;}
+var ratio=1;if(this.backBufferTile.resolution){ratio=this.backBufferTile.resolution/this.layer.getResolution();}
+if(ratio!=1){if(this.layer.transitionEffect=='resize'){var upperLeft=new OpenLayers.LonLat(this.backBufferTile.bounds.left,this.backBufferTile.bounds.top);var size=new OpenLayers.Size(this.backBufferTile.size.w*ratio,this.backBufferTile.size.h*ratio);var px=this.layer.map.getLayerPxFromLonLat(upperLeft);OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame,null,px,size);var imageSize=this.backBufferTile.imageSize;imageSize=new OpenLayers.Size(imageSize.w*ratio,imageSize.h*ratio);var imageOffset=this.backBufferTile.imageOffset;if(imageOffset){imageOffset=new OpenLayers.Pixel(imageOffset.x*ratio,imageOffset.y*ratio);}
+OpenLayers.Util.modifyDOMElement(this.backBufferTile.imgDiv,null,imageOffset,imageSize);this.backBufferTile.show();}}else{if(this.layer.singleTile){this.backBufferTile.show();}else{this.backBufferTile.hide();}}},show:function(){this.frame.style.display='';if(OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1){if(OpenLayers.IS_GECKO===true){this.frame.scrollLeft=this.frame.scrollLeft;}}},hide:function(){this.frame.style.display='none';},CLASS_NAME:"OpenLayers.Tile.Image"});OpenLayers.Tile.Image.useBlankTile=(OpenLayers.BROWSER_NAME=="safari"||OpenLayers.BROWSER_NAME=="opera");OpenLayers.Format.ArcXML=OpenLayers.Class(OpenLayers.Format.XML,{fontStyleKeys:['antialiasing','blockout','font','fontcolor','fontsize','fontstyle','glowing','interval','outline','printmode','shadow','transparency'],request:null,response:null,initialize:function(options){this.request=new OpenLayers.Format.ArcXML.Request();this.response=new OpenLayers.Format.ArcXML.Response();if(options){if(options.requesttype=="feature"){this.request.get_image=null;var qry=this.request.get_feature.query;this.addCoordSys(qry.featurecoordsys,options.featureCoordSys);this.addCoordSys(qry.filtercoordsys,options.filterCoordSys);if(options.polygon){qry.isspatial=true;qry.spatialfilter.polygon=options.polygon;}else if(options.envelope){qry.isspatial=true;qry.spatialfilter.envelope={minx:0,miny:0,maxx:0,maxy:0};this.parseEnvelope(qry.spatialfilter.envelope,options.envelope);}}else if(options.requesttype=="image"){this.request.get_feature=null;var props=this.request.get_image.properties;this.parseEnvelope(props.envelope,options.envelope);this.addLayers(props.layerlist,options.layers);this.addImageSize(props.imagesize,options.tileSize);this.addCoordSys(props.featurecoordsys,options.featureCoordSys);this.addCoordSys(props.filtercoordsys,options.filterCoordSys);}else{this.request=null;}}
+OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},parseEnvelope:function(env,arr){if(arr&&arr.length==4){env.minx=arr[0];env.miny=arr[1];env.maxx=arr[2];env.maxy=arr[3];}},addLayers:function(ll,lyrs){for(var lind=0,len=lyrs.length;lind<len;lind++){ll.push(lyrs[lind]);}},addImageSize:function(imsize,olsize){if(olsize!==null){imsize.width=olsize.w;imsize.height=olsize.h;imsize.printwidth=olsize.w;imsize.printheight=olsize.h;}},addCoordSys:function(featOrFilt,fsys){if(typeof fsys=="string"){featOrFilt.id=parseInt(fsys);featOrFilt.string=fsys;}
+else if(typeof fsys=="object"&&fsys.proj!==null){featOrFilt.id=fsys.proj.srsProjNumber;featOrFilt.string=fsys.proj.srsCode;}else{featOrFilt=fsys;}},iserror:function(data){var ret=null;if(!data){ret=(this.response.error!=='');}else{data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);var errorNodes=data.documentElement.getElementsByTagName("ERROR");ret=(errorNodes!==null&&errorNodes.length>0);}
+return ret;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var arcNode=null;if(data&&data.documentElement){if(data.documentElement.nodeName=="ARCXML"){arcNode=data.documentElement;}else{arcNode=data.documentElement.getElementsByTagName("ARCXML")[0];}}
+if(!arcNode||arcNode.firstChild.nodeName==='parsererror'){var error,source;try{error=data.firstChild.nodeValue;source=data.firstChild.childNodes[1].firstChild.nodeValue;}catch(err){}
+throw{message:"Error parsing the ArcXML request",error:error,source:source};}
+var response=this.parseResponse(arcNode);return response;},write:function(request){if(!request){request=this.request;}
+var root=this.createElementNS("","ARCXML");root.setAttribute("version","1.1");var reqElem=this.createElementNS("","REQUEST");if(request.get_image!=null){var getElem=this.createElementNS("","GET_IMAGE");reqElem.appendChild(getElem);var propElem=this.createElementNS("","PROPERTIES");getElem.appendChild(propElem);var props=request.get_image.properties;if(props.featurecoordsys!=null){var feat=this.createElementNS("","FEATURECOORDSYS");propElem.appendChild(feat);if(props.featurecoordsys.id===0){feat.setAttribute("string",props.featurecoordsys['string']);}
+else{feat.setAttribute("id",props.featurecoordsys.id);}}
+if(props.filtercoordsys!=null){var filt=this.createElementNS("","FILTERCOORDSYS");propElem.appendChild(filt);if(props.filtercoordsys.id===0){filt.setAttribute("string",props.filtercoordsys.string);}
+else{filt.setAttribute("id",props.filtercoordsys.id);}}
+if(props.envelope!=null){var env=this.createElementNS("","ENVELOPE");propElem.appendChild(env);env.setAttribute("minx",props.envelope.minx);env.setAttribute("miny",props.envelope.miny);env.setAttribute("maxx",props.envelope.maxx);env.setAttribute("maxy",props.envelope.maxy);}
+var imagesz=this.createElementNS("","IMAGESIZE");propElem.appendChild(imagesz);imagesz.setAttribute("height",props.imagesize.height);imagesz.setAttribute("width",props.imagesize.width);if(props.imagesize.height!=props.imagesize.printheight||props.imagesize.width!=props.imagesize.printwidth){imagesz.setAttribute("printheight",props.imagesize.printheight);imagesz.setArrtibute("printwidth",props.imagesize.printwidth);}
+if(props.background!=null){var backgrnd=this.createElementNS("","BACKGROUND");propElem.appendChild(backgrnd);backgrnd.setAttribute("color",props.background.color.r+","+
+props.background.color.g+","+
+props.background.color.b);if(props.background.transcolor!==null){backgrnd.setAttribute("transcolor",props.background.transcolor.r+","+
+props.background.transcolor.g+","+
+props.background.transcolor.b);}}
+if(props.layerlist!=null&&props.layerlist.length>0){var layerlst=this.createElementNS("","LAYERLIST");propElem.appendChild(layerlst);for(var ld=0;ld<props.layerlist.length;ld++){var ldef=this.createElementNS("","LAYERDEF");layerlst.appendChild(ldef);ldef.setAttribute("id",props.layerlist[ld].id);ldef.setAttribute("visible",props.layerlist[ld].visible);if(typeof props.layerlist[ld].query=="object"){var query=props.layerlist[ld].query;if(query.where.length<0){continue;}
+var queryElem=null;if(typeof query.spatialfilter=="boolean"&&query.spatialfilter){queryElem=this.createElementNS("","SPATIALQUERY");}
+else{queryElem=this.createElementNS("","QUERY");}
+queryElem.setAttribute("where",query.where);if(typeof query.accuracy=="number"&&query.accuracy>0){queryElem.setAttribute("accuracy",query.accuracy);}
+if(typeof query.featurelimit=="number"&&query.featurelimit<2000){queryElem.setAttribute("featurelimit",query.featurelimit);}
+if(typeof query.subfields=="string"&&query.subfields!="#ALL#"){queryElem.setAttribute("subfields",query.subfields);}
+if(typeof query.joinexpression=="string"&&query.joinexpression.length>0){queryElem.setAttribute("joinexpression",query.joinexpression);}
+if(typeof query.jointables=="string"&&query.jointables.length>0){queryElem.setAttribute("jointables",query.jointables);}
+ldef.appendChild(queryElem);}
+if(typeof props.layerlist[ld].renderer=="object"){this.addRenderer(ldef,props.layerlist[ld].renderer);}}}}else if(request.get_feature!=null){var getElem=this.createElementNS("","GET_FEATURES");getElem.setAttribute("outputmode","newxml");getElem.setAttribute("checkesc","true");if(request.get_feature.geometry){getElem.setAttribute("geometry",request.get_feature.geometry);}
+else{getElem.setAttribute("geometry","false");}
+if(request.get_feature.compact){getElem.setAttribute("compact",request.get_feature.compact);}
+if(request.get_feature.featurelimit=="number"){getElem.setAttribute("featurelimit",request.get_feature.featurelimit);}
+getElem.setAttribute("globalenvelope","true");reqElem.appendChild(getElem);if(request.get_feature.layer!=null&&request.get_feature.layer.length>0){var lyrElem=this.createElementNS("","LAYER");lyrElem.setAttribute("id",request.get_feature.layer);getElem.appendChild(lyrElem);}
+var fquery=request.get_feature.query;if(fquery!=null){var qElem=null;if(fquery.isspatial){qElem=this.createElementNS("","SPATIALQUERY");}else{qElem=this.createElementNS("","QUERY");}
+getElem.appendChild(qElem);if(typeof fquery.accuracy=="number"){qElem.setAttribute("accuracy",fquery.accuracy);}
+if(fquery.featurecoordsys!=null){var fcsElem1=this.createElementNS("","FEATURECOORDSYS");if(fquery.featurecoordsys.id==0){fcsElem1.setAttribute("string",fquery.featurecoordsys.string);}else{fcsElem1.setAttribute("id",fquery.featurecoordsys.id);}
+qElem.appendChild(fcsElem1);}
+if(fquery.filtercoordsys!=null){var fcsElem2=this.createElementNS("","FILTERCOORDSYS");if(fquery.filtercoordsys.id===0){fcsElem2.setAttribute("string",fquery.filtercoordsys.string);}else{fcsElem2.setAttribute("id",fquery.filtercoordsys.id);}
+qElem.appendChild(fcsElem2);}
+if(fquery.buffer>0){var bufElem=this.createElementNS("","BUFFER");bufElem.setAttribute("distance",fquery.buffer);qElem.appendChild(bufElem);}
+if(fquery.isspatial){var spfElem=this.createElementNS("","SPATIALFILTER");spfElem.setAttribute("relation",fquery.spatialfilter.relation);qElem.appendChild(spfElem);if(fquery.spatialfilter.envelope){var envElem=this.createElementNS("","ENVELOPE");envElem.setAttribute("minx",fquery.spatialfilter.envelope.minx);envElem.setAttribute("miny",fquery.spatialfilter.envelope.miny);envElem.setAttribute("maxx",fquery.spatialfilter.envelope.maxx);envElem.setAttribute("maxy",fquery.spatialfilter.envelope.maxy);spfElem.appendChild(envElem);}else if(typeof fquery.spatialfilter.polygon=="object"){spfElem.appendChild(this.writePolygonGeometry(fquery.spatialfilter.polygon));}}
+if(fquery.where!=null&&fquery.where.length>0){qElem.setAttribute("where",fquery.where);}}}
+root.appendChild(reqElem);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},addGroupRenderer:function(ldef,toprenderer){var topRelem=this.createElementNS("","GROUPRENDERER");ldef.appendChild(topRelem);for(var rind=0;rind<toprenderer.length;rind++){var renderer=toprenderer[rind];this.addRenderer(topRelem,renderer);}},addRenderer:function(topRelem,renderer){if(OpenLayers.Util.isArray(renderer)){this.addGroupRenderer(topRelem,renderer);}else{var renderElem=this.createElementNS("",renderer.type.toUpperCase()+"RENDERER");topRelem.appendChild(renderElem);if(renderElem.tagName=="VALUEMAPRENDERER"){this.addValueMapRenderer(renderElem,renderer);}else if(renderElem.tagName=="VALUEMAPLABELRENDERER"){this.addValueMapLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SIMPLELABELRENDERER"){this.addSimpleLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SCALEDEPENDENTRENDERER"){this.addScaleDependentRenderer(renderElem,renderer);}}},addScaleDependentRenderer:function(renderElem,renderer){if(typeof renderer.lower=="string"||typeof renderer.lower=="number"){renderElem.setAttribute("lower",renderer.lower);}
+if(typeof renderer.upper=="string"||typeof renderer.upper=="number"){renderElem.setAttribute("upper",renderer.upper);}
+this.addRenderer(renderElem,renderer.renderer);},addValueMapLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);renderElem.setAttribute("labelfield",renderer.labelfield);if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);}
+if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);}
+if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);}
+renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="text"){selem=this.createElementNS("","TEXTSYMBOL");}
+if(selem!=null){var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(exact.symbol[key]){selem.setAttribute(key,exact.symbol[key]);}}
+eelem.appendChild(selem);}}}}},addValueMapRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);if(typeof renderer.ranges=="object"){for(var rng=0,rnglen=renderer.ranges.length;rng<rnglen;rng++){var range=renderer.ranges[rng];var relem=this.createElementNS("","RANGE");relem.setAttribute("lower",range.lower);relem.setAttribute("upper",range.upper);renderElem.appendChild(relem);if(typeof range.symbol=="object"){var selem=null;if(range.symbol.type=="simplepolygon"){selem=this.createElementNS("","SIMPLEPOLYGONSYMBOL");}
+if(selem!=null){if(typeof range.symbol.boundarycolor=="string"){selem.setAttribute("boundarycolor",range.symbol.boundarycolor);}
+if(typeof range.symbol.fillcolor=="string"){selem.setAttribute("fillcolor",range.symbol.fillcolor);}
+if(typeof range.symbol.filltransparency=="number"){selem.setAttribute("filltransparency",range.symbol.filltransparency);}
+relem.appendChild(selem);}}}}else if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);}
+if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);}
+if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);}
+renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="simplemarker"){selem=this.createElementNS("","SIMPLEMARKERSYMBOL");}
+if(selem!=null){if(typeof exact.symbol.antialiasing=="string"){selem.setAttribute("antialiasing",exact.symbol.antialiasing);}
+if(typeof exact.symbol.color=="string"){selem.setAttribute("color",exact.symbol.color);}
+if(typeof exact.symbol.outline=="string"){selem.setAttribute("outline",exact.symbol.outline);}
+if(typeof exact.symbol.overlap=="string"){selem.setAttribute("overlap",exact.symbol.overlap);}
+if(typeof exact.symbol.shadow=="string"){selem.setAttribute("shadow",exact.symbol.shadow);}
+if(typeof exact.symbol.transparency=="number"){selem.setAttribute("transparency",exact.symbol.transparency);}
+if(typeof exact.symbol.usecentroid=="string"){selem.setAttribute("usecentroid",exact.symbol.usecentroid);}
+if(typeof exact.symbol.width=="number"){selem.setAttribute("width",exact.symbol.width);}
+eelem.appendChild(selem);}}}}},addSimpleLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("field",renderer.field);var keys=['featureweight','howmanylabels','labelbufferratio','labelpriorities','labelweight','linelabelposition','rotationalangles'];for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(renderer[key]){renderElem.setAttribute(key,renderer[key]);}}
+if(renderer.symbol.type=="text"){var symbol=renderer.symbol;var selem=this.createElementNS("","TEXTSYMBOL");renderElem.appendChild(selem);var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(symbol[key]){selem.setAttribute(key,renderer[key]);}}}},writePolygonGeometry:function(polygon){if(!(polygon instanceof OpenLayers.Geometry.Polygon)){throw{message:'Cannot write polygon geometry to ArcXML with an '+
+polygon.CLASS_NAME+' object.',geometry:polygon};}
+var polyElem=this.createElementNS("","POLYGON");for(var ln=0,lnlen=polygon.components.length;ln<lnlen;ln++){var ring=polygon.components[ln];var ringElem=this.createElementNS("","RING");for(var rn=0,rnlen=ring.components.length;rn<rnlen;rn++){var point=ring.components[rn];var pointElem=this.createElementNS("","POINT");pointElem.setAttribute("x",point.x);pointElem.setAttribute("y",point.y);ringElem.appendChild(pointElem);}
+polyElem.appendChild(ringElem);}
+return polyElem;},parseResponse:function(data){if(typeof data=="string"){var newData=new OpenLayers.Format.XML();data=newData.read(data);}
+var response=new OpenLayers.Format.ArcXML.Response();var errorNode=data.getElementsByTagName("ERROR");if(errorNode!=null&&errorNode.length>0){response.error=this.getChildValue(errorNode,"Unknown error.");}else{var responseNode=data.getElementsByTagName("RESPONSE");if(responseNode==null||responseNode.length==0){response.error="No RESPONSE tag found in ArcXML response.";return response;}
+var rtype=responseNode[0].firstChild.nodeName;if(rtype=="#text"){rtype=responseNode[0].firstChild.nextSibling.nodeName;}
+if(rtype=="IMAGE"){var envelopeNode=data.getElementsByTagName("ENVELOPE");var outputNode=data.getElementsByTagName("OUTPUT");if(envelopeNode==null||envelopeNode.length==0){response.error="No ENVELOPE tag found in ArcXML response.";}else if(outputNode==null||outputNode.length==0){response.error="No OUTPUT tag found in ArcXML response.";}else{var envAttr=this.parseAttributes(envelopeNode[0]);var outputAttr=this.parseAttributes(outputNode[0]);if(typeof outputAttr.type=="string"){response.image={envelope:envAttr,output:{type:outputAttr.type,data:this.getChildValue(outputNode[0])}};}else{response.image={envelope:envAttr,output:outputAttr};}}}else if(rtype=="FEATURES"){var features=responseNode[0].getElementsByTagName("FEATURES");var featureCount=features[0].getElementsByTagName("FEATURECOUNT");response.features.featurecount=featureCount[0].getAttribute("count");if(response.features.featurecount>0){var envelope=features[0].getElementsByTagName("ENVELOPE");response.features.envelope=this.parseAttributes(envelope[0],typeof(0));var featureList=features[0].getElementsByTagName("FEATURE");for(var fn=0;fn<featureList.length;fn++){var feature=new OpenLayers.Feature.Vector();var fields=featureList[fn].getElementsByTagName("FIELD");for(var fdn=0;fdn<fields.length;fdn++){var fieldName=fields[fdn].getAttribute("name");var fieldValue=fields[fdn].getAttribute("value");feature.attributes[fieldName]=fieldValue;}
+var geom=featureList[fn].getElementsByTagName("POLYGON");if(geom.length>0){var ring=geom[0].getElementsByTagName("RING");var polys=[];for(var rn=0;rn<ring.length;rn++){var linearRings=[];linearRings.push(this.parsePointGeometry(ring[rn]));var holes=ring[rn].getElementsByTagName("HOLE");for(var hn=0;hn<holes.length;hn++){linearRings.push(this.parsePointGeometry(holes[hn]));}
+holes=null;polys.push(new OpenLayers.Geometry.Polygon(linearRings));linearRings=null;}
+ring=null;if(polys.length==1){feature.geometry=polys[0];}else
+{feature.geometry=new OpenLayers.Geometry.MultiPolygon(polys);}}
+response.features.feature.push(feature);}}}else{response.error="Unidentified response type.";}}
+return response;},parseAttributes:function(node,type){var attributes={};for(var attr=0;attr<node.attributes.length;attr++){if(type=="number"){attributes[node.attributes[attr].nodeName]=parseFloat(node.attributes[attr].nodeValue);}else{attributes[node.attributes[attr].nodeName]=node.attributes[attr].nodeValue;}}
+return attributes;},parsePointGeometry:function(node){var ringPoints=[];var coords=node.getElementsByTagName("COORDS");if(coords.length>0){var coordArr=this.getChildValue(coords[0]);coordArr=coordArr.split(/;/);for(var cn=0;cn<coordArr.length;cn++){var coordItems=coordArr[cn].split(/ /);ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(coordItems[0]),parseFloat(coordItems[1])));}
+coords=null;}else{var point=node.getElementsByTagName("POINT");if(point.length>0){for(var pn=0;pn<point.length;pn++){ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(point[pn].getAttribute("x")),parseFloat(point[pn].getAttribute("y"))));}}
+point=null;}
+return new OpenLayers.Geometry.LinearRing(ringPoints);},CLASS_NAME:"OpenLayers.Format.ArcXML"});OpenLayers.Format.ArcXML.Request=OpenLayers.Class({initialize:function(params){var defaults={get_image:{properties:{background:null,draw:true,envelope:{minx:0,miny:0,maxx:0,maxy:0},featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},imagesize:{height:0,width:0,dpi:96,printheight:0,printwidth:0,scalesymbols:false},layerlist:[],output:{baseurl:"",legendbaseurl:"",legendname:"",legendpath:"",legendurl:"",name:"",path:"",type:"jpg",url:""}}},get_feature:{layer:"",query:{isspatial:false,featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},buffer:0,where:"",spatialfilter:{relation:"envelope_intersection",envelope:null}}},environment:{separators:{cs:" ",ts:";"}},layer:[],workspaces:[]};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Request"});OpenLayers.Format.ArcXML.Response=OpenLayers.Class({initialize:function(params){var defaults={image:{envelope:null,output:''},features:{featurecount:0,envelope:null,feature:[]},error:''};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Response"});OpenLayers.Request={DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:true,user:undefined,password:undefined,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},URL_SPLIT_REGEX:/([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,events:new OpenLayers.Events(this,null,["complete","success","failure"]),issue:function(config){var defaultConfig=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});config=OpenLayers.Util.applyDefaults(config,defaultConfig);var request=new OpenLayers.Request.XMLHttpRequest();var url=OpenLayers.Util.urlAppend(config.url,OpenLayers.Util.getParameterString(config.params||{}));var sameOrigin=!(url.indexOf("http")==0);var urlParts=!sameOrigin&&url.match(this.URL_SPLIT_REGEX);if(urlParts){var location=window.location;sameOrigin=urlParts[1]==location.protocol&&urlParts[3]==location.hostname;var uPort=urlParts[4],lPort=location.port;if(uPort!=80&&uPort!=""||lPort!="80"&&lPort!=""){sameOrigin=sameOrigin&&uPort==lPort;}}
+if(!sameOrigin){if(config.proxy){if(typeof config.proxy=="function"){url=config.proxy(url);}else{url=config.proxy+encodeURIComponent(url);}}else{OpenLayers.Console.warn(OpenLayers.i18n("proxyNeeded"),{url:url});}}
+request.open(config.method,url,config.async,config.user,config.password);for(var header in config.headers){request.setRequestHeader(header,config.headers[header]);}
+var events=this.events;var self=this;request.onreadystatechange=function(){if(request.readyState==OpenLayers.Request.XMLHttpRequest.DONE){var proceed=events.triggerEvent("complete",{request:request,config:config,requestUrl:url});if(proceed!==false){self.runCallbacks({request:request,config:config,requestUrl:url});}}};if(config.async===false){request.send(config.data);}else{window.setTimeout(function(){if(request.readyState!==0){request.send(config.data);}},0);}
+return request;},runCallbacks:function(options){var request=options.request;var config=options.config;var complete=(config.scope)?OpenLayers.Function.bind(config.callback,config.scope):config.callback;var success;if(config.success){success=(config.scope)?OpenLayers.Function.bind(config.success,config.scope):config.success;}
+var failure;if(config.failure){failure=(config.scope)?OpenLayers.Function.bind(config.failure,config.scope):config.failure;}
+if(OpenLayers.Util.createUrlObject(config.url).protocol=="file:"&&request.responseText){request.status=200;}
+complete(request);if(!request.status||(request.status>=200&&request.status<300)){this.events.triggerEvent("success",options);if(success){success(request);}}
+if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("failure",options);if(failure){failure(request);}}},GET:function(config){config=OpenLayers.Util.extend(config,{method:"GET"});return OpenLayers.Request.issue(config);},POST:function(config){config=OpenLayers.Util.extend(config,{method:"POST"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},PUT:function(config){config=OpenLayers.Util.extend(config,{method:"PUT"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},DELETE:function(config){config=OpenLayers.Util.extend(config,{method:"DELETE"});return OpenLayers.Request.issue(config);},HEAD:function(config){config=OpenLayers.Util.extend(config,{method:"HEAD"});return OpenLayers.Request.issue(config);},OPTIONS:function(config){config=OpenLayers.Util.extend(config,{method:"OPTIONS"});return OpenLayers.Request.issue(config);}};OpenLayers.Layer.ArcIMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{ClientVersion:"9.2",ServiceName:''},tileSize:null,featureCoordSys:"4326",filterCoordSys:"4326",layers:null,async:true,name:"ArcIMS",isBaseLayer:true,DEFAULT_OPTIONS:{tileSize:new OpenLayers.Size(512,512),featureCoordSys:"4326",filterCoordSys:"4326",layers:null,isBaseLayer:true,async:true,name:"ArcIMS"},initialize:function(name,url,options){this.tileSize=new OpenLayers.Size(512,512);this.params=OpenLayers.Util.applyDefaults({ServiceName:options.serviceName},this.DEFAULT_PARAMS);this.options=OpenLayers.Util.applyDefaults(options,this.DEFAULT_OPTIONS);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,this.params,options]);if(this.transparent){if(!this.isBaseLayer){this.isBaseLayer=false;}
+if(this.format=="image/jpeg"){this.format=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}
+if(this.options.layers===null){this.options.layers=[];}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},getURL:function(bounds){var url="";bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));var req=new OpenLayers.Request.POST({url:this.getFullRequestString(),data:axlReq.write(),async:false});if(req!=null){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;}
+var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);url=this.getUrlOrImage(arcxml.image.output);}
+return url;},getURLasync:function(bounds,scope,prop,callback){bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));OpenLayers.Request.POST({url:this.getFullRequestString(),async:true,data:axlReq.write(),callback:function(req){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;}
+var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);scope[prop]=this.getUrlOrImage(arcxml.image.output);callback.apply(scope);},scope:this});},getUrlOrImage:function(output){var ret="";if(output.url){ret=output.url;}else if(output.data){ret="data:image/"+output.type+";base64,"+output.data;}
+return ret;},setLayerQuery:function(id,querydef){for(var lyr=0;lyr<this.options.layers.length;lyr++){if(id==this.options.layers[lyr].id){this.options.layers[lyr].query=querydef;return;}}
+this.options.layers.push({id:id,visible:true,query:querydef});},getFeatureInfo:function(geometry,layer,options){var buffer=options.buffer||1;var callback=options.callback||function(){};var scope=options.scope||window;var requestOptions={};OpenLayers.Util.extend(requestOptions,this.options);requestOptions.requesttype="feature";if(geometry instanceof OpenLayers.LonLat){requestOptions.polygon=null;requestOptions.envelope=[geometry.lon-buffer,geometry.lat-buffer,geometry.lon+buffer,geometry.lat+buffer];}else if(geometry instanceof OpenLayers.Geometry.Polygon){requestOptions.envelope=null;requestOptions.polygon=geometry;}
+var arcxml=new OpenLayers.Format.ArcXML(requestOptions);OpenLayers.Util.extend(arcxml.request.get_feature,options);arcxml.request.get_feature.layer=layer.id;if(typeof layer.query.accuracy=="number"){arcxml.request.get_feature.query.accuracy=layer.query.accuracy;}else{var mapCenter=this.map.getCenter();var viewPx=this.map.getViewPortPxFromLonLat(mapCenter);viewPx.x++;var mapOffCenter=this.map.getLonLatFromPixel(viewPx);arcxml.request.get_feature.query.accuracy=mapOffCenter.lon-mapCenter.lon;}
+arcxml.request.get_feature.query.where=layer.query.where;arcxml.request.get_feature.query.spatialfilter.relation="area_intersection";OpenLayers.Request.POST({url:this.getFullRequestString({'CustomService':'Query'}),data:arcxml.write(),callback:function(request){var response=arcxml.parseResponse(request.responseText);if(!arcxml.iserror()){callback.call(scope,response.features);}else{callback.call(scope,null);}}});},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcIMS(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.ArcIMS"});OpenLayers.Format.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Format.XML,{layerIdentifier:'_layer',featureIdentifier:'_feature',regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},gmlFormat:null,read:function(data){var result;if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var root=data.documentElement;if(root){var scope=this;var read=this["read_"+root.nodeName];if(read){result=read.call(this,root);}else{result=new OpenLayers.Format.GML((this.options?this.options:{})).read(data);}}else{result=data;}
+return result;},read_msGMLOutput:function(data){var response=[];var layerNodes=this.getSiblingNodesByTagCriteria(data,this.layerIdentifier);if(layerNodes){for(var i=0,len=layerNodes.length;i<len;++i){var node=layerNodes[i];var layerName=node.nodeName;if(node.prefix){layerName=layerName.split(':')[1];}
+var layerName=layerName.replace(this.layerIdentifier,'');var featureNodes=this.getSiblingNodesByTagCriteria(node,this.featureIdentifier);if(featureNodes){for(var j=0;j<featureNodes.length;j++){var featureNode=featureNodes[j];var geomInfo=this.parseGeometry(featureNode);var attributes=this.parseAttributes(featureNode);var feature=new OpenLayers.Feature.Vector(geomInfo.geometry,attributes,null);feature.bounds=geomInfo.bounds;feature.type=layerName;response.push(feature);}}}}
+return response;},read_FeatureInfoResponse:function(data){var response=[];var featureNodes=this.getElementsByTagNameNS(data,'*','FIELDS');for(var i=0,len=featureNodes.length;i<len;i++){var featureNode=featureNodes[i];var geom=null;var attributes={};var j;var jlen=featureNode.attributes.length;if(jlen>0){for(j=0;j<jlen;j++){var attribute=featureNode.attributes[j];attributes[attribute.nodeName]=attribute.nodeValue;}}else{var nodes=featureNode.childNodes;for(j=0,jlen=nodes.length;j<jlen;++j){var node=nodes[j];if(node.nodeType!=3){attributes[node.getAttribute("name")]=node.getAttribute("value");}}}
+response.push(new OpenLayers.Feature.Vector(geom,attributes,null));}
+return response;},getSiblingNodesByTagCriteria:function(node,criteria){var nodes=[];var children,tagName,n,matchNodes,child;if(node&&node.hasChildNodes()){children=node.childNodes;n=children.length;for(var k=0;k<n;k++){child=children[k];while(child&&child.nodeType!=1){child=child.nextSibling;k++;}
+tagName=(child?child.nodeName:'');if(tagName.length>0&&tagName.indexOf(criteria)>-1){nodes.push(child);}else{matchNodes=this.getSiblingNodesByTagCriteria(child,criteria);if(matchNodes.length>0){(nodes.length==0)?nodes=matchNodes:nodes.push(matchNodes);}}}}
+return nodes;},parseAttributes:function(node){var attributes={};if(node.nodeType==1){var children=node.childNodes;var n=children.length;for(var i=0;i<n;++i){var child=children[i];if(child.nodeType==1){var grandchildren=child.childNodes;var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;if(grandchildren.length==0){attributes[name]=null}else if(grandchildren.length==1){var grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){var value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}}
+return attributes;},parseGeometry:function(node){if(!this.gmlFormat){this.gmlFormat=new OpenLayers.Format.GML();}
+var feature=this.gmlFormat.parseFeature(node);var geometry,bounds=null;if(feature){geometry=feature.geometry&&feature.geometry.clone();bounds=feature.bounds&&feature.bounds.clone();feature.destroy();}
+return{geometry:geometry,bounds:bounds};},CLASS_NAME:"OpenLayers.Format.WMSGetFeatureInfo"});OpenLayers.Format.OWSCommon.v1_1_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows/1.1",xlink:"http://www.w3.org/1999/xlink"},readers:{"ows":OpenLayers.Util.applyDefaults({"ExceptionReport":function(node,obj){obj.exceptionReport={version:node.getAttribute('version'),language:node.getAttribute('xml:lang'),exceptions:[]};this.readChildNodes(node,obj.exceptionReport);},"AllowedValues":function(node,parameter){parameter.allowedValues={};this.readChildNodes(node,parameter.allowedValues);},"AnyValue":function(node,parameter){parameter.anyValue=true;},"DataType":function(node,parameter){parameter.dataType=this.getChildValue(node);},"Range":function(node,allowedValues){allowedValues.range={};this.readChildNodes(node,allowedValues.range);},"MinimumValue":function(node,range){range.minValue=this.getChildValue(node);},"MaximumValue":function(node,range){range.maxValue=this.getChildValue(node);},"Identifier":function(node,obj){obj.identifier=this.getChildValue(node);},"SupportedCRS":function(node,obj){obj.supportedCRS=this.getChildValue(node);}},OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])},writers:{"ows":OpenLayers.Util.applyDefaults({"Range":function(range){var node=this.createElementNSPlus("ows:Range",{attributes:{'ows:rangeClosure':range.closure}});this.writeNode("ows:MinimumValue",range.minValue,node);this.writeNode("ows:MaximumValue",range.maxValue,node);return node;},"MinimumValue":function(minValue){var node=this.createElementNSPlus("ows:MinimumValue",{value:minValue});return node;},"MaximumValue":function(maxValue){var node=this.createElementNSPlus("ows:MaximumValue",{value:maxValue});return node;},"Value":function(value){var node=this.createElementNSPlus("ows:Value",{value:value});return node;}},OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"])},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});OpenLayers.Format.WCSGetCoverage=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows/1.1",wcs:"http://www.opengis.net/wcs/1.1",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},VERSION:"1.1.2",schemaLocation:"http://www.opengis.net/wcs/1.1 http://schemas.opengis.net/wcs/1.1/wcsGetCoverage.xsd",write:function(options){var node=this.writeNode("wcs:GetCoverage",options);this.setAttributeNS(node,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"wcs":{"GetCoverage":function(options){var node=this.createElementNSPlus("wcs:GetCoverage",{attributes:{version:options.version||this.VERSION,service:'WCS'}});this.writeNode("ows:Identifier",options.identifier,node);this.writeNode("wcs:DomainSubset",options.domainSubset,node);this.writeNode("wcs:Output",options.output,node);return node;},"DomainSubset":function(domainSubset){var node=this.createElementNSPlus("wcs:DomainSubset",{});this.writeNode("ows:BoundingBox",domainSubset.boundingBox,node);if(domainSubset.temporalSubset){this.writeNode("wcs:TemporalSubset",domainSubset.temporalSubset,node);}
+return node;},"TemporalSubset":function(temporalSubset){var node=this.createElementNSPlus("wcs:TemporalSubset",{});for(var i=0,len=temporalSubset.timePeriods.length;i<len;++i){this.writeNode("wcs:TimePeriod",temporalSubset.timePeriods[i],node);}
+return node;},"TimePeriod":function(timePeriod){var node=this.createElementNSPlus("wcs:TimePeriod",{});this.writeNode("wcs:BeginPosition",timePeriod.begin,node);this.writeNode("wcs:EndPosition",timePeriod.end,node);if(timePeriod.resolution){this.writeNode("wcs:TimeResolution",timePeriod.resolution,node);}
+return node;},"BeginPosition":function(begin){var node=this.createElementNSPlus("wcs:BeginPosition",{value:begin});return node;},"EndPosition":function(end){var node=this.createElementNSPlus("wcs:EndPosition",{value:end});return node;},"TimeResolution":function(resolution){var node=this.createElementNSPlus("wcs:TimeResolution",{value:resolution});return node;},"Output":function(output){var node=this.createElementNSPlus("wcs:Output",{attributes:{format:output.format,store:output.store}});if(output.gridCRS){this.writeNode("wcs:GridCRS",output.gridCRS,node);}
+return node;},"GridCRS":function(gridCRS){var node=this.createElementNSPlus("wcs:GridCRS",{});this.writeNode("wcs:GridBaseCRS",gridCRS.baseCRS,node);if(gridCRS.type){this.writeNode("wcs:GridType",gridCRS.type,node);}
+if(gridCRS.origin){this.writeNode("wcs:GridOrigin",gridCRS.origin,node);}
+this.writeNode("wcs:GridOffsets",gridCRS.offsets,node);if(gridCRS.CS){this.writeNode("wcs:GridCS",gridCRS.CS,node);}
+return node;},"GridBaseCRS":function(baseCRS){return this.createElementNSPlus("wcs:GridBaseCRS",{value:baseCRS});},"GridOrigin":function(origin){return this.createElementNSPlus("wcs:GridOrigin",{value:origin});},"GridType":function(type){return this.createElementNSPlus("wcs:GridType",{value:type});},"GridOffsets":function(offsets){return this.createElementNSPlus("wcs:GridOffsets",{value:offsets});},"GridCS":function(CS){return this.createElementNSPlus("wcs:GridCS",{value:CS});}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows},CLASS_NAME:"OpenLayers.Format.WCSGetCoverage"});OpenLayers.Format.WPSExecute=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows/1.1",gml:"http://www.opengis.net/gml",wps:"http://www.opengis.net/wps/1.0.0",wfs:"http://www.opengis.net/wfs",ogc:"http://www.opengis.net/ogc",wcs:"http://www.opengis.net/wcs",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",schemaLocationAttr:function(options){return undefined;},write:function(options){var doc;if(window.ActiveXObject){doc=new ActiveXObject("Microsoft.XMLDOM");this.xmldom=doc;}else{doc=document.implementation.createDocument("","",null);}
+var node=this.writeNode("wps:Execute",options,doc);this.setAttributeNS(node,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"wps":{"Execute":function(options){var node=this.createElementNSPlus("wps:Execute",{attributes:{version:this.VERSION,service:'WPS'}});this.writeNode("ows:Identifier",options.identifier,node);this.writeNode("wps:DataInputs",options.dataInputs,node);this.writeNode("wps:ResponseForm",options.responseForm,node);return node;},"ResponseForm":function(responseForm){var node=this.createElementNSPlus("wps:ResponseForm",{});if(responseForm.rawDataOutput){this.writeNode("wps:RawDataOutput",responseForm.rawDataOutput,node);}
+if(responseForm.responseDocument){this.writeNode("wps:ResponseDocument",responseForm.responseDocument,node);}
+return node;},"ResponseDocument":function(responseDocument){var node=this.createElementNSPlus("wps:ResponseDocument",{attributes:{storeExecuteResponse:responseDocument.storeExecuteResponse,lineage:responseDocument.lineage,status:responseDocument.status}});if(responseDocument.output){this.writeNode("wps:Output",responseDocument.output,node);}
+return node;},"Output":function(output){var node=this.createElementNSPlus("wps:Output",{attributes:{asReference:output.asReference}});this.writeNode("ows:Identifier",output.identifier,node);this.writeNode("ows:Title",output.title,node);this.writeNode("ows:Abstract",output["abstract"],node);return node;},"RawDataOutput":function(rawDataOutput){var node=this.createElementNSPlus("wps:RawDataOutput",{attributes:{mimeType:rawDataOutput.mimeType}});this.writeNode("ows:Identifier",rawDataOutput.identifier,node);return node;},"DataInputs":function(dataInputs){var node=this.createElementNSPlus("wps:DataInputs",{});for(var i=0,ii=dataInputs.length;i<ii;++i){this.writeNode("wps:Input",dataInputs[i],node);}
+return node;},"Input":function(input){var node=this.createElementNSPlus("wps:Input",{});this.writeNode("ows:Identifier",input.identifier,node);if(input.title){this.writeNode("ows:Title",input.title,node);}
+if(input.data){this.writeNode("wps:Data",input.data,node);}
+if(input.reference){this.writeNode("wps:Reference",input.reference,node);}
+return node;},"Data":function(data){var node=this.createElementNSPlus("wps:Data",{});if(data.literalData){this.writeNode("wps:LiteralData",data.literalData,node);}else if(data.complexData){this.writeNode("wps:ComplexData",data.complexData,node);}
+return node;},"LiteralData":function(literalData){var node=this.createElementNSPlus("wps:LiteralData",{attributes:{uom:literalData.uom},value:literalData.value});return node;},"ComplexData":function(complexData){var node=this.createElementNSPlus("wps:ComplexData",{attributes:{mimeType:complexData.mimeType,encoding:complexData.encoding,schema:complexData.schema}});node.appendChild(this.getXMLDoc().createCDATASection(complexData.value));return node;},"Reference":function(reference){var node=this.createElementNSPlus("wps:Reference",{attributes:{mimeType:reference.mimeType,"xlink:href":reference.href,method:reference.method,encoding:reference.encoding,schema:reference.schema}});if(reference.body){this.writeNode("wps:Body",reference.body,node);}
+return node;},"Body":function(body){var node=this.createElementNSPlus("wps:Body",{});if(body.wcs){this.writeNode("wcs:GetCoverage",body.wcs,node);}
+else if(body.wfs){this.featureType=body.wfs.featureType;this.version=body.wfs.version;this.writeNode("wfs:GetFeature",body.wfs,node);}else{this.writeNode("wps:Execute",body,node);}
+return node;}},"wcs":OpenLayers.Format.WCSGetCoverage.prototype.writers.wcs,"wfs":OpenLayers.Format.WFST.v1_1_0.prototype.writers.wfs,"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows},CLASS_NAME:"OpenLayers.Format.WPSExecute"});OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;}
+return false;},deactivate:function(){if(this.active){this.active=false;return true;}
+return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Strategy.Filter=OpenLayers.Class(OpenLayers.Strategy,{filter:null,cache:null,caching:false,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.apply(this,arguments);if(activated){this.cache=[];this.layer.events.on({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});}
+return activated;},deactivate:function(){this.cache=null;if(this.layer&&this.layer.events){this.layer.events.un({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});}
+return OpenLayers.Strategy.prototype.deactivate.apply(this,arguments);},handleAdd:function(event){if(!this.caching&&this.filter){var features=event.features;event.features=[];var feature;for(var i=0,ii=features.length;i<ii;++i){feature=features[i];if(this.filter.evaluate(feature)){event.features.push(feature);}else{this.cache.push(feature);}}}},handleRemove:function(event){if(!this.caching){this.cache=[];}},setFilter:function(filter){this.filter=filter;var previousCache=this.cache;this.cache=[];this.handleAdd({features:this.layer.features});if(this.cache.length>0){this.caching=true;this.layer.removeFeatures(this.cache.slice());this.caching=false;}
+if(previousCache.length>0){var event={features:previousCache};this.handleAdd(event);if(event.features.length>0){this.caching=true;this.layer.addFeatures(event.features);this.caching=false;}}},CLASS_NAME:"OpenLayers.Strategy.Filter"});OpenLayers.Format.WFSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.0",errorProperty:"service",CLASS_NAME:"OpenLayers.Format.WFSCapabilities"});OpenLayers.Format.WFSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.WFSCapabilities,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var capabilities={};var root=data.documentElement;this.runChildNodes(capabilities,root);return capabilities;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor;for(var i=0;i<children.length;++i){childNode=children[i];if(childNode.nodeType==1){processor=this["read_cap_"+childNode.nodeName];if(processor){processor.apply(this,[obj,childNode]);}}}},read_cap_FeatureTypeList:function(request,node){var featureTypeList={featureTypes:[]};this.runChildNodes(featureTypeList,node);request.featureTypeList=featureTypeList;},read_cap_FeatureType:function(featureTypeList,node,parentLayer){var featureType={};this.runChildNodes(featureType,node);featureTypeList.featureTypes.push(featureType);},read_cap_Name:function(obj,node){var name=this.getChildValue(node);if(name){var parts=name.split(":");obj.name=parts.pop();if(parts.length>0){obj.featureNS=this.lookupNamespaceURI(node,parts[0]);}}},read_cap_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_cap_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1"});OpenLayers.Format.WFSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},read_cap_DefaultSRS:function(obj,node){var defaultSRS=this.getChildValue(node);if(defaultSRS){obj.srs=defaultSRS;}},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_1_0"});OpenLayers.Layer.Image=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:true,url:null,extent:null,size:null,tile:null,aspectRatio:null,initialize:function(name,url,extent,size,options){this.url=url;this.extent=extent;this.maxExtent=extent;this.size=size;OpenLayers.Layer.prototype.initialize.apply(this,[name,options]);this.aspectRatio=(this.extent.getHeight()/this.size.h)/(this.extent.getWidth()/this.size.w);},destroy:function(){if(this.tile){this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;}
+OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Image(this.name,this.url,this.extent,this.size,this.getOptions());}
+obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setMap:function(map){if(this.options.maxResolution==null){this.options.maxResolution=this.aspectRatio*this.extent.getWidth()/this.size.w;}
+OpenLayers.Layer.prototype.setMap.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var firstRendering=(this.tile==null);if(zoomChanged||firstRendering){this.setTileSize();var ul=new OpenLayers.LonLat(this.extent.left,this.extent.top);var ulPx=this.map.getLayerPxFromLonLat(ul);if(firstRendering){this.tile=new OpenLayers.Tile.Image(this,ulPx,this.extent,null,this.tileSize);this.addTileMonitoringHooks(this.tile);}else{this.tile.size=this.tileSize.clone();this.tile.position=ulPx.clone();}
+this.tile.draw();}},setTileSize:function(){var tileWidth=this.extent.getWidth()/this.map.getResolution();var tileHeight=this.extent.getHeight()/this.map.getResolution();this.tileSize=new OpenLayers.Size(tileWidth,tileHeight);},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){this.events.triggerEvent("loadstart");};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.events.triggerEvent("loadend");};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},setUrl:function(newUrl){this.url=newUrl;this.tile.draw();},getURL:function(bounds){return this.url;},CLASS_NAME:"OpenLayers.Layer.Image"});OpenLayers.Strategy.Save=OpenLayers.Class(OpenLayers.Strategy,{EVENT_TYPES:["start","success","fail"],events:null,auto:false,timer:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.auto){if(typeof this.auto==="number"){this.timer=window.setInterval(OpenLayers.Function.bind(this.save,this),this.auto*1000);}else{this.layer.events.on({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){if(this.auto){if(typeof this.auto==="number"){window.clearInterval(this.timer);}else{this.layer.events.un({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}}
+return deactivated;},triggerSave:function(event){var feature=event.feature;if(feature.state===OpenLayers.State.INSERT||feature.state===OpenLayers.State.UPDATE||feature.state===OpenLayers.State.DELETE){this.save([event.feature]);}},save:function(features){if(!features){features=this.layer.features;}
+this.events.triggerEvent("start",{features:features});var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var len=features.length;var clones=new Array(len);var orig,clone;for(var i=0;i<len;++i){orig=features[i];clone=orig.clone();clone.fid=orig.fid;clone.state=orig.state;if(orig.url){clone.url=orig.url;}
+clone._original=orig;clone.geometry.transform(local,remote);clones[i]=clone;}
+features=clones;}
+this.layer.protocol.commit(features,{callback:this.onCommit,scope:this});},onCommit:function(response){var evt={"response":response};if(response.success()){var features=response.reqFeatures;var state,feature;var destroys=[];var insertIds=response.insertIds||[];var j=0;for(var i=0,len=features.length;i<len;++i){feature=features[i];feature=feature._original||feature;state=feature.state;if(state){if(state==OpenLayers.State.DELETE){destroys.push(feature);}else if(state==OpenLayers.State.INSERT){feature.fid=insertIds[j];++j;}
+feature.state=null;}}
+if(destroys.length>0){this.layer.destroyFeatures(destroys);}
+this.events.triggerEvent("success",evt);}else{this.events.triggerEvent("fail",evt);}},CLASS_NAME:"OpenLayers.Strategy.Save"});OpenLayers.Format.GPX=OpenLayers.Class(OpenLayers.Format.XML,{extractWaypoints:true,extractTracks:true,extractRoutes:true,extractAttributes:true,initialize:function(options){this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
+var features=[];if(this.extractTracks){var tracks=doc.getElementsByTagName("trk");for(var i=0,len=tracks.length;i<len;i++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(tracks[i]);}
+var segs=this.getElementsByTagNameNS(tracks[i],tracks[i].namespaceURI,"trkseg");for(var j=0,seglen=segs.length;j<seglen;j++){var track=this.extractSegment(segs[j],"trkpt");features.push(new OpenLayers.Feature.Vector(track,attrs));}}}
+if(this.extractRoutes){var routes=doc.getElementsByTagName("rte");for(var k=0,klen=routes.length;k<klen;k++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(routes[k]);}
+var route=this.extractSegment(routes[k],"rtept");features.push(new OpenLayers.Feature.Vector(route,attrs));}}
+if(this.extractWaypoints){var waypoints=doc.getElementsByTagName("wpt");for(var l=0,len=waypoints.length;l<len;l++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(waypoints[l]);}
+var wpt=new OpenLayers.Geometry.Point(waypoints[l].getAttribute("lon"),waypoints[l].getAttribute("lat"));features.push(new OpenLayers.Feature.Vector(wpt,attrs));}}
+if(this.internalProjection&&this.externalProjection){for(var g=0,featLength=features.length;g<featLength;g++){features[g].geometry.transform(this.externalProjection,this.internalProjection);}}
+return features;},extractSegment:function(segment,segmentType){var points=this.getElementsByTagNameNS(segment,segment.namespaceURI,segmentType);var point_features=[];for(var i=0,len=points.length;i<len;i++){point_features.push(new OpenLayers.Geometry.Point(points[i].getAttribute("lon"),points[i].getAttribute("lat")));}
+return new OpenLayers.Geometry.LineString(point_features);},parseAttributes:function(node){var attributes={};var attrNode=node.firstChild,value,name;while(attrNode){if(attrNode.nodeType==1){value=attrNode.firstChild;if(value.nodeType==3||value.nodeType==4){name=(attrNode.prefix)?attrNode.nodeName.split(":")[1]:attrNode.nodeName;if(name!="trkseg"&&name!="rtept"){attributes[name]=value.nodeValue;}}}
+attrNode=attrNode.nextSibling;}
+return attributes;},CLASS_NAME:"OpenLayers.Format.GPX"});OpenLayers.Format.WMSDescribeLayer=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.1",getVersion:function(root,options){var version=OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(this,arguments);if(version=="1.1.1"||version=="1.1.0"){version="1.1";}
+return version;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer"});OpenLayers.Format.WMSDescribeLayer.v1_1=OpenLayers.Class(OpenLayers.Format.WMSDescribeLayer,{initialize:function(options){OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var root=data.documentElement;var children=root.childNodes;var describelayer=[];var childNode,nodeName;for(var i=0;i<children.length;++i){childNode=children[i];nodeName=childNode.nodeName;if(nodeName=='LayerDescription'){var layerName=childNode.getAttribute('name');var owsType='';var owsURL='';var typeName='';if(childNode.getAttribute('owsType')){owsType=childNode.getAttribute('owsType');owsURL=childNode.getAttribute('owsURL');}else{if(childNode.getAttribute('wfs')!=''){owsType='WFS';owsURL=childNode.getAttribute('wfs');}else if(childNode.getAttribute('wcs')!=''){owsType='WCS';owsURL=childNode.getAttribute('wcs');}}
+var query=childNode.getElementsByTagName('Query');if(query.length>0){typeName=query[0].getAttribute('typeName');if(!typeName){typeName=query[0].getAttribute('typename');}}
+describelayer.push({layerName:layerName,owsType:owsType,owsURL:owsURL,typeName:typeName});}}
+return describelayer;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer.v1_1"});OpenLayers.Format.WFSDescribeFeatureType=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xsd:"http://www.w3.org/2001/XMLSchema"},readers:{"xsd":{"schema":function(node,obj){var complexTypes=[];var customTypes={};var schema={complexTypes:complexTypes,customTypes:customTypes};this.readChildNodes(node,schema);var attributes=node.attributes;var attr,name;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];name=attr.name;if(name.indexOf("xmlns")==0){this.setNamespace(name.split(":")[1]||"",attr.value);}else{obj[name]=attr.value;}}
+obj.featureTypes=complexTypes;obj.targetPrefix=this.namespaceAlias[obj.targetNamespace];var complexType,customType;for(var i=0,len=complexTypes.length;i<len;++i){complexType=complexTypes[i];customType=customTypes[complexType.typeName];if(customTypes[complexType.typeName]){complexType.typeName=customType.name;}}},"complexType":function(node,obj){var complexType={"typeName":node.getAttribute("name")};this.readChildNodes(node,complexType);obj.complexTypes.push(complexType);},"complexContent":function(node,obj){this.readChildNodes(node,obj);},"extension":function(node,obj){this.readChildNodes(node,obj);},"sequence":function(node,obj){var sequence={elements:[]};this.readChildNodes(node,sequence);obj.properties=sequence.elements;},"element":function(node,obj){if(obj.elements){var element={};var attributes=node.attributes;var attr;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];element[attr.name]=attr.value;}
+var type=element.type;if(!type){type={};this.readChildNodes(node,type);element.restriction=type;element.type=type.base;}
+var fullType=type.base||type;element.localType=fullType.split(":").pop();obj.elements.push(element);}
+if(obj.complexTypes){var type=node.getAttribute("type");var localType=type.split(":").pop();obj.customTypes[localType]={"name":node.getAttribute("name"),"type":type};}},"simpleType":function(node,obj){this.readChildNodes(node,obj);},"restriction":function(node,obj){obj.base=node.getAttribute("base");this.readRestriction(node,obj);}}},readRestriction:function(node,obj){var children=node.childNodes;var child,nodeName,value;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){nodeName=child.nodeName.split(":").pop();value=child.getAttribute("value");if(!obj[nodeName]){obj[nodeName]=value;}else{if(typeof obj[nodeName]=="string"){obj[nodeName]=[obj[nodeName]];}
+obj[nodeName].push(value);}}}},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var schema={};this.readNode(data,schema);return schema;},CLASS_NAME:"OpenLayers.Format.WFSDescribeFeatureType"});OpenLayers.Renderer.Canvas=OpenLayers.Class(OpenLayers.Renderer,{hitDetection:true,hitOverflow:0,canvas:null,features:null,pendingRedraw:false,initialize:function(containerID,options){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.root=document.createElement("canvas");this.container.appendChild(this.root);this.canvas=this.root.getContext("2d");this.features={};if(this.hitDetection){this.hitCanvas=document.createElement("canvas");this.hitContext=this.hitCanvas.getContext("2d");}},eraseGeometry:function(geometry,featureId){this.eraseFeatures(this.features[featureId][0]);},supported:function(){var canvas=document.createElement("canvas");return!!canvas.getContext;},setSize:function(size){this.size=size.clone();var root=this.root;root.style.width=size.w+"px";root.style.height=size.h+"px";root.width=size.w;root.height=size.h;this.resolution=null;if(this.hitDetection){var hitCanvas=this.hitCanvas;hitCanvas.style.width=size.w+"px";hitCanvas.style.height=size.h+"px";hitCanvas.width=size.w;hitCanvas.height=size.h;}},drawFeature:function(feature,style){var rendered;if(feature.geometry){style=this.applyDefaultSymbolizer(style||feature.style);var bounds=feature.geometry.getBounds();rendered=(style.display!=="none")&&!!bounds&&bounds.intersectsBounds(this.extent);if(rendered){this.features[feature.id]=[feature,style];}
+else{delete(this.features[feature.id]);}
+this.pendingRedraw=true;}
+if(this.pendingRedraw&&!this.locked){this.redraw();this.pendingRedraw=false;}
+return rendered;},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0;i<geometry.components.length;i++){this.drawGeometry(geometry.components[i],style,featureId);}
+return;}
+switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":this.drawPoint(geometry,style,featureId);break;case"OpenLayers.Geometry.LineString":this.drawLineString(geometry,style,featureId);break;case"OpenLayers.Geometry.LinearRing":this.drawLinearRing(geometry,style,featureId);break;case"OpenLayers.Geometry.Polygon":this.drawPolygon(geometry,style,featureId);break;default:break;}},drawExternalGraphic:function(geometry,style,featureId){var img=new Image();if(style.graphicTitle){img.title=style.graphicTitle;}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;var onLoad=function(){if(!this.features[featureId]){return;}
+var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(!isNaN(p0)&&!isNaN(p1)){var x=(p0+xOffset)|0;var y=(p1+yOffset)|0;var canvas=this.canvas;canvas.globalAlpha=opacity;var factor=OpenLayers.Renderer.Canvas.drawImageScaleFactor||(OpenLayers.Renderer.Canvas.drawImageScaleFactor=/android 2.1/.test(navigator.userAgent.toLowerCase())?320/window.screen.width:1);canvas.drawImage(img,x*factor,y*factor,width*factor,height*factor);if(this.hitDetection){this.setHitContextStyle("fill",featureId);this.hitContext.fillRect(x,y,width,height);}}};img.onload=OpenLayers.Function.bind(onLoad,this);img.src=style.externalGraphic;},setCanvasStyle:function(type,style){if(type==="fill"){this.canvas.globalAlpha=style['fillOpacity'];this.canvas.fillStyle=style['fillColor'];}else if(type==="stroke"){this.canvas.globalAlpha=style['strokeOpacity'];this.canvas.strokeStyle=style['strokeColor'];this.canvas.lineWidth=style['strokeWidth'];}else{this.canvas.globalAlpha=0;this.canvas.lineWidth=1;}},featureIdToHex:function(featureId){var id=Number(featureId.split("_").pop())+1;if(id>=16777216){this.hitOverflow=id-16777215;id=id%16777216+1;}
+var hex="000000"+id.toString(16);var len=hex.length;hex="#"+hex.substring(len-6,len);return hex;},setHitContextStyle:function(type,featureId,symbolizer){var hex=this.featureIdToHex(featureId);if(type=="fill"){this.hitContext.globalAlpha=1.0;this.hitContext.fillStyle=hex;}else if(type=="stroke"){this.hitContext.globalAlpha=1.0;this.hitContext.strokeStyle=hex;this.hitContext.lineWidth=symbolizer.strokeWidth+2;}else{this.hitContext.globalAlpha=0;this.hitContext.lineWidth=1;}},drawPoint:function(geometry,style,featureId){if(style.graphic!==false){if(style.externalGraphic){this.drawExternalGraphic(geometry,style,featureId);}else{var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(!isNaN(p0)&&!isNaN(p1)){var twoPi=Math.PI*2;var radius=style.pointRadius;if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.fill();if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.fill();}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.stroke();if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.stroke();}
+this.setCanvasStyle("reset");}}}}},drawLineString:function(geometry,style,featureId){style=OpenLayers.Util.applyDefaults({fill:false},style);this.drawLinearRing(geometry,style,featureId);},drawLinearRing:function(geometry,style,featureId){if(style.fill!==false){this.setCanvasStyle("fill",style);this.renderPath(this.canvas,geometry,style,featureId,"fill");if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"fill");}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.renderPath(this.canvas,geometry,style,featureId,"stroke");if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"stroke");}}
+this.setCanvasStyle("reset");},renderPath:function(context,geometry,style,featureId,type){var components=geometry.components;var len=components.length;context.beginPath();var start=this.getLocalXY(components[0]);var x=start[0];var y=start[1];if(!isNaN(x)&&!isNaN(y)){context.moveTo(start[0],start[1]);for(var i=1;i<len;++i){var pt=this.getLocalXY(components[i]);context.lineTo(pt[0],pt[1]);}
+if(type==="fill"){context.fill();}else{context.stroke();}}},drawPolygon:function(geometry,style,featureId){var components=geometry.components;var len=components.length;this.drawLinearRing(components[0],style,featureId);for(var i=1;i<len;++i){this.canvas.globalCompositeOperation="destination-out";if(this.hitDetection){this.hitContext.globalCompositeOperation="destination-out";}
+this.drawLinearRing(components[i],OpenLayers.Util.applyDefaults({stroke:false,fillOpacity:1.0},style),featureId);this.canvas.globalCompositeOperation="source-over";if(this.hitDetection){this.hitContext.globalCompositeOperation="source-over";}
+this.drawLinearRing(components[i],OpenLayers.Util.applyDefaults({fill:false},style),featureId);}},drawText:function(location,style){style=OpenLayers.Util.extend({fontColor:"#000000",labelAlign:"cm"},style);var pt=this.getLocalXY(location);this.setCanvasStyle("reset");this.canvas.fillStyle=style.fontColor;this.canvas.globalAlpha=style.fontOpacity||1.0;var fontStyle=[style.fontStyle?style.fontStyle:"normal","normal",style.fontWeight?style.fontWeight:"normal",style.fontSize?style.fontSize:"1em",style.fontFamily?style.fontFamily:"sans-serif"].join(" ");var labelRows=style.label.split('\n');var numRows=labelRows.length;if(this.canvas.fillText){this.canvas.font=fontStyle;this.canvas.textAlign=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]]||"center";this.canvas.textBaseline=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]]||"middle";var vfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];if(vfactor==null){vfactor=-.5;}
+var lineHeight=this.canvas.measureText('Mg').height||this.canvas.measureText('xx').width;pt[1]+=lineHeight*vfactor*(numRows-1);for(var i=0;i<numRows;i++){this.canvas.fillText(labelRows[i],pt[0],pt[1]+(lineHeight*i));}}else if(this.canvas.mozDrawText){this.canvas.mozTextStyle=fontStyle;var hfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]];if(hfactor==null){hfactor=-.5;}
+var vfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];if(vfactor==null){vfactor=-.5;}
+var lineHeight=this.canvas.mozMeasureText('xx');pt[1]+=lineHeight*(1+(vfactor*numRows));for(var i=0;i<numRows;i++){var x=pt[0]+(hfactor*this.canvas.mozMeasureText(labelRows[i]));var y=pt[1]+(i*lineHeight);this.canvas.translate(x,y);this.canvas.mozDrawText(labelRows[i]);this.canvas.translate(-x,-y);}}
+this.setCanvasStyle("reset");},getLocalXY:function(point){var resolution=this.getResolution();var extent=this.extent;var x=(point.x/resolution+(-extent.left/resolution));var y=((extent.top/resolution)-point.y/resolution);return[x,y];},clear:function(){var height=this.root.height;var width=this.root.width;this.canvas.clearRect(0,0,width,height);this.features={};if(this.hitDetection){this.hitContext.clearRect(0,0,width,height);}},getFeatureIdFromEvent:function(evt){var feature=null;if(this.hitDetection){if(!this.map.dragging){var xy=evt.xy;var x=xy.x|0;var y=xy.y|0;var data=this.hitContext.getImageData(x,y,1,1).data;if(data[3]===255){var id=data[2]+(256*(data[1]+(256*data[0])));if(id){feature=this.features["OpenLayers.Feature.Vector_"+(id-1+this.hitOverflow)][0];}}}}
+return feature;},eraseFeatures:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+for(var i=0;i<features.length;++i){delete this.features[features[i].id];}
+this.redraw();},redraw:function(){if(!this.locked){var height=this.root.height;var width=this.root.width;this.canvas.clearRect(0,0,width,height);if(this.hitDetection){this.hitContext.clearRect(0,0,width,height);}
+var labelMap=[];var feature,style;for(var id in this.features){if(!this.features.hasOwnProperty(id)){continue;}
+feature=this.features[id][0];style=this.features[id][1];this.drawGeometry(feature.geometry,style,feature.id);if(style.label){labelMap.push([feature,style]);}}
+var item;for(var i=0,len=labelMap.length;i<len;++i){item=labelMap[i];this.drawText(item[0].geometry.getCentroid(),item[1]);}}},CLASS_NAME:"OpenLayers.Renderer.Canvas"});OpenLayers.Renderer.Canvas.LABEL_ALIGN={"l":"left","r":"right","t":"top","b":"bottom"};OpenLayers.Renderer.Canvas.LABEL_FACTOR={"l":0,"r":-1,"t":0,"b":-1};OpenLayers.Renderer.Canvas.drawImageScaleFactor=null;OpenLayers.Format.OSM=OpenLayers.Class(OpenLayers.Format.XML,{checkTags:false,interestingTagsExclude:null,areaTags:null,initialize:function(options){var layer_defaults={'interestingTagsExclude':['source','source_ref','source:ref','history','attribution','created_by'],'areaTags':['area','building','leisure','tourism','ruins','historic','landuse','military','natural','sport']};layer_defaults=OpenLayers.Util.extend(layer_defaults,options);var interesting={};for(var i=0;i<layer_defaults.interestingTagsExclude.length;i++){interesting[layer_defaults.interestingTagsExclude[i]]=true;}
+layer_defaults.interestingTagsExclude=interesting;var area={};for(var i=0;i<layer_defaults.areaTags.length;i++){area[layer_defaults.areaTags[i]]=true;}
+layer_defaults.areaTags=area;this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[layer_defaults]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
+var nodes=this.getNodes(doc);var ways=this.getWays(doc);var feat_list=new Array(ways.length);for(var i=0;i<ways.length;i++){var point_list=new Array(ways[i].nodes.length);var poly=this.isWayArea(ways[i])?1:0;for(var j=0;j<ways[i].nodes.length;j++){var node=nodes[ways[i].nodes[j]];var point=new OpenLayers.Geometry.Point(node.lon,node.lat);point.osm_id=parseInt(ways[i].nodes[j]);point_list[j]=point;node.used=true;}
+var geometry=null;if(poly){geometry=new OpenLayers.Geometry.Polygon(new OpenLayers.Geometry.LinearRing(point_list));}else{geometry=new OpenLayers.Geometry.LineString(point_list);}
+if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
+var feat=new OpenLayers.Feature.Vector(geometry,ways[i].tags);feat.osm_id=parseInt(ways[i].id);feat.fid="way."+feat.osm_id;feat_list[i]=feat;}
+for(var node_id in nodes){var node=nodes[node_id];if(!node.used||this.checkTags){var tags=null;if(this.checkTags){var result=this.getTags(node.node,true);if(node.used&&!result[1]){continue;}
+tags=result[0];}else{tags=this.getTags(node.node);}
+var feat=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(node['lon'],node['lat']),tags);if(this.internalProjection&&this.externalProjection){feat.geometry.transform(this.externalProjection,this.internalProjection);}
+feat.osm_id=parseInt(node_id);feat.fid="node."+feat.osm_id;feat_list.push(feat);}
+node.node=null;}
+return feat_list;},getNodes:function(doc){var node_list=doc.getElementsByTagName("node");var nodes={};for(var i=0;i<node_list.length;i++){var node=node_list[i];var id=node.getAttribute("id");nodes[id]={'lat':node.getAttribute("lat"),'lon':node.getAttribute("lon"),'node':node};}
+return nodes;},getWays:function(doc){var way_list=doc.getElementsByTagName("way");var return_ways=[];for(var i=0;i<way_list.length;i++){var way=way_list[i];var way_object={id:way.getAttribute("id")};way_object.tags=this.getTags(way);var node_list=way.getElementsByTagName("nd");way_object.nodes=new Array(node_list.length);for(var j=0;j<node_list.length;j++){way_object.nodes[j]=node_list[j].getAttribute("ref");}
+return_ways.push(way_object);}
+return return_ways;},getTags:function(dom_node,interesting_tags){var tag_list=dom_node.getElementsByTagName("tag");var tags={};var interesting=false;for(var j=0;j<tag_list.length;j++){var key=tag_list[j].getAttribute("k");tags[key]=tag_list[j].getAttribute("v");if(interesting_tags){if(!this.interestingTagsExclude[key]){interesting=true;}}}
+return interesting_tags?[tags,interesting]:tags;},isWayArea:function(way){var poly_shaped=false;var poly_tags=false;if(way.nodes[0]==way.nodes[way.nodes.length-1]){poly_shaped=true;}
+if(this.checkTags){for(var key in way.tags){if(this.areaTags[key]){poly_tags=true;break;}}}
+return poly_shaped&&(this.checkTags?poly_tags:true);},write:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+this.osm_id=1;this.created_nodes={};var root_node=this.createElementNS(null,"osm");root_node.setAttribute("version","0.5");root_node.setAttribute("generator","OpenLayers "+OpenLayers.VERSION_NUMBER);for(var i=features.length-1;i>=0;i--){var nodes=this.createFeatureNodes(features[i]);for(var j=0;j<nodes.length;j++){root_node.appendChild(nodes[j]);}}
+return OpenLayers.Format.XML.prototype.write.apply(this,[root_node]);},createFeatureNodes:function(feature){var nodes=[];var className=feature.geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);type=type.toLowerCase();var builder=this.createXML[type];if(builder){nodes=builder.apply(this,[feature]);}
+return nodes;},createXML:{'point':function(point){var id=null;var geometry=point.geometry?point.geometry:point;if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var already_exists=false;if(point.osm_id){id=point.osm_id;if(this.created_nodes[id]){already_exists=true;}}else{id=-this.osm_id;this.osm_id++;}
+if(already_exists){node=this.created_nodes[id];}else{var node=this.createElementNS(null,"node");}
+this.created_nodes[id]=node;node.setAttribute("id",id);node.setAttribute("lon",geometry.x);node.setAttribute("lat",geometry.y);if(point.attributes){this.serializeTags(point,node);}
+this.setState(point,node);return already_exists?[]:[node];},linestring:function(feature){var id;var nodes=[];var geometry=feature.geometry;if(feature.osm_id){id=feature.osm_id;}else{id=-this.osm_id;this.osm_id++;}
+var way=this.createElementNS(null,"way");way.setAttribute("id",id);for(var i=0;i<geometry.components.length;i++){var node=this.createXML['point'].apply(this,[geometry.components[i]]);if(node.length){node=node[0];var node_ref=node.getAttribute("id");nodes.push(node);}else{node_ref=geometry.components[i].osm_id;node=this.created_nodes[node_ref];}
+this.setState(feature,node);var nd_dom=this.createElementNS(null,"nd");nd_dom.setAttribute("ref",node_ref);way.appendChild(nd_dom);}
+this.serializeTags(feature,way);nodes.push(way);return nodes;},polygon:function(feature){var attrs=OpenLayers.Util.extend({'area':'yes'},feature.attributes);var feat=new OpenLayers.Feature.Vector(feature.geometry.components[0],attrs);feat.osm_id=feature.osm_id;return this.createXML['linestring'].apply(this,[feat]);}},serializeTags:function(feature,node){for(var key in feature.attributes){var tag=this.createElementNS(null,"tag");tag.setAttribute("k",key);tag.setAttribute("v",feature.attributes[key]);node.appendChild(tag);}},setState:function(feature,node){if(feature.state){var state=null;switch(feature.state){case OpenLayers.State.UPDATE:state="modify";case OpenLayers.State.DELETE:state="delete";}
+if(state){node.setAttribute("action",state);}}},CLASS_NAME:"OpenLayers.Format.OSM"});OpenLayers.Handler=OpenLayers.Class({id:null,control:null,map:null,keyMask:null,active:false,evt:null,initialize:function(control,callbacks,options){OpenLayers.Util.extend(this,options);this.control=control;this.callbacks=callbacks;var map=this.map||control.map;if(map){this.setMap(map);}
+this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},setMap:function(map){this.map=map;},checkModifiers:function(evt){if(this.keyMask==null){return true;}
+var keyModifiers=(evt.shiftKey?OpenLayers.Handler.MOD_SHIFT:0)|(evt.ctrlKey?OpenLayers.Handler.MOD_CTRL:0)|(evt.altKey?OpenLayers.Handler.MOD_ALT:0);return(keyModifiers==this.keyMask);},activate:function(){if(this.active){return false;}
+var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.register(events[i],this[events[i]]);}}
+this.active=true;return true;},deactivate:function(){if(!this.active){return false;}
+var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.unregister(events[i],this[events[i]]);}}
+this.active=false;return true;},callback:function(name,args){if(name&&this.callbacks[name]){this.callbacks[name].apply(this.control,args);}},register:function(name,method){this.map.events.registerPriority(name,this,method);this.map.events.registerPriority(name,this,this.setEvent);},unregister:function(name,method){this.map.events.unregister(name,this,method);this.map.events.unregister(name,this,this.setEvent);},setEvent:function(evt){this.evt=evt;return true;},destroy:function(){this.deactivate();this.control=this.map=null;},CLASS_NAME:"OpenLayers.Handler"});OpenLayers.Handler.MOD_NONE=0;OpenLayers.Handler.MOD_SHIFT=1;OpenLayers.Handler.MOD_CTRL=2;OpenLayers.Handler.MOD_ALT=4;OpenLayers.Handler.Drag=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:true,dragging:false,touch:false,last:null,start:null,lastMoveEvt:null,oldOnselectstart:null,interval:0,timeoutId:null,documentDrag:false,documentEvents:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);if(this.documentDrag===true){var me=this;this._docMove=function(evt){me.mousemove({xy:{x:evt.clientX,y:evt.clientY},element:document});};this._docUp=function(evt){me.mouseup({xy:{x:evt.clientX,y:evt.clientY}});};}},dragstart:function(evt){var propagate=true;this.dragging=false;if(this.checkModifiers(evt)&&(OpenLayers.Event.isLeftClick(evt)||OpenLayers.Event.isSingleTouch(evt))){this.started=true;this.start=evt.xy;this.last=evt.xy;OpenLayers.Element.addClass(this.map.viewPortDiv,"olDragDown");this.down(evt);this.callback("down",[evt.xy]);OpenLayers.Event.stop(evt);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart?document.onselectstart:OpenLayers.Function.True;}
+document.onselectstart=OpenLayers.Function.False;propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;}
+return propagate;},dragmove:function(evt){this.lastMoveEvt=evt;if(this.started&&!this.timeoutId&&(evt.xy.x!=this.last.x||evt.xy.y!=this.last.y)){if(this.documentDrag===true&&this.documentEvents){if(evt.element===document){this.adjustXY(evt);this.setEvent(evt);}else{this.removeDocumentEvents();}}
+if(this.interval>0){this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval);}
+this.dragging=true;this.move(evt);this.callback("move",[evt.xy]);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart;document.onselectstart=OpenLayers.Function.False;}
+this.last=evt.xy;}
+return true;},dragend:function(evt){if(this.started){if(this.documentDrag===true&&this.documentEvents){this.adjustXY(evt);this.removeDocumentEvents();}
+var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(evt);this.callback("up",[evt.xy]);if(dragged){this.callback("done",[evt.xy]);}
+document.onselectstart=this.oldOnselectstart;}
+return true;},down:function(evt){},move:function(evt){},up:function(evt){},out:function(evt){},mousedown:function(evt){return this.dragstart(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,scope:this});}
+return this.dragstart(evt);},mousemove:function(evt){return this.dragmove(evt);},touchmove:function(evt){return this.dragmove(evt);},removeTimeout:function(){this.timeoutId=null;if(this.dragging){this.mousemove(this.lastMoveEvt);}},mouseup:function(evt){return this.dragend(evt);},touchend:function(evt){evt.xy=this.last;return this.dragend(evt);},mouseout:function(evt){if(this.started&&OpenLayers.Util.mouseLeft(evt,this.map.eventsDiv)){if(this.documentDrag===true){this.addDocumentEvents();}else{var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(evt);this.callback("out",[]);if(dragged){this.callback("done",[evt.xy]);}
+if(document.onselectstart){document.onselectstart=this.oldOnselectstart;}}}
+return true;},click:function(evt){return(this.start==this.last);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragging=false;activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.touch=false;this.started=false;this.dragging=false;this.start=null;this.last=null;deactivated=true;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");}
+return deactivated;},adjustXY:function(evt){var pos=OpenLayers.Util.pagePosition(this.map.viewPortDiv);evt.xy.x-=pos[0];evt.xy.y-=pos[1];},addDocumentEvents:function(){OpenLayers.Element.addClass(document.body,"olDragDown");this.documentEvents=true;OpenLayers.Event.observe(document,"mousemove",this._docMove);OpenLayers.Event.observe(document,"mouseup",this._docUp);},removeDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents=false;OpenLayers.Event.stopObserving(document,"mousemove",this._docMove);OpenLayers.Event.stopObserving(document,"mouseup",this._docUp);},CLASS_NAME:"OpenLayers.Handler.Drag"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{'click':{'in':'click','out':'clickout'},'mousemove':{'in':'over','out':'out'},'dblclick':{'in':'dblclick','out':null},'mousedown':{'in':null,'out':null},'mouseup':{'in':null,'out':null},'touchstart':{'in':'click','out':'clickout'}},feature:null,lastFeature:null,down:null,up:null,touch:false,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+return OpenLayers.Event.isMultiTouch(evt)?true:this.mousedown(evt);},touchmove:function(evt){OpenLayers.Event.stop(evt);},mousedown:function(evt){this.down=evt.xy;return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;}
+this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
+var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick"||type=="touchstart");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
+if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
+if(this.feature){if(type==="touchstart"){OpenLayers.Event.stop(evt);}
+var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
+this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
+return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
+Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.touch=false;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
+return deactivated;},handleMapEvents:function(evt){if(evt.type=="removelayer"||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Control.DragFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,onStart:function(feature,pixel){},onDrag:function(feature,pixel){},onComplete:function(feature,pixel){},onEnter:function(feature){},onLeave:function(feature){},documentDrag:false,layer:null,feature:null,dragCallbacks:{},featureCallbacks:{},lastPixel:null,initialize:function(layer,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;this.handlers={drag:new OpenLayers.Handler.Drag(this,OpenLayers.Util.extend({down:this.downFeature,move:this.moveFeature,up:this.upFeature,out:this.cancel,done:this.doneDragging},this.dragCallbacks),{documentDrag:this.documentDrag}),feature:new OpenLayers.Handler.Feature(this,this.layer,OpenLayers.Util.extend({click:this.clickFeature,clickout:this.clickoutFeature,over:this.overFeature,out:this.outFeature},this.featureCallbacks),{geometryTypes:this.geometryTypes})};},clickFeature:function(feature){if(this.handlers.feature.touch&&!this.over&&this.overFeature(feature)){this.handlers.drag.dragstart(this.handlers.feature.evt);this.handlers.drag.stopDown=false;}},clickoutFeature:function(feature){if(this.handlers.feature.touch&&this.over){this.outFeature(feature);this.handlers.drag.stopDown=true;}},destroy:function(){this.layer=null;OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return(this.handlers.feature.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){this.handlers.drag.deactivate();this.handlers.feature.deactivate();this.feature=null;this.dragging=false;this.lastPixel=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},overFeature:function(feature){var activated=false;if(!this.handlers.drag.dragging){this.feature=feature;this.handlers.drag.activate();activated=true;this.over=true;OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass+"Over");this.onEnter(feature);}else{if(this.feature.id==feature.id){this.over=true;}else{this.over=false;}}
+return activated;},downFeature:function(pixel){this.lastPixel=pixel;this.onStart(this.feature,pixel);},moveFeature:function(pixel){var res=this.map.getResolution();this.feature.geometry.move(res*(pixel.x-this.lastPixel.x),res*(this.lastPixel.y-pixel.y));this.layer.drawFeature(this.feature);this.lastPixel=pixel;this.onDrag(this.feature,pixel);},upFeature:function(pixel){if(!this.over){this.handlers.drag.deactivate();}},doneDragging:function(pixel){this.onComplete(this.feature,pixel);},outFeature:function(feature){if(!this.handlers.drag.dragging){this.over=false;this.handlers.drag.deactivate();OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");this.onLeave(feature);this.feature=null;}else{if(this.feature.id==feature.id){this.over=false;}}},cancel:function(){this.handlers.drag.deactivate();this.over=false;},setMap:function(map){this.handlers.drag.setMap(map);this.handlers.feature.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.DragFeature"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),"select":new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),"temporary":new OpenLayers.Style(OpenLayers.Feature.Vector.style["temporary"]),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
+OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();}
+this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();}
+if(!this.styles[intent]){intent="default";}
+feature.renderIntent=intent;var defaultSymbolizer={};if(this.extendDefault&&intent!="default"){defaultSymbolizer=this.styles["default"].createSymbolizer(feature);}
+return OpenLayers.Util.extend(defaultSymbolizer,this.styles[intent].createSymbolizer(feature));},addUniqueValueRules:function(renderIntent,property,symbolizers,context){var rules=[];for(var value in symbolizers){rules.push(new OpenLayers.Rule({symbolizer:symbolizers[value],context:context,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:property,value:value})}));}
+this.styles[renderIntent].addRules(rules);},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{EVENT_TYPES:["beforefeatureadded","beforefeaturesadded","featureadded","featuresadded","beforefeatureremoved","beforefeaturesremoved","featureremoved","featuresremoved","beforefeatureselected","featureselected","featureunselected","beforefeaturemodified","featuremodified","afterfeaturemodified","vertexmodified","vertexremoved","sketchstarted","sketchmodified","sketchcomplete","refresh"],isBaseLayer:false,isFixed:false,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:true,style:null,styleMap:null,strategies:null,protocol:null,renderers:['SVG','VML','Canvas'],renderer:null,rendererOptions:null,geometryType:null,drawn:false,initialize:function(name,options){this.EVENT_TYPES=OpenLayers.Layer.Vector.prototype.EVENT_TYPES.concat(OpenLayers.Layer.prototype.EVENT_TYPES);OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(!this.renderer||!this.renderer.supported()){this.assignRenderer();}
+if(!this.renderer||!this.renderer.supported()){this.renderer=null;this.displayError();}
+if(!this.styleMap){this.styleMap=new OpenLayers.StyleMap();}
+this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies){for(var i=0,len=this.strategies.length;i<len;i++){this.strategies[i].setLayer(this);}}},destroy:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoDestroy){strategy.destroy();}}
+this.strategies=null;}
+if(this.protocol){if(this.protocol.autoDestroy){this.protocol.destroy();}
+this.protocol=null;}
+this.destroyFeatures();this.features=null;this.selectedFeatures=null;this.unrenderedFeatures=null;if(this.renderer){this.renderer.destroy();}
+this.renderer=null;this.geometryType=null;this.drawn=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Vector(this.name,this.getOptions());}
+obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);var features=this.features;var len=features.length;var clonedFeatures=new Array(len);for(var i=0;i<len;++i){clonedFeatures[i]=features[i].clone();}
+obj.features=clonedFeatures;return obj;},refresh:function(obj){if(this.calculateInRange()&&this.visibility){this.events.triggerEvent("refresh",obj);}},assignRenderer:function(){for(var i=0,len=this.renderers.length;i<len;i++){var rendererClass=this.renderers[i];var renderer=(typeof rendererClass=="function")?rendererClass:OpenLayers.Renderer[rendererClass];if(renderer&&renderer.prototype.supported()){this.renderer=new renderer(this.div,this.rendererOptions);break;}}},displayError:function(){if(this.reportError){OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",{'renderers':this.renderers.join("\n")}));}},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);if(!this.renderer){this.map.removeLayer(this);}else{this.renderer.map=this.map;this.renderer.setSize(this.map.getSize());}},afterAdd:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.activate();}}}},removeMap:function(map){this.drawn=false;if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.deactivate();}}}},onMapResize:function(){OpenLayers.Layer.prototype.onMapResize.apply(this,arguments);this.renderer.setSize(this.map.getSize());},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var ng=(OpenLayers.Renderer.NG&&this.renderer instanceof OpenLayers.Renderer.NG);if(ng){dragging||this.renderer.updateDimensions(zoomChanged);}else{var coordSysUnchanged=true;if(!dragging){this.renderer.root.style.visibility="hidden";this.div.style.left=-parseInt(this.map.layerContainerDiv.style.left)+"px";this.div.style.top=-parseInt(this.map.layerContainerDiv.style.top)+"px";var extent=this.map.getExtent();coordSysUnchanged=this.renderer.setExtent(extent,zoomChanged);this.renderer.root.style.visibility="visible";if(OpenLayers.IS_GECKO===true){this.div.scrollLeft=this.div.scrollLeft;}
+if(!zoomChanged&&coordSysUnchanged){for(var i in this.unrenderedFeatures){var feature=this.unrenderedFeatures[i];this.drawFeature(feature);}}}}
+if(!this.drawn||(!ng&&(zoomChanged||!coordSysUnchanged))){this.drawn=true;var feature;for(var i=0,len=this.features.length;i<len;i++){this.renderer.locked=(i!==(len-1));feature=this.features[i];this.drawFeature(feature);}}},redraw:function(){if(OpenLayers.Renderer.NG&&this.renderer instanceof OpenLayers.Renderer.NG){this.drawn=false;}
+return OpenLayers.Layer.prototype.redraw.apply(this,arguments);},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);var currentDisplay=this.div.style.display;if(currentDisplay!=this.renderer.root.style.display){this.renderer.root.style.display=currentDisplay;}},addFeatures:function(features,options){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var notify=!options||!options.silent;if(notify){var event={features:features};var ret=this.events.triggerEvent("beforefeaturesadded",event);if(ret===false){return;}
+features=event.features;}
+var featuresAdded=[];for(var i=0,len=features.length;i<len;i++){if(i!=(features.length-1)){this.renderer.locked=true;}else{this.renderer.locked=false;}
+var feature=features[i];if(this.geometryType&&!(feature.geometry instanceof this.geometryType)){var throwStr=OpenLayers.i18n('componentShouldBe',{'geomType':this.geometryType.prototype.CLASS_NAME});throw throwStr;}
+feature.layer=this;if(!feature.style&&this.style){feature.style=OpenLayers.Util.extend({},this.style);}
+if(notify){if(this.events.triggerEvent("beforefeatureadded",{feature:feature})===false){continue;}
+this.preFeatureInsert(feature);}
+featuresAdded.push(feature);this.features.push(feature);this.drawFeature(feature);if(notify){this.events.triggerEvent("featureadded",{feature:feature});this.onFeatureInsert(feature);}}
+if(notify){this.events.triggerEvent("featuresadded",{features:featuresAdded});}},removeFeatures:function(features,options){if(!features||features.length===0){return;}
+if(features===this.features){return this.removeAllFeatures(options);}
+if(!(OpenLayers.Util.isArray(features))){features=[features];}
+if(features===this.selectedFeatures){features=features.slice();}
+var notify=!options||!options.silent;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
+for(var i=features.length-1;i>=0;i--){if(i!=0&&features[i-1].geometry){this.renderer.locked=true;}else{this.renderer.locked=false;}
+var feature=features[i];delete this.unrenderedFeatures[feature.id];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+this.features=OpenLayers.Util.removeItem(this.features,feature);feature.layer=null;if(feature.geometry){this.renderer.eraseFeatures(feature);}
+if(OpenLayers.Util.indexOf(this.selectedFeatures,feature)!=-1){OpenLayers.Util.removeItem(this.selectedFeatures,feature);}
+if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},removeAllFeatures:function(options){var notify=!options||!options.silent;var features=this.features;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
+var feature;for(var i=features.length-1;i>=0;i--){feature=features[i];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+feature.layer=null;if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=[];if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},destroyFeatures:function(features,options){var all=(features==undefined);if(all){features=this.features;}
+if(features){this.removeFeatures(features,options);for(var i=features.length-1;i>=0;i--){features[i].destroy();}}},drawFeature:function(feature,style){if(!this.drawn){return;}
+if(typeof style!="object"){if(!style&&feature.state===OpenLayers.State.DELETE){style="delete";}
+var renderIntent=style||feature.renderIntent;style=feature.style||this.style;if(!style){style=this.styleMap.createSymbolizer(feature,renderIntent);}}
+var drawn=this.renderer.drawFeature(feature,style);if(drawn===false||drawn===null){this.unrenderedFeatures[feature.id]=feature;}else{delete this.unrenderedFeatures[feature.id];}},eraseFeatures:function(features){this.renderer.eraseFeatures(features);},getFeatureFromEvent:function(evt){if(!this.renderer){OpenLayers.Console.error(OpenLayers.i18n("getFeatureError"));return null;}
+var feature=null;var featureId=this.renderer.getFeatureIdFromEvent(evt);if(featureId){if(typeof featureId==="string"){feature=this.getFeatureById(featureId);}else{feature=featureId;}}
+return feature;},getFeatureBy:function(property,value){var feature=null;for(var i=0,len=this.features.length;i<len;++i){if(this.features[i][property]==value){feature=this.features[i];break;}}
+return feature;},getFeatureById:function(featureId){return this.getFeatureBy('id',featureId);},getFeatureByFid:function(featureFid){return this.getFeatureBy('fid',featureFid);},getFeaturesByAttribute:function(attrName,attrValue){var i,feature,len=this.features.length,foundFeatures=[];for(i=0;i<len;i++){feature=this.features[i];if(feature&&feature.attributes){if(feature.attributes[attrName]===attrValue){foundFeatures.push(feature);}}}
+return foundFeatures;},onFeatureInsert:function(feature){},preFeatureInsert:function(feature){},getDataExtent:function(){var maxExtent=null;var features=this.features;if(features&&(features.length>0)){var geometry=null;for(var i=0,len=features.length;i<len;i++){geometry=features[i].geometry;if(geometry){if(maxExtent===null){maxExtent=new OpenLayers.Bounds();}
+maxExtent.extend(geometry.getBounds());}}}
+return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Vector"});OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:false,layers:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},display:function(){},getFeatureFromEvent:function(evt){var layers=this.layers;var feature;for(var i=0;i<layers.length;i++){feature=layers[i].getFeatureFromEvent(evt);if(feature){return feature;}}},setMap:function(map){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);this.collectRoots();map.events.register("changelayer",this,this.handleChangeLayer);},removeMap:function(map){map.events.unregister("changelayer",this,this.handleChangeLayer);this.resetRoots();OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments);},collectRoots:function(){var layer;for(var i=0;i<this.map.layers.length;++i){layer=this.map.layers[i];if(OpenLayers.Util.indexOf(this.layers,layer)!=-1){layer.renderer.moveRoot(this.renderer);}}},resetRoots:function(){var layer;for(var i=0;i<this.layers.length;++i){layer=this.layers[i];if(this.renderer&&layer.renderer.getRenderLayerId()==this.id){this.renderer.moveRoot(layer.renderer);}}},handleChangeLayer:function(evt){var layer=evt.layer;if(evt.property=="order"&&OpenLayers.Util.indexOf(this.layers,layer)!=-1){this.resetRoots();this.collectRoots();}},CLASS_NAME:"OpenLayers.Layer.Vector.RootContainer"});OpenLayers.Control.SelectFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforefeaturehighlighted","featurehighlighted","featureunhighlighted"],multipleKey:null,toggleKey:null,multiple:false,clickout:true,toggle:false,hover:false,highlightOnly:false,box:false,onBeforeSelect:function(){},onSelect:function(){},onUnselect:function(){},scope:null,geometryTypes:null,layer:null,layers:null,callbacks:null,selectStyle:null,renderIntent:"select",handlers:null,initialize:function(layers,options){this.EVENT_TYPES=OpenLayers.Control.SelectFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);if(this.scope===null){this.scope=this;}
+this.initLayer(layers);var callbacks={click:this.clickFeature,clickout:this.clickoutFeature};if(this.hover){callbacks.over=this.overFeature;callbacks.out=this.outFeature;}
+this.callbacks=OpenLayers.Util.extend(callbacks,this.callbacks);this.handlers={feature:new OpenLayers.Handler.Feature(this,this.layer,this.callbacks,{geometryTypes:this.geometryTypes})};if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},{boxDivClassName:"olHandlerBoxSelectFeature"});}},initLayer:function(layers){if(OpenLayers.Util.isArray(layers)){this.layers=layers;this.layer=new OpenLayers.Layer.Vector.RootContainer(this.id+"_container",{layers:layers});}else{this.layer=layers;}},destroy:function(){if(this.active&&this.layers){this.map.removeLayer(this.layer);}
+OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.layers){this.layer.destroy();}},activate:function(){if(!this.active){if(this.layers){this.map.addLayer(this.layer);}
+this.handlers.feature.activate();if(this.box&&this.handlers.box){this.handlers.box.activate();}}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){this.handlers.feature.deactivate();if(this.handlers.box){this.handlers.box.deactivate();}
+if(this.layers){this.map.removeLayer(this.layer);}}
+return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},unselectAll:function(options){var layers=this.layers||[this.layer];var layer,feature;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=layer.selectedFeatures.length-1;i>=0;--i){feature=layer.selectedFeatures[i];if(!options||options.except!=feature){this.unselect(feature);}}}},clickFeature:function(feature){if(!this.hover){var selected=(OpenLayers.Util.indexOf(feature.layer.selectedFeatures,feature)>-1);if(selected){if(this.toggleSelect()){this.unselect(feature);}else if(!this.multipleSelect()){this.unselectAll({except:feature});}}else{if(!this.multipleSelect()){this.unselectAll({except:feature});}
+this.select(feature);}}},multipleSelect:function(){return this.multiple||(this.handlers.feature.evt&&this.handlers.feature.evt[this.multipleKey]);},toggleSelect:function(){return this.toggle||(this.handlers.feature.evt&&this.handlers.feature.evt[this.toggleKey]);},clickoutFeature:function(feature){if(!this.hover&&this.clickout){this.unselectAll();}},overFeature:function(feature){var layer=feature.layer;if(this.hover){if(this.highlightOnly){this.highlight(feature);}else if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}},outFeature:function(feature){if(this.hover){if(this.highlightOnly){if(feature._lastHighlighter==this.id){if(feature._prevHighlighter&&feature._prevHighlighter!=this.id){delete feature._lastHighlighter;var control=this.map.getControl(feature._prevHighlighter);if(control){control.highlight(feature);}}else{this.unhighlight(feature);}}}else{this.unselect(feature);}}},highlight:function(feature){var layer=feature.layer;var cont=this.events.triggerEvent("beforefeaturehighlighted",{feature:feature});if(cont!==false){feature._prevHighlighter=feature._lastHighlighter;feature._lastHighlighter=this.id;var style=this.selectStyle||this.renderIntent;layer.drawFeature(feature,style);this.events.triggerEvent("featurehighlighted",{feature:feature});}},unhighlight:function(feature){var layer=feature.layer;if(feature._prevHighlighter==undefined){delete feature._lastHighlighter;}else if(feature._prevHighlighter==this.id){delete feature._prevHighlighter;}else{feature._lastHighlighter=feature._prevHighlighter;delete feature._prevHighlighter;}
+layer.drawFeature(feature,feature.style||feature.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:feature});},select:function(feature){var cont=this.onBeforeSelect.call(this.scope,feature);var layer=feature.layer;if(cont!==false){cont=layer.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){layer.selectedFeatures.push(feature);this.highlight(feature);if(!this.handlers.feature.lastFeature){this.handlers.feature.lastFeature=layer.selectedFeatures[0];}
+layer.events.triggerEvent("featureselected",{feature:feature});this.onSelect.call(this.scope,feature);}}},unselect:function(feature){var layer=feature.layer;this.unhighlight(feature);OpenLayers.Util.removeItem(layer.selectedFeatures,feature);layer.events.triggerEvent("featureunselected",{feature:feature});this.onUnselect.call(this.scope,feature);},selectBox:function(position){if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));var bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);if(!this.multipleSelect()){this.unselectAll();}
+var prevMultiple=this.multiple;this.multiple=true;var layers=this.layers||[this.layer];var layer;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=0,len=layer.features.length;i<len;++i){var feature=layer.features[i];if(!feature.getVisibility()){continue;}
+if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1){if(bounds.toGeometry().intersects(feature.geometry)){if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}}}}
+this.multiple=prevMultiple;}},setMap:function(map){this.handlers.feature.setMap(map);if(this.box){this.handlers.box.setMap(map);}
+OpenLayers.Control.prototype.setMap.apply(this,arguments);},setLayer:function(layers){var isActive=this.active;this.unselectAll();this.deactivate();if(this.layers){this.layer.destroy();this.layers=null;}
+this.initLayer(layers);this.handlers.feature.layer=this.layer;if(isActive){this.activate();}},CLASS_NAME:"OpenLayers.Control.SelectFeature"});OpenLayers.Handler.Keyboard=OpenLayers.Class(OpenLayers.Handler,{KEY_EVENTS:["keydown","keyup"],eventListener:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.eventListener=OpenLayers.Function.bindAsEventListener(this.handleKeyEvent,this);},destroy:function(){this.deactivate();this.eventListener=null;OpenLayers.Handler.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.observe(document,this.KEY_EVENTS[i],this.eventListener);}
+return true;}else{return false;}},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.stopObserving(document,this.KEY_EVENTS[i],this.eventListener);}
+deactivated=true;}
+return deactivated;},handleKeyEvent:function(evt){if(this.checkModifiers(evt)){this.callback(evt.type,[evt]);}},CLASS_NAME:"OpenLayers.Handler.Keyboard"});OpenLayers.Control.ModifyFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,clickout:true,toggle:true,standalone:false,layer:null,feature:null,vertices:null,virtualVertices:null,selectControl:null,dragControl:null,handlers:null,deleteCodes:null,virtualStyle:null,vertexRenderIntent:null,mode:null,modified:false,radiusHandle:null,dragHandle:null,onModificationStart:function(){},onModification:function(){},onModificationEnd:function(){},initialize:function(layer,options){options=options||{};this.layer=layer;this.vertices=[];this.virtualVertices=[];this.virtualStyle=OpenLayers.Util.extend({},this.layer.style||this.layer.styleMap.createSymbolizer(null,options.vertexRenderIntent));this.virtualStyle.fillOpacity=0.3;this.virtualStyle.strokeOpacity=0.3;this.deleteCodes=[46,68];this.mode=OpenLayers.Control.ModifyFeature.RESHAPE;OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!(OpenLayers.Util.isArray(this.deleteCodes))){this.deleteCodes=[this.deleteCodes];}
+var control=this;var selectOptions={geometryTypes:this.geometryTypes,clickout:this.clickout,toggle:this.toggle,onBeforeSelect:this.beforeSelectFeature,onSelect:this.selectFeature,onUnselect:this.unselectFeature,scope:this};if(this.standalone===false){this.selectControl=new OpenLayers.Control.SelectFeature(layer,selectOptions);}
+var dragOptions={geometryTypes:["OpenLayers.Geometry.Point"],snappingOptions:this.snappingOptions,onStart:function(feature,pixel){control.dragStart.apply(control,[feature,pixel]);},onDrag:function(feature,pixel){control.dragVertex.apply(control,[feature,pixel]);},onComplete:function(feature){control.dragComplete.apply(control,[feature]);},featureCallbacks:{over:function(feature){if(control.standalone!==true||feature._sketch||control.feature===feature){control.dragControl.overFeature.apply(control.dragControl,[feature]);}}}};this.dragControl=new OpenLayers.Control.DragFeature(layer,dragOptions);var keyboardOptions={keydown:this.handleKeypress};this.handlers={keyboard:new OpenLayers.Handler.Keyboard(this,keyboardOptions)};},destroy:function(){this.layer=null;this.standalone||this.selectControl.destroy();this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return((this.standalone||this.selectControl.activate())&&this.handlers.keyboard.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.vertices,{silent:true});this.layer.removeFeatures(this.virtualVertices,{silent:true});this.vertices=[];this.dragControl.deactivate();var feature=this.feature;var valid=feature&&feature.geometry&&feature.layer;if(this.standalone===false){if(valid){this.selectControl.unselect.apply(this.selectControl,[feature]);}
+this.selectControl.deactivate();}else{if(valid){this.unselectFeature(feature);}}
+this.handlers.keyboard.deactivate();deactivated=true;}
+return deactivated;},beforeSelectFeature:function(feature){return this.layer.events.triggerEvent("beforefeaturemodified",{feature:feature});},selectFeature:function(feature){if(!this.standalone||this.beforeSelectFeature(feature)!==false){this.feature=feature;this.modified=false;this.resetVertices();this.dragControl.activate();this.onModificationStart(this.feature);}
+var modified=feature.modified;if(feature.geometry&&!(modified&&modified.geometry)){this._originalGeometry=feature.geometry.clone();}},unselectFeature:function(feature){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});delete this.dragHandle;}
+if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});delete this.radiusHandle;}
+this.feature=null;this.dragControl.deactivate();this.onModificationEnd(feature);this.layer.events.triggerEvent("afterfeaturemodified",{feature:feature,modified:this.modified});this.modified=false;},dragStart:function(feature,pixel){if(feature!=this.feature&&!feature.geometry.parent&&feature!=this.dragHandle&&feature!=this.radiusHandle){if(this.standalone===false&&this.feature){this.selectControl.clickFeature.apply(this.selectControl,[this.feature]);}
+if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)!=-1){this.standalone||this.selectControl.clickFeature.apply(this.selectControl,[feature]);this.dragControl.overFeature.apply(this.dragControl,[feature]);this.dragControl.lastPixel=pixel;this.dragControl.handlers.drag.started=true;this.dragControl.handlers.drag.start=pixel;this.dragControl.handlers.drag.last=pixel;}}},dragVertex:function(vertex,pixel){this.modified=true;if(this.feature.geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){if(this.feature!=vertex){this.feature=vertex;}
+this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});}else{if(vertex._index){vertex.geometry.parent.addComponent(vertex.geometry,vertex._index);delete vertex._index;OpenLayers.Util.removeItem(this.virtualVertices,vertex);this.vertices.push(vertex);}else if(vertex==this.dragHandle){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;}}else if(vertex!==this.radiusHandle){this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});}
+if(this.virtualVertices.length>0){this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];}
+this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);}
+this.layer.drawFeature(vertex);},dragComplete:function(vertex){this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature});},setFeatureState:function(){if(this.feature.state!=OpenLayers.State.INSERT&&this.feature.state!=OpenLayers.State.DELETE){this.feature.state=OpenLayers.State.UPDATE;if(this.modified&&this._originalGeometry){var feature=this.feature;feature.modified=OpenLayers.Util.extend(feature.modified,{geometry:this._originalGeometry});delete this._originalGeometry;}}},resetVertices:function(){if(this.dragControl.feature){this.dragControl.outFeature(this.dragControl.feature);}
+if(this.vertices.length>0){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];}
+if(this.virtualVertices.length>0){this.layer.removeFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];}
+if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});this.dragHandle=null;}
+if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;}
+if(this.feature&&this.feature.geometry.CLASS_NAME!="OpenLayers.Geometry.Point"){if((this.mode&OpenLayers.Control.ModifyFeature.DRAG)){this.collectDragHandle();}
+if((this.mode&(OpenLayers.Control.ModifyFeature.ROTATE|OpenLayers.Control.ModifyFeature.RESIZE))){this.collectRadiusHandle();}
+if(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE){if(!(this.mode&OpenLayers.Control.ModifyFeature.RESIZE)){this.collectVertices();}}}},handleKeypress:function(evt){var code=evt.keyCode;if(this.feature&&OpenLayers.Util.indexOf(this.deleteCodes,code)!=-1){var vertex=this.dragControl.feature;if(vertex&&OpenLayers.Util.indexOf(this.vertices,vertex)!=-1&&!this.dragControl.handlers.drag.dragging&&vertex.geometry.parent){vertex.geometry.parent.removeComponent(vertex.geometry);this.layer.events.triggerEvent("vertexremoved",{vertex:vertex.geometry,feature:this.feature,pixel:evt.xy});this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);this.modified=true;this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature});}}},collectVertices:function(){this.vertices=[];this.virtualVertices=[];var control=this;function collectComponentVertices(geometry){var i,vertex,component,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(geometry);vertex._sketch=true;vertex.renderIntent=control.vertexRenderIntent;control.vertices.push(vertex);}else{var numVert=geometry.components.length;if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){numVert-=1;}
+for(i=0;i<numVert;++i){component=geometry.components[i];if(component.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(component);vertex._sketch=true;vertex.renderIntent=control.vertexRenderIntent;control.vertices.push(vertex);}else{collectComponentVertices(component);}}
+if(geometry.CLASS_NAME!="OpenLayers.Geometry.MultiPoint"){for(i=0,len=geometry.components.length;i<len-1;++i){var prevVertex=geometry.components[i];var nextVertex=geometry.components[i+1];if(prevVertex.CLASS_NAME=="OpenLayers.Geometry.Point"&&nextVertex.CLASS_NAME=="OpenLayers.Geometry.Point"){var x=(prevVertex.x+nextVertex.x)/2;var y=(prevVertex.y+nextVertex.y)/2;var point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(x,y),null,control.virtualStyle);point.geometry.parent=geometry;point._index=i+1;point._sketch=true;control.virtualVertices.push(point);}}}}}
+collectComponentVertices.call(this,this.feature.geometry);this.layer.addFeatures(this.virtualVertices,{silent:true});this.layer.addFeatures(this.vertices,{silent:true});},collectDragHandle:function(){var geometry=this.feature.geometry;var center=geometry.getBounds().getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var origin=new OpenLayers.Feature.Vector(originGeometry);originGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);geometry.move(x,y);};origin._sketch=true;this.dragHandle=origin;this.layer.addFeatures([this.dragHandle],{silent:true});},collectRadiusHandle:function(){var geometry=this.feature.geometry;var bounds=geometry.getBounds();var center=bounds.getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var radiusGeometry=new OpenLayers.Geometry.Point(bounds.right,bounds.bottom);var radius=new OpenLayers.Feature.Vector(radiusGeometry);var resize=(this.mode&OpenLayers.Control.ModifyFeature.RESIZE);var reshape=(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE);var rotate=(this.mode&OpenLayers.Control.ModifyFeature.ROTATE);radiusGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);var dx1=this.x-originGeometry.x;var dy1=this.y-originGeometry.y;var dx0=dx1-x;var dy0=dy1-y;if(rotate){var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;geometry.rotate(angle,originGeometry);}
+if(resize){var scale,ratio;if(reshape){scale=dy1/dy0;ratio=(dx1/dx0)/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;}
+geometry.resize(scale,originGeometry,ratio);}};radius._sketch=true;this.radiusHandle=radius;this.layer.addFeatures([this.radiusHandle],{silent:true});},setMap:function(map){this.standalone||this.selectControl.setMap(map);this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.ModifyFeature"});OpenLayers.Control.ModifyFeature.RESHAPE=1;OpenLayers.Control.ModifyFeature.RESIZE=2;OpenLayers.Control.ModifyFeature.ROTATE=4;OpenLayers.Control.ModifyFeature.DRAG=8;OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,serverResolutions:null,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({maxExtent:new OpenLayers.Bounds(-128*156543.03390625,-128*156543.03390625,128*156543.03390625,128*156543.03390625),maxResolution:156543.03390625,numZoomLevels:19,units:"m",projection:"EPSG:900913"},options);}
+url=url||this.url;name=name||this.name;var newArguments=[name,url,{},options];OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var xyz=this.getXYZ(bounds);var url=this.url;if(OpenLayers.Util.isArray(url)){var s=''+xyz.x+xyz.y+xyz.z;url=this.selectUrl(s,url);}
+return OpenLayers.String.format(url,xyz);},getXYZ:function(bounds){var res=this.map.getResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom()+this.zoomOffset;var limit=Math.pow(2,z);if(this.wrapDateLine)
+{x=((x%limit)+limit)%limit;}
+return{'x':x,'y':y,'z':z};},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",attribution:"Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",sphericalMercator:true,url:'http://tile.openstreetmap.org/${z}/${x}/${y}.png',clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},wrapDateLine:true,CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Layer.Bing=OpenLayers.Class(OpenLayers.Layer.XYZ,{serverResolutions:[156543.03390625,78271.516953125,39135.7584765625,19567.87923828125,9783.939619140625,4891.9698095703125,2445.9849047851562,1222.9924523925781,611.4962261962891,305.74811309814453,152.87405654907226,76.43702827453613,38.218514137268066,19.109257068634033,9.554628534317017,4.777314267158508,2.388657133579254,1.194328566789627,0.5971642833948135,0.29858214169740677,0.14929107084870338,0.07464553542435169],attributionTemplate:'<span class="olBingAttribution ${type}">'+'<div><a target="_blank" href="http://www.bing.com/maps/">'+'<img src="${logo}" /></a></div>${copyrights}'+'<a style="white-space: nowrap" target="_blank" '+'href="http://www.microsoft.com/maps/product/terms.html">'+'Terms of Use</a></span>',metadata:null,type:"Road",metadataParams:null,initialize:function(options){options=OpenLayers.Util.applyDefaults({sphericalMercator:true},options);var name=options.name||"Bing "+(options.type||this.type);var newArgs=[name,null,options];OpenLayers.Layer.XYZ.prototype.initialize.apply(this,newArgs);this.loadMetadata();},loadMetadata:function(){this._callbackId="_callback_"+this.id.replace(/\./g,"_");window[this._callbackId]=OpenLayers.Function.bind(OpenLayers.Layer.Bing.processMetadata,this);var params=OpenLayers.Util.applyDefaults({key:this.key,jsonp:this._callbackId,include:"ImageryProviders"},this.metadataParams);var url="http://dev.virtualearth.net/REST/v1/Imagery/Metadata/"+
+this.type+"?"+OpenLayers.Util.getParameterString(params);var script=document.createElement("script");script.type="text/javascript";script.src=url;script.id=this._callbackId;document.getElementsByTagName("head")[0].appendChild(script);},initLayer:function(){var res=this.metadata.resourceSets[0].resources[0];var url=res.imageUrl.replace("{quadkey}","${quadkey}");this.url=[];for(var i=0;i<res.imageUrlSubdomains.length;++i){this.url.push(url.replace("{subdomain}",res.imageUrlSubdomains[i]));};this.addOptions({maxResolution:Math.min(this.serverResolutions[res.zoomMin],this.maxResolution),zoomOffset:res.zoomMin,numZoomLevels:Math.min(res.zoomMax+1-res.zoomMin,this.numZoomLevels)},true);},getURL:function(bounds){if(!this.url){return OpenLayers.Util.getImagesLocation()+"blank.gif";}
+var xyz=this.getXYZ(bounds),x=xyz.x,y=xyz.y,z=xyz.z;var quadDigits=[];for(var i=z;i>0;--i){var digit='0';var mask=1<<(i-1);if((x&mask)!=0){digit++;}
+if((y&mask)!=0){digit++;digit++;}
+quadDigits.push(digit);}
+var quadKey=quadDigits.join("");var url=this.selectUrl(''+x+y+z,this.url);return OpenLayers.String.format(url,{'quadkey':quadKey});},updateAttribution:function(){var metadata=this.metadata;if(!metadata||!this.map||!this.map.center){return;}
+var res=metadata.resourceSets[0].resources[0];var extent=this.map.getExtent().transform(this.map.getProjectionObject(),new OpenLayers.Projection("EPSG:4326"));var providers=res.imageryProviders,zoom=this.map.getZoom()+1,copyrights="",provider,i,ii,j,jj,bbox,coverage;for(i=0,ii=providers.length;i<ii;++i){provider=providers[i];for(j=0,jj=provider.coverageAreas.length;j<jj;++j){coverage=provider.coverageAreas[j];bbox=OpenLayers.Bounds.fromArray(coverage.bbox);if(extent.intersectsBounds(bbox)&&zoom<=coverage.zoomMax&&zoom>=coverage.zoomMin){copyrights+=provider.attribution+" ";}}}
+this.attribution=OpenLayers.String.format(this.attributionTemplate,{type:this.type.toLowerCase(),logo:metadata.brandLogoUri,copyrights:copyrights});this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"attribution"});},setMap:function(){OpenLayers.Layer.XYZ.prototype.setMap.apply(this,arguments);this.updateAttribution();this.map.events.register("moveend",this,this.updateAttribution);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Bing(this.options);}
+obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},destroy:function(){this.map&&this.map.events.unregister("moveend",this,this.updateAttribution);OpenLayers.Layer.XYZ.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Layer.Bing"});OpenLayers.Layer.Bing.processMetadata=function(metadata){this.metadata=metadata;this.initLayer();var script=document.getElementById(this._callbackId);script.parentNode.removeChild(script);window[this._callbackId]=undefined;delete this._callbackId;};OpenLayers.Format.SOSGetFeatureOfInterest=OpenLayers.Class(OpenLayers.Format.XML,{VERSION:"1.0.0",namespaces:{sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",sa:"http://www.opengis.net/sampling/1.0",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",defaultPrefix:"sos",regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var info={features:[]};this.readNode(data,info);var features=[];for(var i=0,len=info.features.length;i<len;i++){var container=info.features[i];if(this.internalProjection&&this.externalProjection&&container.components[0]){container.components[0].transform(this.externalProjection,this.internalProjection);}
+var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);features.push(feature);}
+return features;},readers:{"sa":{"SamplingPoint":function(node,obj){if(!obj.attributes){var feature={attributes:{}};obj.features.push(feature);obj=feature;}
+obj.attributes.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"position":function(node,obj){this.readChildNodes(node,obj);}},"gml":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);},"featureMember":function(node,obj){var feature={attributes:{}};obj.features.push(feature);this.readChildNodes(node,feature);},"name":function(node,obj){obj.attributes.name=this.getChildValue(node);},"pos":function(node,obj){if(!this.externalProjection){this.externalProjection=new OpenLayers.Projection(node.getAttribute("srsName"));}
+OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[node,obj]);}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{"sos":{"GetFeatureOfInterest":function(options){var node=this.createElementNSPlus("GetFeatureOfInterest",{attributes:{version:this.VERSION,service:'SOS',"xsi:schemaLocation":this.schemaLocation}});for(var i=0,len=options.fois.length;i<len;i++){this.writeNode("FeatureOfInterestId",{foi:options.fois[i]},node);}
+return node;},"FeatureOfInterestId":function(options){var node=this.createElementNSPlus("FeatureOfInterestId",{value:options.foi});return node;}}},CLASS_NAME:"OpenLayers.Format.SOSGetFeatureOfInterest"});OpenLayers.Format.SOSGetObservation=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows",gml:"http://www.opengis.net/gml",sos:"http://www.opengis.net/sos/1.0",ogc:"http://www.opengis.net/ogc",om:"http://www.opengis.net/om/1.0",sa:"http://www.opengis.net/sampling/1.0",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",defaultPrefix:"sos",read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var info={measurements:[],observations:[]};this.readNode(data,info);return info;},write:function(options){var node=this.writeNode("sos:GetObservation",options);node.setAttribute("xmlns:om",this.namespaces.om);node.setAttribute("xmlns:ogc",this.namespaces.ogc);this.setAttributeNS(node,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},readers:{"om":{"ObservationCollection":function(node,obj){obj.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"member":function(node,observationCollection){this.readChildNodes(node,observationCollection);},"Measurement":function(node,observationCollection){var measurement={};observationCollection.measurements.push(measurement);this.readChildNodes(node,measurement);},"Observation":function(node,observationCollection){var observation={};observationCollection.observations.push(observation);this.readChildNodes(node,observation);},"samplingTime":function(node,measurement){var samplingTime={};measurement.samplingTime=samplingTime;this.readChildNodes(node,samplingTime);},"observedProperty":function(node,measurement){measurement.observedProperty=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"procedure":function(node,measurement){measurement.procedure=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"featureOfInterest":function(node,observation){var foi={features:[]};observation.fois=[];observation.fois.push(foi);this.readChildNodes(node,foi);var features=[];for(var i=0,len=foi.features.length;i<len;i++){var feature=foi.features[i];features.push(new OpenLayers.Feature.Vector(feature.components[0],feature.attributes));}
+foi.features=features;},"result":function(node,measurement){var result={};measurement.result=result;if(this.getChildValue(node)!==''){result.value=this.getChildValue(node);result.uom=node.getAttribute("uom");}else{this.readChildNodes(node,result);}}},"sa":OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.sa,"gml":OpenLayers.Util.applyDefaults({"TimeInstant":function(node,samplingTime){var timeInstant={};samplingTime.timeInstant=timeInstant;this.readChildNodes(node,timeInstant);},"timePosition":function(node,timeInstant){timeInstant.timePosition=this.getChildValue(node);}},OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.gml)},writers:{"sos":{"GetObservation":function(options){var node=this.createElementNSPlus("GetObservation",{attributes:{version:this.VERSION,service:'SOS'}});this.writeNode("offering",options,node);if(options.eventTime){this.writeNode("eventTime",options,node);}
+for(var procedure in options.procedures){this.writeNode("procedure",options.procedures[procedure],node);}
+for(var observedProperty in options.observedProperties){this.writeNode("observedProperty",options.observedProperties[observedProperty],node);}
+if(options.foi){this.writeNode("featureOfInterest",options.foi,node);}
+this.writeNode("responseFormat",options,node);if(options.resultModel){this.writeNode("resultModel",options,node);}
+if(options.responseMode){this.writeNode("responseMode",options,node);}
+return node;},"featureOfInterest":function(foi){var node=this.createElementNSPlus("featureOfInterest");this.writeNode("ObjectID",foi.objectId,node);return node;},"ObjectID":function(options){return this.createElementNSPlus("ObjectID",{value:options});},"responseFormat":function(options){return this.createElementNSPlus("responseFormat",{value:options.responseFormat});},"procedure":function(procedure){return this.createElementNSPlus("procedure",{value:procedure});},"offering":function(options){return this.createElementNSPlus("offering",{value:options.offering});},"observedProperty":function(observedProperty){return this.createElementNSPlus("observedProperty",{value:observedProperty});},"eventTime":function(options){var node=this.createElementNSPlus("eventTime");if(options.eventTime==='latest'){this.writeNode("ogc:TM_Equals",options,node);}
+return node;},"resultModel":function(options){return this.createElementNSPlus("resultModel",{value:options.resultModel});},"responseMode":function(options){return this.createElementNSPlus("responseMode",{value:options.responseMode});}},"ogc":{"TM_Equals":function(options){var node=this.createElementNSPlus("ogc:TM_Equals");this.writeNode("ogc:PropertyName",{property:"urn:ogc:data:time:iso8601"},node);if(options.eventTime==='latest'){this.writeNode("gml:TimeInstant",{value:'latest'},node);}
+return node;},"PropertyName":function(options){return this.createElementNSPlus("ogc:PropertyName",{value:options.property});}},"gml":{"TimeInstant":function(options){var node=this.createElementNSPlus("gml:TimeInstant");this.writeNode("gml:timePosition",options,node);return node;},"timePosition":function(options){var node=this.createElementNSPlus("gml:timePosition",{value:options.value});return node;}}},CLASS_NAME:"OpenLayers.Format.SOSGetObservation"});OpenLayers.Handler.MouseWheel=OpenLayers.Class(OpenLayers.Handler,{wheelListener:null,mousePosition:null,interval:0,delta:0,cumulative:true,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.wheelListener=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.wheelListener=null;},onWheelEvent:function(e){if(!this.map||!this.checkModifiers(e)){return;}
+var overScrollableDiv=false;var overLayerDiv=false;var overMapDiv=false;var elem=OpenLayers.Event.element(e);while((elem!=null)&&!overMapDiv&&!overScrollableDiv){if(!overScrollableDiv){try{if(elem.currentStyle){overflow=elem.currentStyle["overflow"];}else{var style=document.defaultView.getComputedStyle(elem,null);var overflow=style.getPropertyValue("overflow");}
+overScrollableDiv=(overflow&&(overflow=="auto")||(overflow=="scroll"));}catch(err){}}
+if(!overLayerDiv){for(var i=0,len=this.map.layers.length;i<len;i++){if(elem==this.map.layers[i].div||elem==this.map.layers[i].pane){overLayerDiv=true;break;}}}
+overMapDiv=(elem==this.map.div);elem=elem.parentNode;}
+if(!overScrollableDiv&&overMapDiv){if(overLayerDiv){var delta=0;if(!e){e=window.event;}
+if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;}
+this.delta=this.delta+delta;if(this.interval){window.clearTimeout(this._timeoutId);this._timeoutId=window.setTimeout(OpenLayers.Function.bind(function(){this.wheelZoom(e);},this),this.interval);}else{this.wheelZoom(e);}}
+OpenLayers.Event.stop(e);}},wheelZoom:function(e){var delta=this.delta;this.delta=0;if(delta){if(this.mousePosition){e.xy=this.mousePosition;}
+if(!e.xy){e.xy=this.map.getPixelFromLonLat(this.map.getCenter());}
+if(delta<0){this.callback("down",[e,this.cumulative?delta:-1]);}else{this.callback("up",[e,this.cumulative?delta:1]);}}},mousemove:function(evt){this.mousePosition=evt.xy;},activate:function(evt){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.observe(window,"mousewheel",wheelListener);OpenLayers.Event.observe(document,"mousewheel",wheelListener);return true;}else{return false;}},deactivate:function(evt){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.stopObserving(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.stopObserving(window,"mousewheel",wheelListener);OpenLayers.Event.stopObserving(document,"mousewheel",wheelListener);return true;}else{return false;}},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Format.WFST.v1_0_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,OpenLayers.Format.WFST.v1,{version:"1.0.0",srsNameInQuery:false,schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readNode:function(node,obj,first){return OpenLayers.Format.GML.v2.prototype.readNode.apply(this,[node,obj]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"WFS_TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"InsertResult":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);},"TransactionResult":function(node,obj){this.readChildNodes(node,obj);},"Status":function(node,obj){this.readChildNodes(node,obj);},"SUCCESS":function(node,obj){obj.success=true;}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v2.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName,srsNameInQuery:this.srsNameInQuery},options);var prefix=options.featurePrefix;var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(prefix?prefix+":":"")+
+options.featureType}});if(options.srsNameInQuery&&options.srsName){node.setAttribute("srsName",options.srsName);}
+if(options.featureNS){node.setAttribute("xmlns:"+prefix,options.featureNS);}
+if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("ogc:PropertyName",{property:options.propertyNames[i]},node);}}
+if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);}
+return node;}},OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),"gml":OpenLayers.Format.GML.v2.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.writers["feature"],"ogc":OpenLayers.Format.Filter.v1_0_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.WFST.v1_0_0"});OpenLayers.Control.ArgParser=OpenLayers.Class(OpenLayers.Control,{center:null,zoom:null,layers:null,displayProjection:null,getParameters:function(url){url=url||window.location.href;var parameters=OpenLayers.Util.getParameters(url);var index=url.indexOf('#');if(index>0){url='?'+url.substring(index+1,url.length);OpenLayers.Util.extend(parameters,OpenLayers.Util.getParameters(url));}
+return parameters;},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if((control!=this)&&(control.CLASS_NAME=="OpenLayers.Control.ArgParser")){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;}
+break;}}
+if(i==this.map.controls.length){var args=this.getParameters();if(args.layers){this.layers=args.layers;this.map.events.register('addlayer',this,this.configureLayers);this.configureLayers();}
+if(args.lat&&args.lon){this.center=new OpenLayers.LonLat(parseFloat(args.lon),parseFloat(args.lat));if(args.zoom){this.zoom=parseInt(args.zoom);}
+this.map.events.register('changebaselayer',this,this.setCenter);this.setCenter();}}},setCenter:function(){if(this.map.baseLayer){this.map.events.unregister('changebaselayer',this,this.setCenter);if(this.displayProjection){this.center.transform(this.displayProjection,this.map.getProjectionObject());}
+this.map.setCenter(this.center,this.zoom);}},configureLayers:function(){if(this.layers.length==this.map.layers.length){this.map.events.unregister('addlayer',this,this.configureLayers);for(var i=0,len=this.layers.length;i<len;i++){var layer=this.map.layers[i];var c=this.layers.charAt(i);if(c=="B"){this.map.setBaseLayer(layer);}else if((c=="T")||(c=="F")){layer.setVisibility(c=="T");}}}},CLASS_NAME:"OpenLayers.Control.ArgParser"});OpenLayers.Control.Permalink=OpenLayers.Class(OpenLayers.Control,{argParserClass:OpenLayers.Control.ArgParser,element:null,anchor:false,base:'',displayProjection:null,initialize:function(element,base,options){if(element!==null&&typeof element=='object'&&!OpenLayers.Util.isElement(element)){options=element;this.base=document.location.href;OpenLayers.Control.prototype.initialize.apply(this,[options]);if(this.element!=null){this.element=OpenLayers.Util.getElement(this.element);}}
+else{OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);this.base=base||document.location.href;}},destroy:function(){if(this.element.parentNode==this.div){this.div.removeChild(this.element);}
+this.element=null;this.map.events.unregister('moveend',this,this.updateLink);OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if(control.CLASS_NAME==this.argParserClass.CLASS_NAME){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;}
+break;}}
+if(i==this.map.controls.length){this.map.addControl(new this.argParserClass({'displayProjection':this.displayProjection}));}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element&&!this.anchor){this.element=document.createElement("a");this.element.innerHTML=OpenLayers.i18n("Permalink");this.element.href="";this.div.appendChild(this.element);}
+this.map.events.on({'moveend':this.updateLink,'changelayer':this.updateLink,'changebaselayer':this.updateLink,scope:this});this.updateLink();return this.div;},updateLink:function(){var separator=this.anchor?'#':'?';var href=this.base;if(href.indexOf(separator)!=-1){href=href.substring(0,href.indexOf(separator));}
+href+=separator+OpenLayers.Util.getParameterString(this.createParams());if(this.anchor&&!this.element){window.location.href=href;}
+else{this.element.href=href;}},createParams:function(center,zoom,layers){center=center||this.map.getCenter();var params=OpenLayers.Util.getParameters(this.base);if(center){params.zoom=zoom||this.map.getZoom();var lat=center.lat;var lon=center.lon;if(this.displayProjection){var mapPosition=OpenLayers.Projection.transform({x:lon,y:lat},this.map.getProjectionObject(),this.displayProjection);lon=mapPosition.x;lat=mapPosition.y;}
+params.lat=Math.round(lat*100000)/100000;params.lon=Math.round(lon*100000)/100000;layers=layers||this.map.layers;params.layers='';for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer.isBaseLayer){params.layers+=(layer==this.map.baseLayer)?"B":"0";}else{params.layers+=(layer.getVisibility())?"T":"F";}}}
+return params;},CLASS_NAME:"OpenLayers.Control.Permalink"});OpenLayers.Layer.TMS=OpenLayers.Class(OpenLayers.Layer.Grid,{serviceVersion:"1.0.0",layername:null,type:null,isBaseLayer:true,tileOrigin:null,serverResolutions:null,zoomOffset:0,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,url,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TMS(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((bounds.bottom-this.tileOrigin.lat)/(res*this.tileSize.h));var z=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom()+this.zoomOffset;var path=this.serviceVersion+"/"+this.layername+"/"+z+"/"+x+"/"+y+"."+this.type;var url=this.url;if(OpenLayers.Util.isArray(url)){url=this.selectUrl(path,url);}
+return url+path;},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.TMS"});OpenLayers.Strategy.Fixed=OpenLayers.Class(OpenLayers.Strategy,{preload:false,activate:function(){if(OpenLayers.Strategy.prototype.activate.apply(this,arguments)){this.layer.events.on({"refresh":this.load,scope:this});if(this.layer.visibility==true||this.preload){this.load();}else{this.layer.events.on({"visibilitychanged":this.load,scope:this});}
+return true;}
+return false;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"refresh":this.load,"visibilitychanged":this.load,scope:this});}
+return deactivated;},load:function(options){var layer=this.layer;layer.events.triggerEvent("loadstart");layer.protocol.read(OpenLayers.Util.applyDefaults({callback:OpenLayers.Function.bind(this.merge,this,layer.map.getProjectionObject()),filter:layer.filter},options));layer.events.un({"visibilitychanged":this.load,scope:this});},merge:function(mapProjection,resp){var layer=this.layer;layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){if(!mapProjection.equals(layer.projection)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(layer.projection,mapProjection);}}}
+layer.addFeatures(features);}
+layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.Fixed"});OpenLayers.Control.MouseDefaults=OpenLayers.Class(OpenLayers.Control,{performedDrag:false,wheelObserver:null,initialize:function(){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.handler){this.handler.destroy();}
+this.handler=null;this.map.events.un({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});OpenLayers.Event.stopObserving(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.stopObserving(window,"mousewheel",this.wheelObserver);OpenLayers.Event.stopObserving(document,"mousewheel",this.wheelObserver);this.wheelObserver=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){this.map.events.on({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});this.registerWheelEvents();},registerWheelEvents:function(){this.wheelObserver=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);OpenLayers.Event.observe(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.observe(window,"mousewheel",this.wheelObserver);OpenLayers.Event.observe(document,"mousewheel",this.wheelObserver);},defaultClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+var notAfterDrag=!this.performedDrag;this.performedDrag=false;return notAfterDrag;},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+this.mouseDragStart=evt.xy.clone();this.performedDrag=false;if(evt.shiftKey){this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.eventsDiv.appendChild(this.zoomBox);}
+document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},defaultMouseMove:function(evt){this.mousePosition=evt.xy.clone();if(this.mouseDragStart!=null){if(this.zoomBox){var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";}
+if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";}}else{var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();this.map.div.style.cursor="move";}
+this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+if(this.zoomBox){this.zoomBoxEnd(evt);}else{if(this.performedDrag){this.map.setCenter(this.map.center);}}
+document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.eventsDiv)){if(this.zoomBox){this.removeZoomBox();}
+this.mouseDragStart=null;}},defaultWheelUp:function(evt){if(this.map.getZoom()<=this.map.getNumZoomLevels()){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()+1);}},defaultWheelDown:function(evt){if(this.map.getZoom()>0){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()-1);}},zoomBoxEnd:function(evt){if(this.mouseDragStart!=null){if(Math.abs(this.mouseDragStart.x-evt.xy.x)>5||Math.abs(this.mouseDragStart.y-evt.xy.y)>5){var start=this.map.getLonLatFromViewPortPx(this.mouseDragStart);var end=this.map.getLonLatFromViewPortPx(evt.xy);var top=Math.max(start.lat,end.lat);var bottom=Math.min(start.lat,end.lat);var left=Math.min(start.lon,end.lon);var right=Math.max(start.lon,end.lon);var bounds=new OpenLayers.Bounds(left,bottom,right,top);this.map.zoomToExtent(bounds);}else{var end=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(new OpenLayers.LonLat((end.lon),(end.lat)),this.map.getZoom()+1);}
+this.removeZoomBox();}},removeZoomBox:function(){this.map.eventsDiv.removeChild(this.zoomBox);this.zoomBox=null;},onWheelEvent:function(e){var inMap=false;var elem=OpenLayers.Event.element(e);while(elem!=null){if(this.map&&elem==this.map.div){inMap=true;break;}
+elem=elem.parentNode;}
+if(inMap){var delta=0;if(!e){e=window.event;}
+if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;}
+if(delta){e.xy=this.mousePosition;if(delta<0){this.defaultWheelDown(e);}else{this.defaultWheelUp(e);}}
+OpenLayers.Event.stop(e);}},CLASS_NAME:"OpenLayers.Control.MouseDefaults"});OpenLayers.Control.MouseToolbar=OpenLayers.Class(OpenLayers.Control.MouseDefaults,{mode:null,buttons:null,direction:"vertical",buttonClicked:null,initialize:function(position,direction){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.position=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,OpenLayers.Control.MouseToolbar.Y);if(position){this.position=position;}
+if(direction){this.direction=direction;}
+this.measureDivs=[];},destroy:function(){for(var btnId in this.buttons){var btn=this.buttons[btnId];btn.map=null;btn.events.destroy();}
+OpenLayers.Control.MouseDefaults.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);OpenLayers.Control.MouseDefaults.prototype.draw.apply(this,arguments);this.buttons={};var sz=new OpenLayers.Size(28,28);var centered=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,0);this._addButton("zoombox","drag-rectangle-off.png","drag-rectangle-on.png",centered,sz,"Shift->Drag to zoom to area");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this._addButton("pan","panning-hand-off.png","panning-hand-on.png",centered,sz,"Drag the map to pan.");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this.switchModeTo("pan");return this.div;},_addButton:function(id,img,activeImg,xy,sz,title){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var activeImgLocation=OpenLayers.Util.getImagesLocation()+activeImg;var btn=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MouseToolbar_"+id,xy,sz,imgLocation,"absolute");this.div.appendChild(btn);btn.imgLocation=imgLocation;btn.activeImgLocation=activeImgLocation;btn.events=new OpenLayers.Events(this,btn,null,true);btn.events.on({"mousedown":this.buttonDown,"mouseup":this.buttonUp,"dblclick":OpenLayers.Event.stop,scope:this});btn.action=id;btn.title=title;btn.alt=title;btn.map=this.map;this.buttons[id]=btn;return btn;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+this.buttonClicked=evt.element.action;OpenLayers.Event.stop(evt);},buttonUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+if(this.buttonClicked!=null){if(this.buttonClicked==evt.element.action){this.switchModeTo(evt.element.action);}
+OpenLayers.Event.stop(evt);this.buttonClicked=null;}},defaultDblClick:function(evt){this.switchModeTo("pan");this.performedDrag=false;var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+this.mouseDragStart=evt.xy.clone();this.performedDrag=false;this.startViaKeyboard=false;if(evt.shiftKey&&this.mode!="zoombox"){this.switchModeTo("zoombox");this.startViaKeyboard=true;}else if(evt.altKey&&this.mode!="measure"){this.switchModeTo("measure");}else if(!this.mode){this.switchModeTo("pan");}
+switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.eventsDiv.appendChild(this.zoomBox);this.performedDrag=true;break;case"measure":var distance="";if(this.measureStart){var measureEnd=this.map.getLonLatFromViewPortPx(this.mouseDragStart);distance=OpenLayers.Util.distVincenty(this.measureStart,measureEnd);distance=Math.round(distance*100)/100;distance=distance+"km";this.measureStartBox=this.measureBox;}
+this.measureStart=this.map.getLonLatFromViewPortPx(this.mouseDragStart);;this.measureBox=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),-2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBox.style.width="4px";this.measureBox.style.height="4px";this.measureBox.style.fontSize="1px";this.measureBox.style.backgroundColor="red";this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);if(distance){this.measureBoxDistance=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBoxDistance.innerHTML=distance;this.measureBoxDistance.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBoxDistance);this.measureDivs.push(this.measureBoxDistance);}
+this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);this.measureDivs.push(this.measureBox);break;default:this.map.div.style.cursor="move";break;}
+document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},switchModeTo:function(mode){if(mode!=this.mode){if(this.mode&&this.buttons[this.mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[this.mode],null,null,null,this.buttons[this.mode].imgLocation);}
+if(this.mode=="measure"&&mode!="measure"){for(var i=0,len=this.measureDivs.length;i<len;i++){if(this.measureDivs[i]){this.map.layerContainerDiv.removeChild(this.measureDivs[i]);}}
+this.measureDivs=[];this.measureStart=null;}
+this.mode=mode;if(this.buttons[mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[mode],null,null,null,this.buttons[mode].activeImgLocation);}
+switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";break;default:this.map.div.style.cursor="";break;}}},leaveMode:function(){this.switchModeTo("pan");},defaultMouseMove:function(evt){if(this.mouseDragStart!=null){switch(this.mode){case"zoombox":var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";}
+if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";}
+break;default:var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();}
+this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+switch(this.mode){case"zoombox":this.zoomBoxEnd(evt);if(this.startViaKeyboard){this.leaveMode();}
+break;case"pan":if(this.performedDrag){this.map.setCenter(this.map.center);}}
+document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="default";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.eventsDiv)){if(this.zoomBox){this.removeZoomBox();if(this.startViaKeyboard){this.leaveMode();}}
+this.mouseDragStart=null;this.map.div.style.cursor="default";}},defaultClick:function(evt){if(this.performedDrag){this.performedDrag=false;return false;}},CLASS_NAME:"OpenLayers.Control.MouseToolbar"});OpenLayers.Control.MouseToolbar.X=6;OpenLayers.Control.MouseToolbar.Y=300;OpenLayers.Layer.PointTrack=OpenLayers.Class(OpenLayers.Layer.Vector,{dataFrom:null,styleFrom:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},addNodes:function(pointFeatures,options){if(pointFeatures.length<2){OpenLayers.Console.error("At least two point features have to be added to create"+"a line from");return;}
+var lines=new Array(pointFeatures.length-1);var pointFeature,startPoint,endPoint;for(var i=0,len=pointFeatures.length;i<len;i++){pointFeature=pointFeatures[i];endPoint=pointFeature.geometry;if(!endPoint){var lonlat=pointFeature.lonlat;endPoint=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);}else if(endPoint.CLASS_NAME!="OpenLayers.Geometry.Point"){OpenLayers.Console.error("Only features with point geometries are supported.");return;}
+if(i>0){var attributes=(this.dataFrom!=null)?(pointFeatures[i+this.dataFrom].data||pointFeatures[i+this.dataFrom].attributes):null;var style=(this.styleFrom!=null)?(pointFeatures[i+this.styleFrom].style):null;var line=new OpenLayers.Geometry.LineString([startPoint,endPoint]);lines[i-1]=new OpenLayers.Feature.Vector(line,attributes,style);}
+startPoint=endPoint;}
+this.addFeatures(lines,options);},CLASS_NAME:"OpenLayers.Layer.PointTrack"});OpenLayers.Layer.PointTrack.SOURCE_NODE=-1;OpenLayers.Layer.PointTrack.TARGET_NODE=0;OpenLayers.Layer.PointTrack.dataFrom={'SOURCE_NODE':-1,'TARGET_NODE':0};OpenLayers.Protocol.WFS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.WFS.DEFAULTS);var cls=OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFS version: "+options.version;}
+return new cls(options);};OpenLayers.Protocol.WFS.fromWMSLayer=function(layer,options){var typeName,featurePrefix;var param=layer.params["LAYERS"];var parts=(OpenLayers.Util.isArray(param)?param[0]:param).split(":");if(parts.length>1){featurePrefix=parts[0];}
+typeName=parts.pop();var protocolOptions={url:layer.url,featureType:typeName,featurePrefix:featurePrefix,srsName:layer.projection&&layer.projection.getCode()||layer.map&&layer.map.getProjectionObject().getCode(),version:"1.1.0"};return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(options,protocolOptions));};OpenLayers.Protocol.WFS.DEFAULTS={"version":"1.0.0"};OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,markers:null,drawn:false,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.markers=[];},destroy:function(){this.clearMarkers();this.markers=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.markers.length;i<len;i++){this.markers[i].setOpacity(this.opacity);}}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(zoomChanged||!this.drawn){for(var i=0,len=this.markers.length;i<len;i++){this.drawMarker(this.markers[i]);}
+this.drawn=true;}},addMarker:function(marker){this.markers.push(marker);if(this.opacity!=null){marker.setOpacity(this.opacity);}
+if(this.map&&this.map.getExtent()){marker.map=this.map;this.drawMarker(marker);}},removeMarker:function(marker){if(this.markers&&this.markers.length){OpenLayers.Util.removeItem(this.markers,marker);marker.erase();}},clearMarkers:function(){if(this.markers!=null){while(this.markers.length>0){this.removeMarker(this.markers[0]);}}},drawMarker:function(marker){var px=this.map.getLayerPxFromLonLat(marker.lonlat);if(px==null){marker.display(false);}else{if(!marker.isDrawn()){var markerImg=marker.draw(px);this.div.appendChild(markerImg);}else if(marker.icon){marker.icon.moveTo(px);}}},getDataExtent:function(){var maxExtent=null;if(this.markers&&(this.markers.length>0)){var maxExtent=new OpenLayers.Bounds();for(var i=0,len=this.markers.length;i<len;i++){var marker=this.markers[i];maxExtent.extend(marker.lonlat);}}
+return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Control.Pan=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,direction:null,type:OpenLayers.Control.TYPE_BUTTON,initialize:function(direction,options){this.direction=direction;this.CLASS_NAME+=this.direction;OpenLayers.Control.prototype.initialize.apply(this,[options]);},trigger:function(){var getSlideFactor=OpenLayers.Function.bind(function(dim){return this.slideRatio?this.map.getSize()[dim]*this.slideRatio:this.slideFactor;},this);switch(this.direction){case OpenLayers.Control.Pan.NORTH:this.map.pan(0,-getSlideFactor("h"));break;case OpenLayers.Control.Pan.SOUTH:this.map.pan(0,getSlideFactor("h"));break;case OpenLayers.Control.Pan.WEST:this.map.pan(-getSlideFactor("w"),0);break;case OpenLayers.Control.Pan.EAST:this.map.pan(getSlideFactor("w"),0);break;}},CLASS_NAME:"OpenLayers.Control.Pan"});OpenLayers.Control.Pan.NORTH="North";OpenLayers.Control.Pan.SOUTH="South";OpenLayers.Control.Pan.EAST="East";OpenLayers.Control.Pan.WEST="West";OpenLayers.Layer.WMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{service:"WMS",version:"1.1.1",request:"GetMap",styles:"",format:"image/jpeg"},reproject:false,isBaseLayer:true,encodeBBOX:false,noMagic:false,yx:{'EPSG:4326':true},initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);if(parseFloat(params.VERSION)>=1.3&&!params.EXCEPTIONS){params.EXCEPTIONS="INIMAGE";}
+newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(!this.noMagic&&this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;}
+if(this.params.FORMAT=="image/jpeg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},reverseAxisOrder:function(){return(parseFloat(this.params.VERSION)>=1.3&&!!this.yx[this.map.getProjectionObject().getCode()]);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var imageSize=this.getImageSize();var newParams={};var reverseAxisOrder=this.reverseAxisOrder();newParams.BBOX=this.encodeBBOX?bounds.toBBOX(null,reverseAxisOrder):bounds.toArray(reverseAxisOrder);newParams.WIDTH=imageSize.w;newParams.HEIGHT=imageSize.h;var requestString=this.getFullRequestString(newParams);return requestString;},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},getFullRequestString:function(newParams,altUrl){var mapProjection=this.map.getProjectionObject();var projectionCode=this.projection&&this.projection.equals(mapProjection)?this.projection.getCode():mapProjection.getCode();var value=(projectionCode=="none")?null:projectionCode;if(parseFloat(this.params.VERSION)>=1.3){this.params.CRS=value;}else{this.params.SRS=value;}
+if(typeof this.params.TRANSPARENT=="boolean"){newParams.TRANSPARENT=this.params.TRANSPARENT?"TRUE":"FALSE";}
+return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},CLASS_NAME:"OpenLayers.Layer.WMS"});OpenLayers.Layer.WMS.Untiled=OpenLayers.Class(OpenLayers.Layer.WMS,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.WMS.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.WMS.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.WMS class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS.Untiled(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.WMS.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.WMS.Untiled"});OpenLayers.Geometry.Surface=OpenLayers.Class(OpenLayers.Geometry,{initialize:function(){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.Surface"});OpenLayers.Format.ArcXML.Features=OpenLayers.Class(OpenLayers.Format.XML,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var axl=new OpenLayers.Format.ArcXML();var parsed=axl.read(data);return parsed.features.feature;}});OpenLayers.Control.Snapping=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesnap","snap","unsnap"],DEFAULTS:{tolerance:10,node:true,edge:true,vertex:true},greedy:true,precedence:["node","vertex","edge"],resolution:null,geoToleranceCache:null,layer:null,feature:null,point:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.layer){this.setLayer(this.options.layer);}
+var defaults=OpenLayers.Util.extend({},this.options.defaults);this.defaults=OpenLayers.Util.applyDefaults(defaults,this.DEFAULTS);this.setTargets(this.options.targets);if(this.targets.length===0&&this.layer){this.addTargetLayer(this.layer);}
+this.geoToleranceCache={};},setLayer:function(layer){if(this.active){this.deactivate();this.layer=layer;this.activate();}else{this.layer=layer;}},setTargets:function(targets){this.targets=[];if(targets&&targets.length){var target;for(var i=0,len=targets.length;i<len;++i){target=targets[i];if(target instanceof OpenLayers.Layer.Vector){this.addTargetLayer(target);}else{this.addTarget(target);}}}},addTargetLayer:function(layer){this.addTarget({layer:layer});},addTarget:function(target){target=OpenLayers.Util.applyDefaults(target,this.defaults);target.nodeTolerance=target.nodeTolerance||target.tolerance;target.vertexTolerance=target.vertexTolerance||target.tolerance;target.edgeTolerance=target.edgeTolerance||target.tolerance;this.targets.push(target);},removeTargetLayer:function(layer){var target;for(var i=this.targets.length-1;i>=0;--i){target=this.targets[i];if(target.layer===layer){this.removeTarget(target);}}},removeTarget:function(target){return OpenLayers.Util.removeItem(this.targets,target);},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(this.layer&&this.layer.events){this.layer.events.on({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.layer&&this.layer.events){this.layer.events.un({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}}
+this.feature=null;this.point=null;return deactivated;},onSketchModified:function(event){this.feature=event.feature;this.considerSnapping(event.vertex,event.vertex);},onVertexModified:function(event){this.feature=event.feature;var loc=this.layer.map.getLonLatFromViewPortPx(event.pixel);this.considerSnapping(event.vertex,new OpenLayers.Geometry.Point(loc.lon,loc.lat));},considerSnapping:function(point,loc){var best={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY,x:null,y:null};var snapped=false;var result,target;for(var i=0,len=this.targets.length;i<len;++i){target=this.targets[i];result=this.testTarget(target,loc);if(result){if(this.greedy){best=result;best.target=target;snapped=true;break;}else{if((result.rank<best.rank)||(result.rank===best.rank&&result.dist<best.dist)){best=result;best.target=target;snapped=true;}}}}
+if(snapped){var proceed=this.events.triggerEvent("beforesnap",{point:point,x:best.x,y:best.y,distance:best.dist,layer:best.target.layer,snapType:this.precedence[best.rank]});if(proceed!==false){point.x=best.x;point.y=best.y;this.point=point;this.events.triggerEvent("snap",{point:point,snapType:this.precedence[best.rank],layer:best.target.layer,distance:best.dist});}else{snapped=false;}}
+if(this.point&&!snapped){point.x=loc.x;point.y=loc.y;this.point=null;this.events.triggerEvent("unsnap",{point:point});}},testTarget:function(target,loc){var resolution=this.layer.map.getResolution();if("minResolution"in target){if(resolution<target.minResolution){return null;}}
+if("maxResolution"in target){if(resolution>=target.maxResolution){return null;}}
+var tolerance={node:this.getGeoTolerance(target.nodeTolerance,resolution),vertex:this.getGeoTolerance(target.vertexTolerance,resolution),edge:this.getGeoTolerance(target.edgeTolerance,resolution)};var maxTolerance=Math.max(tolerance.node,tolerance.vertex,tolerance.edge);var result={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY};var eligible=false;var features=target.layer.features;var feature,type,vertices,vertex,closest,dist,found;var numTypes=this.precedence.length;var ll=new OpenLayers.LonLat(loc.x,loc.y);for(var i=0,len=features.length;i<len;++i){feature=features[i];if(feature!==this.feature&&!feature._sketch&&feature.state!==OpenLayers.State.DELETE&&(!target.filter||target.filter.evaluate(feature.attributes))){if(feature.atPoint(ll,maxTolerance,maxTolerance)){for(var j=0,stop=Math.min(result.rank+1,numTypes);j<stop;++j){type=this.precedence[j];if(target[type]){if(type==="edge"){closest=feature.geometry.distanceTo(loc,{details:true});dist=closest.distance;if(dist<=tolerance[type]&&dist<result.dist){result={rank:j,dist:dist,x:closest.x0,y:closest.y0};eligible=true;break;}}else{vertices=feature.geometry.getVertices(type==="node");found=false;for(var k=0,klen=vertices.length;k<klen;++k){vertex=vertices[k];dist=vertex.distanceTo(loc);if(dist<=tolerance[type]&&(j<result.rank||(j===result.rank&&dist<result.dist))){result={rank:j,dist:dist,x:vertex.x,y:vertex.y};eligible=true;found=true;}}
+if(found){break;}}}}}}}
+return eligible?result:null;},getGeoTolerance:function(tolerance,resolution){if(resolution!==this.resolution){this.resolution=resolution;this.geoToleranceCache={};}
+var geoTolerance=this.geoToleranceCache[tolerance];if(geoTolerance===undefined){geoTolerance=tolerance*resolution;this.geoToleranceCache[tolerance]=geoTolerance;}
+return geoTolerance;},destroy:function(){if(this.active){this.deactivate();}
+delete this.layer;delete this.targets;OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Snapping"});OpenLayers.Format.CSWGetDomain=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetDomain.DEFAULTS);var cls=OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetDomain version: "+options.version;}
+return new cls(options);};OpenLayers.Format.CSWGetDomain.DEFAULTS={"version":"2.0.2"};OpenLayers.Format.CSWGetDomain.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",csw:"http://www.opengis.net/cat/csw/2.0.2"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",PropertyName:null,ParameterName:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetDomainResponse":function(node,obj){this.readChildNodes(node,obj);},"DomainValues":function(node,obj){if(!(OpenLayers.Util.isArray(obj.DomainValues))){obj.DomainValues=[];}
+var attrs=node.attributes;var domainValue={};for(var i=0,len=attrs.length;i<len;++i){domainValue[attrs[i].name]=attrs[i].nodeValue;}
+this.readChildNodes(node,domainValue);obj.DomainValues.push(domainValue);},"PropertyName":function(node,obj){obj.PropertyName=this.getChildValue(node);},"ParameterName":function(node,obj){obj.ParameterName=this.getChildValue(node);},"ListOfValues":function(node,obj){if(!(OpenLayers.Util.isArray(obj.ListOfValues))){obj.ListOfValues=[];}
+this.readChildNodes(node,obj.ListOfValues);},"Value":function(node,obj){var attrs=node.attributes;var value={};for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
+value.value=this.getChildValue(node);obj.push({Value:value});},"ConceptualScheme":function(node,obj){obj.ConceptualScheme={};this.readChildNodes(node,obj.ConceptualScheme);},"Name":function(node,obj){obj.Name=this.getChildValue(node);},"Document":function(node,obj){obj.Document=this.getChildValue(node);},"Authority":function(node,obj){obj.Authority=this.getChildValue(node);},"RangeOfValues":function(node,obj){obj.RangeOfValues={};this.readChildNodes(node,obj.RangeOfValues);},"MinValue":function(node,obj){var attrs=node.attributes;var value={};for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
+value.value=this.getChildValue(node);obj.MinValue=value;},"MaxValue":function(node,obj){var attrs=node.attributes;var value={};for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
+value.value=this.getChildValue(node);obj.MaxValue=value;}}},write:function(options){var node=this.writeNode("csw:GetDomain",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetDomain":function(options){var node=this.createElementNSPlus("csw:GetDomain",{attributes:{service:"CSW",version:this.version}});if(options.PropertyName||this.PropertyName){this.writeNode("csw:PropertyName",options.PropertyName||this.PropertyName,node);}else if(options.ParameterName||this.ParameterName){this.writeNode("csw:ParameterName",options.ParameterName||this.ParameterName,node);}
+this.readChildNodes(node,options);return node;},"PropertyName":function(value){var node=this.createElementNSPlus("csw:PropertyName",{value:value});return node;},"ParameterName":function(value){var node=this.createElementNSPlus("csw:ParameterName",{value:value});return node;}}},CLASS_NAME:"OpenLayers.Format.CSWGetDomain.v2_0_2"});OpenLayers.Date={toISOString:(function(){if("toISOString"in Date.prototype){return function(date){return date.toISOString();};}else{function pad(num,len){var str=num+"";while(str.length<len){str="0"+str;}
+return str;}
+return function(date){var str;if(isNaN(date.getTime())){str="Invalid Date";}else{str=date.getUTCFullYear()+"-"+
+pad(date.getUTCMonth()+1,2)+"-"+
+pad(date.getUTCDate(),2)+"T"+
+pad(date.getUTCHours(),2)+":"+
+pad(date.getUTCMinutes(),2)+":"+
+pad(date.getUTCSeconds(),2)+"."+
+pad(date.getUTCMilliseconds(),3)+"Z";}
+return str;};}})(),parse:function(str){var date;var match=str.match(/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))?$/);if(match&&(match[1]||match[7])){var year=parseInt(match[1],10)||0;var month=(parseInt(match[2],10)-1)||0;var day=parseInt(match[3],10)||1;date=new Date(Date.UTC(year,month,day));var type=match[7];if(type){var hours=parseInt(match[4],10);var minutes=parseInt(match[5],10);var secFrac=parseFloat(match[6]);var seconds=secFrac|0;var milliseconds=Math.round(1000*(secFrac-seconds));date.setUTCHours(hours,minutes,seconds,milliseconds);if(type!=="Z"){var hoursOffset=parseInt(type,10);var minutesOffset=parseInt(match[8],10)||0;var offset=-1000*(60*(hoursOffset*60)+minutesOffset*60);date=new Date(date.getTime()+offset);}}}else{date=new Date("invalid");}
+return date;}};(function(){var oXMLHttpRequest=window.XMLHttpRequest;var bGecko=!!window.controllers,bIE=window.document.all&&!window.opera,bIE7=bIE&&window.navigator.userAgent.match(/MSIE 7.0/);function fXMLHttpRequest(){this._object=oXMLHttpRequest&&!bIE7?new oXMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[];};function cXMLHttpRequest(){return new fXMLHttpRequest;};cXMLHttpRequest.prototype=fXMLHttpRequest.prototype;if(bGecko&&oXMLHttpRequest.wrapped)
+cXMLHttpRequest.wrapped=oXMLHttpRequest.wrapped;cXMLHttpRequest.UNSENT=0;cXMLHttpRequest.OPENED=1;cXMLHttpRequest.HEADERS_RECEIVED=2;cXMLHttpRequest.LOADING=3;cXMLHttpRequest.DONE=4;cXMLHttpRequest.prototype.readyState=cXMLHttpRequest.UNSENT;cXMLHttpRequest.prototype.responseText='';cXMLHttpRequest.prototype.responseXML=null;cXMLHttpRequest.prototype.status=0;cXMLHttpRequest.prototype.statusText='';cXMLHttpRequest.prototype.priority="NORMAL";cXMLHttpRequest.prototype.onreadystatechange=null;cXMLHttpRequest.onreadystatechange=null;cXMLHttpRequest.onopen=null;cXMLHttpRequest.onsend=null;cXMLHttpRequest.onabort=null;cXMLHttpRequest.prototype.open=function(sMethod,sUrl,bAsync,sUser,sPassword){delete this._headers;if(arguments.length<3)
+bAsync=true;this._async=bAsync;var oRequest=this,nState=this.readyState,fOnUnload;if(bIE&&bAsync){fOnUnload=function(){if(nState!=cXMLHttpRequest.DONE){fCleanTransport(oRequest);oRequest.abort();}};window.attachEvent("onunload",fOnUnload);}
+if(cXMLHttpRequest.onopen)
+cXMLHttpRequest.onopen.apply(this,arguments);if(arguments.length>4)
+this._object.open(sMethod,sUrl,bAsync,sUser,sPassword);else
+if(arguments.length>3)
+this._object.open(sMethod,sUrl,bAsync,sUser);else
+this._object.open(sMethod,sUrl,bAsync);this.readyState=cXMLHttpRequest.OPENED;fReadyStateChange(this);this._object.onreadystatechange=function(){if(bGecko&&!bAsync)
+return;oRequest.readyState=oRequest._object.readyState;fSynchronizeValues(oRequest);if(oRequest._aborted){oRequest.readyState=cXMLHttpRequest.UNSENT;return;}
+if(oRequest.readyState==cXMLHttpRequest.DONE){delete oRequest._data;fCleanTransport(oRequest);if(bIE&&bAsync)
+window.detachEvent("onunload",fOnUnload);}
+if(nState!=oRequest.readyState)
+fReadyStateChange(oRequest);nState=oRequest.readyState;}};function fXMLHttpRequest_send(oRequest){oRequest._object.send(oRequest._data);if(bGecko&&!oRequest._async){oRequest.readyState=cXMLHttpRequest.OPENED;fSynchronizeValues(oRequest);while(oRequest.readyState<cXMLHttpRequest.DONE){oRequest.readyState++;fReadyStateChange(oRequest);if(oRequest._aborted)
+return;}}};cXMLHttpRequest.prototype.send=function(vData){if(cXMLHttpRequest.onsend)
+cXMLHttpRequest.onsend.apply(this,arguments);if(!arguments.length)
+vData=null;if(vData&&vData.nodeType){vData=window.XMLSerializer?new window.XMLSerializer().serializeToString(vData):vData.xml;if(!oRequest._headers["Content-Type"])
+oRequest._object.setRequestHeader("Content-Type","application/xml");}
+this._data=vData;fXMLHttpRequest_send(this);};cXMLHttpRequest.prototype.abort=function(){if(cXMLHttpRequest.onabort)
+cXMLHttpRequest.onabort.apply(this,arguments);if(this.readyState>cXMLHttpRequest.UNSENT)
+this._aborted=true;this._object.abort();fCleanTransport(this);this.readyState=cXMLHttpRequest.UNSENT;delete this._data;};cXMLHttpRequest.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders();};cXMLHttpRequest.prototype.getResponseHeader=function(sName){return this._object.getResponseHeader(sName);};cXMLHttpRequest.prototype.setRequestHeader=function(sName,sValue){if(!this._headers)
+this._headers={};this._headers[sName]=sValue;return this._object.setRequestHeader(sName,sValue);};cXMLHttpRequest.prototype.addEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+return;this._listeners.push([sName,fHandler,bUseCapture]);};cXMLHttpRequest.prototype.removeEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+break;if(oListener)
+this._listeners.splice(nIndex,1);};cXMLHttpRequest.prototype.dispatchEvent=function(oEvent){var oEventPseudo={'type':oEvent.type,'target':this,'currentTarget':this,'eventPhase':2,'bubbles':oEvent.bubbles,'cancelable':oEvent.cancelable,'timeStamp':oEvent.timeStamp,'stopPropagation':function(){},'preventDefault':function(){},'initEvent':function(){}};if(oEventPseudo.type=="readystatechange"&&this.onreadystatechange)
+(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[oEventPseudo]);for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==oEventPseudo.type&&!oListener[2])
+(oListener[1].handleEvent||oListener[1]).apply(this,[oEventPseudo]);};cXMLHttpRequest.prototype.toString=function(){return'['+"object"+' '+"XMLHttpRequest"+']';};cXMLHttpRequest.toString=function(){return'['+"XMLHttpRequest"+']';};function fReadyStateChange(oRequest){if(cXMLHttpRequest.onreadystatechange)
+cXMLHttpRequest.onreadystatechange.apply(oRequest);oRequest.dispatchEvent({'type':"readystatechange",'bubbles':false,'cancelable':false,'timeStamp':new Date+0});};function fGetDocument(oRequest){var oDocument=oRequest.responseXML,sResponse=oRequest.responseText;if(bIE&&sResponse&&oDocument&&!oDocument.documentElement&&oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){oDocument=new window.ActiveXObject("Microsoft.XMLDOM");oDocument.async=false;oDocument.validateOnParse=false;oDocument.loadXML(sResponse);}
+if(oDocument)
+if((bIE&&oDocument.parseError!=0)||!oDocument.documentElement||(oDocument.documentElement&&oDocument.documentElement.tagName=="parsererror"))
+return null;return oDocument;};function fSynchronizeValues(oRequest){try{oRequest.responseText=oRequest._object.responseText;}catch(e){}
+try{oRequest.responseXML=fGetDocument(oRequest._object);}catch(e){}
+try{oRequest.status=oRequest._object.status;}catch(e){}
+try{oRequest.statusText=oRequest._object.statusText;}catch(e){}};function fCleanTransport(oRequest){oRequest._object.onreadystatechange=new window.Function;};if(!window.Function.prototype.apply){window.Function.prototype.apply=function(oRequest,oArguments){if(!oArguments)
+oArguments=[];oRequest.__func=this;oRequest.__func(oArguments[0],oArguments[1],oArguments[2],oArguments[3],oArguments[4]);delete oRequest.__func;};};OpenLayers.Request.XMLHttpRequest=cXMLHttpRequest;})();OpenLayers.Format.KML=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{kml:"http://www.opengis.net/kml/2.2",gx:"http://www.google.com/kml/ext/2.2"},kmlns:"http://earth.google.com/kml/2.0",placemarksDesc:"No description available",foldersName:"OpenLayers export",foldersDesc:"Exported on "+new Date(),extractAttributes:true,extractStyles:false,extractTracks:false,trackAttributes:null,internalns:null,features:null,styles:null,styleBaseUrl:"",fetched:null,maxDepth:0,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g),kmlColor:(/(\w{2})(\w{2})(\w{2})(\w{2})/),kmlIconPalette:(/root:\/\/icons\/palette-(\d+)(\.\w+)/),straightBracket:(/\$\[(.*?)\]/g)};this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){this.features=[];this.styles={};this.fetched={};var options={depth:0,styleBaseUrl:this.styleBaseUrl};return this.parseData(data,options);},parseData:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var types=["Link","NetworkLink","Style","StyleMap","Placemark"];for(var i=0,len=types.length;i<len;++i){var type=types[i];var nodes=this.getElementsByTagNameNS(data,"*",type);if(nodes.length==0){continue;}
+switch(type.toLowerCase()){case"link":case"networklink":this.parseLinks(nodes,options);break;case"style":if(this.extractStyles){this.parseStyles(nodes,options);}
+break;case"stylemap":if(this.extractStyles){this.parseStyleMaps(nodes,options);}
+break;case"placemark":this.parseFeatures(nodes,options);break;}}
+return this.features;},parseLinks:function(nodes,options){if(options.depth>=this.maxDepth){return false;}
+var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;for(var i=0,len=nodes.length;i<len;i++){var href=this.parseProperty(nodes[i],"*","href");if(href&&!this.fetched[href]){this.fetched[href]=true;var data=this.fetchLink(href);if(data){this.parseData(data,newOptions);}}}},fetchLink:function(href){var request=OpenLayers.Request.GET({url:href,async:false});if(request){return request.responseText;}},parseStyles:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var style=this.parseStyle(nodes[i]);if(style){var styleName=(options.styleBaseUrl||"")+"#"+style.id;this.styles[styleName]=style;}}},parseKmlColor:function(kmlColor){var color=null;if(kmlColor){var matches=kmlColor.match(this.regExes.kmlColor);if(matches){color={color:'#'+matches[4]+matches[3]+matches[2],opacity:parseInt(matches[1],16)/255};}}
+return color;},parseStyle:function(node){var style={};var types=["LineStyle","PolyStyle","IconStyle","BalloonStyle","LabelStyle"];var type,styleTypeNode,nodeList,geometry,parser;for(var i=0,len=types.length;i<len;++i){type=types[i];styleTypeNode=this.getElementsByTagNameNS(node,"*",type)[0];if(!styleTypeNode){continue;}
+switch(type.toLowerCase()){case"linestyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["strokeColor"]=color.color;style["strokeOpacity"]=color.opacity;}
+var width=this.parseProperty(styleTypeNode,"*","width");if(width){style["strokeWidth"]=width;}
+break;case"polystyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fillOpacity"]=color.opacity;style["fillColor"]=color.color;}
+var fill=this.parseProperty(styleTypeNode,"*","fill");if(fill=="0"){style["fillColor"]="none";}
+var outline=this.parseProperty(styleTypeNode,"*","outline");if(outline=="0"){style["strokeWidth"]="0";}
+break;case"iconstyle":var scale=parseFloat(this.parseProperty(styleTypeNode,"*","scale")||1);var width=32*scale;var height=32*scale;var iconNode=this.getElementsByTagNameNS(styleTypeNode,"*","Icon")[0];if(iconNode){var href=this.parseProperty(iconNode,"*","href");if(href){var w=this.parseProperty(iconNode,"*","w");var h=this.parseProperty(iconNode,"*","h");var google="http://maps.google.com/mapfiles/kml";if(OpenLayers.String.startsWith(href,google)&&!w&&!h){w=64;h=64;scale=scale/2;}
+w=w||h;h=h||w;if(w){width=parseInt(w)*scale;}
+if(h){height=parseInt(h)*scale;}
+var matches=href.match(this.regExes.kmlIconPalette);if(matches){var palette=matches[1];var file_extension=matches[2];var x=this.parseProperty(iconNode,"*","x");var y=this.parseProperty(iconNode,"*","y");var posX=x?x/32:0;var posY=y?(7-y/32):7;var pos=posY*8+posX;href="http://maps.google.com/mapfiles/kml/pal"
++palette+"/icon"+pos+file_extension;}
+style["graphicOpacity"]=1;style["externalGraphic"]=href;}}
+var hotSpotNode=this.getElementsByTagNameNS(styleTypeNode,"*","hotSpot")[0];if(hotSpotNode){var x=parseFloat(hotSpotNode.getAttribute("x"));var y=parseFloat(hotSpotNode.getAttribute("y"));var xUnits=hotSpotNode.getAttribute("xunits");if(xUnits=="pixels"){style["graphicXOffset"]=-x*scale;}
+else if(xUnits=="insetPixels"){style["graphicXOffset"]=-width+(x*scale);}
+else if(xUnits=="fraction"){style["graphicXOffset"]=-width*x;}
+var yUnits=hotSpotNode.getAttribute("yunits");if(yUnits=="pixels"){style["graphicYOffset"]=-height+(y*scale)+1;}
+else if(yUnits=="insetPixels"){style["graphicYOffset"]=-(y*scale)+1;}
+else if(yUnits=="fraction"){style["graphicYOffset"]=-height*(1-y)+1;}}
+style["graphicWidth"]=width;style["graphicHeight"]=height;break;case"balloonstyle":var balloonStyle=OpenLayers.Util.getXmlNodeValue(styleTypeNode);if(balloonStyle){style["balloonStyle"]=balloonStyle.replace(this.regExes.straightBracket,"${$1}");}
+break;case"labelstyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fontColor"]=color.color;style["fontOpacity"]=color.opacity;}
+break;default:}}
+if(!style["strokeColor"]&&style["fillColor"]){style["strokeColor"]=style["fillColor"];}
+var id=node.getAttribute("id");if(id&&style){style.id=id;}
+return style;},parseStyleMaps:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var node=nodes[i];var pairs=this.getElementsByTagNameNS(node,"*","Pair");var id=node.getAttribute("id");for(var j=0,jlen=pairs.length;j<jlen;j++){var pair=pairs[j];var key=this.parseProperty(pair,"*","key");var styleUrl=this.parseProperty(pair,"*","styleUrl");if(styleUrl&&key=="normal"){this.styles[(options.styleBaseUrl||"")+"#"+id]=this.styles[(options.styleBaseUrl||"")+styleUrl];}
+if(styleUrl&&key=="highlight"){}}}},parseFeatures:function(nodes,options){var features=[];for(var i=0,len=nodes.length;i<len;i++){var featureNode=nodes[i];var feature=this.parseFeature.apply(this,[featureNode]);if(feature){if(this.extractStyles&&feature.attributes&&feature.attributes.styleUrl){feature.style=this.getStyle(feature.attributes.styleUrl,options);}
+if(this.extractStyles){var inlineStyleNode=this.getElementsByTagNameNS(featureNode,"*","Style")[0];if(inlineStyleNode){var inlineStyle=this.parseStyle(inlineStyleNode);if(inlineStyle){feature.style=OpenLayers.Util.extend(feature.style,inlineStyle);}}}
+if(this.extractTracks){var tracks=this.getElementsByTagNameNS(featureNode,this.namespaces.gx,"Track");if(tracks&&tracks.length>0){var track=tracks[0];var container={features:[],feature:feature};this.readNode(track,container);if(container.features.length>0){features.push.apply(features,container.features);}}}else{features.push(feature);}}else{throw"Bad Placemark: "+i;}}
+this.features=this.features.concat(features);},readers:{"kml":{"when":function(node,container){container.whens.push(OpenLayers.Date.parse(this.getChildValue(node)));},"_trackPointAttribute":function(node,container){var name=node.nodeName.split(":").pop();container.attributes[name].push(this.getChildValue(node));}},"gx":{"Track":function(node,container){var obj={whens:[],points:[],angles:[]};if(this.trackAttributes){var name;obj.attributes={};for(var i=0,ii=this.trackAttributes.length;i<ii;++i){name=this.trackAttributes[i];obj.attributes[name]=[];if(!(name in this.readers.kml)){this.readers.kml[name]=this.readers.kml._trackPointAttribute;}}}
+this.readChildNodes(node,obj);if(obj.whens.length!==obj.points.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:coord ("+obj.points.length+") elements.");}
+var hasAngles=obj.angles.length>0;if(hasAngles&&obj.whens.length!==obj.angles.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:angles ("+obj.angles.length+") elements.");}
+var feature,point,angles;for(var i=0,ii=obj.whens.length;i<ii;++i){feature=container.feature.clone();feature.fid=container.feature.fid||container.feature.id;point=obj.points[i];feature.geometry=point;if("z"in point){feature.attributes.altitude=point.z;}
+if(this.internalProjection&&this.externalProjection){feature.geometry.transform(this.externalProjection,this.internalProjection);}
+if(this.trackAttributes){for(var j=0,jj=this.trackAttributes.length;j<jj;++j){feature.attributes[name]=obj.attributes[this.trackAttributes[j]][i];}}
+feature.attributes.when=obj.whens[i];feature.attributes.trackId=container.feature.id;if(hasAngles){angles=obj.angles[i];feature.attributes.heading=parseFloat(angles[0]);feature.attributes.tilt=parseFloat(angles[1]);feature.attributes.roll=parseFloat(angles[2]);}
+container.features.push(feature);}},"coord":function(node,container){var str=this.getChildValue(node);var coords=str.replace(this.regExes.trimSpace,"").split(/\s+/);var point=new OpenLayers.Geometry.Point(coords[0],coords[1]);if(coords.length>2){point.z=parseFloat(coords[2]);}
+container.points.push(point);},"angles":function(node,container){var str=this.getChildValue(node);var parts=str.replace(this.regExes.trimSpace,"").split(/\s+/);container.angles.push(parts);}}},parseFeature:function(node){var order=["MultiGeometry","Polygon","LineString","Point"];var type,nodeList,geometry,parser;for(var i=0,len=order.length;i<len;++i){type=order[i];this.internalns=node.namespaceURI?node.namespaceURI:this.kmlns;nodeList=this.getElementsByTagNameNS(node,this.internalns,type);if(nodeList.length>0){var parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));}
+break;}}
+var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);}
+var feature=new OpenLayers.Feature.Vector(geometry,attributes);var fid=node.getAttribute("id")||node.getAttribute("name");if(fid!=null){feature.fid=fid;}
+return feature;},getStyle:function(styleUrl,options){var styleBaseUrl=OpenLayers.Util.removeTail(styleUrl);var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;newOptions.styleBaseUrl=styleBaseUrl;if(!this.styles[styleUrl]&&!OpenLayers.String.startsWith(styleUrl,"#")&&newOptions.depth<=this.maxDepth&&!this.fetched[styleBaseUrl]){var data=this.fetchLink(styleBaseUrl);if(data){this.parseData(data,newOptions);}}
+var style=OpenLayers.Util.extend({},this.styles[styleUrl]);return style;},parseGeometry:{point:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var coords=[];if(nodeList.length>0){var coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}
+var point=null;if(coords.length>1){if(coords.length==2){coords[2]=null;}
+point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad coordinate string: "+coordString;}
+return point;},linestring:function(node,ring){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var line=null;if(nodeList.length>0){var coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);var numPoints=pointList.length;var points=new Array(numPoints);var coords,numCoords;for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");numCoords=coords.length;if(numCoords>1){if(coords.length==2){coords[2]=null;}
+points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad LineString point coordinates: "+
+pointList[i];}}
+if(numPoints){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}}else{throw"Bad LineString coordinates: "+coordString;}}
+return line;},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"LinearRing");var numRings=nodeList.length;var components=new Array(numRings);if(numRings>0){var ring;for(var i=0,len=nodeList.length;i<len;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components[i]=ring;}else{throw"Bad LinearRing geometry: "+i;}}}
+return new OpenLayers.Geometry.Polygon(components);},multigeometry:function(node){var child,parser;var parts=[];var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){var type=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var parser=this.parseGeometry[type.toLowerCase()];if(parser){parts.push(parser.apply(this,[child]));}}}
+return new OpenLayers.Geometry.Collection(parts);}},parseAttributes:function(node){var attributes={};var edNodes=node.getElementsByTagName("ExtendedData");if(edNodes.length){attributes=this.parseExtendedData(edNodes[0]);}
+var child,grandchildren,grandchild;var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length>=1&&grandchildren.length<=3){var grandchild;switch(grandchildren.length){case 1:grandchild=grandchildren[0];break;case 2:var c1=grandchildren[0];var c2=grandchildren[1];grandchild=(c1.nodeType==3||c1.nodeType==4)?c1:c2;break;case 3:default:grandchild=grandchildren[1];break;}
+if(grandchild.nodeType==3||grandchild.nodeType==4){var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var value=OpenLayers.Util.getXmlNodeValue(grandchild);if(value){value=value.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}}
+return attributes;},parseExtendedData:function(node){var attributes={};var i,len,data,key;var dataNodes=node.getElementsByTagName("Data");for(i=0,len=dataNodes.length;i<len;i++){data=dataNodes[i];key=data.getAttribute("name");var ed={};var valueNode=data.getElementsByTagName("value");if(valueNode.length){ed['value']=this.getChildValue(valueNode[0]);}
+var nameNode=data.getElementsByTagName("displayName");if(nameNode.length){ed['displayName']=this.getChildValue(nameNode[0]);}
+attributes[key]=ed;}
+var simpleDataNodes=node.getElementsByTagName("SimpleData");for(i=0,len=simpleDataNodes.length;i<len;i++){var ed={};data=simpleDataNodes[i];key=data.getAttribute("name");ed['value']=this.getChildValue(data);ed['displayName']=key;attributes[key]=ed;}
+return attributes;},parseProperty:function(xmlNode,namespace,tagName){var value;var nodeList=this.getElementsByTagNameNS(xmlNode,namespace,tagName);try{value=OpenLayers.Util.getXmlNodeValue(nodeList[0]);}catch(e){value=null;}
+return value;},write:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var kml=this.createElementNS(this.kmlns,"kml");var folder=this.createFolderXML();for(var i=0,len=features.length;i<len;++i){folder.appendChild(this.createPlacemarkXML(features[i]));}
+kml.appendChild(folder);return OpenLayers.Format.XML.prototype.write.apply(this,[kml]);},createFolderXML:function(){var folder=this.createElementNS(this.kmlns,"Folder");if(this.foldersName){var folderName=this.createElementNS(this.kmlns,"name");var folderNameText=this.createTextNode(this.foldersName);folderName.appendChild(folderNameText);folder.appendChild(folderName);}
+if(this.foldersDesc){var folderDesc=this.createElementNS(this.kmlns,"description");var folderDescText=this.createTextNode(this.foldersDesc);folderDesc.appendChild(folderDescText);folder.appendChild(folderDesc);}
+return folder;},createPlacemarkXML:function(feature){var placemarkName=this.createElementNS(this.kmlns,"name");var name=feature.style&&feature.style.label?feature.style.label:feature.attributes.name||feature.id;placemarkName.appendChild(this.createTextNode(name));var placemarkDesc=this.createElementNS(this.kmlns,"description");var desc=feature.attributes.description||this.placemarksDesc;placemarkDesc.appendChild(this.createTextNode(desc));var placemarkNode=this.createElementNS(this.kmlns,"Placemark");if(feature.fid!=null){placemarkNode.setAttribute("id",feature.fid);}
+placemarkNode.appendChild(placemarkName);placemarkNode.appendChild(placemarkDesc);var geometryNode=this.buildGeometryNode(feature.geometry);placemarkNode.appendChild(geometryNode);return placemarkNode;},buildGeometryNode:function(geometry){var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];var node=null;if(builder){node=builder.apply(this,[geometry]);}
+return node;},buildGeometry:{point:function(geometry){var kml=this.createElementNS(this.kmlns,"Point");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multipoint:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linestring:function(geometry){var kml=this.createElementNS(this.kmlns,"LineString");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multilinestring:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linearring:function(geometry){var kml=this.createElementNS(this.kmlns,"LinearRing");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},polygon:function(geometry){var kml=this.createElementNS(this.kmlns,"Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0,len=rings.length;i<len;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.kmlns,type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);kml.appendChild(ringMember);}
+return kml;},multipolygon:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},collection:function(geometry){var kml=this.createElementNS(this.kmlns,"MultiGeometry");var child;for(var i=0,len=geometry.components.length;i<len;++i){child=this.buildGeometryNode.apply(this,[geometry.components[i]]);if(child){kml.appendChild(child);}}
+return kml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.kmlns,"coordinates");var path;var points=geometry.components;if(points){var point;var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;++i){point=points[i];parts[i]=this.buildCoordinates(point);}
+path=parts.join(" ");}else{path=this.buildCoordinates(geometry);}
+var txtNode=this.createTextNode(path);coordinatesNode.appendChild(txtNode);return coordinatesNode;},buildCoordinates:function(point){if(this.internalProjection&&this.externalProjection){point=point.clone();point.transform(this.internalProjection,this.externalProjection);}
+return point.x+","+point.y;},CLASS_NAME:"OpenLayers.Format.KML"});OpenLayers.Protocol.WFS.v1=OpenLayers.Class(OpenLayers.Protocol,{version:null,srsName:"EPSG:4326",featureType:null,featureNS:null,geometryName:"the_geom",schema:null,featurePrefix:"feature",formatOptions:null,readFormat:null,readOptions:null,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=OpenLayers.Format.WFST(OpenLayers.Util.extend({version:this.version,featureType:this.featureType,featureNS:this.featureNS,featurePrefix:this.featurePrefix,geometryName:this.geometryName,srsName:this.srsName,schema:this.schema},this.formatOptions));}
+if(!options.geometryName&&parseFloat(this.format.version)>1.0){this.setGeometryName(null);}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();}
+this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[this.format.writeNode("wfs:GetFeature",options)]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),params:options.params,headers:options.headers,data:data});return response;},setFeatureType:function(featureType){this.featureType=featureType;this.format.featureType=featureType;},setGeometryName:function(geometryName){this.geometryName=geometryName;this.format.geometryName=geometryName;},handleRead:function(response,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){var result=this.parseResponse(request,options.readOptions);if(result&&result.success!==false){if(options.readOptions&&options.readOptions.output=="object"){OpenLayers.Util.extend(response,result);}else{response.features=result;}
+response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;response.error=result;}}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,response);}},parseResponse:function(request,options){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+var result=(this.readFormat!==null)?this.readFormat.read(doc):this.format.read(doc,options);if(!this.featureNS){var format=this.readFormat||this.format;this.featureNS=format.featureNS;format.autoConfig=false;if(!this.geometryName){this.setGeometryName(format.geometryName);}}
+return result;},commit:function(features,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:features});response.priv=OpenLayers.Request.POST({url:options.url,headers:options.headers,data:this.format.write(features,options),callback:this.createCallback(this.handleCommit,response,options)});return response;},handleCommit:function(response,options){if(options.callback){var request=response.priv;var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+var obj=this.format.read(data)||{};response.insertIds=obj.insertIds||[];if(obj.success){response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;response.error=obj;}
+options.callback.call(options.scope,response);}},filterDelete:function(filter,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit"});var root=this.format.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});var deleteNode=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(options.featureNS?this.featurePrefix+":":"")+
+options.featureType}});if(options.featureNS){deleteNode.setAttribute("xmlns:"+this.featurePrefix,options.featureNS);}
+var filterNode=this.format.writeNode("ogc:Filter",filter);deleteNode.appendChild(filterNode);root.appendChild(deleteNode);var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[root]);return OpenLayers.Request.POST({url:this.url,callback:options.callback||function(){},data:data});},abort:function(response){if(response){response.priv.abort();}},CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.Protocol.WFS.v1_1_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.1.0",initialize:function(options){OpenLayers.Protocol.WFS.v1.prototype.initialize.apply(this,arguments);if(this.outputFormat&&!this.readFormat){if(this.outputFormat.toLowerCase()=="gml2"){this.readFormat=new OpenLayers.Format.GML.v2({featureType:this.featureType,featureNS:this.featureNS,geometryName:this.geometryName});}else if(this.outputFormat.toLowerCase()=="json"){this.readFormat=new OpenLayers.Format.GeoJSON();}}},CLASS_NAME:"OpenLayers.Protocol.WFS.v1_1_0"});OpenLayers.Format.WMSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.1",profile:null,CLASS_NAME:"OpenLayers.Format.WMSCapabilities"});OpenLayers.Format.WMSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{wms:"http://www.opengis.net/wms",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"wms",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var raw=data;if(data&&data.nodeType==9){data=data.documentElement;}
+var capabilities={};this.readNode(data,capabilities);if(capabilities.service===undefined){var parser=new OpenLayers.Format.OGCExceptionReport();capabilities.error=parser.read(raw);}else{this.postProcessLayers(capabilities);}
+return capabilities;},postProcessLayers:function(capabilities){if(capabilities.capability){capabilities.capability.layers=[];var layers=capabilities.capability.nestedLayers;for(var i=0,len=layers.length;i<len;++i){var layer=layers[i];this.processLayer(capabilities.capability,layer);}}},processLayer:function(capability,layer,parentLayer){if(layer.formats===undefined){layer.formats=capability.request.getmap.formats;}
+var i,len;if(parentLayer){layer.styles=layer.styles.concat(parentLayer.styles);var attributes=["queryable","cascaded","fixedWidth","fixedHeight","opaque","noSubsets","llbbox","minScale","maxScale","attribution"];var complexAttr=["srs","bbox","dimensions","authorityURLs"];var key;for(i=0,len=attributes.length;i<len;i++){key=attributes[i];if(key in parentLayer){if(layer[key]==null){layer[key]=parentLayer[key];}
+if(layer[key]==null){var intAttr=["cascaded","fixedWidth","fixedHeight"];var boolAttr=["queryable","opaque","noSubsets"];if(OpenLayers.Util.indexOf(intAttr,key)!=-1){layer[key]=0;}
+if(OpenLayers.Util.indexOf(boolAttr,key)!=-1){layer[key]=false;}}}}
+for(i=0,len=complexAttr.length;i<len;i++){key=complexAttr[i];layer[key]=OpenLayers.Util.applyDefaults(layer[key],parentLayer[key]);}}
+for(i=0,len=layer.nestedLayers.length;i<len;i++){var childLayer=layer.nestedLayers[i];this.processLayer(capability,childLayer,layer);}
+if(layer.name){capability.layers.push(layer);}},readers:{"wms":{"Service":function(node,obj){obj.service={};this.readChildNodes(node,obj.service);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj["abstract"]=this.getChildValue(node);},"BoundingBox":function(node,obj){var bbox={};bbox.bbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];var res={x:parseFloat(node.getAttribute("resx")),y:parseFloat(node.getAttribute("resy"))};if(!(isNaN(res.x)&&isNaN(res.y))){bbox.res=res;}
+return bbox;},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ContactInformation":function(node,obj){obj.contactInformation={};this.readChildNodes(node,obj.contactInformation);},"ContactPersonPrimary":function(node,obj){obj.personPrimary={};this.readChildNodes(node,obj.personPrimary);},"ContactPerson":function(node,obj){obj.person=this.getChildValue(node);},"ContactOrganization":function(node,obj){obj.organization=this.getChildValue(node);},"ContactPosition":function(node,obj){obj.position=this.getChildValue(node);},"ContactAddress":function(node,obj){obj.contactAddress={};this.readChildNodes(node,obj.contactAddress);},"AddressType":function(node,obj){obj.type=this.getChildValue(node);},"Address":function(node,obj){obj.address=this.getChildValue(node);},"City":function(node,obj){obj.city=this.getChildValue(node);},"StateOrProvince":function(node,obj){obj.stateOrProvince=this.getChildValue(node);},"PostCode":function(node,obj){obj.postcode=this.getChildValue(node);},"Country":function(node,obj){obj.country=this.getChildValue(node);},"ContactVoiceTelephone":function(node,obj){obj.phone=this.getChildValue(node);},"ContactFacsimileTelephone":function(node,obj){obj.fax=this.getChildValue(node);},"ContactElectronicMailAddress":function(node,obj){obj.email=this.getChildValue(node);},"Fees":function(node,obj){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){obj.fees=fees;}},"AccessConstraints":function(node,obj){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){obj.accessConstraints=constraints;}},"Capability":function(node,obj){obj.capability={nestedLayers:[]};this.readChildNodes(node,obj.capability);},"Request":function(node,obj){obj.request={};this.readChildNodes(node,obj.request);},"GetCapabilities":function(node,obj){obj.getcapabilities={formats:[]};this.readChildNodes(node,obj.getcapabilities);},"Format":function(node,obj){if(OpenLayers.Util.isArray(obj.formats)){obj.formats.push(this.getChildValue(node));}else{obj.format=this.getChildValue(node);}},"DCPType":function(node,obj){this.readChildNodes(node,obj);},"HTTP":function(node,obj){this.readChildNodes(node,obj);},"Get":function(node,obj){obj.get={};this.readChildNodes(node,obj.get);if(!obj.href){obj.href=obj.get.href;}},"Post":function(node,obj){obj.post={};this.readChildNodes(node,obj.post);if(!obj.href){obj.href=obj.get.href;}},"GetMap":function(node,obj){obj.getmap={formats:[]};this.readChildNodes(node,obj.getmap);},"GetFeatureInfo":function(node,obj){obj.getfeatureinfo={formats:[]};this.readChildNodes(node,obj.getfeatureinfo);},"Exception":function(node,obj){obj.exception={formats:[]};this.readChildNodes(node,obj.exception);},"Layer":function(node,obj){var attrNode=node.getAttributeNode("queryable");var queryable=(attrNode&&attrNode.specified)?node.getAttribute("queryable"):null;attrNode=node.getAttributeNode("cascaded");var cascaded=(attrNode&&attrNode.specified)?node.getAttribute("cascaded"):null;attrNode=node.getAttributeNode("opaque");var opaque=(attrNode&&attrNode.specified)?node.getAttribute('opaque'):null;var noSubsets=node.getAttribute('noSubsets');var fixedWidth=node.getAttribute('fixedWidth');var fixedHeight=node.getAttribute('fixedHeight');var layer={nestedLayers:[],styles:[],srs:{},metadataURLs:[],bbox:{},dimensions:{},authorityURLs:{},identifiers:{},keywords:[],queryable:(queryable&&queryable!=="")?(queryable==="1"||queryable==="true"):null,cascaded:(cascaded!==null)?parseInt(cascaded):null,opaque:opaque?(opaque==="1"||opaque==="true"):null,noSubsets:(noSubsets!==null)?(noSubsets==="1"||noSubsets==="true"):null,fixedWidth:(fixedWidth!=null)?parseInt(fixedWidth):null,fixedHeight:(fixedHeight!=null)?parseInt(fixedHeight):null};obj.nestedLayers.push(layer);this.readChildNodes(node,layer);if(layer.name){var parts=layer.name.split(":");if(parts.length>0){layer.prefix=parts[0];}}},"Attribution":function(node,obj){obj.attribution={};this.readChildNodes(node,obj.attribution);},"LogoURL":function(node,obj){obj.logo={width:node.getAttribute("width"),height:node.getAttribute("height")};this.readChildNodes(node,obj.logo);},"Style":function(node,obj){var style={};obj.styles.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={width:node.getAttribute("width"),height:node.getAttribute("height")};obj.legend=legend;this.readChildNodes(node,legend);},"MetadataURL":function(node,obj){var metadataURL={type:node.getAttribute("type")};obj.metadataURLs.push(metadataURL);this.readChildNodes(node,metadataURL);},"DataURL":function(node,obj){obj.dataURL={};this.readChildNodes(node,obj.dataURL);},"FeatureListURL":function(node,obj){obj.featureListURL={};this.readChildNodes(node,obj.featureListURL);},"AuthorityURL":function(node,obj){var name=node.getAttribute("name");var authority={};this.readChildNodes(node,authority);obj.authorityURLs[name]=authority.href;},"Identifier":function(node,obj){var authority=node.getAttribute("authority");obj.identifiers[authority]=this.getChildValue(node);},"KeywordList":function(node,obj){this.readChildNodes(node,obj);},"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1"});OpenLayers.Format.WMSCapabilities.v1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMT_MS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Keyword":function(node,obj){if(obj.keywords){obj.keywords.push(this.getChildValue(node));}},"DescribeLayer":function(node,obj){obj.describelayer={formats:[]};this.readChildNodes(node,obj.describelayer);},"GetLegendGraphic":function(node,obj){obj.getlegendgraphic={formats:[]};this.readChildNodes(node,obj.getlegendgraphic);},"GetStyles":function(node,obj){obj.getstyles={formats:[]};this.readChildNodes(node,obj.getstyles);},"PutStyles":function(node,obj){obj.putstyles={formats:[]};this.readChildNodes(node,obj.putstyles);},"UserDefinedSymbolization":function(node,obj){var userSymbols={supportSLD:parseInt(node.getAttribute("SupportSLD"))==1,userLayer:parseInt(node.getAttribute("UserLayer"))==1,userStyle:parseInt(node.getAttribute("UserStyle"))==1,remoteWFS:parseInt(node.getAttribute("RemoteWFS"))==1};obj.userSymbols=userSymbols;},"LatLonBoundingBox":function(node,obj){obj.llbbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("SRS");obj.bbox[bbox.srs]=bbox;},"ScaleHint":function(node,obj){var min=node.getAttribute("min");var max=node.getAttribute("max");var rad2=Math.pow(2,0.5);var ipm=OpenLayers.INCHES_PER_UNIT["m"];obj.maxScale=parseFloat(((min/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));obj.minScale=parseFloat(((max/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol")};obj.dimensions[dim.name]=dim;},"Extent":function(node,obj){var name=node.getAttribute("name").toLowerCase();if(name in obj["dimensions"]){var extent=obj.dimensions[name];extent.nearestVal=node.getAttribute("nearestValue")==="1";extent.multipleVal=node.getAttribute("multipleValues")==="1";extent.current=node.getAttribute("current")==="1";extent["default"]=node.getAttribute("default")||"";var values=this.getChildValue(node);extent.values=values.split(",");}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1"});OpenLayers.Format.WMSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.0",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){var srs=this.getChildValue(node);var values=srs.split(/ +/);for(var i=0,len=values.length;i<len;i++){obj.srs[values[i]]=true;}}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_0"});OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,scope:this});this.layer.events.on({"refresh":this.update,scope:this});if(this.layer.visibility===true&&this.layer.inRange===true){this.update();}else{this.layer.events.on({"visibilitychanged":this.update,scope:this});}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});}
+return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if(mapBounds!==null&&((options&&options.force)||this.invalidBounds(mapBounds))){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead(options);}},getMapBounds:function(){if(this.layer.map===null){return null;}
+var bounds=this.layer.map.getExtent();if(bounds&&!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);}
+return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));}
+return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(options){if(this.response){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");}
+this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:this.createFilter(),callback:this.merge,scope:this},options));},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});}
+return filter;},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}}
+this.layer.addFeatures(features);}
+this.response=null;this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:false,mouseDown:false,stoppedDown:null,lastDown:null,lastUp:null,persist:false,stopDown:false,stopUp:false,layerOptions:null,pixelTolerance:5,touch:false,lastTouchPx:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.prototype.initialize.apply(this,arguments);},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,arguments)){return false;}
+var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);return true;},createFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.layer.addFeatures([this.point],{silent:true});},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){return false;}
+this.cancel();if(this.layer.map!=null){this.destroyFeature(true);this.layer.destroy(false);}
+this.layer=null;this.touch=false;return true;},destroyFeature:function(force){if(this.layer&&(force||!this.persist)){this.layer.destroyFeatures();}
+this.point=null;},destroyPersistedFeature:function(){var layer=this.layer;if(layer&&layer.features.length>1){this.layer.features[0].destroy();}},finalize:function(cancel){var key=cancel?"cancel":"done";this.mouseDown=false;this.lastDown=null;this.lastUp=null;this.lastTouchPx=null;this.callback(key,[this.geometryClone()]);this.destroyFeature(cancel);},cancel:function(){this.finalize(true);},click:function(evt){OpenLayers.Event.stop(evt);return false;},dblclick:function(evt){OpenLayers.Event.stop(evt);return false;},modifyFeature:function(pixel){if(!this.point){this.createFeature(pixel);}
+var lonlat=this.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.point,false]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.point,this.style);},getGeometry:function(){var geometry=this.point&&this.point.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPoint([geometry]);}
+return geometry;},geometryClone:function(){var geom=this.getGeometry();return geom&&geom.clone();},mousedown:function(evt){return this.down(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+this.lastTouchPx=evt.xy;return this.down(evt);},mousemove:function(evt){return this.move(evt);},touchmove:function(evt){this.lastTouchPx=evt.xy;return this.move(evt);},mouseup:function(evt){return this.up(evt);},touchend:function(evt){evt.xy=this.lastTouchPx;return this.up(evt);},down:function(evt){this.mouseDown=true;this.lastDown=evt.xy;if(!this.touch){this.modifyFeature(evt.xy);}
+this.stoppedDown=this.stopDown;return!this.stopDown;},move:function(evt){if(!this.touch&&(!this.mouseDown||this.stoppedDown)){this.modifyFeature(evt.xy);}
+return true;},up:function(evt){this.mouseDown=false;this.stoppedDown=this.stopDown;if(!this.checkModifiers(evt)){return true;}
+if(this.lastUp&&this.lastUp.equals(evt.xy)){return true;}
+if(this.lastDown&&this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance)){if(this.touch){this.modifyFeature(evt.xy);}
+if(this.persist){this.destroyPersistedFeature();}
+this.lastUp=evt.xy;this.finalize();return!this.stopUp;}else{return true;}},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.eventsDiv)){this.stoppedDown=this.stopDown;this.mouseDown=false;}},passesTolerance:function(pixel1,pixel2,tolerance){var passes=true;if(tolerance!=null&&pixel1&&pixel2){var dist=pixel1.distanceTo(pixel2);if(dist>tolerance){passes=false;}}
+return passes;},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,maxVertices:null,doubleTouchTolerance:20,freehand:false,freehandToggle:'shiftKey',timerId:null,redoStack:null,initialize:function(control,callbacks,options){OpenLayers.Handler.Point.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([this.point.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.line,this.point],{silent:true});},destroyFeature:function(force){OpenLayers.Handler.Point.prototype.destroyFeature.call(this,force);this.line=null;},destroyPersistedFeature:function(){var layer=this.layer;if(layer&&layer.features.length>2){this.layer.features[0].destroy();}},removePoint:function(){if(this.point){this.layer.removeFeatures([this.point]);}},addPoint:function(pixel){this.layer.removeFeatures([this.point]);var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line.geometry.addComponent(this.point.geometry,this.line.geometry.components.length);this.layer.addFeatures([this.point]);this.callback("point",[this.point.geometry,this.getGeometry()]);this.callback("modify",[this.point.geometry,this.getSketch()]);this.drawFeature();delete this.redoStack;},insertXY:function(x,y){this.line.geometry.addComponent(new OpenLayers.Geometry.Point(x,y),this.getCurrentPointIndex());this.drawFeature();delete this.redoStack;},insertDeltaXY:function(dx,dy){var previousIndex=this.getCurrentPointIndex()-1;var p0=this.line.geometry.components[previousIndex];if(p0&&!isNaN(p0.x)&&!isNaN(p0.y)){this.insertXY(p0.x+dx,p0.y+dy);}},insertDirectionLength:function(direction,length){direction*=Math.PI/180;var dx=length*Math.cos(direction);var dy=length*Math.sin(direction);this.insertDeltaXY(dx,dy);},insertDeflectionLength:function(deflection,length){var previousIndex=this.getCurrentPointIndex()-1;if(previousIndex>0){var p1=this.line.geometry.components[previousIndex];var p0=this.line.geometry.components[previousIndex-1];var theta=Math.atan2(p1.y-p0.y,p1.x-p0.x);this.insertDirectionLength((theta*180/Math.PI)+deflection,length);}},getCurrentPointIndex:function(){return this.line.geometry.components.length-1;},undo:function(){var geometry=this.line.geometry;var components=geometry.components;var index=this.getCurrentPointIndex()-1;var target=components[index];var undone=geometry.removeComponent(target);if(undone){if(!this.redoStack){this.redoStack=[];}
+this.redoStack.push(target);this.drawFeature();}
+return undone;},redo:function(){var target=this.redoStack&&this.redoStack.pop();if(target){this.line.geometry.addComponent(target,this.getCurrentPointIndex());this.drawFeature();}
+return!!target;},freehandMode:function(evt){return(this.freehandToggle&&evt[this.freehandToggle])?!this.freehand:this.freehand;},modifyFeature:function(pixel,drawing){if(!this.line){this.createFeature(pixel);}
+var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.getSketch(),drawing]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.line,this.style);this.layer.drawFeature(this.point,this.style);},getSketch:function(){return this.line;},getGeometry:function(){var geometry=this.line&&this.line.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiLineString([geometry]);}
+return geometry;},touchstart:function(evt){if(this.timerId&&this.passesTolerance(this.lastTouchPx,evt.xy,this.doubleTouchTolerance)){this.finishGeometry();window.clearTimeout(this.timerId);this.timerId=null;return false;}else{if(this.timerId){window.clearTimeout(this.timerId);this.timerId=null;}
+this.timerId=window.setTimeout(OpenLayers.Function.bind(function(){this.timerId=null;},this),300);return OpenLayers.Handler.Point.prototype.touchstart.call(this,evt);}},down:function(evt){var stopDown=this.stopDown;if(this.freehandMode(evt)){stopDown=true;}
+if(!this.touch&&(!this.lastDown||!this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance))){this.modifyFeature(evt.xy,!!this.lastUp);}
+this.mouseDown=true;this.lastDown=evt.xy;this.stoppedDown=stopDown;return!stopDown;},move:function(evt){if(this.stoppedDown&&this.freehandMode(evt)){if(this.persist){this.destroyPersistedFeature();}
+this.addPoint(evt.xy);return false;}
+if(!this.touch&&(!this.mouseDown||this.stoppedDown)){this.modifyFeature(evt.xy,!!this.lastUp);}
+return true;},up:function(evt){if(this.mouseDown&&(!this.lastUp||!this.lastUp.equals(evt.xy))){if(this.stoppedDown&&this.freehandMode(evt)){if(this.persist){this.destroyPersistedFeature();}
+this.removePoint();this.finalize();}else{if(this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance)){if(this.touch){this.modifyFeature(evt.xy);}
+if(this.lastUp==null&&this.persist){this.destroyPersistedFeature();}
+this.addPoint(evt.xy);this.lastUp=evt.xy;if(this.line.geometry.components.length===this.maxVertices+1){this.finishGeometry();}}}}
+this.stoppedDown=this.stopDown;this.mouseDown=false;return!this.stopUp;},finishGeometry:function(){var index=this.line.geometry.components.length-1;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();},dblclick:function(evt){if(!this.freehandMode(evt)){this.finishGeometry();}
+return false;},CLASS_NAME:"OpenLayers.Handler.Path"});OpenLayers.Layer.GML=OpenLayers.Class(OpenLayers.Layer.Vector,{loaded:false,format:null,formatOptions:null,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);this.url=url;},setVisibility:function(visibility,noEvent){OpenLayers.Layer.Vector.prototype.setVisibility.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},loadGML:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.url,success:this.requestSuccess,failure:this.requestFailure,scope:this});this.loaded=true;}},setUrl:function(url){this.url=url;this.destroyFeatures();this.loaded=false;this.loadGML();},requestSuccess:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
+var gml=this.format?new this.format(options):new OpenLayers.Format.GML(options);this.addFeatures(gml.read(doc));this.events.triggerEvent("loadend");},requestFailure:function(request){OpenLayers.Console.userError(OpenLayers.i18n("errorLoadingGML",{'url':this.url}));this.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Layer.GML"});OpenLayers.Control.PanPanel=OpenLayers.Class(OpenLayers.Control.Panel,{slideFactor:50,slideRatio:null,initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);var options={slideFactor:this.slideFactor,slideRatio:this.slideRatio};this.addControls([new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH,options),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH,options),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST,options),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST,options)]);},CLASS_NAME:"OpenLayers.Control.PanPanel"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",destroy:function(){this.map.events.un({"removelayer":this.updateAttribution,"addlayer":this.updateAttribution,"changelayer":this.updateAttribution,"changebaselayer":this.updateAttribution,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.map.events.on({'changebaselayer':this.updateAttribution,'changelayer':this.updateAttribution,'addlayer':this.updateAttribution,'removelayer':this.updateAttribution,scope:this});this.updateAttribution();return this.div;},updateAttribution:function(){var attributions=[];if(this.map&&this.map.layers){for(var i=0,len=this.map.layers.length;i<len;i++){var layer=this.map.layers[i];if(layer.attribution&&layer.getVisibility()){if(OpenLayers.Util.indexOf(attributions,layer.attribution)===-1){attributions.push(layer.attribution);}}}
+this.div.innerHTML=attributions.join(this.separator);}},CLASS_NAME:"OpenLayers.Control.Attribution"});OpenLayers.Renderer.SVG2=OpenLayers.Class(OpenLayers.Renderer.NG,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",symbolMetrics:null,labelNodeType:"g",initialize:function(containerID){if(!this.supported()){return;}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.symbolMetrics={};},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},updateDimensions:function(zoomChanged){OpenLayers.Renderer.NG.prototype.updateDimensions.apply(this,arguments);var res=this.getResolution();var width=this.extent.getWidth();var height=this.extent.getHeight();var extentString=[this.extent.left,-this.extent.top,width,height].join(" ");this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.rendererRoot.setAttributeNS(null,"width",width/res);this.rendererRoot.setAttributeNS(null,"height",height/res);if(zoomChanged===true){var i,len;var nodes=this.vectorRoot.childNodes;for(i=0,len=nodes.length;i<len;++i){this.setStyle(nodes[i]);}
+var textNodes=this.textRoot.childNodes;var label;for(i=0,len=textNodes.length;i<len;++i){label=textNodes[i];this.drawText(label,label._style,new OpenLayers.Geometry.Point(label._x,label._y));}}},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType="svg";}else{nodeType="circle";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="path";break;default:break;}
+return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var resolution=this.getResolution();var r=node._radius;var widthFactor=resolution;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){if(style.graphicTitle){node.setAttributeNS(null,"title",style.graphicTitle);var label=this.nodeFactory(null,"title");label.textContent=style.graphicTitle;node.appendChild(label);}
+if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;width*=resolution;height*=resolution;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset*resolution:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset*resolution:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",node._x+xOffset);node.setAttributeNS(null,"y",node._y+yOffset);node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);node.onclick=OpenLayers.Renderer.SVG2.preventDefault;}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3*resolution;var size=offset*2;var src=this.importSymbol(style.graphicName);widthFactor=this.symbolMetrics[src.id].size*3/size*resolution;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
+node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",node._x-offset);node.setAttributeNS(null,"y",node._y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius*resolution);}
+var rotation=style.rotation;if(rotation!==undefined||node._rotation!==undefined){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform",["rotate(",rotation,node._x,node._y,")"].join(" "));}else{var metrics=this.symbolMetrics[src.id];node.firstChild.setAttributeNS(null,"transform",["rotate(",rotation,metrics.x,metrics.y,")"].join(" "));}}}
+if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
+if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");}
+if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);}
+if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);}
+return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[widthFactor,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,widthFactor,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,widthFactor,4*w].join();default:var parts=OpenLayers.String.trim(str).split(/\s+/g);for(var i=0,ii=parts.length;i<ii;i++){parts[i]=parts[i]*widthFactor;}
+return parts.join();}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);}
+return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_svgRoot","svg");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var x=geometry.x;var y=-geometry.y;node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node._x=x;node._y=y;node._radius=radius;return node;},drawLineString:function(node,geometry){var path=this.getComponentsString(geometry.components);node.setAttributeNS(null,"points",path);return node;},drawLinearRing:function(node,geometry){var path=this.getComponentsString(geometry.components);node.setAttributeNS(null,"points",path);return node;},drawPolygon:function(node,geometry){var d=[];var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;j<len;j++){d.push("M");path=this.getComponentsString(geometry.components[j].components," ");d.push(path);}
+d.push("z");node.setAttributeNS(null,"d",d.join(" "));node.setAttributeNS(null,"fill-rule","evenodd");return node;},drawRectangle:function(node,geometry){node.setAttributeNS(null,"x",geometry.x);node.setAttributeNS(null,"y",-geometry.y);node.setAttributeNS(null,"width",geometry.width);node.setAttributeNS(null,"height",geometry.height);return node;},drawSurface:function(node,geometry){var d=[];var draw=true;for(var i=0,len=geometry.components.length;i<len;i++){if((i%3)==0&&(i/3)==0){var component=this.getShortString(geometry.components[i]);d.push("M",component);}else if((i%3)==1){var component=this.getShortString(geometry.components[i]);d.push("C",component);}else{var component=this.getShortString(geometry.components[i]);d.push(component);}}
+d.push("Z");node.setAttributeNS(null,"d",d.join(" "));return node;},drawText:function(featureId,style,location){var g=OpenLayers.Renderer.NG.prototype.drawText.apply(this,arguments);var text=g.firstChild||this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_text","text");var res=this.getResolution();text.setAttributeNS(null,"x",location.x/res);text.setAttributeNS(null,"y",-location.y/res);g.setAttributeNS(null,"transform","scale("+res+")");if(style.fontColor){text.setAttributeNS(null,"fill",style.fontColor);}
+if(style.fontOpacity){text.setAttributeNS(null,"opacity",style.fontOpacity);}
+if(style.fontFamily){text.setAttributeNS(null,"font-family",style.fontFamily);}
+if(style.fontSize){text.setAttributeNS(null,"font-size",style.fontSize);}
+if(style.fontWeight){text.setAttributeNS(null,"font-weight",style.fontWeight);}
+if(style.fontStyle){text.setAttributeNS(null,"font-style",style.fontStyle);}
+if(style.labelSelect===true){text.setAttributeNS(null,"pointer-events","visible");text._featureId=featureId;}else{text.setAttributeNS(null,"pointer-events","none");}
+var align=style.labelAlign||"cm";text.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]]||"middle");if(OpenLayers.IS_GECKO===true){text.setAttributeNS(null,"dominant-baseline",OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]]||"central");}
+var labelRows=style.label.split('\n');var numRows=labelRows.length;while(text.childNodes.length>numRows){text.removeChild(text.lastChild);}
+for(var i=0;i<numRows;i++){var tspan=text.childNodes[i]||this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_tspan_"+i,"tspan");if(style.labelSelect===true){tspan._featureId=featureId;}
+if(OpenLayers.IS_GECKO===false){tspan.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG2.LABEL_VSHIFT[align[1]]||"-35%");}
+tspan.setAttribute("x",location.x/res);if(i==0){var vfactor=OpenLayers.Renderer.SVG2.LABEL_VFACTOR[align[1]];if(vfactor==null){vfactor=-.5;}
+tspan.setAttribute("dy",(vfactor*(numRows-1))+"em");}else{tspan.setAttribute("dy","1em");}
+tspan.textContent=(labelRows[i]==='')?' ':labelRows[i];if(!tspan.parentNode){text.appendChild(tspan);}}
+if(!text.parentNode){g.appendChild(text);}
+return g;},getComponentsString:function(components,separator){var len=components.length;var strings=new Array(len);for(var i=0;i<len;i++){strings[i]=this.getShortString(components[i]);}
+return strings.join(separator||",");},getShortString:function(point){return point.x+","+(-point.y);},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();}
+var id=this.container.id+"-"+graphicName;var existing=document.getElementById(id);if(existing!=null){return existing;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0,len=symbol.length;i<len;i=i+2){x=symbol[i];y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);points.push(x,",",y);}
+node.setAttributeNS(null,"points",points.join(" "));var width=symbolExtent.getWidth();var height=symbolExtent.getHeight();var viewBox=[symbolExtent.left-width,symbolExtent.bottom-height,width*3,height*3];symbolNode.setAttributeNS(null,"viewBox",viewBox.join(" "));this.symbolMetrics[id]={size:Math.max(width,height),x:symbolExtent.getCenterLonLat().lon,y:symbolExtent.getCenterLonLat().lat};this.defs.appendChild(symbolNode);return symbolNode;},getFeatureIdFromEvent:function(evt){var featureId=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,arguments);if(!featureId){var target=evt.target;featureId=target.parentNode&&target!=this.rendererRoot&&target.parentNode._featureId;}
+return featureId;},CLASS_NAME:"OpenLayers.Renderer.SVG2"});OpenLayers.Renderer.SVG2.LABEL_ALIGN={"l":"start","r":"end","b":"bottom","t":"hanging"};OpenLayers.Renderer.SVG2.LABEL_VSHIFT={"t":"-70%","b":"0"};OpenLayers.Renderer.SVG2.LABEL_VFACTOR={"t":0,"b":-1};OpenLayers.Renderer.SVG2.preventDefault=function(e){e.preventDefault&&e.preventDefault();};OpenLayers.Kinetic=OpenLayers.Class({threshold:0,interval:10,deceleration:0.0035,nbPoints:100,delay:200,points:undefined,timerId:undefined,initialize:function(options){OpenLayers.Util.extend(this,options);},begin:function(){clearInterval(this.timerId);this.timerId=undefined;this.points=[];},update:function(xy){this.points.unshift({xy:xy,tick:new Date().getTime()});if(this.points.length>this.nbPoints){this.points.pop();}},end:function(xy){var last,now=new Date().getTime();for(var i=0,l=this.points.length,point;i<l;i++){point=this.points[i];if(now-point.tick>this.delay){break;}
+last=point;}
+if(!last){return;}
+var time=new Date().getTime()-last.tick;var dist=Math.sqrt(Math.pow(xy.x-last.xy.x,2)+
+Math.pow(xy.y-last.xy.y,2));var speed=dist/time;if(speed==0||speed<this.threshold){return;}
+var theta=Math.asin((xy.y-last.xy.y)/dist);if(last.xy.x<=xy.x){theta=Math.PI-theta;}
+return{speed:speed,theta:theta};},move:function(info,callback){var v0=info.speed;var fx=Math.cos(info.theta);var fy=-Math.sin(info.theta);var time=0;var initialTime=new Date().getTime();var lastX=0;var lastY=0;var timerCallback=function(){if(this.timerId==null){return;}
+time+=this.interval;var realTime=new Date().getTime()-initialTime;var t=(time+realTime)/2.0;var p=(-this.deceleration*Math.pow(t,2))/2.0+v0*t;var x=p*fx;var y=p*fy;var args={};args.end=false;var v=-this.deceleration*t+v0;if(v<=0){clearInterval(this.timerId);this.timerId=null;args.end=true;}
+args.x=x-lastX;args.y=y-lastY;lastX=x;lastY=y;callback(args.x,args.y,args.end);};this.timerId=window.setInterval(OpenLayers.Function.bind(timerCallback,this),this.interval);},CLASS_NAME:"OpenLayers.Kinetic"});OpenLayers.ProxyHost="";OpenLayers.nullHandler=function(request){OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest",{'statusText':request.statusText}));};OpenLayers.loadURL=function(uri,params,caller,onComplete,onFailure){if(typeof params=='string'){params=OpenLayers.Util.getParameters(params);}
+var success=(onComplete)?onComplete:OpenLayers.nullHandler;var failure=(onFailure)?onFailure:OpenLayers.nullHandler;return OpenLayers.Request.GET({url:uri,params:params,success:success,failure:failure,scope:caller});};OpenLayers.parseXMLString=function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
+var ajaxResponse=OpenLayers.Util.Try(function(){var xmldom=new ActiveXObject('Microsoft.XMLDOM');xmldom.loadXML(text);return xmldom;},function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
+req.send(null);return req.responseXML;});return ajaxResponse;};OpenLayers.Ajax={emptyFunction:function(){},getTransport:function(){return OpenLayers.Util.Try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject('Msxml2.XMLHTTP');},function(){return new ActiveXObject('Microsoft.XMLHTTP');})||false;},activeRequestCount:0};OpenLayers.Ajax.Responders={responders:[],register:function(responderToAdd){for(var i=0;i<this.responders.length;i++){if(responderToAdd==this.responders[i]){return;}}
+this.responders.push(responderToAdd);},unregister:function(responderToRemove){OpenLayers.Util.removeItem(this.reponders,responderToRemove);},dispatch:function(callback,request,transport){var responder;for(var i=0;i<this.responders.length;i++){responder=this.responders[i];if(responder[callback]&&typeof responder[callback]=='function'){try{responder[callback].apply(responder,[request,transport]);}catch(e){}}}}};OpenLayers.Ajax.Responders.register({onCreate:function(){OpenLayers.Ajax.activeRequestCount++;},onComplete:function(){OpenLayers.Ajax.activeRequestCount--;}});OpenLayers.Ajax.Base=OpenLayers.Class({initialize:function(options){this.options={method:'post',asynchronous:true,contentType:'application/xml',parameters:''};OpenLayers.Util.extend(this.options,options||{});this.options.method=this.options.method.toLowerCase();if(typeof this.options.parameters=='string'){this.options.parameters=OpenLayers.Util.getParameters(this.options.parameters);}}});OpenLayers.Ajax.Request=OpenLayers.Class(OpenLayers.Ajax.Base,{_complete:false,initialize:function(url,options){OpenLayers.Ajax.Base.prototype.initialize.apply(this,[options]);if(OpenLayers.ProxyHost&&OpenLayers.String.startsWith(url,"http")){url=OpenLayers.ProxyHost+encodeURIComponent(url);}
+this.transport=OpenLayers.Ajax.getTransport();this.request(url);},request:function(url){this.url=url;this.method=this.options.method;var params=OpenLayers.Util.extend({},this.options.parameters);if(this.method!='get'&&this.method!='post'){params['_method']=this.method;this.method='post';}
+this.parameters=params;if(params=OpenLayers.Util.getParameterString(params)){if(this.method=='get'){this.url+=((this.url.indexOf('?')>-1)?'&':'?')+params;}else if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){params+='&_=';}}
+try{var response=new OpenLayers.Ajax.Response(this);if(this.options.onCreate){this.options.onCreate(response);}
+OpenLayers.Ajax.Responders.dispatch('onCreate',this,response);this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);if(this.options.asynchronous){window.setTimeout(OpenLayers.Function.bind(this.respondToReadyState,this,1),10);}
+this.transport.onreadystatechange=OpenLayers.Function.bind(this.onStateChange,this);this.setRequestHeaders();this.body=this.method=='post'?(this.options.postBody||params):null;this.transport.send(this.body);if(!this.options.asynchronous&&this.transport.overrideMimeType){this.onStateChange();}}catch(e){this.dispatchException(e);}},onStateChange:function(){var readyState=this.transport.readyState;if(readyState>1&&!((readyState==4)&&this._complete)){this.respondToReadyState(this.transport.readyState);}},setRequestHeaders:function(){var headers={'X-Requested-With':'XMLHttpRequest','Accept':'text/javascript, text/html, application/xml, text/xml, */*','OpenLayers':true};if(this.method=='post'){headers['Content-type']=this.options.contentType+
+(this.options.encoding?'; charset='+this.options.encoding:'');if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005){headers['Connection']='close';}}
+if(typeof this.options.requestHeaders=='object'){var extras=this.options.requestHeaders;if(typeof extras.push=='function'){for(var i=0,length=extras.length;i<length;i+=2){headers[extras[i]]=extras[i+1];}}else{for(var i in extras){headers[i]=extras[i];}}}
+for(var name in headers){this.transport.setRequestHeader(name,headers[name]);}},success:function(){var status=this.getStatus();return!status||(status>=200&&status<300);},getStatus:function(){try{return this.transport.status||0;}catch(e){return 0;}},respondToReadyState:function(readyState){var state=OpenLayers.Ajax.Request.Events[readyState];var response=new OpenLayers.Ajax.Response(this);if(state=='Complete'){try{this._complete=true;(this.options['on'+response.status]||this.options['on'+(this.success()?'Success':'Failure')]||OpenLayers.Ajax.emptyFunction)(response);}catch(e){this.dispatchException(e);}
+var contentType=response.getHeader('Content-type');}
+try{(this.options['on'+state]||OpenLayers.Ajax.emptyFunction)(response);OpenLayers.Ajax.Responders.dispatch('on'+state,this,response);}catch(e){this.dispatchException(e);}
+if(state=='Complete'){this.transport.onreadystatechange=OpenLayers.Ajax.emptyFunction;}},getHeader:function(name){try{return this.transport.getResponseHeader(name);}catch(e){return null;}},dispatchException:function(exception){var handler=this.options.onException;if(handler){handler(this,exception);OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{var listener=false;var responders=OpenLayers.Ajax.Responders.responders;for(var i=0;i<responders.length;i++){if(responders[i].onException){listener=true;break;}}
+if(listener){OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{throw exception;}}}});OpenLayers.Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];OpenLayers.Ajax.Response=OpenLayers.Class({status:0,statusText:'',initialize:function(request){this.request=request;var transport=this.transport=request.transport,readyState=this.readyState=transport.readyState;if((readyState>2&&!(!!(window.attachEvent&&!window.opera)))||readyState==4){this.status=this.getStatus();this.statusText=this.getStatusText();this.responseText=transport.responseText==null?'':String(transport.responseText);}
+if(readyState==4){var xml=transport.responseXML;this.responseXML=xml===undefined?null:xml;}},getStatus:OpenLayers.Ajax.Request.prototype.getStatus,getStatusText:function(){try{return this.transport.statusText||'';}catch(e){return'';}},getHeader:OpenLayers.Ajax.Request.prototype.getHeader,getResponseHeader:function(name){return this.transport.getResponseHeader(name);}});OpenLayers.Ajax.getElementsByTagNameNS=function(parentnode,nsuri,nsprefix,tagname){var elem=null;if(parentnode.getElementsByTagNameNS){elem=parentnode.getElementsByTagNameNS(nsuri,tagname);}else{elem=parentnode.getElementsByTagName(nsprefix+':'+tagname);}
+return elem;};OpenLayers.Ajax.serializeXMLToString=function(xmldom){var serializer=new XMLSerializer();var data=serializer.serializeToString(xmldom);return data;};OpenLayers.Layer.GeoRSS=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,icon:null,popupSize:null,useFeedTitle:true,initialize:function(name,location,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,[name,options]);this.location=location;this.features=[];},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadRSS:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,scope:this});this.loaded=true;}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadRSS();}},parseData:function(ajaxRequest){var doc=ajaxRequest.responseXML;if(!doc||!doc.documentElement){doc=OpenLayers.Format.XML.prototype.read(ajaxRequest.responseText);}
+if(this.useFeedTitle){var name=null;try{name=doc.getElementsByTagNameNS('*','title')[0].firstChild.nodeValue;}
+catch(e){name=doc.getElementsByTagName('title')[0].firstChild.nodeValue;}
+if(name){this.setName(name);}}
+var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
+var format=new OpenLayers.Format.GeoRSS(options);var features=format.read(doc);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];if(!feature.geometry){continue;}
+var title=feature.attributes.title?feature.attributes.title:"Untitled";var description=feature.attributes.description?feature.attributes.description:"No description.";var link=feature.attributes.link?feature.attributes.link:"";var location=feature.geometry.getBounds().getCenterLonLat();data.icon=this.icon==null?OpenLayers.Marker.defaultIcon():this.icon.clone();data.popupSize=this.popupSize?this.popupSize.clone():new OpenLayers.Size(250,120);if(title||description){data.title=title;data.description=description;var contentHTML='<div class="olLayerGeoRSSClose">[x]</div>';contentHTML+='<div class="olLayerGeoRSSTitle">';if(link){contentHTML+='<a class="link" href="'+link+'" target="_blank">';}
+contentHTML+=title;if(link){contentHTML+='</a>';}
+contentHTML+='</div>';contentHTML+='<div style="" class="olLayerGeoRSSDescription">';contentHTML+=description;contentHTML+='</div>';data['popupContentHTML']=contentHTML;}
+var feature=new OpenLayers.Feature(this,location,data);this.features.push(feature);var marker=feature.createMarker();marker.events.register('click',feature,this.markerClick);this.addMarker(marker);}
+this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}
+if(!sameMarkerClicked){var popup=this.createPopup();OpenLayers.Event.observe(popup.div,"click",OpenLayers.Function.bind(function(){for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}},this));this.layer.map.addPopup(popup);}
+OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.GeoRSS"});OpenLayers.Popup=OpenLayers.Class({events:null,id:"",lonlat:null,div:null,contentSize:null,size:null,contentHTML:null,backgroundColor:"",opacity:"",border:"",contentDiv:null,groupDiv:null,closeDiv:null,autoSize:false,minSize:null,maxSize:null,displayClass:"olPopup",contentDisplayClass:"olPopupContent",padding:0,disableFirefoxOverflowHack:false,fixPadding:function(){if(typeof this.padding=="number"){this.padding=new OpenLayers.Bounds(this.padding,this.padding,this.padding,this.padding);}},panMapIfOutOfView:false,keepInMap:false,closeOnMove:false,map:null,initialize:function(id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback){if(id==null){id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}
+this.id=id;this.lonlat=lonlat;this.contentSize=(contentSize!=null)?contentSize:new OpenLayers.Size(OpenLayers.Popup.WIDTH,OpenLayers.Popup.HEIGHT);if(contentHTML!=null){this.contentHTML=contentHTML;}
+this.backgroundColor=OpenLayers.Popup.COLOR;this.opacity=OpenLayers.Popup.OPACITY;this.border=OpenLayers.Popup.BORDER;this.div=OpenLayers.Util.createDiv(this.id,null,null,null,null,null,"hidden");this.div.className=this.displayClass;var groupDivId=this.id+"_GroupDiv";this.groupDiv=OpenLayers.Util.createDiv(groupDivId,null,null,null,"relative",null,"hidden");var id=this.div.id+"_contentDiv";this.contentDiv=OpenLayers.Util.createDiv(id,null,this.contentSize.clone(),null,"relative");this.contentDiv.className=this.contentDisplayClass;this.groupDiv.appendChild(this.contentDiv);this.div.appendChild(this.groupDiv);if(closeBox){this.addCloseBox(closeBoxCallback);}
+this.registerEvents();},destroy:function(){this.id=null;this.lonlat=null;this.size=null;this.contentHTML=null;this.backgroundColor=null;this.opacity=null;this.border=null;if(this.closeOnMove&&this.map){this.map.events.unregister("movestart",this,this.hide);}
+this.events.destroy();this.events=null;if(this.closeDiv){OpenLayers.Event.stopObservingElement(this.closeDiv);this.groupDiv.removeChild(this.closeDiv);}
+this.closeDiv=null;this.div.removeChild(this.groupDiv);this.groupDiv=null;if(this.map!=null){this.map.removePopup(this);}
+this.map=null;this.div=null;this.autoSize=null;this.minSize=null;this.maxSize=null;this.padding=null;this.panMapIfOutOfView=null;},draw:function(px){if(px==null){if((this.lonlat!=null)&&(this.map!=null)){px=this.map.getLayerPxFromLonLat(this.lonlat);}}
+if(this.closeOnMove){this.map.events.register("movestart",this,this.hide);}
+if(!this.disableFirefoxOverflowHack&&OpenLayers.BROWSER_NAME=='firefox'){this.map.events.register("movestart",this,function(){var style=document.defaultView.getComputedStyle(this.contentDiv,null);var currentOverflow=style.getPropertyValue("overflow");if(currentOverflow!="hidden"){this.contentDiv._oldOverflow=currentOverflow;this.contentDiv.style.overflow="hidden";}});this.map.events.register("moveend",this,function(){var oldOverflow=this.contentDiv._oldOverflow;if(oldOverflow){this.contentDiv.style.overflow=oldOverflow;this.contentDiv._oldOverflow=null;}});}
+this.moveTo(px);if(!this.autoSize&&!this.size){this.setSize(this.contentSize);}
+this.setBackgroundColor();this.setOpacity();this.setBorder();this.setContentHTML();if(this.panMapIfOutOfView){this.panIntoView();}
+return this.div;},updatePosition:function(){if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);if(px){this.moveTo(px);}}},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},visible:function(){return OpenLayers.Element.visible(this.div);},toggle:function(){if(this.visible()){this.hide();}else{this.show();}},show:function(){this.div.style.display='';if(this.panMapIfOutOfView){this.panIntoView();}},hide:function(){this.div.style.display='none';},setSize:function(contentSize){this.size=contentSize.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
+this.size.w+=wPadding;this.size.h+=hPadding;if(OpenLayers.BROWSER_NAME=="msie"){this.contentSize.w+=contentDivPadding.left+contentDivPadding.right;this.contentSize.h+=contentDivPadding.bottom+contentDivPadding.top;}
+if(this.div!=null){this.div.style.width=this.size.w+"px";this.div.style.height=this.size.h+"px";}
+if(this.contentDiv!=null){this.contentDiv.style.width=contentSize.w+"px";this.contentDiv.style.height=contentSize.h+"px";}},updateSize:function(){var preparedHTML="<div class='"+this.contentDisplayClass+"'>"+
+this.contentDiv.innerHTML+"</div>";var containerElement=(this.map)?this.map.layerContainerDiv:document.body;var realSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,null,{displayClass:this.displayClass,containerElement:containerElement});var safeSize=this.getSafeContentSize(realSize);var newSize=null;if(safeSize.equals(realSize)){newSize=realSize;}else{var fixedSize=new OpenLayers.Size();fixedSize.w=(safeSize.w<realSize.w)?safeSize.w:null;fixedSize.h=(safeSize.h<realSize.h)?safeSize.h:null;if(fixedSize.w&&fixedSize.h){newSize=safeSize;}else{var clippedSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,fixedSize,{displayClass:this.contentDisplayClass,containerElement:containerElement});var currentOverflow=OpenLayers.Element.getStyle(this.contentDiv,"overflow");if((currentOverflow!="hidden")&&(clippedSize.equals(safeSize))){var scrollBar=OpenLayers.Util.getScrollbarWidth();if(fixedSize.w){clippedSize.h+=scrollBar;}else{clippedSize.w+=scrollBar;}}
+newSize=this.getSafeContentSize(clippedSize);}}
+this.setSize(newSize);},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;}
+if(this.div!=null){this.div.style.backgroundColor=this.backgroundColor;}},setOpacity:function(opacity){if(opacity!=undefined){this.opacity=opacity;}
+if(this.div!=null){this.div.style.opacity=this.opacity;this.div.style.filter='alpha(opacity='+this.opacity*100+')';}},setBorder:function(border){if(border!=undefined){this.border=border;}
+if(this.div!=null){this.div.style.border=this.border;}},setContentHTML:function(contentHTML){if(contentHTML!=null){this.contentHTML=contentHTML;}
+if((this.contentDiv!=null)&&(this.contentHTML!=null)&&(this.contentHTML!=this.contentDiv.innerHTML)){this.contentDiv.innerHTML=this.contentHTML;if(this.autoSize){this.registerImageListeners();this.updateSize();}}},registerImageListeners:function(){var onImgLoad=function(){this.popup.updateSize();if(this.popup.visible()&&this.popup.panMapIfOutOfView){this.popup.panIntoView();}
+OpenLayers.Event.stopObserving(this.img,"load",this.img._onImageLoad);};var images=this.contentDiv.getElementsByTagName("img");for(var i=0,len=images.length;i<len;i++){var img=images[i];if(img.width==0||img.height==0){var context={'popup':this,'img':img};img._onImgLoad=OpenLayers.Function.bind(onImgLoad,context);OpenLayers.Event.observe(img,'load',img._onImgLoad);}}},getSafeContentSize:function(size){var safeContentSize=size.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
+if(this.minSize){safeContentSize.w=Math.max(safeContentSize.w,(this.minSize.w-wPadding));safeContentSize.h=Math.max(safeContentSize.h,(this.minSize.h-hPadding));}
+if(this.maxSize){safeContentSize.w=Math.min(safeContentSize.w,(this.maxSize.w-wPadding));safeContentSize.h=Math.min(safeContentSize.h,(this.maxSize.h-hPadding));}
+if(this.map&&this.map.size){var extraX=0,extraY=0;if(this.keepInMap&&!this.panMapIfOutOfView){var px=this.map.getPixelFromLonLat(this.lonlat);switch(this.relativePosition){case"tr":extraX=px.x;extraY=this.map.size.h-px.y;break;case"tl":extraX=this.map.size.w-px.x;extraY=this.map.size.h-px.y;break;case"bl":extraX=this.map.size.w-px.x;extraY=px.y;break;case"br":extraX=px.x;extraY=px.y;break;default:extraX=px.x;extraY=this.map.size.h-px.y;break;}}
+var maxY=this.map.size.h-
+this.map.paddingForPopups.top-
+this.map.paddingForPopups.bottom-
+hPadding-extraY;var maxX=this.map.size.w-
+this.map.paddingForPopups.left-
+this.map.paddingForPopups.right-
+wPadding-extraX;safeContentSize.w=Math.min(safeContentSize.w,maxX);safeContentSize.h=Math.min(safeContentSize.h,maxY);}
+return safeContentSize;},getContentDivPadding:function(){var contentDivPadding=this._contentDivPadding;if(!contentDivPadding){if(this.div.parentNode==null){this.div.style.display="none";document.body.appendChild(this.div);}
+contentDivPadding=new OpenLayers.Bounds(OpenLayers.Element.getStyle(this.contentDiv,"padding-left"),OpenLayers.Element.getStyle(this.contentDiv,"padding-bottom"),OpenLayers.Element.getStyle(this.contentDiv,"padding-right"),OpenLayers.Element.getStyle(this.contentDiv,"padding-top"));this._contentDivPadding=contentDivPadding;if(this.div.parentNode==document.body){document.body.removeChild(this.div);this.div.style.display="";}}
+return contentDivPadding;},addCloseBox:function(callback){this.closeDiv=OpenLayers.Util.createDiv(this.id+"_close",null,new OpenLayers.Size(17,17));this.closeDiv.className="olPopupCloseBox";var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+"px";this.closeDiv.style.top=contentDivPadding.top+"px";this.groupDiv.appendChild(this.closeDiv);var closePopup=callback||function(e){this.hide();OpenLayers.Event.stop(e);};OpenLayers.Event.observe(this.closeDiv,"touchend",OpenLayers.Function.bindAsEventListener(closePopup,this));OpenLayers.Event.observe(this.closeDiv,"click",OpenLayers.Function.bindAsEventListener(closePopup,this));},panIntoView:function(){var mapSize=this.map.getSize();var origTL=this.map.getViewPortPxFromLayerPx(new OpenLayers.Pixel(parseInt(this.div.style.left),parseInt(this.div.style.top)));var newTL=origTL.clone();if(origTL.x<this.map.paddingForPopups.left){newTL.x=this.map.paddingForPopups.left;}else
+if((origTL.x+this.size.w)>(mapSize.w-this.map.paddingForPopups.right)){newTL.x=mapSize.w-this.map.paddingForPopups.right-this.size.w;}
+if(origTL.y<this.map.paddingForPopups.top){newTL.y=this.map.paddingForPopups.top;}else
+if((origTL.y+this.size.h)>(mapSize.h-this.map.paddingForPopups.bottom)){newTL.y=mapSize.h-this.map.paddingForPopups.bottom-this.size.h;}
+var dx=origTL.x-newTL.x;var dy=origTL.y-newTL.y;this.map.pan(dx,dy);},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,true);function onTouchstart(evt){OpenLayers.Event.stop(evt,true);}
+this.events.on({"mousedown":this.onmousedown,"mousemove":this.onmousemove,"mouseup":this.onmouseup,"click":this.onclick,"mouseout":this.onmouseout,"dblclick":this.ondblclick,"touchstart":onTouchstart,scope:this});},onmousedown:function(evt){this.mousedown=true;OpenLayers.Event.stop(evt,true);},onmousemove:function(evt){if(this.mousedown){OpenLayers.Event.stop(evt,true);}},onmouseup:function(evt){if(this.mousedown){this.mousedown=false;OpenLayers.Event.stop(evt,true);}},onclick:function(evt){OpenLayers.Event.stop(evt,true);},onmouseout:function(evt){this.mousedown=false;},ondblclick:function(evt){OpenLayers.Event.stop(evt,true);},CLASS_NAME:"OpenLayers.Popup"});OpenLayers.Popup.WIDTH=200;OpenLayers.Popup.HEIGHT=200;OpenLayers.Popup.COLOR="white";OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:true,anchor:null,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){var newArguments=[id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback];OpenLayers.Popup.prototype.initialize.apply(this,newArguments);this.anchor=(anchor!=null)?anchor:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)};},destroy:function(){this.anchor=null;this.relativePosition=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments);},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments);},moveTo:function(px){var oldRelativePosition=this.relativePosition;this.relativePosition=this.calculateRelativePosition(px);var newPx=this.calculateNewPx(px);var newArguments=new Array(newPx);OpenLayers.Popup.prototype.moveTo.apply(this,newArguments);if(this.relativePosition!=oldRelativePosition){this.updateRelativePosition();}},setSize:function(contentSize){OpenLayers.Popup.prototype.setSize.apply(this,arguments);if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);this.moveTo(px);}},calculateRelativePosition:function(px){var lonlat=this.map.getLonLatFromLayerPx(px);var extent=this.map.getExtent();var quadrant=extent.determineQuadrant(lonlat);return OpenLayers.Bounds.oppositeQuadrant(quadrant);},updateRelativePosition:function(){},calculateNewPx:function(px){var newPx=px.offset(this.anchor.offset);var size=this.size||this.contentSize;var top=(this.relativePosition.charAt(0)=='t');newPx.y+=(top)?-size.h:this.anchor.size.h;var left=(this.relativePosition.charAt(1)=='l');newPx.x+=(left)?-size.w:this.anchor.size.w;return newPx;},CLASS_NAME:"OpenLayers.Popup.Anchored"});OpenLayers.Popup.Framed=OpenLayers.Class(OpenLayers.Popup.Anchored,{imageSrc:null,imageSize:null,isAlphaImage:false,positionBlocks:null,blocks:null,fixedRelativePosition:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);if(this.fixedRelativePosition){this.updateRelativePosition();this.calculateRelativePosition=function(px){return this.relativePosition;};}
+this.contentDiv.style.position="absolute";this.contentDiv.style.zIndex=1;if(closeBox){this.closeDiv.style.zIndex=1;}
+this.groupDiv.style.position="absolute";this.groupDiv.style.top="0px";this.groupDiv.style.left="0px";this.groupDiv.style.height="100%";this.groupDiv.style.width="100%";},destroy:function(){this.imageSrc=null;this.imageSize=null;this.isAlphaImage=null;this.fixedRelativePosition=false;this.positionBlocks=null;for(var i=0;i<this.blocks.length;i++){var block=this.blocks[i];if(block.image){block.div.removeChild(block.image);}
+block.image=null;if(block.div){this.groupDiv.removeChild(block.div);}
+block.div=null;}
+this.blocks=null;OpenLayers.Popup.Anchored.prototype.destroy.apply(this,arguments);},setBackgroundColor:function(color){},setBorder:function(){},setOpacity:function(opacity){},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.updateBlocks();},updateRelativePosition:function(){this.padding=this.positionBlocks[this.relativePosition].padding;if(this.closeDiv){var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+
+this.padding.right+"px";this.closeDiv.style.top=contentDivPadding.top+
+this.padding.top+"px";}
+this.updateBlocks();},calculateNewPx:function(px){var newPx=OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(this,arguments);newPx=newPx.offset(this.positionBlocks[this.relativePosition].offset);return newPx;},createBlocks:function(){this.blocks=[];var firstPosition=null;for(var key in this.positionBlocks){firstPosition=key;break;}
+var position=this.positionBlocks[firstPosition];for(var i=0;i<position.blocks.length;i++){var block={};this.blocks.push(block);var divId=this.id+'_FrameDecorationDiv_'+i;block.div=OpenLayers.Util.createDiv(divId,null,null,null,"absolute",null,"hidden",null);var imgId=this.id+'_FrameDecorationImg_'+i;var imageCreator=(this.isAlphaImage)?OpenLayers.Util.createAlphaImageDiv:OpenLayers.Util.createImage;block.image=imageCreator(imgId,null,this.imageSize,this.imageSrc,"absolute",null,null,null);block.div.appendChild(block.image);this.groupDiv.appendChild(block.div);}},updateBlocks:function(){if(!this.blocks){this.createBlocks();}
+if(this.size&&this.relativePosition){var position=this.positionBlocks[this.relativePosition];for(var i=0;i<position.blocks.length;i++){var positionBlock=position.blocks[i];var block=this.blocks[i];var l=positionBlock.anchor.left;var b=positionBlock.anchor.bottom;var r=positionBlock.anchor.right;var t=positionBlock.anchor.top;var w=(isNaN(positionBlock.size.w))?this.size.w-(r+l):positionBlock.size.w;var h=(isNaN(positionBlock.size.h))?this.size.h-(b+t):positionBlock.size.h;block.div.style.width=(w<0?0:w)+'px';block.div.style.height=(h<0?0:h)+'px';block.div.style.left=(l!=null)?l+'px':'';block.div.style.bottom=(b!=null)?b+'px':'';block.div.style.right=(r!=null)?r+'px':'';block.div.style.top=(t!=null)?t+'px':'';block.image.style.left=positionBlock.position.x+'px';block.image.style.top=positionBlock.position.y+'px';}
+this.contentDiv.style.left=this.padding.left+"px";this.contentDiv.style.top=this.padding.top+"px";}},CLASS_NAME:"OpenLayers.Popup.Framed"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxOffsets:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask});},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv('zoomBox',new OpenLayers.Pixel(-9999,-9999));this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.eventsDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.eventsDiv,"olDrawBox");},moveBox:function(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);var offset=this.getBoxOffsets();this.zoomBox.style.width=(deltaX+offset.width+1)+"px";this.zoomBox.style.height=(deltaY+offset.height+1)+"px";this.zoomBox.style.left=(xy.x<startX?startX-deltaX-offset.left:startX-offset.left)+"px";this.zoomBox.style.top=(xy.y<startY?startY-deltaY-offset.top:startY-offset.top)+"px";},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
+this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.eventsDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxOffsets=null;OpenLayers.Element.removeClass(this.map.eventsDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){if(this.dragHandler.deactivate()){if(this.zoomBox){this.removeBox();}}
+return true;}else{return false;}},getBoxOffsets:function(){if(!this.boxOffsets){var testDiv=document.createElement("div");testDiv.style.position="absolute";testDiv.style.border="1px solid black";testDiv.style.width="3px";document.body.appendChild(testDiv);var w3cBoxModel=testDiv.clientWidth==3;document.body.removeChild(testDiv);var left=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"));var right=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"));var top=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"));var bottom=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"));this.boxOffsets={left:left,right:right,top:top,bottom:bottom,width:w3cBoxModel===false?left+right:0,height:w3cBoxModel===false?top+bottom:0};}
+return this.boxOffsets;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,alwaysZoom:false,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);}
+var lastZoom=this.map.getZoom();this.map.zoomToExtent(bounds);if(lastZoom==this.map.getZoom()&&this.alwaysZoom==true){this.map.zoomTo(lastZoom+(this.out?-1:1));}}else{if(!this.out){this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()+1);}else{this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()-1);}}},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:false,interval:1,documentDrag:false,kinetic:null,enableKinetic:false,kineticInterval:10,draw:function(){if(this.enableKinetic){var config={interval:this.kineticInterval};if(typeof this.enableKinetic==="object"){config=OpenLayers.Util.extend(config,this.enableKinetic);}
+this.kinetic=new OpenLayers.Kinetic(config);}
+this.handler=new OpenLayers.Handler.Drag(this,{"move":this.panMap,"done":this.panMapDone,"down":this.panMapStart},{interval:this.interval,documentDrag:this.documentDrag});},panMapStart:function(){if(this.kinetic){this.kinetic.begin();}},panMap:function(xy){if(this.kinetic){this.kinetic.update(xy);}
+this.panned=true;this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:true,animate:false});},panMapDone:function(xy){if(this.panned){var res=null;if(this.kinetic){res=this.kinetic.end(xy);}
+this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:!!res,animate:false});if(res){var self=this;this.kinetic.move(res,function(x,y,end){self.map.pan(x,y,{dragging:!end,animate:false});});}
+this.panned=false;}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:true,'double':false,pixelTolerance:0,dblclickTolerance:13,stopSingle:false,stopDouble:false,timerId:null,touch:false,down:null,last:null,first:null,rightclickTimerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},touchstart:function(evt){if(!this.touch){this.unregisterMouseListeners();this.touch=true;}
+this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},touchmove:function(evt){this.last=this.getEventInfo(evt);return true;},touchend:function(evt){if(this.down){evt.xy=this.last.xy;evt.lastTouches=this.last.touches;this.handleSingle(evt);this.down=null;}
+return true;},unregisterMouseListeners:function(){this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,click:this.click,dblclick:this.dblclick,scope:this});},mousedown:function(evt){this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},mouseup:function(evt){var propagate=true;if(this.checkModifiers(evt)&&this.control.handleRightClicks&&OpenLayers.Event.isRightClick(evt)){propagate=this.rightclick(evt);}
+return propagate;},rightclick:function(evt){if(this.passesTolerance(evt)){if(this.rightclickTimerId!=null){this.clearTimer();this.callback('dblrightclick',[evt]);return!this.stopDouble;}else{var clickEvent=this['double']?OpenLayers.Util.extend({},evt):this.callback('rightclick',[evt]);var delayedRightCall=OpenLayers.Function.bind(this.delayedRightCall,this,clickEvent);this.rightclickTimerId=window.setTimeout(delayedRightCall,this.delay);}}
+return!this.stopSingle;},delayedRightCall:function(evt){this.rightclickTimerId=null;if(evt){this.callback('rightclick',[evt]);}},click:function(evt){if(!this.last){this.last=this.getEventInfo(evt);}
+this.handleSingle(evt);return!this.stopSingle;},dblclick:function(evt){this.handleDouble(evt);return!this.stopDouble;},handleDouble:function(evt){if(this["double"]&&this.passesDblclickTolerance(evt)){this.callback("dblclick",[evt]);}},handleSingle:function(evt){if(this.passesTolerance(evt)){if(this.timerId!=null){if(this.last.touches&&this.last.touches.length===1){if(this["double"]){OpenLayers.Event.stop(evt);}
+this.handleDouble(evt);}
+if(!this.last.touches||this.last.touches.length!==2){this.clearTimer();}}else{this.first=this.getEventInfo(evt);var clickEvent=this.single?OpenLayers.Util.extend({},evt):null;this.queuePotentialClick(clickEvent);}}},queuePotentialClick:function(evt){this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);},passesTolerance:function(evt){var passes=true;if(this.pixelTolerance!=null&&this.down&&this.down.xy){passes=this.pixelTolerance>=this.down.xy.distanceTo(evt.xy);if(passes&&this.touch&&this.down.touches.length===this.last.touches.length){for(var i=0,ii=this.down.touches.length;i<ii;++i){if(this.getTouchDistance(this.down.touches[i],this.last.touches[i])>this.pixelTolerance){passes=false;break;}}}}
+return passes;},getTouchDistance:function(from,to){return Math.sqrt(Math.pow(from.clientX-to.clientX,2)+
+Math.pow(from.clientY-to.clientY,2));},passesDblclickTolerance:function(evt){var passes=true;if(this.down&&this.first){passes=this.down.xy.distanceTo(this.first.xy)<=this.dblclickTolerance;}
+return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}
+if(this.rightclickTimerId!=null){window.clearTimeout(this.rightclickTimerId);this.rightclickTimerId=null;}},delayedCall:function(evt){this.timerId=null;if(evt){this.callback("click",[evt]);}},getEventInfo:function(evt){var touches;if(evt.touches){var len=evt.touches.length;touches=new Array(len);var touch;for(var i=0;i<len;i++){touch=evt.touches[i];touches[i]={clientX:touch.clientX,clientY:touch.clientY};}}
+return{xy:evt.xy,touches:touches};},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();this.down=null;this.first=null;this.last=null;this.touch=false;deactivated=true;}
+return deactivated;},CLASS_NAME:"OpenLayers.Handler.Click"});OpenLayers.Control.Navigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,pinchZoom:null,pinchZoomOptions:null,documentDrag:false,zoomBox:null,zoomBoxEnabled:true,zoomWheelEnabled:true,mouseWheelOptions:null,handleRightClicks:false,zoomBoxKeyMask:OpenLayers.Handler.MOD_SHIFT,autoActivate:true,initialize:function(options){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();if(this.dragPan){this.dragPan.destroy();}
+this.dragPan=null;if(this.zoomBox){this.zoomBox.destroy();}
+this.zoomBox=null;if(this.pinchZoom){this.pinchZoom.destroy();}
+this.pinchZoom=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){this.dragPan.activate();if(this.zoomWheelEnabled){this.handlers.wheel.activate();}
+this.handlers.click.activate();if(this.zoomBoxEnabled){this.zoomBox.activate();}
+if(this.pinchZoom){this.pinchZoom.activate();}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.pinchZoom){this.pinchZoom.deactivate();}
+this.zoomBox.deactivate();this.dragPan.deactivate();this.handlers.click.deactivate();this.handlers.wheel.deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},draw:function(){if(this.handleRightClicks){this.map.viewPortDiv.oncontextmenu=OpenLayers.Function.False;}
+var clickCallbacks={'click':this.defaultClick,'dblclick':this.defaultDblClick,'dblrightclick':this.defaultDblRightClick};var clickOptions={'double':true,'stopDouble':true};this.handlers.click=new OpenLayers.Handler.Click(this,clickCallbacks,clickOptions);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,documentDrag:this.documentDrag},this.dragPanOptions));this.zoomBox=new OpenLayers.Control.ZoomBox({map:this.map,keyMask:this.zoomBoxKeyMask});this.dragPan.draw();this.zoomBox.draw();this.handlers.wheel=new OpenLayers.Handler.MouseWheel(this,{"up":this.wheelUp,"down":this.wheelDown},this.mouseWheelOptions);if(OpenLayers.Control.PinchZoom){this.pinchZoom=new OpenLayers.Control.PinchZoom(OpenLayers.Util.extend({map:this.map},this.pinchZoomOptions));}},defaultClick:function(evt){if(evt.lastTouches&&evt.lastTouches.length==2){this.map.zoomOut();}},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);},defaultDblRightClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom-1);},wheelChange:function(evt,deltaZ){var currentZoom=this.map.getZoom();var newZoom=this.map.getZoom()+Math.round(deltaZ);newZoom=Math.max(newZoom,0);newZoom=Math.min(newZoom,this.map.getNumZoomLevels());if(newZoom===currentZoom){return;}
+var size=this.map.getSize();var deltaX=size.w/2-evt.xy.x;var deltaY=evt.xy.y-size.h/2;var newRes=this.map.baseLayer.getResolutionForZoom(newZoom);var zoomPoint=this.map.getLonLatFromPixel(evt.xy);var newCenter=new OpenLayers.LonLat(zoomPoint.lon+deltaX*newRes,zoomPoint.lat+deltaY*newRes);this.map.setCenter(newCenter,newZoom);},wheelUp:function(evt,delta){this.wheelChange(evt,delta||1);},wheelDown:function(evt,delta){this.wheelChange(evt,delta||-1);},disableZoomBox:function(){this.zoomBoxEnabled=false;this.zoomBox.deactivate();},enableZoomBox:function(){this.zoomBoxEnabled=true;if(this.active){this.zoomBox.activate();}},disableZoomWheel:function(){this.zoomWheelEnabled=false;this.handlers.wheel.deactivate();},enableZoomWheel:function(){this.zoomWheelEnabled=true;if(this.active){this.handlers.wheel.activate();}},CLASS_NAME:"OpenLayers.Control.Navigation"});OpenLayers.Layer.KaMap=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,units:null,resolution:OpenLayers.DOTS_PER_INCH,DEFAULT_PARAMS:{i:'jpeg',map:''},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);return this.getFullRequestString({t:pY,l:pX,s:scale});},calculateGridLayout:function(bounds,origin,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=tilecol*tilelon;var offsetlat=bounds.top;var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-(tilerowremain+1)*this.tileSize.h;var tileoffsetlat=tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.KaMap(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();}
+obj.grid=[];return obj;},getTileBounds:function(viewPortPx){var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=tileMapWidth*Math.floor(mapPoint.lon/tileMapWidth);var tileBottom=tileMapHeight*Math.floor(mapPoint.lat/tileMapHeight);return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.KaMap"});OpenLayers.Format.Context=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{layerOptions:null,layerParams:null,read:function(data,options){var context=OpenLayers.Format.XML.VersionedOGC.prototype.read.apply(this,arguments);var map;if(options&&options.map){this.context=context;if(options.map instanceof OpenLayers.Map){map=this.mergeContextToMap(context,options.map);}else{var mapOptions=options.map;if(OpenLayers.Util.isElement(mapOptions)||typeof mapOptions=="string"){mapOptions={div:mapOptions};}
+map=this.contextToMap(context,mapOptions);}}else{map=context;}
+return map;},getLayerFromContext:function(layerContext){var i,len;var options={queryable:layerContext.queryable,visibility:layerContext.visibility,maxExtent:layerContext.maxExtent,metadata:OpenLayers.Util.applyDefaults(layerContext.metadata,{styles:layerContext.styles,formats:layerContext.formats,"abstract":layerContext["abstract"],dataURL:layerContext.dataURL}),numZoomLevels:layerContext.numZoomLevels,units:layerContext.units,isBaseLayer:layerContext.isBaseLayer,opacity:layerContext.opacity,displayInLayerSwitcher:layerContext.displayInLayerSwitcher,singleTile:layerContext.singleTile,tileSize:(layerContext.tileSize)?new OpenLayers.Size(layerContext.tileSize.width,layerContext.tileSize.height):undefined,minScale:layerContext.minScale||layerContext.maxScaleDenominator,maxScale:layerContext.maxScale||layerContext.minScaleDenominator,srs:layerContext.srs,dimensions:layerContext.dimensions,metadataURL:layerContext.metadataURL};if(this.layerOptions){OpenLayers.Util.applyDefaults(options,this.layerOptions);}
+var params={layers:layerContext.name,transparent:layerContext.transparent,version:layerContext.version};if(layerContext.formats&&layerContext.formats.length>0){params.format=layerContext.formats[0].value;for(i=0,len=layerContext.formats.length;i<len;i++){var format=layerContext.formats[i];if(format.current==true){params.format=format.value;break;}}}
+if(layerContext.styles&&layerContext.styles.length>0){for(i=0,len=layerContext.styles.length;i<len;i++){var style=layerContext.styles[i];if(style.current==true){if(style.href){params.sld=style.href;}else if(style.body){params.sld_body=style.body;}else{params.styles=style.name;}
+break;}}}
+if(this.layerParams){OpenLayers.Util.applyDefaults(params,this.layerParams);}
+var layer=null;var service=layerContext.service;if(service==OpenLayers.Format.Context.serviceTypes.WFS){options.strategies=[new OpenLayers.Strategy.BBOX()];options.protocol=new OpenLayers.Protocol.WFS({url:layerContext.url,featurePrefix:layerContext.name.split(":")[0],featureType:layerContext.name.split(":").pop()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.KML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.KML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.GML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.GML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(layerContext.features){layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);layer.addFeatures(layerContext.features);}else if(layerContext.categoryLayer!==true){layer=new OpenLayers.Layer.WMS(layerContext.title||layerContext.name,layerContext.url,params,options);}
+return layer;},getLayersFromContext:function(layersContext){var layers=[];for(var i=0,len=layersContext.length;i<len;i++){var layer=this.getLayerFromContext(layersContext[i]);if(layer!==null){layers.push(layer);}}
+return layers;},contextToMap:function(context,options){options=OpenLayers.Util.applyDefaults({maxExtent:context.maxExtent,projection:context.projection,units:context.units},options);if(options.maxExtent){options.maxResolution=options.maxExtent.getWidth()/OpenLayers.Map.TILE_WIDTH;}
+var metadata={contactInformation:context.contactInformation,"abstract":context["abstract"],keywords:context.keywords,logo:context.logo,descriptionURL:context.descriptionURL}
+options.metadata=metadata;var map=new OpenLayers.Map(options);map.addLayers(this.getLayersFromContext(context.layersContext));map.setCenter(context.bounds.getCenterLonLat(),map.getZoomForExtent(context.bounds,true));return map;},mergeContextToMap:function(context,map){map.addLayers(this.getLayersFromContext(context.layersContext));return map;},write:function(obj,options){obj=this.toContext(obj);return OpenLayers.Format.XML.VersionedOGC.prototype.write.apply(this,arguments);},CLASS_NAME:"OpenLayers.Format.Context"});OpenLayers.Format.Context.serviceTypes={"WMS":"urn:ogc:serviceType:WMS","WFS":"urn:ogc:serviceType:WFS","WCS":"urn:ogc:serviceType:WCS","GML":"urn:ogc:serviceType:GML","SLD":"urn:ogc:serviceType:SLD","FES":"urn:ogc:serviceType:FES","KML":"urn:ogc:serviceType:KML"};OpenLayers.Format.WMC=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"1.1.0",layerToContext:function(layer){var parser=this.getParser();var layerContext={queryable:layer.queryable,visibility:layer.visibility,name:layer.params["LAYERS"],title:layer.name,"abstract":layer.metadata["abstract"],dataURL:layer.metadata.dataURL,metadataURL:layer.metadataURL,server:{version:layer.params["VERSION"],url:layer.url},maxExtent:layer.maxExtent,transparent:layer.params["TRANSPARENT"],numZoomLevels:layer.numZoomLevels,units:layer.units,isBaseLayer:layer.isBaseLayer,opacity:layer.opacity,displayInLayerSwitcher:layer.displayInLayerSwitcher,singleTile:layer.singleTile,tileSize:(layer.singleTile||!layer.tileSize)?undefined:{width:layer.tileSize.w,height:layer.tileSize.h},minScale:(layer.options.resolutions||layer.options.scales||layer.options.maxResolution||layer.options.minScale)?layer.minScale:undefined,maxScale:(layer.options.resolutions||layer.options.scales||layer.options.minResolution||layer.options.maxScale)?layer.maxScale:undefined,formats:[],styles:[],srs:layer.srs,dimensions:layer.dimensions};if(layer.metadata.servertitle){layerContext.server.title=layer.metadata.servertitle;}
+if(layer.metadata.formats&&layer.metadata.formats.length>0){for(var i=0,len=layer.metadata.formats.length;i<len;i++){var format=layer.metadata.formats[i];var mformat=null;if(format.value==undefined){mformat=format;}else{mformat=format.value;}
+layerContext.formats.push({value:mformat,current:(mformat==layer.params["FORMAT"])});}}else{layerContext.formats.push({value:layer.params["FORMAT"],current:true});}
+if(layer.metadata.styles&&layer.metadata.styles.length>0){for(var i=0,len=layer.metadata.styles.length;i<len;i++){var style=layer.metadata.styles[i];if((style.href==layer.params["SLD"])||(style.body==layer.params["SLD_BODY"])||(style.name==layer.params["STYLES"])){style.current=true;}else{style.current=false;}
+layerContext.styles.push(style);}}else{layerContext.styles.push({href:layer.params["SLD"],body:layer.params["SLD_BODY"],name:layer.params["STYLES"]||parser.defaultStyleName,title:parser.defaultStyleTitle,current:true});}
+return layerContext;},toContext:function(obj){var context={};var layers=obj.layers;if(obj.CLASS_NAME=="OpenLayers.Map"){var metadata=obj.metadata||{};context.size=obj.getSize();context.bounds=obj.getExtent();context.projection=obj.projection;context.title=obj.title;context.keywords=metadata.keywords;context["abstract"]=metadata["abstract"];context.logo=metadata.logo;context.descriptionURL=metadata.descriptionURL;context.contactInformation=metadata.contactInformation;context.maxExtent=obj.maxExtent;}else{OpenLayers.Util.applyDefaults(context,obj);if(context.layers!=undefined){delete(context.layers);}}
+if(context.layersContext==undefined){context.layersContext=[];}
+if(layers!=undefined&&OpenLayers.Util.isArray(layers)){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer instanceof OpenLayers.Layer.WMS){context.layersContext.push(this.layerToContext(layer));}}}
+return context;},CLASS_NAME:"OpenLayers.Format.WMC"});OpenLayers.Format.WMC.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ol:"http://openlayers.org/context",wmc:"http://www.opengis.net/context",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"",getNamespacePrefix:function(uri){var prefix=null;if(uri==null){prefix=this.namespaces[this.defaultPrefix];}else{for(prefix in this.namespaces){if(this.namespaces[prefix]==uri){break;}}}
+return prefix;},defaultPrefix:"wmc",rootPrefix:null,defaultStyleName:"",defaultStyleTitle:"Default",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+var root=data.documentElement;this.rootPrefix=root.prefix;var context={version:root.getAttribute("version")};this.runChildNodes(context,root);return context;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor,prefix,local;for(var i=0,len=children.length;i<len;++i){childNode=children[i];if(childNode.nodeType==1){prefix=this.getNamespacePrefix(childNode.namespaceURI);local=childNode.nodeName.split(":").pop();processor=this["read_"+prefix+"_"+local];if(processor){processor.apply(this,[obj,childNode]);}}}},read_wmc_General:function(context,node){this.runChildNodes(context,node);},read_wmc_BoundingBox:function(context,node){context.projection=node.getAttribute("SRS");context.bounds=new OpenLayers.Bounds(parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy")));},read_wmc_LayerList:function(context,node){context.layersContext=[];this.runChildNodes(context,node);},read_wmc_Layer:function(context,node){var layerContext={visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),formats:[],styles:[],metadata:{}};this.runChildNodes(layerContext,node);context.layersContext.push(layerContext);},read_wmc_Extension:function(obj,node){this.runChildNodes(obj,node);},read_ol_units:function(layerContext,node){layerContext.units=this.getChildValue(node);},read_ol_maxExtent:function(obj,node){var bounds=new OpenLayers.Bounds(node.getAttribute("minx"),node.getAttribute("miny"),node.getAttribute("maxx"),node.getAttribute("maxy"));obj.maxExtent=bounds;},read_ol_transparent:function(layerContext,node){layerContext.transparent=this.getChildValue(node);},read_ol_numZoomLevels:function(layerContext,node){layerContext.numZoomLevels=parseInt(this.getChildValue(node));},read_ol_opacity:function(layerContext,node){layerContext.opacity=parseFloat(this.getChildValue(node));},read_ol_singleTile:function(layerContext,node){layerContext.singleTile=(this.getChildValue(node)=="true");},read_ol_tileSize:function(layerContext,node){var obj={"width":node.getAttribute("width"),"height":node.getAttribute("height")};layerContext.tileSize=obj;},read_ol_isBaseLayer:function(layerContext,node){layerContext.isBaseLayer=(this.getChildValue(node)=="true");},read_ol_displayInLayerSwitcher:function(layerContext,node){layerContext.displayInLayerSwitcher=(this.getChildValue(node)=="true");},read_wmc_Server:function(layerContext,node){layerContext.version=node.getAttribute("version");layerContext.url=this.getOnlineResource_href(node);layerContext.metadata.servertitle=node.getAttribute("title");},read_wmc_FormatList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Format:function(layerContext,node){var format={value:this.getChildValue(node)};if(node.getAttribute("current")=="1"){format.current=true;}
+layerContext.formats.push(format);},read_wmc_StyleList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Style:function(layerContext,node){var style={};this.runChildNodes(style,node);if(node.getAttribute("current")=="1"){style.current=true;}
+layerContext.styles.push(style);},read_wmc_SLD:function(style,node){this.runChildNodes(style,node);},read_sld_StyledLayerDescriptor:function(sld,node){var xml=OpenLayers.Format.XML.prototype.write.apply(this,[node]);sld.body=xml;},read_sld_FeatureTypeStyle:function(sld,node){var xml=OpenLayers.Format.XML.prototype.write.apply(this,[node]);sld.body=xml;},read_wmc_OnlineResource:function(obj,node){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},read_wmc_Name:function(obj,node){var name=this.getChildValue(node);if(name){obj.name=name;}},read_wmc_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_wmc_MetadataURL:function(layerContext,node){layerContext.metadataURL=this.getOnlineResource_href(node);},read_wmc_KeywordList:function(context,node){context.keywords=[];this.runChildNodes(context.keywords,node);},read_wmc_Keyword:function(keywords,node){keywords.push(this.getChildValue(node));},read_wmc_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},read_wmc_LogoURL:function(context,node){context.logo={width:node.getAttribute("width"),height:node.getAttribute("height"),format:node.getAttribute("format"),href:this.getOnlineResource_href(node)};},read_wmc_DescriptionURL:function(context,node){context.descriptionURL=this.getOnlineResource_href(node);},read_wmc_ContactInformation:function(obj,node){var contact={};this.runChildNodes(contact,node);obj.contactInformation=contact;},read_wmc_ContactPersonPrimary:function(contact,node){var personPrimary={};this.runChildNodes(personPrimary,node);contact.personPrimary=personPrimary;},read_wmc_ContactPerson:function(primaryPerson,node){var person=this.getChildValue(node);if(person){primaryPerson.person=person;}},read_wmc_ContactOrganization:function(primaryPerson,node){var organization=this.getChildValue(node);if(organization){primaryPerson.organization=organization;}},read_wmc_ContactPosition:function(contact,node){var position=this.getChildValue(node);if(position){contact.position=position;}},read_wmc_ContactAddress:function(contact,node){var contactAddress={};this.runChildNodes(contactAddress,node);contact.contactAddress=contactAddress;},read_wmc_AddressType:function(contactAddress,node){var type=this.getChildValue(node);if(type){contactAddress.type=type;}},read_wmc_Address:function(contactAddress,node){var address=this.getChildValue(node);if(address){contactAddress.address=address;}},read_wmc_City:function(contactAddress,node){var city=this.getChildValue(node);if(city){contactAddress.city=city;}},read_wmc_StateOrProvince:function(contactAddress,node){var stateOrProvince=this.getChildValue(node);if(stateOrProvince){contactAddress.stateOrProvince=stateOrProvince;}},read_wmc_PostCode:function(contactAddress,node){var postcode=this.getChildValue(node);if(postcode){contactAddress.postcode=postcode;}},read_wmc_Country:function(contactAddress,node){var country=this.getChildValue(node);if(country){contactAddress.country=country;}},read_wmc_ContactVoiceTelephone:function(contact,node){var phone=this.getChildValue(node);if(phone){contact.phone=phone;}},read_wmc_ContactFacsimileTelephone:function(contact,node){var fax=this.getChildValue(node);if(fax){contact.fax=fax;}},read_wmc_ContactElectronicMailAddress:function(contact,node){var email=this.getChildValue(node);if(email){contact.email=email;}},read_wmc_DataURL:function(layerContext,node){layerContext.dataURL=this.getOnlineResource_href(node);},read_wmc_LegendURL:function(style,node){var legend={width:node.getAttribute('width'),height:node.getAttribute('height'),format:node.getAttribute('format'),href:this.getOnlineResource_href(node)};style.legend=legend;},read_wmc_DimensionList:function(layerContext,node){layerContext.dimensions={};this.runChildNodes(layerContext.dimensions,node);},read_wmc_Dimension:function(dimensions,node){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units")||"",unitSymbol:node.getAttribute("unitSymbol")||"",userValue:node.getAttribute("userValue")||"",nearestValue:node.getAttribute("nearestValue")==="1",multipleValues:node.getAttribute("multipleValues")==="1",current:node.getAttribute("current")==="1","default":node.getAttribute("default")||""};var values=this.getChildValue(node);dim.values=values.split(",");dimensions[dim.name]=dim;},write:function(context,options){var root=this.createElementDefaultNS("ViewContext");this.setAttributes(root,{version:this.VERSION,id:(options&&typeof options.id=="string")?options.id:OpenLayers.Util.createUniqueID("OpenLayers_Context_")});this.setAttributeNS(root,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);root.appendChild(this.write_wmc_General(context));root.appendChild(this.write_wmc_LayerList(context));return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},createElementDefaultNS:function(name,childValue,attributes){var node=this.createElementNS(this.namespaces[this.defaultPrefix],name);if(childValue){node.appendChild(this.createTextNode(childValue));}
+if(attributes){this.setAttributes(node,attributes);}
+return node;},setAttributes:function(node,obj){var value;for(var name in obj){value=obj[name].toString();if(value.match(/[A-Z]/)){this.setAttributeNS(node,null,name,value);}else{node.setAttribute(name,value);}}},write_wmc_General:function(context){var node=this.createElementDefaultNS("General");if(context.size){node.appendChild(this.createElementDefaultNS("Window",null,{width:context.size.w,height:context.size.h}));}
+var bounds=context.bounds;node.appendChild(this.createElementDefaultNS("BoundingBox",null,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18),SRS:context.projection}));node.appendChild(this.createElementDefaultNS("Title",context.title));if(context.keywords){node.appendChild(this.write_wmc_KeywordList(context.keywords));}
+if(context["abstract"]){node.appendChild(this.createElementDefaultNS("Abstract",context["abstract"]));}
+if(context.logo){node.appendChild(this.write_wmc_URLType("LogoURL",context.logo.href,context.logo));}
+if(context.descriptionURL){node.appendChild(this.write_wmc_URLType("DescriptionURL",context.descriptionURL));}
+if(context.contactInformation){node.appendChild(this.write_wmc_ContactInformation(context.contactInformation));}
+node.appendChild(this.write_ol_MapExtension(context));return node;},write_wmc_KeywordList:function(keywords){var node=this.createElementDefaultNS("KeywordList");for(var i=0,len=keywords.length;i<len;i++){node.appendChild(this.createElementDefaultNS("Keyword",keywords[i]));}
+return node;},write_wmc_ContactInformation:function(contact){var node=this.createElementDefaultNS("ContactInformation");if(contact.personPrimary){node.appendChild(this.write_wmc_ContactPersonPrimary(contact.personPrimary));}
+if(contact.position){node.appendChild(this.createElementDefaultNS("ContactPosition",contact.position));}
+if(contact.contactAddress){node.appendChild(this.write_wmc_ContactAddress(contact.contactAddress));}
+if(contact.phone){node.appendChild(this.createElementDefaultNS("ContactVoiceTelephone",contact.phone));}
+if(contact.fax){node.appendChild(this.createElementDefaultNS("ContactFacsimileTelephone",contact.fax));}
+if(contact.email){node.appendChild(this.createElementDefaultNS("ContactElectronicMailAddress",contact.email));}
+return node;},write_wmc_ContactPersonPrimary:function(personPrimary){var node=this.createElementDefaultNS("ContactPersonPrimary");if(personPrimary.person){node.appendChild(this.createElementDefaultNS("ContactPerson",personPrimary.person));}
+if(personPrimary.organization){node.appendChild(this.createElementDefaultNS("ContactOrganization",personPrimary.organization));}
+return node;},write_wmc_ContactAddress:function(contactAddress){var node=this.createElementDefaultNS("ContactAddress");if(contactAddress.type){node.appendChild(this.createElementDefaultNS("AddressType",contactAddress.type));}
+if(contactAddress.address){node.appendChild(this.createElementDefaultNS("Address",contactAddress.address));}
+if(contactAddress.city){node.appendChild(this.createElementDefaultNS("City",contactAddress.city));}
+if(contactAddress.stateOrProvince){node.appendChild(this.createElementDefaultNS("StateOrProvince",contactAddress.stateOrProvince));}
+if(contactAddress.postcode){node.appendChild(this.createElementDefaultNS("PostCode",contactAddress.postcode));}
+if(contactAddress.country){node.appendChild(this.createElementDefaultNS("Country",contactAddress.country));}
+return node;},write_ol_MapExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;if(bounds){var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);}
+return node;},write_wmc_LayerList:function(context){var list=this.createElementDefaultNS("LayerList");for(var i=0,len=context.layersContext.length;i<len;++i){list.appendChild(this.write_wmc_Layer(context.layersContext[i]));}
+return list;},write_wmc_Layer:function(context){var node=this.createElementDefaultNS("Layer",null,{queryable:context.queryable?"1":"0",hidden:context.visibility?"0":"1"});node.appendChild(this.write_wmc_Server(context));node.appendChild(this.createElementDefaultNS("Name",context.name));node.appendChild(this.createElementDefaultNS("Title",context.title));if(context["abstract"]){node.appendChild(this.createElementDefaultNS("Abstract",context["abstract"]));}
+if(context.dataURL){node.appendChild(this.write_wmc_URLType("DataURL",context.dataURL));}
+if(context.metadataURL){node.appendChild(this.write_wmc_URLType("MetadataURL",context.metadataURL));}
+return node;},write_wmc_LayerExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);if(context.tileSize&&!context.singleTile){var size=this.createElementNS(this.namespaces.ol,"ol:tileSize");this.setAttributes(size,context.tileSize);node.appendChild(size);}
+var properties=["transparent","numZoomLevels","units","isBaseLayer","opacity","displayInLayerSwitcher","singleTile"];var child;for(var i=0,len=properties.length;i<len;++i){child=this.createOLPropertyNode(context,properties[i]);if(child){node.appendChild(child);}}
+return node;},createOLPropertyNode:function(obj,prop){var node=null;if(obj[prop]!=null){node=this.createElementNS(this.namespaces.ol,"ol:"+prop);node.appendChild(this.createTextNode(obj[prop].toString()));}
+return node;},write_wmc_Server:function(context){var server=context.server;var node=this.createElementDefaultNS("Server");var attributes={service:"OGC:WMS",version:server.version};if(server.title){attributes.title=server.title}
+this.setAttributes(node,attributes);node.appendChild(this.write_wmc_OnlineResource(server.url));return node;},write_wmc_URLType:function(elName,url,attr){var node=this.createElementDefaultNS(elName);node.appendChild(this.write_wmc_OnlineResource(url));if(attr){var optionalAttributes=["width","height","format"];for(var i=0;i<optionalAttributes.length;i++){if(optionalAttributes[i]in attr){node.setAttribute(optionalAttributes[i],attr[optionalAttributes[i]]);}}}
+return node;},write_wmc_DimensionList:function(context){var node=this.createElementDefaultNS("DimensionList");var required_attributes={name:true,units:true,unitSymbol:true,userValue:true};for(var dim in context.dimensions){var attributes={};var dimension=context.dimensions[dim];for(var name in dimension){if(typeof dimension[name]=="boolean"){attributes[name]=Number(dimension[name]);}else{attributes[name]=dimension[name];}}
+var values="";if(attributes.values){values=attributes.values.join(",");delete attributes.values;}
+node.appendChild(this.createElementDefaultNS("Dimension",values,attributes));}
+return node;},write_wmc_FormatList:function(context){var node=this.createElementDefaultNS("FormatList");for(var i=0,len=context.formats.length;i<len;i++){var format=context.formats[i];node.appendChild(this.createElementDefaultNS("Format",format.value,(format.current&&format.current==true)?{current:"1"}:null));}
+return node;},write_wmc_StyleList:function(layer){var node=this.createElementDefaultNS("StyleList");var styles=layer.styles;if(styles&&OpenLayers.Util.isArray(styles)){var sld;for(var i=0,len=styles.length;i<len;i++){var s=styles[i];var style=this.createElementDefaultNS("Style",null,(s.current&&s.current==true)?{current:"1"}:null);if(s.href){sld=this.createElementDefaultNS("SLD");if(s.name){sld.appendChild(this.createElementDefaultNS("Name",s.name));}
+if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));}
+if(s.legend){sld.appendChild(this.write_wmc_URLType("LegendURL",s.legend.href,s.legend));}
+var link=this.write_wmc_OnlineResource(s.href);sld.appendChild(link);style.appendChild(sld);}else if(s.body){sld=this.createElementDefaultNS("SLD");if(s.name){sld.appendChild(this.createElementDefaultNS("Name",s.name));}
+if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));}
+if(s.legend){sld.appendChild(this.write_wmc_URLType("LegendURL",s.legend.href,s.legend));}
+var doc=OpenLayers.Format.XML.prototype.read.apply(this,[s.body]);var imported=doc.documentElement;if(sld.ownerDocument&&sld.ownerDocument.importNode){imported=sld.ownerDocument.importNode(imported,true);}
+sld.appendChild(imported);style.appendChild(sld);}else{style.appendChild(this.createElementDefaultNS("Name",s.name));style.appendChild(this.createElementDefaultNS("Title",s.title));if(s['abstract']){style.appendChild(this.createElementDefaultNS("Abstract",s['abstract']));}
+if(s.legend){style.appendChild(this.write_wmc_URLType("LegendURL",s.legend.href,s.legend));}}
+node.appendChild(style);}}
+return node;},write_wmc_OnlineResource:function(href){var node=this.createElementDefaultNS("OnlineResource");this.setAttributeNS(node,this.namespaces.xlink,"xlink:type","simple");this.setAttributeNS(node,this.namespaces.xlink,"xlink:href",href);return node;},getOnlineResource_href:function(node){var object={};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(object,links[0]);}
+return object.href;},CLASS_NAME:"OpenLayers.Format.WMC.v1"});OpenLayers.Format.WMC.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd",initialize:function(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},read_sld_MinScaleDenominator:function(layerContext,node){var minScaleDenominator=parseFloat(this.getChildValue(node));if(minScaleDenominator>0){layerContext.maxScale=minScaleDenominator;}},read_sld_MaxScaleDenominator:function(layerContext,node){layerContext.minScale=parseFloat(this.getChildValue(node));},read_wmc_SRS:function(layerContext,node){if(!("srs"in layerContext)){layerContext.srs={};}
+layerContext.srs[this.getChildValue(node)]=true;},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);if(context.maxScale){var minSD=this.createElementNS(this.namespaces.sld,"sld:MinScaleDenominator");minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));node.appendChild(minSD);}
+if(context.minScale){var maxSD=this.createElementNS(this.namespaces.sld,"sld:MaxScaleDenominator");maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));node.appendChild(maxSD);}
+if(context.srs){for(var name in context.srs){node.appendChild(this.createElementDefaultNS("SRS",name));}}
+node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));if(context.dimensions){node.appendChild(this.write_wmc_DimensionList(context));}
+node.appendChild(this.write_wmc_LayerExtension(context));return node;},CLASS_NAME:"OpenLayers.Format.WMC.v1_1_0"});OpenLayers.Format.XLS=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.0",stringifyOutput:true,CLASS_NAME:"OpenLayers.Format.XLS"});OpenLayers.Format.XLS.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xls:"http://www.opengis.net/xls",gml:"http://www.opengis.net/gml",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},xy:true,defaultPrefix:"xls",schemaLocation:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data,options){options=OpenLayers.Util.applyDefaults(options,this.options);var xls={};this.readChildNodes(data,xls);return xls;},readers:{"xls":{"XLS":function(node,xls){xls.version=node.getAttribute("version");this.readChildNodes(node,xls);},"Response":function(node,xls){this.readChildNodes(node,xls);},"GeocodeResponse":function(node,xls){xls.responseLists=[];this.readChildNodes(node,xls);},"GeocodeResponseList":function(node,xls){var responseList={features:[],numberOfGeocodedAddresses:parseInt(node.getAttribute("numberOfGeocodedAddresses"))};xls.responseLists.push(responseList);this.readChildNodes(node,responseList);},"GeocodedAddress":function(node,responseList){var feature=new OpenLayers.Feature.Vector();responseList.features.push(feature);this.readChildNodes(node,feature);feature.geometry=feature.components[0];},"GeocodeMatchCode":function(node,feature){feature.attributes.matchCode={accuracy:parseFloat(node.getAttribute("accuracy")),matchType:node.getAttribute("matchType")};},"Address":function(node,feature){var address={countryCode:node.getAttribute("countryCode"),addressee:node.getAttribute("addressee"),street:[],place:[]};feature.attributes.address=address;this.readChildNodes(node,address);},"freeFormAddress":function(node,address){address.freeFormAddress=this.getChildValue(node);},"StreetAddress":function(node,address){this.readChildNodes(node,address);},"Building":function(node,address){address.building={'number':node.getAttribute("number"),subdivision:node.getAttribute("subdivision"),buildingName:node.getAttribute("buildingName")};},"Street":function(node,address){address.street.push(this.getChildValue(node));},"Place":function(node,address){address.place[node.getAttribute("type")]=this.getChildValue(node);},"PostalCode":function(node,address){address.postalCode=this.getChildValue(node);}},"gml":OpenLayers.Format.GML.v3.prototype.readers.gml},write:function(request){return this.writers.xls.XLS.apply(this,[request]);},writers:{"xls":{"XLS":function(request){var root=this.createElementNSPlus("xls:XLS",{attributes:{"version":this.VERSION,"xsi:schemaLocation":this.schemaLocation}});this.writeNode("RequestHeader",request.header,root);this.writeNode("Request",request,root);return root;},"RequestHeader":function(header){return this.createElementNSPlus("xls:RequestHeader");},"Request":function(request){var node=this.createElementNSPlus("xls:Request",{attributes:{methodName:"GeocodeRequest",requestID:request.requestID||"",version:this.VERSION}});this.writeNode("GeocodeRequest",request.addresses,node);return node;},"GeocodeRequest":function(addresses){var node=this.createElementNSPlus("xls:GeocodeRequest");for(var i=0,len=addresses.length;i<len;i++){this.writeNode("Address",addresses[i],node);}
+return node;},"Address":function(address){var node=this.createElementNSPlus("xls:Address",{attributes:{countryCode:address.countryCode}});if(address.freeFormAddress){this.writeNode("freeFormAddess",address.freeFormAddress,node);}else{if(address.street){this.writeNode("StreetAddress",address,node);}
+if(address.municipality){this.writeNode("Municipality",address.municipality,node);}
+if(address.countrySubdivision){this.writeNode("CountrySubdivision",address.countrySubdivision,node);}
+if(address.postalCode){this.writeNode("PostalCode",address.postalCode,node);}}
+return node;},"freeFormAddress":function(freeFormAddress){return this.createElementNSPlus("freeFormAddress",{value:freeFormAddress});},"StreetAddress":function(address){var node=this.createElementNSPlus("xls:StreetAddress");if(address.building){this.writeNode(node,"Building",address.building);}
+var street=address.street;if(!(OpenLayers.Util.isArray(street))){street=[street];}
+for(var i=0,len=street.length;i<len;i++){this.writeNode("Street",street[i],node);}
+return node;},"Building":function(building){return this.createElementNSPlus("xls:Building",{attributes:{"number":building["number"],"subdivision":building.subdivision,"buildingName":building.buildingName}});},"Street":function(street){return this.createElementNSPlus("xls:Street",{value:street});},"Municipality":function(municipality){return this.createElementNSPlus("xls:Place",{attributes:{type:"Municipality"},value:municipality});},"CountrySubdivision":function(countrySubdivision){return this.createElementNSPlus("xls:Place",{attributes:{type:"CountrySubdivision"},value:countrySubdivision});},"PostalCode":function(postalCode){return this.createElementNSPlus("xls:PostalCode",{value:postalCode});}}},CLASS_NAME:"OpenLayers.Format.XLS.v1"});OpenLayers.Format.XLS.v1_1_0=OpenLayers.Class(OpenLayers.Format.XLS.v1,{VERSION:"1.1",schemaLocation:"http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd",initialize:function(options){OpenLayers.Format.XLS.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.XLS.v1_1_0"});OpenLayers.Format.XLS.v1_1=OpenLayers.Format.XLS.v1_1_0;OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15000,translationParameters:null,symbolMetrics:null,initialize:function(containerID){if(!this.supported()){return;}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.translationParameters={x:0,y:0};this.symbolMetrics={};},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},inValidRange:function(x,y,xyOnly){var left=x+(xyOnly?0:this.translationParameters.x);var top=y+(xyOnly?0:this.translationParameters.y);return(left>=-this.MAX_PIXEL&&left<=this.MAX_PIXEL&&top>=-this.MAX_PIXEL&&top<=this.MAX_PIXEL);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=-extent.left/resolution;var top=extent.top/resolution;if(resolutionChanged){this.left=left;this.top=top;var extentString="0 0 "+this.size.w+" "+this.size.h;this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.translate(0,0);return true;}else{var inRange=this.translate(left-this.left,top-this.top);if(!inRange){this.setExtent(extent,true);}
+return inRange;}},translate:function(x,y){if(!this.inValidRange(x,y,true)){return false;}else{var transformString="";if(x||y){transformString="translate("+x+","+y+")";}
+this.root.setAttributeNS(null,"transform",transformString);this.translationParameters={x:x,y:y};return true;}},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w);this.rendererRoot.setAttributeNS(null,"height",this.size.h);},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType="svg";}else{nodeType="circle";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="path";break;default:break;}
+return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var r=parseFloat(node.getAttributeNS(null,"r"));var widthFactor=1;var pos;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){pos=this.getPosition(node);if(style.graphicTitle){node.setAttributeNS(null,"title",style.graphicTitle);var label=this.nodeFactory(null,"title");label.textContent=style.graphicTitle;node.appendChild(label);}
+if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);node.onclick=OpenLayers.Renderer.SVG.preventDefault;}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var src=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[src.id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
+node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);}
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
+pos.y+")");}else{var metrics=this.symbolMetrics[src.id];node.firstChild.setAttributeNS(null,"transform","rotate("
++rotation+" "
++metrics[1]+" "
++metrics[2]+")");}}}
+if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
+if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");}
+if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);}
+if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);}
+return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[1,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,1,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,1,4*w].join();default:return OpenLayers.String.trim(str).replace(/\s+/g,",");}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);}
+return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_svgRoot","svg");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node.setAttributeNS(null,"r",radius);return node;}else{return false;}},drawLineString:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawLinearRing:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawPolygon:function(node,geometry){var d="";var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;j<len;j++){d+=" M";linearRingResult=this.getComponentsString(geometry.components[j].components," ");path=linearRingResult.path;if(path){d+=" "+path;complete=linearRingResult.complete&&complete;}else{draw=false;}}
+d+=" z";if(draw){node.setAttributeNS(null,"d",d);node.setAttributeNS(null,"fill-rule","evenodd");return complete?node:null;}else{return false;}},drawRectangle:function(node,geometry){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"x",x);node.setAttributeNS(null,"y",y);node.setAttributeNS(null,"width",geometry.width/resolution);node.setAttributeNS(null,"height",geometry.height/resolution);return node;}else{return false;}},drawSurface:function(node,geometry){var d=null;var draw=true;for(var i=0,len=geometry.components.length;i<len;i++){if((i%3)==0&&(i/3)==0){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
+d="M "+component;}else if((i%3)==1){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
+d+=" C "+component;}else{var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
+d+=" "+component;}}
+d+=" Z";if(draw){node.setAttributeNS(null,"d",d);return node;}else{return false;}},drawText:function(featureId,style,location){var resolution=this.getResolution();var x=(location.x/resolution+this.left);var y=(location.y/resolution-this.top);var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"text");label.setAttributeNS(null,"x",x);label.setAttributeNS(null,"y",-y);if(style.fontColor){label.setAttributeNS(null,"fill",style.fontColor);}
+if(style.fontOpacity){label.setAttributeNS(null,"opacity",style.fontOpacity);}
+if(style.fontFamily){label.setAttributeNS(null,"font-family",style.fontFamily);}
+if(style.fontSize){label.setAttributeNS(null,"font-size",style.fontSize);}
+if(style.fontWeight){label.setAttributeNS(null,"font-weight",style.fontWeight);}
+if(style.fontStyle){label.setAttributeNS(null,"font-style",style.fontStyle);}
+if(style.labelSelect===true){label.setAttributeNS(null,"pointer-events","visible");label._featureId=featureId;}else{label.setAttributeNS(null,"pointer-events","none");}
+var align=style.labelAlign||"cm";label.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]]||"middle");if(OpenLayers.IS_GECKO===true){label.setAttributeNS(null,"dominant-baseline",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]]||"central");}
+var labelRows=style.label.split('\n');var numRows=labelRows.length;while(label.childNodes.length>numRows){label.removeChild(label.lastChild);}
+for(var i=0;i<numRows;i++){var tspan=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_tspan_"+i,"tspan");if(style.labelSelect===true){tspan._featureId=featureId;tspan._geometry=location;tspan._geometryClass=location.CLASS_NAME;}
+if(OpenLayers.IS_GECKO===false){tspan.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]]||"-35%");}
+tspan.setAttribute("x",x);if(i==0){var vfactor=OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]];if(vfactor==null){vfactor=-.5;}
+tspan.setAttribute("dy",(vfactor*(numRows-1))+"em");}else{tspan.setAttribute("dy","1em");}
+tspan.textContent=(labelRows[i]==='')?' ':labelRows[i];if(!tspan.parentNode){label.appendChild(tspan);}}
+if(!label.parentNode){this.textRoot.appendChild(label);}},getComponentsString:function(components,separator){var renderCmp=[];var complete=true;var len=components.length;var strings=[];var str,component;for(var i=0;i<len;i++){component=components[i];renderCmp.push(component);str=this.getShortString(component);if(str){strings.push(str);}else{if(i>0){if(this.getShortString(components[i-1])){strings.push(this.clipLine(components[i],components[i-1]));}}
+if(i<len-1){if(this.getShortString(components[i+1])){strings.push(this.clipLine(components[i],components[i+1]));}}
+complete=false;}}
+return{path:strings.join(separator||","),complete:complete};},clipLine:function(badComponent,goodComponent){if(goodComponent.equals(badComponent)){return"";}
+var resolution=this.getResolution();var maxX=this.MAX_PIXEL-this.translationParameters.x;var maxY=this.MAX_PIXEL-this.translationParameters.y;var x1=goodComponent.x/resolution+this.left;var y1=this.top-goodComponent.y/resolution;var x2=badComponent.x/resolution+this.left;var y2=this.top-badComponent.y/resolution;var k;if(x2<-maxX||x2>maxX){k=(y2-y1)/(x2-x1);x2=x2<0?-maxX:maxX;y2=y1+(x2-x1)*k;}
+if(y2<-maxY||y2>maxY){k=(x2-x1)/(y2-y1);y2=y2<0?-maxY:maxY;x2=x1+(y2-y1)*k;}
+return x2+","+y2;},getShortString:function(point){var resolution=this.getResolution();var x=(point.x/resolution+this.left);var y=(this.top-point.y/resolution);if(this.inValidRange(x,y)){return x+","+y;}else{return false;}},getPosition:function(node){return({x:parseFloat(node.getAttributeNS(null,"cx")),y:parseFloat(node.getAttributeNS(null,"cy"))});},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();}
+var id=this.container.id+"-"+graphicName;var existing=document.getElementById(id)
+if(existing!=null){return existing;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);points.push(x,",",y);}
+node.setAttributeNS(null,"points",points.join(" "));var width=symbolExtent.getWidth();var height=symbolExtent.getHeight();var viewBox=[symbolExtent.left-width,symbolExtent.bottom-height,width*3,height*3];symbolNode.setAttributeNS(null,"viewBox",viewBox.join(" "));this.symbolMetrics[id]=[Math.max(width,height),symbolExtent.getCenterLonLat().lon,symbolExtent.getCenterLonLat().lat];this.defs.appendChild(symbolNode);return symbolNode;},getFeatureIdFromEvent:function(evt){var featureId=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,arguments);if(!featureId){var target=evt.target;featureId=target.parentNode&&target!=this.rendererRoot&&target.parentNode._featureId;}
+return featureId;},CLASS_NAME:"OpenLayers.Renderer.SVG"});OpenLayers.Renderer.SVG.LABEL_ALIGN={"l":"start","r":"end","b":"bottom","t":"hanging"};OpenLayers.Renderer.SVG.LABEL_VSHIFT={"t":"-70%","b":"0"};OpenLayers.Renderer.SVG.LABEL_VFACTOR={"t":0,"b":-1};OpenLayers.Renderer.SVG.preventDefault=function(e){e.preventDefault&&e.preventDefault();};OpenLayers.Format.SLD.v1_0_0=OpenLayers.Class(OpenLayers.Format.SLD.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",initialize:function(options){OpenLayers.Format.SLD.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.SLD.v1_0_0"});OpenLayers.Format.OWSContext=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"0.3.1",getVersion:function(root,options){var version=OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(this,arguments);if(version==="0.3.0"){version=this.defaultVersion;}
+return version;},toContext:function(obj){var context={};if(obj.CLASS_NAME=="OpenLayers.Map"){context.bounds=obj.getExtent();context.maxExtent=obj.maxExtent;context.projection=obj.projection;context.size=obj.getSize();context.layers=obj.layers;}
+return context;},CLASS_NAME:"OpenLayers.Format.OWSContext"});OpenLayers.Format.OWSContext.v0_3_1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{owc:"http://www.opengis.net/ows-context",gml:"http://www.opengis.net/gml",kml:"http://www.opengis.net/kml/2.2",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},VERSION:"0.3.1",schemaLocation:"http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",defaultPrefix:"owc",extractAttributes:true,xy:true,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},featureNS:"http://mapserver.gis.umn.edu/mapserver",featureType:'vector',geometryName:'geometry',nestingLayerLookup:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);},setNestingPath:function(l){if(l.layersContext){for(var i=0,len=l.layersContext.length;i<len;i++){var layerContext=l.layersContext[i];var nPath=[];var nTitle=l.title||"";if(l.metadata&&l.metadata.nestingPath){nPath=l.metadata.nestingPath.slice();}
+if(nTitle!=""){nPath.push(nTitle);}
+layerContext.metadata.nestingPath=nPath;if(layerContext.layersContext){this.setNestingPath(layerContext);}}}},decomposeNestingPath:function(nPath){var a=[];if(OpenLayers.Util.isArray(nPath)){var path=nPath.slice();while(path.length>0){a.push(path.slice());path.pop();}
+a.reverse();}
+return a;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var context={};this.readNode(data,context);this.setNestingPath({layersContext:context.layersContext});var layers=[];this.processLayer(layers,context);delete context.layersContext;context.layersContext=layers;return context;},processLayer:function(layerArray,layer){if(layer.layersContext){for(var i=0,len=layer.layersContext.length;i<len;i++){var l=layer.layersContext[i];layerArray.push(l);if(l.layersContext){this.processLayer(layerArray,l);}}}},write:function(context,options){var name="OWSContext";this.nestingLayerLookup={};options=options||{};OpenLayers.Util.applyDefaults(options,context);var root=this.writeNode(name,options);this.nestingLayerLookup=null;this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},readers:{"kml":{"Document":function(node,obj){obj.features=new OpenLayers.Format.KML({kmlns:this.namespaces.kml,extractStyles:true}).read(node);}},"owc":{"OWSContext":function(node,obj){this.readChildNodes(node,obj);},"General":function(node,obj){this.readChildNodes(node,obj);},"ResourceList":function(node,obj){this.readChildNodes(node,obj);},"Layer":function(node,obj){var layerContext={metadata:{},visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),opacity:((node.getAttribute("opacity")!=null)?parseFloat(node.getAttribute("opacity")):null),name:node.getAttribute("name"),categoryLayer:(node.getAttribute("name")==null),formats:[],styles:[]};if(!obj.layersContext){obj.layersContext=[];}
+obj.layersContext.push(layerContext);this.readChildNodes(node,layerContext);},"InlineGeometry":function(node,obj){obj.features=[];var elements=this.getElementsByTagNameNS(node,this.namespaces.gml,"featureMember");var el;if(elements.length>=1){el=elements[0];}
+if(el&&el.firstChild){var featurenode=(el.firstChild.nextSibling)?el.firstChild.nextSibling:el.firstChild;this.setNamespace("feature",featurenode.namespaceURI);this.featureType=featurenode.localName||featurenode.nodeName.split(":").pop();this.readChildNodes(node,obj);}},"Server":function(node,obj){if((!obj.service&&!obj.version)||(obj.service!=OpenLayers.Format.Context.serviceTypes.WMS)){obj.service=node.getAttribute("service");obj.version=node.getAttribute("version");this.readChildNodes(node,obj);}},"Name":function(node,obj){obj.name=this.getChildValue(node);this.readChildNodes(node,obj);},"Title":function(node,obj){obj.title=this.getChildValue(node);this.readChildNodes(node,obj);},"StyleList":function(node,obj){this.readChildNodes(node,obj.styles);},"Style":function(node,obj){var style={};obj.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={};obj.legend=legend;this.readChildNodes(node,legend);},"OnlineResource":function(node,obj){obj.url=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,obj);}},"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,"gml":OpenLayers.Format.GML.v2.prototype.readers.gml,"sld":OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,"feature":OpenLayers.Format.GML.v2.prototype.readers.feature},writers:{"owc":{"OWSContext":function(options){var node=this.createElementNSPlus("OWSContext",{attributes:{version:this.VERSION,id:options.id||OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")}});this.writeNode("General",options,node);this.writeNode("ResourceList",options,node);return node;},"General":function(options){var node=this.createElementNSPlus("General");this.writeNode("ows:BoundingBox",options,node);this.writeNode("ows:Title",options.title||'OpenLayers OWSContext',node);return node;},"ResourceList":function(options){var node=this.createElementNSPlus("ResourceList");for(var i=0,len=options.layers.length;i<len;i++){var layer=options.layers[i];var decomposedPath=this.decomposeNestingPath(layer.metadata.nestingPath);this.writeNode("_Layer",{layer:layer,subPaths:decomposedPath},node);}
+return node;},"Server":function(options){var node=this.createElementNSPlus("Server",{attributes:{version:options.version,service:options.service}});this.writeNode("OnlineResource",options,node);return node;},"OnlineResource":function(options){var node=this.createElementNSPlus("OnlineResource",{attributes:{"xlink:href":options.url}});return node;},"InlineGeometry":function(layer){var node=this.createElementNSPlus("InlineGeometry");this.writeNode("gml:boundedBy",layer.getDataExtent(),node);for(var i=0,len=layer.features.length;i<len;i++){this.writeNode("gml:featureMember",layer.features[i],node);}
+return node;},"StyleList":function(styles){var node=this.createElementNSPlus("StyleList");for(var i=0,len=styles.length;i<len;i++){this.writeNode("Style",styles[i],node);}
+return node;},"Style":function(style){var node=this.createElementNSPlus("Style");this.writeNode("Name",style,node);this.writeNode("Title",style,node);if(style.legend){this.writeNode("LegendURL",style,node);}
+return node;},"Name":function(obj){var node=this.createElementNSPlus("Name",{value:obj.name});return node;},"Title":function(obj){var node=this.createElementNSPlus("Title",{value:obj.title});return node;},"LegendURL":function(style){var node=this.createElementNSPlus("LegendURL");this.writeNode("OnlineResource",style.legend,node);return node;},"_WMS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.params.LAYERS,queryable:layer.queryable?"1":"0",hidden:layer.visibility?"0":"1",opacity:layer.opacity?layer.opacity:null}});this.writeNode("ows:Title",layer.name,node);this.writeNode("ows:OutputFormat",layer.params.FORMAT,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WMS,version:layer.params.VERSION,url:layer.url},node);if(layer.metadata.styles&&layer.metadata.styles.length>0){this.writeNode("StyleList",layer.metadata.styles,node);}
+return node;},"_Layer":function(options){var layer,subPaths,node,title;layer=options.layer;subPaths=options.subPaths;node=null;title=null;if(subPaths.length>0){var path=subPaths[0].join("/");var index=path.lastIndexOf("/");node=this.nestingLayerLookup[path];title=(index>0)?path.substring(index+1,path.length):path;if(!node){node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",title,node);this.nestingLayerLookup[path]=node;}
+options.subPaths.shift();this.writeNode("_Layer",options,node);return node;}else{if(layer instanceof OpenLayers.Layer.WMS){node=this.writeNode("_WMS",layer);}else if(layer instanceof OpenLayers.Layer.Vector){if(layer.protocol instanceof OpenLayers.Protocol.WFS.v1){node=this.writeNode("_WFS",layer);}else if(layer.protocol instanceof OpenLayers.Protocol.HTTP){if(layer.protocol.format instanceof OpenLayers.Format.GML){layer.protocol.format.version="2.1.2";node=this.writeNode("_GML",layer);}else if(layer.protocol.format instanceof OpenLayers.Format.KML){layer.protocol.format.version="2.2";node=this.writeNode("_KML",layer);}}else{this.setNamespace("feature",this.featureNS);node=this.writeNode("_InlineGeometry",layer);}}
+if(layer.options.maxScale){this.writeNode("sld:MinScaleDenominator",layer.options.maxScale,node);}
+if(layer.options.minScale){this.writeNode("sld:MaxScaleDenominator",layer.options.minScale,node);}
+this.nestingLayerLookup[layer.name]=node;return node;}},"_WFS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.protocol.featurePrefix+":"+layer.protocol.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WFS,version:layer.protocol.version,url:layer.protocol.url},node);return node;},"_InlineGeometry":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:this.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("InlineGeometry",layer,node);return node;},"_GML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.GML,url:layer.protocol.url,version:layer.protocol.format.version},node);return node;},"_KML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.KML,version:layer.protocol.format.version,url:layer.protocol.url},node);return node;}},"gml":OpenLayers.Util.applyDefaults({"boundedBy":function(bounds){var node=this.createElementNSPlus("gml:boundedBy");this.writeNode("gml:Box",bounds,node);return node;}},OpenLayers.Format.GML.v2.prototype.writers.gml),"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,"sld":OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,"feature":OpenLayers.Format.GML.v2.prototype.writers.feature},CLASS_NAME:"OpenLayers.Format.OWSContext.v0_3_1"});OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:false,draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.eTop){this.eTop=document.createElement("div");this.eTop.className=this.displayClass+"Top";var theLen=this.topInUnits.length;this.div.appendChild(this.eTop);if((this.topOutUnits=="")||(this.topInUnits=="")){this.eTop.style.visibility="hidden";}else{this.eTop.style.visibility="visible";}
+this.eBottom=document.createElement("div");this.eBottom.className=this.displayClass+"Bottom";this.div.appendChild(this.eBottom);if((this.bottomOutUnits=="")||(this.bottomInUnits=="")){this.eBottom.style.visibility="hidden";}else{this.eBottom.style.visibility="visible";}}
+this.map.events.register('moveend',this,this.update);this.update();return this.div;},getBarLen:function(maxLen){var digits=parseInt(Math.log(maxLen)/Math.log(10));var pow10=Math.pow(10,digits);var firstChar=parseInt(maxLen/pow10);var barLen;if(firstChar>5){barLen=5;}else if(firstChar>2){barLen=2;}else{barLen=1;}
+return barLen*pow10;},update:function(){var res=this.map.getResolution();if(!res){return;}
+var curMapUnits=this.map.getUnits();var inches=OpenLayers.INCHES_PER_UNIT;var maxSizeData=this.maxWidth*res*inches[curMapUnits];var geodesicRatio=1;if(this.geodesic===true){var maxSizeGeodesic=(this.map.getGeodesicPixelSize().w||0.000001)*this.maxWidth;var maxSizeKilometers=maxSizeData/inches["km"];geodesicRatio=maxSizeGeodesic/maxSizeKilometers;maxSizeData*=geodesicRatio;}
+var topUnits;var bottomUnits;if(maxSizeData>100000){topUnits=this.topOutUnits;bottomUnits=this.bottomOutUnits;}else{topUnits=this.topInUnits;bottomUnits=this.bottomInUnits;}
+var topMax=maxSizeData/inches[topUnits];var bottomMax=maxSizeData/inches[bottomUnits];var topRounded=this.getBarLen(topMax);var bottomRounded=this.getBarLen(bottomMax);topMax=topRounded/inches[curMapUnits]*inches[topUnits];bottomMax=bottomRounded/inches[curMapUnits]*inches[bottomUnits];var topPx=topMax/res/geodesicRatio;var bottomPx=bottomMax/res/geodesicRatio;if(this.eBottom.style.visibility=="visible"){this.eBottom.style.width=Math.round(bottomPx)+"px";this.eBottom.innerHTML=bottomRounded+" "+bottomUnits;}
+if(this.eTop.style.visibility=="visible"){this.eTop.style.width=Math.round(topPx)+"px";this.eTop.innerHTML=topRounded+" "+topUnits;}},CLASS_NAME:"OpenLayers.Control.ScaleLine"});OpenLayers.Control.PanZoom=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,buttons:null,position:null,initialize:function(options){this.position=new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,OpenLayers.Control.PanZoom.Y);OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.removeButtons();this.buttons=null;this.position=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position;this.buttons=[];var sz=new OpenLayers.Size(18,18);var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);this._addButton("panright","east-mini.png",px.add(sz.w,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);this._addButton("zoomworld","zoom-world-mini.png",centered.add(0,sz.h*4+5),sz);this._addButton("zoomout","zoom-minus-mini.png",centered.add(0,sz.h*5+5),sz);return this.div;},_addButton:function(id,img,xy,sz){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var btn=OpenLayers.Util.createAlphaImageDiv(this.id+"_"+id,xy,sz,imgLocation,"absolute");btn.style.cursor="pointer";this.div.appendChild(btn);OpenLayers.Event.observe(btn,"mousedown",OpenLayers.Function.bindAsEventListener(this.buttonDown,btn));OpenLayers.Event.observe(btn,"dblclick",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));OpenLayers.Event.observe(btn,"click",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));btn.action=id;btn.map=this.map;if(!this.slideRatio){var slideFactorPixels=this.slideFactor;var getSlideFactor=function(){return slideFactorPixels;};}else{var slideRatio=this.slideRatio;var getSlideFactor=function(dim){return this.map.getSize()[dim]*slideRatio;};}
+btn.getSlideFactor=getSlideFactor;this.buttons.push(btn);return btn;},_removeButton:function(btn){OpenLayers.Event.stopObservingElement(btn);btn.map=null;btn.getSlideFactor=null;this.div.removeChild(btn);OpenLayers.Util.removeItem(this.buttons,btn);},removeButtons:function(){for(var i=this.buttons.length-1;i>=0;--i){this._removeButton(this.buttons[i]);}},doubleClick:function(evt){OpenLayers.Event.stop(evt);return false;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+switch(this.action){case"panup":this.map.pan(0,-this.getSlideFactor("h"));break;case"pandown":this.map.pan(0,this.getSlideFactor("h"));break;case"panleft":this.map.pan(-this.getSlideFactor("w"),0);break;case"panright":this.map.pan(this.getSlideFactor("w"),0);break;case"zoomin":this.map.zoomIn();break;case"zoomout":this.map.zoomOut();break;case"zoomworld":this.map.zoomToMaxExtent();break;}
+OpenLayers.Event.stop(evt);},CLASS_NAME:"OpenLayers.Control.PanZoom"});OpenLayers.Control.PanZoom.X=4;OpenLayers.Control.PanZoom.Y=4;OpenLayers.Icon=OpenLayers.Class({url:null,size:null,offset:null,calculateOffset:null,imageDiv:null,px:null,initialize:function(url,size,offset,calculateOffset){this.url=url;this.size=(size)?size:new OpenLayers.Size(20,20);this.offset=offset?offset:new OpenLayers.Pixel(-(this.size.w/2),-(this.size.h/2));this.calculateOffset=calculateOffset;var id=OpenLayers.Util.createUniqueID("OL_Icon_");this.imageDiv=OpenLayers.Util.createAlphaImageDiv(id);},destroy:function(){this.erase();OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);this.imageDiv.innerHTML="";this.imageDiv=null;},clone:function(){return new OpenLayers.Icon(this.url,this.size,this.offset,this.calculateOffset);},setSize:function(size){if(size!=null){this.size=size;}
+this.draw();},setUrl:function(url){if(url!=null){this.url=url;}
+this.draw();},draw:function(px){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,this.size,this.url,"absolute");this.moveTo(px);return this.imageDiv;},erase:function(){if(this.imageDiv!=null&&this.imageDiv.parentNode!=null){OpenLayers.Element.remove(this.imageDiv);}},setOpacity:function(opacity){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,null,null,null,null,null,opacity);},moveTo:function(px){if(px!=null){this.px=px;}
+if(this.imageDiv!=null){if(this.px==null){this.display(false);}else{if(this.calculateOffset){this.offset=this.calculateOffset(this.size);}
+var offsetPx=this.px.offset(this.offset);OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,offsetPx);}}},display:function(display){this.imageDiv.style.display=(display)?"":"none";},isDrawn:function(){var isDrawn=(this.imageDiv&&this.imageDiv.parentNode&&(this.imageDiv.parentNode.nodeType!=11));return isDrawn;},CLASS_NAME:"OpenLayers.Icon"});OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(lonlat,icon){this.lonlat=lonlat;var newIcon=(icon)?icon:OpenLayers.Marker.defaultIcon();if(this.icon==null){this.icon=newIcon;}else{this.icon.url=newIcon.url;this.icon.size=newIcon.size;this.icon.offset=newIcon.offset;this.icon.calculateOffset=newIcon.calculateOffset;}
+this.events=new OpenLayers.Events(this,this.icon.imageDiv,null);},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;if(this.icon!=null){this.icon.destroy();this.icon=null;}},draw:function(px){return this.icon.draw(px);},erase:function(){if(this.icon!=null){this.icon.erase();}},moveTo:function(px){if((px!=null)&&(this.icon!=null)){this.icon.moveTo(px);}
+this.lonlat=this.map.getLonLatFromLayerPx(px);},isDrawn:function(){var isDrawn=(this.icon&&this.icon.isDrawn());return isDrawn;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
+return onScreen;},inflate:function(inflate){if(this.icon){var newSize=new OpenLayers.Size(this.icon.size.w*inflate,this.icon.size.h*inflate);this.icon.setSize(newSize);}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){var url=OpenLayers.Util.getImagesLocation()+"marker.png";var size=new OpenLayers.Size(21,25);var calculateOffset=function(size){return new OpenLayers.Pixel(-(size.w/2),-size.h);};return new OpenLayers.Icon(url,size,null,calculateOffset);};OpenLayers.Strategy.Paging=OpenLayers.Class(OpenLayers.Strategy,{features:null,length:10,num:null,paging:false,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,scope:this});}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,scope:this});}
+return deactivated;},cacheFeatures:function(event){if(!this.paging){this.clearCache();this.features=event.features;this.pageNext(event);}},clearCache:function(){if(this.features){for(var i=0;i<this.features.length;++i){this.features[i].destroy();}}
+this.features=null;this.num=null;},pageCount:function(){var numFeatures=this.features?this.features.length:0;return Math.ceil(numFeatures/this.length);},pageNum:function(){return this.num;},pageLength:function(newLength){if(newLength&&newLength>0){this.length=newLength;}
+return this.length;},pageNext:function(event){var changed=false;if(this.features){if(this.num===null){this.num=-1;}
+var start=(this.num+1)*this.length;changed=this.page(start,event);}
+return changed;},pagePrevious:function(){var changed=false;if(this.features){if(this.num===null){this.num=this.pageCount();}
+var start=(this.num-1)*this.length;changed=this.page(start);}
+return changed;},page:function(start,event){var changed=false;if(this.features){if(start>=0&&start<this.features.length){var num=Math.floor(start/this.length);if(num!=this.num){this.paging=true;var features=this.features.slice(start,start+this.length);this.layer.removeFeatures(this.layer.features);this.num=num;if(event&&event.features){event.features=features;}else{this.layer.addFeatures(features);}
+this.paging=false;changed=true;}}}
+return changed;},CLASS_NAME:"OpenLayers.Strategy.Paging"});OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,serverResolutions:null,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({maxExtent:new OpenLayers.Bounds(-128*156543.03390625,-128*156543.03390625,128*156543.03390625,128*156543.03390625),maxResolution:156543.03390625,numZoomLevels:19,units:"m",projection:"EPSG:900913"},options);}
+url=url||this.url;name=name||this.name;var newArguments=[name,url,{},options];OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var xyz=this.getXYZ(bounds);var url=this.url;if(OpenLayers.Util.isArray(url)){var s=''+xyz.x+xyz.y+xyz.z;url=this.selectUrl(s,url);}
+return OpenLayers.String.format(url,xyz);},getXYZ:function(bounds){var res=this.map.getResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom()+this.zoomOffset;var limit=Math.pow(2,z);if(this.wrapDateLine)
+{x=((x%limit)+limit)%limit;}
+return{'x':x,'y':y,'z':z};},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",attribution:"Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",sphericalMercator:true,url:'http://tile.openstreetmap.org/${z}/${x}/${y}.png',clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},wrapDateLine:true,CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,EVENT_TYPES:["featureadded"],multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){this.EVENT_TYPES=OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;}
+var sketchStyle=this.layer.styleMap&&this.layer.styleMap.styles.temporary;if(sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":sketchStyle})});}
+this.handler=new handler(this,this.callbacks,this.handlerOptions);},drawFeature:function(geometry){var feature=new OpenLayers.Feature.Vector(geometry);var proceed=this.layer.events.triggerEvent("sketchcomplete",{feature:feature});if(proceed!==false){feature.state=OpenLayers.State.INSERT;this.layer.addFeatures([feature]);this.featureAdded(feature);this.events.triggerEvent("featureadded",{feature:feature});}},insertXY:function(x,y){if(this.handler&&this.handler.line){this.handler.insertXY(x,y);}},insertDeltaXY:function(dx,dy){if(this.handler&&this.handler.line){this.handler.insertDeltaXY(dx,dy);}},insertDirectionLength:function(direction,length){if(this.handler&&this.handler.line){this.handler.insertDirectionLength(direction,length);}},insertDeflectionLength:function(deflection,length){if(this.handler&&this.handler.line){this.handler.insertDeflectionLength(deflection,length);}},undo:function(){return this.handler.undo&&this.handler.undo();},redo:function(){return this.handler.redo&&this.handler.redo();},finishSketch:function(){this.handler.finishGeometry();},cancel:function(){this.handler.cancel();},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Handler.Polygon=OpenLayers.Class(OpenLayers.Handler.Path,{holeModifier:null,drawingHole:false,polygon:null,initialize:function(control,callbacks,options){OpenLayers.Handler.Path.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LinearRing([this.point.geometry]));this.polygon=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([this.line.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.polygon,this.point],{silent:true});},addPoint:function(pixel){if(!this.drawingHole&&this.holeModifier&&this.evt&&this.evt[this.holeModifier]){var geometry=this.point.geometry;var features=this.control.layer.features;var candidate,polygon;for(var i=features.length-1;i>=0;--i){candidate=features[i].geometry;if((candidate instanceof OpenLayers.Geometry.Polygon||candidate instanceof OpenLayers.Geometry.MultiPolygon)&&candidate.intersects(geometry)){polygon=features[i];this.control.layer.removeFeatures([polygon],{silent:true});this.control.layer.events.registerPriority("sketchcomplete",this,this.finalizeInteriorRing);this.control.layer.events.registerPriority("sketchmodified",this,this.enforceTopology);polygon.geometry.addComponent(this.line.geometry);this.polygon=polygon;this.drawingHole=true;break;}}}
+OpenLayers.Handler.Path.prototype.addPoint.apply(this,arguments);},getCurrentPointIndex:function(){return this.line.geometry.components.length-2;},enforceTopology:function(event){var point=event.vertex;var components=this.line.geometry.components;if(!this.polygon.geometry.intersects(point)){var last=components[components.length-3];point.x=last.x;point.y=last.y;}},finishGeometry:function(){var index=this.line.geometry.components.length-2;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();},finalizeInteriorRing:function(){var ring=this.line.geometry;var modified=(ring.getArea()!==0);if(modified){var rings=this.polygon.geometry.components;for(var i=rings.length-2;i>=0;--i){if(ring.intersects(rings[i])){modified=false;break;}}
+if(modified){var target;outer:for(var i=rings.length-2;i>0;--i){var points=rings[i].components;for(var j=0,jj=points.length;j<jj;++j){if(ring.containsPoint(points[j])){modified=false;break outer;}}}}}
+if(modified){if(this.polygon.state!==OpenLayers.State.INSERT){this.polygon.state=OpenLayers.State.UPDATE;}}else{this.polygon.geometry.removeComponent(ring);}
+this.restoreFeature();return false;},cancel:function(){if(this.drawingHole){this.polygon.geometry.removeComponent(this.line.geometry);this.restoreFeature(true);}
+return OpenLayers.Handler.Path.prototype.cancel.apply(this,arguments);},restoreFeature:function(cancel){this.control.layer.events.unregister("sketchcomplete",this,this.finalizeInteriorRing);this.control.layer.events.unregister("sketchmodified",this,this.enforceTopology);this.layer.removeFeatures([this.polygon],{silent:true});this.control.layer.addFeatures([this.polygon],{silent:true});this.drawingHole=false;if(!cancel){this.control.layer.events.triggerEvent("sketchcomplete",{feature:this.polygon});}},destroyFeature:function(force){OpenLayers.Handler.Path.prototype.destroyFeature.call(this,force);this.polygon=null;},drawFeature:function(){this.layer.drawFeature(this.polygon,this.style);this.layer.drawFeature(this.point,this.style);},getSketch:function(){return this.polygon;},getGeometry:function(){var geometry=this.polygon&&this.polygon.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPolygon([geometry]);}
+return geometry;},CLASS_NAME:"OpenLayers.Handler.Polygon"});OpenLayers.Control.EditingToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(layer,options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation()]);var controls=[new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Point,{'displayClass':'olControlDrawFeaturePoint'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Path,{'displayClass':'olControlDrawFeaturePath'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Polygon,{'displayClass':'olControlDrawFeaturePolygon'})];this.addControls(controls);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);if(this.defaultControl===null){this.defaultControl=this.controls[0];}
+return div;},CLASS_NAME:"OpenLayers.Control.EditingToolbar"});OpenLayers.Rico=OpenLayers.Rico||{};OpenLayers.Rico.Color=OpenLayers.Class({initialize:function(red,green,blue){this.rgb={r:red,g:green,b:blue};},setRed:function(r){this.rgb.r=r;},setGreen:function(g){this.rgb.g=g;},setBlue:function(b){this.rgb.b=b;},setHue:function(h){var hsb=this.asHSB();hsb.h=h;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setSaturation:function(s){var hsb=this.asHSB();hsb.s=s;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setBrightness:function(b){var hsb=this.asHSB();hsb.b=b;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},darken:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.max(hsb.b-percent,0));},brighten:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.min(hsb.b+percent,1));},blend:function(other){this.rgb.r=Math.floor((this.rgb.r+other.rgb.r)/2);this.rgb.g=Math.floor((this.rgb.g+other.rgb.g)/2);this.rgb.b=Math.floor((this.rgb.b+other.rgb.b)/2);},isBright:function(){var hsb=this.asHSB();return this.asHSB().b>0.5;},isDark:function(){return!this.isBright();},asRGB:function(){return"rgb("+this.rgb.r+","+this.rgb.g+","+this.rgb.b+")";},asHex:function(){return"#"+this.rgb.r.toColorPart()+this.rgb.g.toColorPart()+this.rgb.b.toColorPart();},asHSB:function(){return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r,this.rgb.g,this.rgb.b);},toString:function(){return this.asHex();}});OpenLayers.Rico.Color.createFromHex=function(hexCode){if(hexCode.length==4){var shortHexCode=hexCode;var hexCode='#';for(var i=1;i<4;i++){hexCode+=(shortHexCode.charAt(i)+
+shortHexCode.charAt(i));}}
+if(hexCode.indexOf('#')==0){hexCode=hexCode.substring(1);}
+var red=hexCode.substring(0,2);var green=hexCode.substring(2,4);var blue=hexCode.substring(4,6);return new OpenLayers.Rico.Color(parseInt(red,16),parseInt(green,16),parseInt(blue,16));};OpenLayers.Rico.Color.createColorFromBackground=function(elem){var actualColor=OpenLayers.Element.getStyle(OpenLayers.Util.getElement(elem),"backgroundColor");if(actualColor=="transparent"&&elem.parentNode){return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);}
+if(actualColor==null){return new OpenLayers.Rico.Color(255,255,255);}
+if(actualColor.indexOf("rgb(")==0){var colors=actualColor.substring(4,actualColor.length-1);var colorArray=colors.split(",");return new OpenLayers.Rico.Color(parseInt(colorArray[0]),parseInt(colorArray[1]),parseInt(colorArray[2]));}
+else if(actualColor.indexOf("#")==0){return OpenLayers.Rico.Color.createFromHex(actualColor);}
+else{return new OpenLayers.Rico.Color(255,255,255);}};OpenLayers.Rico.Color.HSBtoRGB=function(hue,saturation,brightness){var red=0;var green=0;var blue=0;if(saturation==0){red=parseInt(brightness*255.0+0.5);green=red;blue=red;}
+else{var h=(hue-Math.floor(hue))*6.0;var f=h-Math.floor(h);var p=brightness*(1.0-saturation);var q=brightness*(1.0-saturation*f);var t=brightness*(1.0-(saturation*(1.0-f)));switch(parseInt(h)){case 0:red=(brightness*255.0+0.5);green=(t*255.0+0.5);blue=(p*255.0+0.5);break;case 1:red=(q*255.0+0.5);green=(brightness*255.0+0.5);blue=(p*255.0+0.5);break;case 2:red=(p*255.0+0.5);green=(brightness*255.0+0.5);blue=(t*255.0+0.5);break;case 3:red=(p*255.0+0.5);green=(q*255.0+0.5);blue=(brightness*255.0+0.5);break;case 4:red=(t*255.0+0.5);green=(p*255.0+0.5);blue=(brightness*255.0+0.5);break;case 5:red=(brightness*255.0+0.5);green=(p*255.0+0.5);blue=(q*255.0+0.5);break;}}
+return{r:parseInt(red),g:parseInt(green),b:parseInt(blue)};};OpenLayers.Rico.Color.RGBtoHSB=function(r,g,b){var hue;var saturation;var brightness;var cmax=(r>g)?r:g;if(b>cmax){cmax=b;}
+var cmin=(r<g)?r:g;if(b<cmin){cmin=b;}
+brightness=cmax/255.0;if(cmax!=0){saturation=(cmax-cmin)/cmax;}else{saturation=0;}
+if(saturation==0){hue=0;}else{var redc=(cmax-r)/(cmax-cmin);var greenc=(cmax-g)/(cmax-cmin);var bluec=(cmax-b)/(cmax-cmin);if(r==cmax){hue=bluec-greenc;}else if(g==cmax){hue=2.0+redc-bluec;}else{hue=4.0+greenc-redc;}
+hue=hue/6.0;if(hue<0){hue=hue+1.0;}}
+return{h:hue,s:saturation,b:brightness};};OpenLayers.Rico=OpenLayers.Rico||{};OpenLayers.Rico.Corner={round:function(e,options){e=OpenLayers.Util.getElement(e);this._setOptions(options);var color=this.options.color;if(this.options.color=="fromElement"){color=this._background(e);}
+var bgColor=this.options.bgColor;if(this.options.bgColor=="fromParent"){bgColor=this._background(e.offsetParent);}
+this._roundCornersImpl(e,color,bgColor);},changeColor:function(theDiv,newColor){theDiv.style.backgroundColor=newColor;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.backgroundColor=newColor;}},changeOpacity:function(theDiv,newOpacity){var mozillaOpacity=newOpacity;var ieOpacity='alpha(opacity='+newOpacity*100+')';theDiv.style.opacity=mozillaOpacity;theDiv.style.filter=ieOpacity;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.opacity=mozillaOpacity;spanElements[currIdx].style.filter=ieOpacity;}},reRound:function(theDiv,options){var topRico=theDiv.parentNode.childNodes[0];var bottomRico=theDiv.parentNode.childNodes[2];theDiv.parentNode.removeChild(topRico);theDiv.parentNode.removeChild(bottomRico);this.round(theDiv.parentNode,options);},_roundCornersImpl:function(e,color,bgColor){if(this.options.border){this._renderBorder(e,bgColor);}
+if(this._isTopRounded()){this._roundTopCorners(e,color,bgColor);}
+if(this._isBottomRounded()){this._roundBottomCorners(e,color,bgColor);}},_renderBorder:function(el,bgColor){var borderValue="1px solid "+this._borderColor(bgColor);var borderL="border-left: "+borderValue;var borderR="border-right: "+borderValue;var style="style='"+borderL+";"+borderR+"'";el.innerHTML="<div "+style+">"+el.innerHTML+"</div>";},_roundTopCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=0;i<this.options.numSlices;i++){corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));}
+el.style.paddingTop=0;el.insertBefore(corner,el.firstChild);},_roundBottomCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=(this.options.numSlices-1);i>=0;i--){corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));}
+el.style.paddingBottom=0;el.appendChild(corner);},_createCorner:function(bgColor){var corner=document.createElement("div");corner.style.backgroundColor=(this._isTransparent()?"transparent":bgColor);return corner;},_createCornerSlice:function(color,bgColor,n,position){var slice=document.createElement("span");var inStyle=slice.style;inStyle.backgroundColor=color;inStyle.display="block";inStyle.height="1px";inStyle.overflow="hidden";inStyle.fontSize="1px";var borderColor=this._borderColor(color,bgColor);if(this.options.border&&n==0){inStyle.borderTopStyle="solid";inStyle.borderTopWidth="1px";inStyle.borderLeftWidth="0px";inStyle.borderRightWidth="0px";inStyle.borderBottomWidth="0px";inStyle.height="0px";inStyle.borderColor=borderColor;}
+else if(borderColor){inStyle.borderColor=borderColor;inStyle.borderStyle="solid";inStyle.borderWidth="0px 1px";}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){inStyle.height="2px";}
+this._setMargin(slice,n,position);this._setBorder(slice,n,position);return slice;},_setOptions:function(options){this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false};OpenLayers.Util.extend(this.options,options||{});this.options.numSlices=this.options.compact?2:4;if(this._isTransparent()){this.options.blend=false;}},_whichSideTop:function(){if(this._hasString(this.options.corners,"all","top")){return"";}
+if(this.options.corners.indexOf("tl")>=0&&this.options.corners.indexOf("tr")>=0){return"";}
+if(this.options.corners.indexOf("tl")>=0){return"left";}else if(this.options.corners.indexOf("tr")>=0){return"right";}
+return"";},_whichSideBottom:function(){if(this._hasString(this.options.corners,"all","bottom")){return"";}
+if(this.options.corners.indexOf("bl")>=0&&this.options.corners.indexOf("br")>=0){return"";}
+if(this.options.corners.indexOf("bl")>=0){return"left";}else if(this.options.corners.indexOf("br")>=0){return"right";}
+return"";},_borderColor:function(color,bgColor){if(color=="transparent"){return bgColor;}else if(this.options.border){return this.options.border;}else if(this.options.blend){return this._blend(bgColor,color);}else{return"";}},_setMargin:function(el,n,corners){var marginSize=this._marginSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.marginLeft=marginSize+"px";el.style.marginRight="0px";}
+else if(whichSide=="right"){el.style.marginRight=marginSize+"px";el.style.marginLeft="0px";}
+else{el.style.marginLeft=marginSize+"px";el.style.marginRight=marginSize+"px";}},_setBorder:function(el,n,corners){var borderSize=this._borderSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth="0px";}
+else if(whichSide=="right"){el.style.borderRightWidth=borderSize+"px";el.style.borderLeftWidth="0px";}
+else{el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";}
+if(this.options.border!=false){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";}},_marginSize:function(n){if(this._isTransparent()){return 0;}
+var marginSizes=[5,3,2,1];var blendedMarginSizes=[3,2,1,0];var compactMarginSizes=[2,1];var smBlendedMarginSizes=[1,0];if(this.options.compact&&this.options.blend){return smBlendedMarginSizes[n];}else if(this.options.compact){return compactMarginSizes[n];}else if(this.options.blend){return blendedMarginSizes[n];}else{return marginSizes[n];}},_borderSize:function(n){var transparentBorderSizes=[5,3,2,1];var blendedBorderSizes=[2,1,1,1];var compactBorderSizes=[1,0];var actualBorderSizes=[0,2,0,0];if(this.options.compact&&(this.options.blend||this._isTransparent())){return 1;}else if(this.options.compact){return compactBorderSizes[n];}else if(this.options.blend){return blendedBorderSizes[n];}else if(this.options.border){return actualBorderSizes[n];}else if(this._isTransparent()){return transparentBorderSizes[n];}
+return 0;},_hasString:function(str){for(var i=1;i<arguments.length;i++)if(str.indexOf(arguments[i])>=0){return true;}return false;},_blend:function(c1,c2){var cc1=OpenLayers.Rico.Color.createFromHex(c1);cc1.blend(OpenLayers.Rico.Color.createFromHex(c2));return cc1;},_background:function(el){try{return OpenLayers.Rico.Color.createColorFromBackground(el).asHex();}catch(err){return"#ffffff";}},_isTransparent:function(){return this.options.color=="transparent";},_isTopRounded:function(){return this._hasString(this.options.corners,"all","top","tl","tr");},_isBottomRounded:function(){return this._hasString(this.options.corners,"all","bottom","bl","br");},_hasSingleTextChild:function(el){return el.childNodes.length==1&&el.childNodes[0].nodeType==3;}};OpenLayers.Popup.AnchoredBubble=OpenLayers.Class(OpenLayers.Popup.Anchored,{rounded:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.padding=new OpenLayers.Bounds(0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE,0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE);OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);},draw:function(px){OpenLayers.Popup.Anchored.prototype.draw.apply(this,arguments);this.setContentHTML();this.setBackgroundColor();this.setOpacity();return this.div;},updateRelativePosition:function(){this.setRicoCorners();},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.setRicoCorners();},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;}
+if(this.div!=null){if(this.contentDiv!=null){this.div.style.background="transparent";OpenLayers.Rico.Corner.changeColor(this.groupDiv,this.backgroundColor);}}},setOpacity:function(opacity){OpenLayers.Popup.Anchored.prototype.setOpacity.call(this,opacity);if(this.div!=null){if(this.groupDiv!=null){OpenLayers.Rico.Corner.changeOpacity(this.groupDiv,this.opacity);}}},setBorder:function(border){this.border=0;},setRicoCorners:function(){var corners=this.getCornersToRound(this.relativePosition);var options={corners:corners,color:this.backgroundColor,bgColor:"transparent",blend:false};if(!this.rounded){OpenLayers.Rico.Corner.round(this.div,options);this.rounded=true;}else{OpenLayers.Rico.Corner.reRound(this.groupDiv,options);this.setBackgroundColor();this.setOpacity();}},getCornersToRound:function(){var corners=['tl','tr','bl','br'];var corner=OpenLayers.Bounds.oppositeQuadrant(this.relativePosition);OpenLayers.Util.removeItem(corners,corner);return corners.join(" ");},CLASS_NAME:"OpenLayers.Popup.AnchoredBubble"});OpenLayers.Popup.AnchoredBubble.CORNER_SIZE=5;OpenLayers.Layer.WorldWind=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{},isBaseLayer:true,lzd:null,zoomLevels:null,initialize:function(name,url,lzd,zoomLevels,params,options){this.lzd=lzd;this.zoomLevels=zoomLevels;var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},getZoom:function(){var zoom=this.map.getZoom();var extent=this.map.getMaxExtent();zoom=zoom-Math.log(this.maxResolution/(this.lzd/512))/Math.log(2);return zoom;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var zoom=this.getZoom();var extent=this.map.getMaxExtent();var deg=this.lzd/Math.pow(2,this.getZoom());var x=Math.floor((bounds.left-extent.left)/deg);var y=Math.floor((bounds.bottom-extent.bottom)/deg);if(this.map.getResolution()<=(this.lzd/512)&&this.getZoom()<=this.zoomLevels){return this.getFullRequestString({L:zoom,X:x,Y:y});}else{return OpenLayers.Util.getImagesLocation()+"blank.gif";}},CLASS_NAME:"OpenLayers.Layer.WorldWind"});if(!OpenLayers.Format.GML){OpenLayers.Format.GML={};}
+OpenLayers.Format.GML.Base=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{gml:"http://www.opengis.net/gml",gml32:"http://www.opengis.net/gml/3.2",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs"},defaultPrefix:"gml",schemaLocation:null,featureType:null,featureNS:null,geometryName:"geometry",extractAttributes:true,srsName:null,xy:true,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g),featureMember:(/^(.*:)?featureMembers?$/)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.setGeometryTypes();if(options&&options.featureNS){this.setNamespace("feature",options.featureNS);}
+this.singleFeatureType=!options||(typeof options.featureType==="string");},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var features=[];this.readNode(data,{features:features},true);if(features.length==0){var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMember");if(elements.length){for(var i=0,len=elements.length;i<len;++i){this.readNode(elements[i],{features:features},true);}}else{var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMembers");if(elements.length){this.readNode(elements[0],{features:features},true);}}}
+return features;},readNode:function(node,obj,first){if(first===true&&this.autoConfig===true){this.featureType=null;delete this.namespaceAlias[this.featureNS];delete this.namespaces["feature"];this.featureNS=null;}
+if(!this.featureNS&&(!(node.prefix in this.namespaces)&&node.parentNode.namespaceURI==this.namespaces["gml"]&&this.regExes.featureMember.test(node.parentNode.nodeName))){this.featureType=node.nodeName.split(":").pop();this.setNamespace("feature",node.namespaceURI);this.featureNS=node.namespaceURI;this.autoConfig=true;}
+return OpenLayers.Format.XML.prototype.readNode.apply(this,[node,obj]);},readers:{"gml":{"featureMember":function(node,obj){this.readChildNodes(node,obj);},"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"name":function(node,obj){obj.name=this.getChildValue(node);},"boundedBy":function(node,obj){var container={};this.readChildNodes(node,container);if(container.components&&container.components.length>0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");if(this.xy){points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{points[i]=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+obj.points=points;},"coord":function(node,obj){var coord={};this.readChildNodes(node,coord);if(!obj.points){obj.points=[];}
+obj.points.push(new OpenLayers.Geometry.Point(coord.x,coord.y,coord.z));},"X":function(node,coord){coord.x=this.getChildValue(node);},"Y":function(node,coord){coord.y=this.getChildValue(node);},"Z":function(node,coord){coord.z=this.getChildValue(node);},"MultiPoint":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPoint(obj.components)];},"pointMember":function(node,obj){this.readChildNodes(node,obj);},"LineString":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"MultiLineString":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];},"lineStringMember":function(node,obj){this.readChildNodes(node,obj);},"Polygon":function(node,container){var obj={outer:null,inner:[]};this.readChildNodes(node,obj);obj.inner.unshift(obj.outer);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.Polygon(obj.inner));},"LinearRing":function(node,obj){var container={};this.readChildNodes(node,container);obj.components=[new OpenLayers.Geometry.LinearRing(container.points)];},"MultiPolygon":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];},"polygonMember":function(node,obj){this.readChildNodes(node,obj);},"GeometryCollection":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.Collection(obj.components)];},"geometryMember":function(node,obj){this.readChildNodes(node,obj);}},"feature":{"*":function(node,obj){var name;var local=node.localName||node.nodeName.split(":").pop();if(obj.features){if(!this.singleFeatureType&&(OpenLayers.Util.indexOf(this.featureType,local)!==-1)){name="_typeName";}else if(local===this.featureType){name="_typeName";}}else{if(node.childNodes.length==0||(node.childNodes.length==1&&node.firstChild.nodeType==3)){if(this.extractAttributes){name="_attribute";}}else{name="_geometry";}}
+if(name){this.readers.feature[name].apply(this,[node,obj]);}},"_typeName":function(node,obj){var container={components:[],attributes:{}};this.readChildNodes(node,container);if(container.name){container.attributes.name=container.name;}
+var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);if(!this.singleFeatureType){feature.type=node.nodeName.split(":").pop();feature.namespace=node.namespaceURI;}
+var fid=node.getAttribute("fid")||this.getAttributeNS(node,this.namespaces["gml"],"id");if(fid){feature.fid=fid;}
+if(this.internalProjection&&this.externalProjection&&feature.geometry){feature.geometry.transform(this.externalProjection,this.internalProjection);}
+if(container.bounds){feature.bounds=container.bounds;}
+obj.features.push(feature);},"_geometry":function(node,obj){if(!this.geometryName){this.geometryName=node.nodeName.split(":").pop();}
+this.readChildNodes(node,obj);},"_attribute":function(node,obj){var local=node.localName||node.nodeName.split(":").pop();var value=this.getChildValue(node);obj.attributes[local]=value;}},"wfs":{"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);},}},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":{"featureMember":function(feature){var node=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",feature,node);return node;},"MultiPoint":function(geometry){var node=this.createElementNSPlus("gml:MultiPoint");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("pointMember",components[i],node);}
+return node;},"pointMember":function(geometry){var node=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",geometry,node);return node;},"MultiLineString":function(geometry){var node=this.createElementNSPlus("gml:MultiLineString");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("lineStringMember",components[i],node);}
+return node;},"lineStringMember":function(geometry){var node=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",geometry,node);return node;},"MultiPolygon":function(geometry){var node=this.createElementNSPlus("gml:MultiPolygon");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("polygonMember",components[i],node);}
+return node;},"polygonMember":function(geometry){var node=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",geometry,node);return node;},"GeometryCollection":function(geometry){var node=this.createElementNSPlus("gml:GeometryCollection");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("geometryMember",geometry.components[i],node);}
+return node;},"geometryMember":function(geometry){var node=this.createElementNSPlus("gml:geometryMember");var child=this.writeNode("feature:_geometry",geometry);node.appendChild(child.firstChild);return node;}},"feature":{"_typeName":function(feature){var node=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:feature.fid}});if(feature.geometry){this.writeNode("feature:_geometry",feature.geometry,node);}
+for(var name in feature.attributes){var value=feature.attributes[name];if(value!=null){this.writeNode("feature:_attribute",{name:name,value:value},node);}}
+return node;},"_geometry":function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone().transform(this.internalProjection,this.externalProjection);}
+var node=this.createElementNSPlus("feature:"+this.geometryName);var type=this.geometryTypes[geometry.CLASS_NAME];var child=this.writeNode("gml:"+type,geometry,node);if(this.srsName){child.setAttribute("srsName",this.srsName);}
+return node;},"_attribute":function(obj){return this.createElementNSPlus("feature:"+obj.name,{value:obj.value});}},"wfs":{"FeatureCollection":function(features){var node=this.createElementNSPlus("wfs:FeatureCollection");for(var i=0,len=features.length;i<len;++i){this.writeNode("gml:featureMember",features[i],node);}
+return node;}}},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":"LineString","OpenLayers.Geometry.MultiLineString":"MultiLineString","OpenLayers.Geometry.Polygon":"Polygon","OpenLayers.Geometry.MultiPolygon":"MultiPolygon","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.Base"});OpenLayers.Format.WMTSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",yx:{"urn:ogc:def:crs:EPSG::4326":true},createLayer:function(capabilities,config){var layer;var required={layer:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}}
+var contents=capabilities.contents;var matrixSet=contents.tileMatrixSets[config.matrixSet];var layers=contents.layers;var layerDef;for(var i=0,ii=contents.layers.length;i<ii;++i){if(contents.layers[i].identifier===config.layer){layerDef=contents.layers[i];break;}}
+if(layerDef&&matrixSet){var style;for(var i=0,ii=layerDef.styles.length;i<ii;++i){style=layerDef.styles[i];if(style.isDefault){break;}}
+layer=new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults(config,{url:capabilities.operationsMetadata.GetTile.dcp.http.get,name:layerDef.title,style:style.identifier,matrixIds:matrixSet.matrixIds}));}
+return layer;},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities"});OpenLayers.Layer.Google.v3={DEFAULTS:{maxExtent:new OpenLayers.Bounds(-128*156543.03390625,-128*156543.03390625,128*156543.03390625,128*156543.03390625),sphericalMercator:true,maxResolution:156543.03390625,units:"m",projection:"EPSG:900913"},animationEnabled:true,loadMapObject:function(){if(!this.type){this.type=google.maps.MapTypeId.ROADMAP;}
+var mapObject;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMapContainer";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);var center=this.map.getCenter();mapObject=new google.maps.Map(div,{center:center?new google.maps.LatLng(center.lat,center.lon):new google.maps.LatLng(0,0),zoom:this.map.getZoom()||0,mapTypeId:this.type,disableDefaultUI:true,keyboardShortcuts:false,draggable:false,disableDoubleClickZoom:true,scrollwheel:false,streetViewControl:false});cache={mapObject:mapObject,count:1};OpenLayers.Layer.Google.cache[this.map.id]=cache;this.repositionListener=google.maps.event.addListenerOnce(mapObject,"center_changed",OpenLayers.Function.bind(this.repositionMapElements,this));}
+this.mapObject=mapObject;this.setGMapVisibility(this.visibility);},repositionMapElements:function(){google.maps.event.trigger(this.mapObject,"resize");var div=this.mapObject.getDiv().firstChild;if(!div||div.childNodes.length<3){this.repositionTimer=window.setTimeout(OpenLayers.Function.bind(this.repositionMapElements,this),250);return false;}
+var cache=OpenLayers.Layer.Google.cache[this.map.id];var container=this.map.viewPortDiv;while(div.lastChild.style.display=="none"){container.appendChild(div.lastChild);}
+var termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright olLayerGoogleV3";termsOfUse.style.display="";cache.termsOfUse=termsOfUse;var poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";poweredBy.style.display="";cache.poweredBy=poweredBy;this.setGMapVisibility(this.visibility);},onMapResize:function(){if(this.visibility){google.maps.event.trigger(this.mapObject,"resize");}else{var cache=OpenLayers.Layer.Google.cache[this.map.id];if(!cache.resized){var layer=this;google.maps.event.addListenerOnce(this.mapObject,"tilesloaded",function(){google.maps.event.trigger(layer.mapObject,"resize");layer.moveTo(layer.map.getCenter(),layer.map.getZoom());delete cache.resized;});}
+cache.resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var type=this.type;var layers=this.map.layers;var layer;for(var i=layers.length-1;i>=0;--i){layer=layers[i];if(layer instanceof OpenLayers.Layer.Google&&layer.visibility===true&&layer.inRange===true){type=layer.type;visible=true;break;}}
+var container=this.mapObject.getDiv();if(visible===true){this.mapObject.setMapTypeId(type);container.style.left="";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.left="";cache.termsOfUse.style.display="";cache.poweredBy.style.display="";}
+cache.displayed=this.id;}else{delete cache.displayed;container.style.left="-9999px";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.display="none";cache.termsOfUse.style.left="-9999px";cache.poweredBy.style.display="none";}}}},getMapContainer:function(){return this.mapObject.getDiv();},getMapObjectBoundsFromOLBounds:function(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new google.maps.LatLngBounds(new google.maps.LatLng(sw.lat,sw.lon),new google.maps.LatLng(ne.lat,ne.lon));}
+return moBounds;},getMapObjectLonLatFromMapObjectPixel:function(moPixel){var size=this.map.getSize();var lon=this.getLongitudeFromMapObjectLonLat(this.mapObject.center);var lat=this.getLatitudeFromMapObjectLonLat(this.mapObject.center);var res=this.map.getResolution();var delta_x=moPixel.x-(size.w/2);var delta_y=moPixel.y-(size.h/2);var lonlat=new OpenLayers.LonLat(lon+delta_x*res,lat-delta_y*res);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}
+return this.getMapObjectLonLatFromLonLat(lonlat.lon,lonlat.lat);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);var res=this.map.getResolution();var extent=this.map.getExtent();var px=new OpenLayers.Pixel((1/res*(lon-extent.left)),(1/res*(extent.top-lat)));return this.getMapObjectPixelFromXY(px.x,px.y);},setMapObjectCenter:function(center,zoom){if(this.animationEnabled===false&&zoom!=this.mapObject.zoom){var mapContainer=this.getMapContainer();google.maps.event.addListenerOnce(this.mapObject,"idle",function(){mapContainer.style.visibility="";});mapContainer.style.visibility="hidden";}
+this.mapObject.setOptions({center:center,zoom:zoom});},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new google.maps.LatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new google.maps.LatLng(lat,lon);}
+return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new google.maps.Point(x,y);},destroy:function(){if(this.repositionListener){google.maps.event.removeListener(this.repositionListener);}
+if(this.repositionTimer){window.clearTimeout(this.repositionTimer);}
+OpenLayers.Layer.Google.prototype.destroy.apply(this,arguments);}};OpenLayers.Format.WPSDescribeProcess=OpenLayers.Class(OpenLayers.Format.XML,{VERSION:"1.0.0",namespaces:{wps:"http://www.opengis.net/wps/1.0.0",ows:"http://www.opengis.net/ows/1.1",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",defaultPrefix:"wps",regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var info={};this.readNode(data,info);return info;},readers:{"wps":{"ProcessDescriptions":function(node,obj){obj.processDescriptions={};this.readChildNodes(node,obj.processDescriptions);},"ProcessDescription":function(node,processDescriptions){var processVersion=this.getAttributeNS(node,this.namespaces.wps,"processVersion");var processDescription={processVersion:processVersion,statusSupported:(node.getAttribute("statusSupported")==="true"),storeSupported:(node.getAttribute("storeSupported")==="true")};this.readChildNodes(node,processDescription);processDescriptions[processDescription.identifier]=processDescription;},"DataInputs":function(node,processDescription){processDescription.dataInputs=[];this.readChildNodes(node,processDescription.dataInputs);},"ProcessOutputs":function(node,processDescription){processDescription.processOutputs=[];this.readChildNodes(node,processDescription.processOutputs);},"Output":function(node,processOutputs){var output={};this.readChildNodes(node,output);processOutputs.push(output);},"ComplexOutput":function(node,output){output.complexOutput={};this.readChildNodes(node,output.complexOutput);},"Input":function(node,dataInputs){var input={maxOccurs:parseInt(node.getAttribute("maxOccurs")),minOccurs:parseInt(node.getAttribute("minOccurs"))};this.readChildNodes(node,input);dataInputs.push(input);},"BoundingBoxData":function(node,input){input.boundingBoxData={};this.readChildNodes(node,input.boundingBoxData);},"CRS":function(node,obj){if(!obj.CRSs){obj.CRSs={};}
+obj.CRSs[this.getChildValue(node)]=true;},"LiteralData":function(node,input){input.literalData={};this.readChildNodes(node,input.literalData);},"ComplexData":function(node,input){input.complexData={};this.readChildNodes(node,input.complexData);},"Default":function(node,complexData){complexData["default"]={};this.readChildNodes(node,complexData["default"]);},"Supported":function(node,complexData){complexData["supported"]={};this.readChildNodes(node,complexData["supported"]);},"Format":function(node,obj){var format={};this.readChildNodes(node,format);if(!obj.formats){obj.formats={};}
+obj.formats[format.mimeType]=true;},"MimeType":function(node,format){format.mimeType=this.getChildValue(node);}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.WPSDescribeProcess"});OpenLayers.Format.CSWGetRecords.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{csw:"http://www.opengis.net/cat/csw/2.0.2",dc:"http://purl.org/dc/elements/1.1/",dct:"http://purl.org/dc/terms/",geonet:"http://www.fao.org/geonetwork",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",requestId:null,resultType:null,outputFormat:null,outputSchema:null,startPosition:null,maxRecords:null,DistributedSearch:null,ResponseHandler:null,Query:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetRecordsResponse":function(node,obj){obj.records=[];this.readChildNodes(node,obj);var version=this.getAttributeNS(node,"",'version');if(version!=""){obj.version=version;}},"RequestId":function(node,obj){obj.RequestId=this.getChildValue(node);},"SearchStatus":function(node,obj){obj.SearchStatus={};var timestamp=this.getAttributeNS(node,"",'timestamp');if(timestamp!=""){obj.SearchStatus.timestamp=timestamp;}},"SearchResults":function(node,obj){this.readChildNodes(node,obj);var attrs=node.attributes;var SearchResults={};for(var i=0,len=attrs.length;i<len;++i){if((attrs[i].name=="numberOfRecordsMatched")||(attrs[i].name=="numberOfRecordsReturned")||(attrs[i].name=="nextRecord")){SearchResults[attrs[i].name]=parseInt(attrs[i].nodeValue);}else{SearchResults[attrs[i].name]=attrs[i].nodeValue;}}
+obj.SearchResults=SearchResults;},"SummaryRecord":function(node,obj){var record={type:"SummaryRecord"};this.readChildNodes(node,record);obj.records.push(record);},"BriefRecord":function(node,obj){var record={type:"BriefRecord"};this.readChildNodes(node,record);obj.records.push(record);},"DCMIRecord":function(node,obj){var record={type:"DCMIRecord"};this.readChildNodes(node,record);obj.records.push(record);},"Record":function(node,obj){var record={type:"Record"};this.readChildNodes(node,record);obj.records.push(record);},"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();obj[name]=this.getChildValue(node);}},"geonet":{"info":function(node,obj){var gninfo={};this.readChildNodes(node,gninfo);obj.gninfo=gninfo;}},"dc":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(OpenLayers.Util.isArray(obj[name]))){obj[name]=new Array();}
+var dc_element={};var attrs=node.attributes;for(var i=0,len=attrs.length;i<len;++i){dc_element[attrs[i].name]=attrs[i].nodeValue;}
+dc_element.value=this.getChildValue(node);obj[name].push(dc_element);}},"dct":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(OpenLayers.Util.isArray(obj[name]))){obj[name]=new Array();}
+obj[name].push(this.getChildValue(node));}},"ows":OpenLayers.Util.applyDefaults({"BoundingBox":function(node,obj){if(obj.bounds){obj.BoundingBox=[{crs:obj.projection,value:[obj.bounds.left,obj.bounds.bottom,obj.bounds.right,obj.bounds.top]}];delete obj.projection;delete obj.bounds;}
+OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(this,arguments);}},OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])},write:function(options){var node=this.writeNode("csw:GetRecords",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetRecords":function(options){if(!options){options={};}
+var node=this.createElementNSPlus("csw:GetRecords",{attributes:{service:"CSW",version:this.version,requestId:options.requestId||this.requestId,resultType:options.resultType||this.resultType,outputFormat:options.outputFormat||this.outputFormat,outputSchema:options.outputSchema||this.outputSchema,startPosition:options.startPosition||this.startPosition,maxRecords:options.maxRecords||this.maxRecords}});if(options.DistributedSearch||this.DistributedSearch){this.writeNode("csw:DistributedSearch",options.DistributedSearch||this.DistributedSearch,node);}
+var ResponseHandler=options.ResponseHandler||this.ResponseHandler;if(OpenLayers.Util.isArray(ResponseHandler)&&ResponseHandler.length>0){for(var i=0,len=ResponseHandler.length;i<len;i++){this.writeNode("csw:ResponseHandler",ResponseHandler[i],node);}}
+this.writeNode("Query",options.Query||this.Query,node);return node;},"DistributedSearch":function(options){var node=this.createElementNSPlus("csw:DistributedSearch",{attributes:{hopCount:options.hopCount}});return node;},"ResponseHandler":function(options){var node=this.createElementNSPlus("csw:ResponseHandler",{value:options.value});return node;},"Query":function(options){if(!options){options={};}
+var node=this.createElementNSPlus("csw:Query",{attributes:{typeNames:options.typeNames||"csw:Record"}});var ElementName=options.ElementName;if(OpenLayers.Util.isArray(ElementName)&&ElementName.length>0){for(var i=0,len=ElementName.length;i<len;i++){this.writeNode("csw:ElementName",ElementName[i],node);}}else{this.writeNode("csw:ElementSetName",options.ElementSetName||{value:'summary'},node);}
+if(options.Constraint){this.writeNode("csw:Constraint",options.Constraint,node);}
+if(options.SortBy){this.writeNode("ogc:SortBy",options.SortBy,node);}
+return node;},"ElementName":function(options){var node=this.createElementNSPlus("csw:ElementName",{value:options.value});return node;},"ElementSetName":function(options){var node=this.createElementNSPlus("csw:ElementSetName",{attributes:{typeNames:options.typeNames},value:options.value});return node;},"Constraint":function(options){var node=this.createElementNSPlus("csw:Constraint",{attributes:{version:options.version}});if(options.Filter){var format=new OpenLayers.Format.Filter({version:options.version});node.appendChild(format.write(options.Filter));}else if(options.CqlText){var child=this.createElementNSPlus("CqlText",{value:options.CqlText.value});node.appendChild(child);}
+return node;}},"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.CSWGetRecords.v2_0_2"});OpenLayers.Marker.Box=OpenLayers.Class(OpenLayers.Marker,{bounds:null,div:null,initialize:function(bounds,borderColor,borderWidth){this.bounds=bounds;this.div=OpenLayers.Util.createDiv();this.div.style.overflow='hidden';this.events=new OpenLayers.Events(this,this.div,null);this.setBorder(borderColor,borderWidth);},destroy:function(){this.bounds=null;this.div=null;OpenLayers.Marker.prototype.destroy.apply(this,arguments);},setBorder:function(color,width){if(!color){color="red";}
+if(!width){width=2;}
+this.div.style.border=width+"px solid "+color;},draw:function(px,sz){OpenLayers.Util.modifyDOMElement(this.div,null,px,sz);return this.div;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsBounds(this.bounds,true,true);}
+return onScreen;},display:function(display){this.div.style.display=(display)?"":"none";},CLASS_NAME:"OpenLayers.Marker.Box"});OpenLayers.Format.Text=OpenLayers.Class(OpenLayers.Format,{defaultStyle:null,extractStyles:true,initialize:function(options){options=options||{};if(options.extractStyles!==false){options.defaultStyle={'externalGraphic':OpenLayers.Util.getImagesLocation()+"marker.png",'graphicWidth':21,'graphicHeight':25,'graphicXOffset':-10.5,'graphicYOffset':-12.5};}
+OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(text){var lines=text.split('\n');var columns;var features=[];for(var lcv=0;lcv<(lines.length-1);lcv++){var currLine=lines[lcv].replace(/^\s*/,'').replace(/\s*$/,'');if(currLine.charAt(0)!='#'){if(!columns){columns=currLine.split('\t');}else{var vals=currLine.split('\t');var geometry=new OpenLayers.Geometry.Point(0,0);var attributes={};var style=this.defaultStyle?OpenLayers.Util.applyDefaults({},this.defaultStyle):null;var icon,iconSize,iconOffset,overflow;var set=false;for(var valIndex=0;valIndex<vals.length;valIndex++){if(vals[valIndex]){if(columns[valIndex]=='point'){var coords=vals[valIndex].split(',');geometry.y=parseFloat(coords[0]);geometry.x=parseFloat(coords[1]);set=true;}else if(columns[valIndex]=='lat'){geometry.y=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='lon'){geometry.x=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='title')
+attributes['title']=vals[valIndex];else if(columns[valIndex]=='image'||columns[valIndex]=='icon'&&style){style['externalGraphic']=vals[valIndex];}else if(columns[valIndex]=='iconSize'&&style){var size=vals[valIndex].split(',');style['graphicWidth']=parseFloat(size[0]);style['graphicHeight']=parseFloat(size[1]);}else if(columns[valIndex]=='iconOffset'&&style){var offset=vals[valIndex].split(',');style['graphicXOffset']=parseFloat(offset[0]);style['graphicYOffset']=parseFloat(offset[1]);}else if(columns[valIndex]=='description'){attributes['description']=vals[valIndex];}else if(columns[valIndex]=='overflow'){attributes['overflow']=vals[valIndex];}else{attributes[columns[valIndex]]=vals[valIndex];}}}
+if(set){if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
+var feature=new OpenLayers.Feature.Vector(geometry,attributes,style);features.push(feature);}}}}
+return features;},CLASS_NAME:"OpenLayers.Format.Text"});OpenLayers.Layer.Text=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);this.features=new Array();},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadText:function(){if(!this.loaded){if(this.location!=null){var onFail=function(e){this.events.triggerEvent("loadend");};this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,failure:onFail,scope:this});this.loaded=true;}}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadText();}},parseData:function(ajaxRequest){var text=ajaxRequest.responseText;var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
+var parser=new OpenLayers.Format.Text(options);var features=parser.read(text);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];var location;var iconSize,iconOffset;location=new OpenLayers.LonLat(feature.geometry.x,feature.geometry.y);if(feature.style.graphicWidth&&feature.style.graphicHeight){iconSize=new OpenLayers.Size(feature.style.graphicWidth,feature.style.graphicHeight);}
+if(feature.style.graphicXOffset!==undefined&&feature.style.graphicYOffset!==undefined){iconOffset=new OpenLayers.Pixel(feature.style.graphicXOffset,feature.style.graphicYOffset);}
+if(feature.style.externalGraphic!=null){data.icon=new OpenLayers.Icon(feature.style.externalGraphic,iconSize,iconOffset);}else{data.icon=OpenLayers.Marker.defaultIcon();if(iconSize!=null){data.icon.setSize(iconSize);}}
+if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){data['popupContentHTML']='<h2>'+feature.attributes.title+'</h2>'+'<p>'+feature.attributes.description+'</p>';}
+data['overflow']=feature.attributes.overflow||"auto";var markerFeature=new OpenLayers.Feature(this,location,data);this.features.push(markerFeature);var marker=markerFeature.createMarker();if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){marker.events.register('click',markerFeature,this.markerClick);}
+this.addMarker(marker);}
+this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}
+if(!sameMarkerClicked){this.layer.map.addPopup(this.createPopup());}
+OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.Text"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.Drag.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.Drag.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();}
+if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}}
+this.layer=null;this.feature=null;deactivated=true;}
+return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.map.getLonLatFromPixel(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();}
+if(this.persist){this.clear();}
+this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.map.getLonLatFromPixel(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));}
+this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;}
+this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);}
+this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);}
+this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];}
+for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);}
+if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Control.SLDSelect=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["selected"],clearOnDeactivate:false,layers:null,callbacks:null,selectionSymbolizer:{'Polygon':{fillColor:'#FF0000',stroke:false},'Line':{strokeColor:'#FF0000',strokeWidth:2},'Point':{graphicName:'square',fillColor:'#FF0000',pointRadius:5}},layerOptions:null,handlerOptions:null,sketchStyle:null,wfsCache:{},layerCache:{},initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.select,click:this.select},this.callbacks);this.handlerOptions=this.handlerOptions||{};this.layerOptions=OpenLayers.Util.applyDefaults(this.layerOptions,{displayInLayerSwitcher:false,tileOptions:{maxGetUrlLength:2048}});if(this.sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":this.sketchStyle})});}
+this.handler=new handler(this,this.callbacks,this.handlerOptions);},destroy:function(){for(var key in this.layerCache){delete this.layerCache[key];}
+for(var key in this.wfsCache){delete this.wfsCache[key];}
+OpenLayers.Control.prototype.destroy.apply(this,arguments);},coupleLayerVisiblity:function(evt){this.setVisibility(evt.object.getVisibility());},createSelectionLayer:function(source){var selectionLayer;if(!this.layerCache[source.id]){selectionLayer=new OpenLayers.Layer.WMS(source.name,source.url,source.params,OpenLayers.Util.applyDefaults(this.layerOptions,source.getOptions()));this.layerCache[source.id]=selectionLayer;if(this.layerOptions.displayInLayerSwitcher===false){source.events.on({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});}
+this.map.addLayer(selectionLayer);}else{selectionLayer=this.layerCache[source.id];}
+return selectionLayer;},createSLD:function(layer,filters,geometryAttributes){var sld={version:"1.0.0",namedLayers:{}};var layerNames=[layer.params.LAYERS].join(",").split(",");for(var i=0,len=layerNames.length;i<len;i++){var name=layerNames[i];sld.namedLayers[name]={name:name,userStyles:[]};var symbolizer=this.selectionSymbolizer;var geometryAttribute=geometryAttributes[i];if(geometryAttribute.type.indexOf('Polygon')>=0){symbolizer={Polygon:this.selectionSymbolizer['Polygon']};}else if(geometryAttribute.type.indexOf('LineString')>=0){symbolizer={Line:this.selectionSymbolizer['Line']};}else if(geometryAttribute.type.indexOf('Point')>=0){symbolizer={Point:this.selectionSymbolizer['Point']};}
+var filter=filters[i];sld.namedLayers[name].userStyles.push({name:'default',rules:[new OpenLayers.Rule({symbolizer:symbolizer,filter:filter,maxScaleDenominator:layer.options.minScale})]});}
+return new OpenLayers.Format.SLD({srsName:this.map.getProjection()}).write(sld);},parseDescribeLayer:function(request){var format=new OpenLayers.Format.WMSDescribeLayer();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+var describeLayer=format.read(doc);var typeNames=[];var url=null;for(var i=0,len=describeLayer.length;i<len;i++){if(describeLayer[i].owsType=="WFS"){typeNames.push(describeLayer[i].typeName);url=describeLayer[i].owsURL;}}
+var options={url:url,params:{SERVICE:"WFS",TYPENAME:typeNames.toString(),REQUEST:"DescribeFeatureType",VERSION:"1.0.0"},callback:function(request){var format=new OpenLayers.Format.WFSDescribeFeatureType();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+var describeFeatureType=format.read(doc);this.control.wfsCache[this.layer.id]=describeFeatureType;this.control._queue&&this.control.applySelection();},scope:this};OpenLayers.Request.GET(options);},getGeometryAttributes:function(layer){var result=[];var cache=this.wfsCache[layer.id];for(var i=0,len=cache.featureTypes.length;i<len;i++){var typeName=cache.featureTypes[i];var properties=typeName.properties;for(var j=0,lenj=properties.length;j<lenj;j++){var property=properties[j];var type=property.type;if((type.indexOf('LineString')>=0)||(type.indexOf('GeometryAssociationType')>=0)||(type.indexOf('GeometryPropertyType')>=0)||(type.indexOf('Point')>=0)||(type.indexOf('Polygon')>=0)){result.push(property);}}}
+return result;},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&!this.wfsCache[layer.id]){var options={url:layer.url,params:{SERVICE:"WMS",VERSION:layer.params.VERSION,LAYERS:layer.params.LAYERS,REQUEST:"DescribeLayer"},callback:this.parseDescribeLayer,scope:{layer:layer,control:this}};OpenLayers.Request.GET(options);}}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&this.clearOnDeactivate===true){var layerCache=this.layerCache;var selectionLayer=layerCache[layer.id];if(selectionLayer){layer.events.un({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});selectionLayer.destroy();delete layerCache[layer.id];}}}}
+return deactivated;},setLayers:function(layers){if(this.active){this.deactivate();this.layers=layers;this.activate();}else{this.layers=layers;}},createFilter:function(geometryAttribute,geometry){var filter=null;if(this.handler instanceof OpenLayers.Handler.RegularPolygon){if(this.handler.irregular===true){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:geometryAttribute.name,value:geometry.getBounds()});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Polygon){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else if(this.handler instanceof OpenLayers.Handler.Path){if(geometryAttribute.type.indexOf('Point')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Click){if(geometryAttribute.type.indexOf('Polygon')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}}
+return filter;},select:function(geometry){this._queue=function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];var geometryAttributes=this.getGeometryAttributes(layer);var filters=[];for(var j=0,lenj=geometryAttributes.length;j<lenj;j++){var geometryAttribute=geometryAttributes[j];if(geometryAttribute!==null){if(!(geometry instanceof OpenLayers.Geometry)){var point=this.map.getLonLatFromPixel(geometry.xy);geometry=new OpenLayers.Geometry.Point(point.lon,point.lat);}
+var filter=this.createFilter(geometryAttribute,geometry);if(filter!==null){filters.push(filter);}}}
+var selectionLayer=this.createSelectionLayer(layer);var sld=this.createSLD(layer,filters,geometryAttributes);this.events.triggerEvent("selected",{layer:layer,filters:filters});selectionLayer.mergeNewParams({SLD_BODY:sld});delete this._queue;}};this.applySelection();},applySelection:function(){var canApply=true;for(var i=0,len=this.layers.length;i<len;i++){if(!this.wfsCache[this.layers[i].id]){canApply=false;break;}}
+canApply&&this._queue.call(this);},CLASS_NAME:"OpenLayers.Control.SLDSelect"});OpenLayers.Control.Scale=OpenLayers.Class(OpenLayers.Control,{element:null,geodesic:false,initialize:function(element,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.element=document.createElement("div");this.div.appendChild(this.element);}
+this.map.events.register('moveend',this,this.updateScale);this.updateScale();return this.div;},updateScale:function(){var scale;if(this.geodesic===true){var units=this.map.getUnits();if(!units){return;}
+var inches=OpenLayers.INCHES_PER_UNIT;scale=(this.map.getGeodesicPixelSize().w||0.000001)*inches["km"]*OpenLayers.DOTS_PER_INCH;}else{scale=this.map.getScale();}
+if(!scale){return;}
+if(scale>=9500&&scale<=950000){scale=Math.round(scale/1000)+"K";}else if(scale>=950000){scale=Math.round(scale/1000000)+"M";}else{scale=Math.round(scale);}
+this.element.innerHTML=OpenLayers.i18n("Scale = 1 : ${scaleDenom}",{'scaleDenom':scale});},CLASS_NAME:"OpenLayers.Control.Scale"});OpenLayers.Layer.MapGuide=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,useHttpTile:false,singleTile:false,useOverlay:false,useAsyncOverlay:true,TILE_PARAMS:{operation:'GETTILEIMAGE',version:'1.2.0'},SINGLE_TILE_PARAMS:{operation:'GETMAPIMAGE',format:'PNG',locale:'en',clip:'1',version:'1.0.0'},OVERLAY_PARAMS:{operation:'GETDYNAMICMAPOVERLAYIMAGE',format:'PNG',locale:'en',clip:'1',version:'2.0.0'},FOLDER_PARAMS:{tileColumnsPerFolder:30,tileRowsPerFolder:30,format:'png',querystring:null},defaultSize:new OpenLayers.Size(300,300),tileOriginCorner:"tl",initialize:function(name,url,params,options){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.transparent!="true")&&(this.transparent!=true));}
+if(options&&options.useOverlay!=null){this.useOverlay=options.useOverlay;}
+if(this.singleTile){if(this.useOverlay){OpenLayers.Util.applyDefaults(this.params,this.OVERLAY_PARAMS);if(!this.useAsyncOverlay){this.params.version="1.0.0";}}else{OpenLayers.Util.applyDefaults(this.params,this.SINGLE_TILE_PARAMS);}}else{if(this.useHttpTile){OpenLayers.Util.applyDefaults(this.params,this.FOLDER_PARAMS);}else{OpenLayers.Util.applyDefaults(this.params,this.TILE_PARAMS);}
+this.setTileSize(this.defaultSize);}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapGuide(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var url;var center=bounds.getCenterLonLat();var mapSize=this.map.getSize();if(this.singleTile){var params={setdisplaydpi:OpenLayers.DOTS_PER_INCH,setdisplayheight:mapSize.h*this.ratio,setdisplaywidth:mapSize.w*this.ratio,setviewcenterx:center.lon,setviewcentery:center.lat,setviewscale:this.map.getScale()};if(this.useOverlay&&!this.useAsyncOverlay){var getVisParams={};getVisParams=OpenLayers.Util.extend(getVisParams,params);getVisParams.operation="GETVISIBLEMAPEXTENT";getVisParams.version="1.0.0";getVisParams.session=this.params.session;getVisParams.mapName=this.params.mapName;getVisParams.format='text/xml';url=this.getFullRequestString(getVisParams);OpenLayers.Request.GET({url:url,async:false});}
+url=this.getFullRequestString(params);}else{var currentRes=this.map.getResolution();var colidx=Math.floor((bounds.left-this.maxExtent.left)/currentRes);colidx=Math.round(colidx/this.tileSize.w);var rowidx=Math.floor((this.maxExtent.top-bounds.top)/currentRes);rowidx=Math.round(rowidx/this.tileSize.h);if(this.useHttpTile){url=this.getImageFilePath({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}else{url=this.getFullRequestString({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}}
+return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];}
+var requestString=url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
+var paramsString=OpenLayers.Util.getParameterString(allParams);paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}}
+return requestString;},getImageFilePath:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];}
+var requestString=url;var tileRowGroup="";var tileColGroup="";if(newParams.tilerow<0){tileRowGroup='-';}
+if(newParams.tilerow==0){tileRowGroup+='0';}else{tileRowGroup+=Math.floor(Math.abs(newParams.tilerow/this.params.tileRowsPerFolder))*this.params.tileRowsPerFolder;}
+if(newParams.tilecol<0){tileColGroup='-';}
+if(newParams.tilecol==0){tileColGroup+='0';}else{tileColGroup+=Math.floor(Math.abs(newParams.tilecol/this.params.tileColumnsPerFolder))*this.params.tileColumnsPerFolder;}
+var tilePath='/S'+Math.floor(newParams.scaleindex)
++'/'+this.params.basemaplayergroupname
++'/R'+tileRowGroup
++'/C'+tileColGroup
++'/'+(newParams.tilerow%this.params.tileRowsPerFolder)
++'_'+(newParams.tilecol%this.params.tileColumnsPerFolder)
++'.'+this.params.format;if(this.params.querystring){tilePath+="?"+this.params.querystring;}
+requestString+=tilePath;return requestString;},calculateGridLayout:function(bounds,origin,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-origin.lon;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=origin.lon+tilecol*tilelon;var offsetlat=origin.lat-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=origin.lat-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.MapGuide"});OpenLayers.Control.Measure=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:['measure','measurepartial'],handlerOptions:null,callbacks:null,displaySystem:'metric',geodesic:false,displaySystemUnits:{geographic:['dd'],english:['mi','ft','in'],metric:['km','m']},partialDelay:300,delayedTrigger:null,persist:false,immediate:false,initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.Measure.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);var callbacks={done:this.measureComplete,point:this.measurePartial};if(this.immediate){callbacks.modify=this.measureImmediate;}
+this.callbacks=OpenLayers.Util.extend(callbacks,this.callbacks);this.handlerOptions=OpenLayers.Util.extend({persist:this.persist},this.handlerOptions);this.handler=new handler(this,this.callbacks,this.handlerOptions);},deactivate:function(){this.cancelDelay();return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},cancel:function(){this.cancelDelay();this.handler.cancel();},setImmediate:function(immediate){this.immediate=immediate;if(this.immediate){this.callbacks.modify=this.measureImmediate;}else{delete this.callbacks.modify;}},updateHandler:function(handler,options){var active=this.active;if(active){this.deactivate();}
+this.handler=new handler(this,this.callbacks,options);if(active){this.activate();}},measureComplete:function(geometry){this.cancelDelay();this.measure(geometry,"measure");},measurePartial:function(point,geometry){this.cancelDelay();geometry=geometry.clone();if(this.handler.freehandMode(this.handler.evt)){this.measure(geometry,"measurepartial");}else{this.delayedTrigger=window.setTimeout(OpenLayers.Function.bind(function(){this.delayedTrigger=null;this.measure(geometry,"measurepartial");},this),this.partialDelay);}},measureImmediate:function(point,feature,drawing){if(drawing&&this.delayedTrigger===null&&!this.handler.freehandMode(this.handler.evt)){this.measure(feature.geometry,"measurepartial");}},cancelDelay:function(){if(this.delayedTrigger!==null){window.clearTimeout(this.delayedTrigger);this.delayedTrigger=null;}},measure:function(geometry,eventType){var stat,order;if(geometry.CLASS_NAME.indexOf('LineString')>-1){stat=this.getBestLength(geometry);order=1;}else{stat=this.getBestArea(geometry);order=2;}
+this.events.triggerEvent(eventType,{measure:stat[0],units:stat[1],order:order,geometry:geometry});},getBestArea:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,area;for(var i=0,len=units.length;i<len;++i){unit=units[i];area=this.getArea(geometry,unit);if(area>1){break;}}
+return[area,unit];},getArea:function(geometry,units){var area,geomUnits;if(this.geodesic){area=geometry.getGeodesicArea(this.map.getProjectionObject());geomUnits="m";}else{area=geometry.getArea();geomUnits=this.map.getUnits();}
+var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];area*=Math.pow((inPerMapUnit/inPerDisplayUnit),2);}
+return area;},getBestLength:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,length;for(var i=0,len=units.length;i<len;++i){unit=units[i];length=this.getLength(geometry,unit);if(length>1){break;}}
+return[length,unit];},getLength:function(geometry,units){var length,geomUnits;if(this.geodesic){length=geometry.getGeodesicLength(this.map.getProjectionObject());geomUnits="m";}else{length=geometry.getLength();geomUnits=this.map.getUnits();}
+var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];length*=(inPerMapUnit/inPerDisplayUnit);}
+return length;},CLASS_NAME:"OpenLayers.Control.Measure"});OpenLayers.Format.WMC.v1_0_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd",initialize:function(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},read_wmc_SRS:function(layerContext,node){var srs=this.getChildValue(node);if(typeof layerContext.projections!="object"){layerContext.projections={};}
+var values=srs.split(/ +/);for(var i=0,len=values.length;i<len;i++){layerContext.projections[values[i]]=true;}},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);if(context.srs){var projections=[];for(var name in context.srs){projections.push(name);}
+node.appendChild(this.createElementDefaultNS("SRS",projections.join(" ")));}
+node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));if(context.dimensions){node.appendChild(this.write_wmc_DimensionList(context));}
+node.appendChild(this.write_wmc_LayerExtension(context));},CLASS_NAME:"OpenLayers.Format.WMC.v1_0_0"});OpenLayers.Format.WMTSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1_1_0,{version:"1.0.0",namespaces:{ows:"http://www.opengis.net/ows/1.1",wmts:"http://www.opengis.net/wmts/1.0",xlink:"http://www.w3.org/1999/xlink"},yx:null,defaultPrefix:"wmts",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;var yx=OpenLayers.Util.extend({},OpenLayers.Format.WMTSCapabilities.prototype.yx);this.yx=OpenLayers.Util.extend(yx,this.yx);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var capabilities={};this.readNode(data,capabilities);capabilities.version=this.version;return capabilities;},readers:{"wmts":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};obj.contents.layers=[];obj.contents.tileMatrixSets={};this.readChildNodes(node,obj.contents);},"Layer":function(node,obj){var layer={styles:[],formats:[],tileMatrixSetLinks:[]};layer.layers=[];this.readChildNodes(node,layer);obj.layers.push(layer);},"Style":function(node,obj){var style={};style.isDefault=(node.getAttribute("isDefault")==="true");this.readChildNodes(node,style);obj.styles.push(style);},"Format":function(node,obj){obj.formats.push(this.getChildValue(node));},"TileMatrixSetLink":function(node,obj){var tileMatrixSetLink={};this.readChildNodes(node,tileMatrixSetLink);obj.tileMatrixSetLinks.push(tileMatrixSetLink);},"TileMatrixSet":function(node,obj){if(obj.layers){var tileMatrixSet={matrixIds:[]};this.readChildNodes(node,tileMatrixSet);obj.tileMatrixSets[tileMatrixSet.identifier]=tileMatrixSet;}else{obj.tileMatrixSet=this.getChildValue(node);}},"TileMatrix":function(node,obj){var tileMatrix={supportedCRS:obj.supportedCRS};this.readChildNodes(node,tileMatrix);obj.matrixIds.push(tileMatrix);},"ScaleDenominator":function(node,obj){obj.scaleDenominator=parseFloat(this.getChildValue(node));},"TopLeftCorner":function(node,obj){var topLeftCorner=this.getChildValue(node);var coords=topLeftCorner.split(" ");var yx;if(obj.supportedCRS){var crs=obj.supportedCRS.replace(/urn:ogc:def:crs:(\w+):.+:(\w+)$/,"urn:ogc:def:crs:$1::$2");yx=!!this.yx[crs];}
+if(yx){obj.topLeftCorner=new OpenLayers.LonLat(coords[1],coords[0]);}else{obj.topLeftCorner=new OpenLayers.LonLat(coords[0],coords[1]);}},"TileWidth":function(node,obj){obj.tileWidth=parseInt(this.getChildValue(node));},"TileHeight":function(node,obj){obj.tileHeight=parseInt(this.getChildValue(node));},"MatrixWidth":function(node,obj){obj.matrixWidth=parseInt(this.getChildValue(node));},"MatrixHeight":function(node,obj){obj.matrixHeight=parseInt(this.getChildValue(node));},"ResourceURL":function(node,obj){obj.resourceUrl=obj.resourceUrl||{};obj.resourceUrl[node.getAttribute("resourceType")]={format:node.getAttribute("format"),template:node.getAttribute("template")};},"WSDL":function(node,obj){obj.wsdl={};obj.wsdl.href=node.getAttribute("xlink:href");},"ServiceMetadataURL":function(node,obj){obj.serviceMetadataUrl={};obj.serviceMetadataUrl.href=node.getAttribute("xlink:href");}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities.v1_0_0"});OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:true,panMapIfOutOfView:true,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:false,fixedRelativePosition:false,positionBlocks:{"tl":{'offset':new OpenLayers.Pixel(44,0),'padding':new OpenLayers.Bounds(8,40,8,9),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,18),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-632)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(0,-688)}]},"tr":{'offset':new OpenLayers.Pixel(-45,0),'padding':new OpenLayers.Bounds(8,40,8,9),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,19),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-631)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(0,0,null,null),position:new OpenLayers.Pixel(-215,-687)}]},"bl":{'offset':new OpenLayers.Pixel(45,0),'padding':new OpenLayers.Bounds(8,9,8,40),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(null,null,0,0),position:new OpenLayers.Pixel(-101,-674)}]},"br":{'offset':new OpenLayers.Pixel(-44,0),'padding':new OpenLayers.Bounds(8,9,8,40),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(0,null,null,0),position:new OpenLayers.Pixel(-311,-674)}]}},minSize:new OpenLayers.Size(105,10),maxSize:new OpenLayers.Size(1200,660),initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.imageSrc=OpenLayers.Util.getImagesLocation()+'cloud-popup-relative.png';OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass;},destroy:function(){OpenLayers.Popup.Framed.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Tile.Image.IFrame={useIFrame:null,clear:function(){if(this.useIFrame){if(this.imgDiv){var iFrame=this.imgDiv.firstChild;OpenLayers.Event.stopObservingElement(iFrame);this.imgDiv.removeChild(iFrame);delete iFrame;}}else{OpenLayers.Tile.Image.prototype.clear.apply(this,arguments);}},renderTile:function(){if(OpenLayers.Tile.Image.prototype.renderTile.apply(this,arguments)&&this.useIFrame){var form=this.createRequestForm();this.imgDiv.appendChild(form);form.submit();this.imgDiv.removeChild(form);delete form;}
+return true;},initImgDiv:function(){this.useIFrame=this.maxGetUrlLength!==null&&!this.layer.async&&this.url.length>this.maxGetUrlLength;if(this.imgDiv!=null){var nodeName=this.imgDiv.nodeName.toLowerCase();if((this.useIFrame&&nodeName=="img")||(!this.useIFrame&&nodeName=="div")){this.removeImgDiv();this.imgDiv=null;}}
+if(this.useIFrame){if(this.imgDiv==null){var eventPane=document.createElement("div");if(OpenLayers.BROWSER_NAME=="msie"){eventPane.style.backgroundColor='#FFFFFF';eventPane.style.filter='chroma(color=#FFFFFF)';}
+OpenLayers.Util.modifyDOMElement(eventPane,null,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");this.imgDiv=document.createElement("div");this.imgDiv.appendChild(eventPane);OpenLayers.Util.modifyDOMElement(this.imgDiv,this.id,null,this.layer.getImageSize(),"relative");this.imgDiv.className='olTileImage';this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);}
+this.imgDiv.map=this.layer.map;}
+this.imgDiv.viewRequestID=this.layer.map.viewRequestID;}else{OpenLayers.Tile.Image.prototype.initImgDiv.apply(this,arguments);}},createIFrame:function(){var id=this.id+'_iFrame';var iframe;if(OpenLayers.BROWSER_NAME=="msie"){iframe=document.createElement('<iframe name="'+id+'">');iframe.style.backgroundColor='#FFFFFF';iframe.style.filter='chroma(color=#FFFFFF)';}
+else{iframe=document.createElement('iframe');iframe.style.backgroundColor='transparent';iframe.name=id;}
+iframe.id=id;iframe.scrolling='no';iframe.marginWidth='0px';iframe.marginHeight='0px';iframe.frameBorder='0';OpenLayers.Util.modifyDOMElement(iframe,id,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");var onload=function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};OpenLayers.Event.observe(iframe,'load',OpenLayers.Function.bind(onload,this));return iframe;},createRequestForm:function(){var form=document.createElement('form');form.method='POST';var cacheId=this.layer.params["_OLSALT"];cacheId=(cacheId?cacheId+"_":"")+this.bounds.toBBOX();form.action=OpenLayers.Util.urlAppend(this.layer.url,cacheId);this.imgDiv.insertBefore(this.createIFrame(),this.imgDiv.firstChild);form.target=this.id+'_iFrame';var imageSize=this.layer.getImageSize();var params=OpenLayers.Util.getParameters(this.url);for(var par in params){var field=document.createElement('input');field.type='hidden';field.name=par;field.value=params[par];form.appendChild(field);}
+return form;}};OpenLayers.Geometry.Rectangle=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,width:null,height:null,initialize:function(x,y,width,height){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=x;this.y=y;this.width=width;this.height=height;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x+this.width,this.y+this.height);},getLength:function(){var length=(2*this.width)+(2*this.height);return length;},getArea:function(){var area=this.width*this.height;return area;},CLASS_NAME:"OpenLayers.Geometry.Rectangle"});OpenLayers.Strategy.Refresh=OpenLayers.Class(OpenLayers.Strategy,{force:false,interval:0,timer:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.layer.visibility===true){this.start();}
+this.layer.events.on({"visibilitychanged":this.reset,scope:this});}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.stop();}
+return deactivated;},reset:function(){if(this.layer.visibility===true){this.start();}else{this.stop();}},start:function(){if(this.interval&&typeof this.interval==="number"&&this.interval>0){this.timer=window.setInterval(OpenLayers.Function.bind(this.refresh,this),this.interval);}},refresh:function(){if(this.layer&&this.layer.refresh&&typeof this.layer.refresh=="function"){this.layer.refresh({force:this.force});}},stop:function(){if(this.timer!==null){window.clearInterval(this.timer);this.timer=null;}},CLASS_NAME:"OpenLayers.Strategy.Refresh"});OpenLayers.Format.SOSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.SOSCapabilities"});OpenLayers.Format.SOSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.SOSCapabilities,{namespaces:{ows:"http://www.opengis.net/ows/1.1",sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var capabilities={};this.readNode(data,capabilities);return capabilities;},readers:{"gml":OpenLayers.Util.applyDefaults({"name":function(node,obj){obj.name=this.getChildValue(node);},"TimePeriod":function(node,obj){obj.timePeriod={};this.readChildNodes(node,obj.timePeriod);},"beginPosition":function(node,timePeriod){timePeriod.beginPosition=this.getChildValue(node);},"endPosition":function(node,timePeriod){timePeriod.endPosition=this.getChildValue(node);}},OpenLayers.Format.GML.v3.prototype.readers["gml"]),"sos":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};this.readChildNodes(node,obj.contents);},"ObservationOfferingList":function(node,contents){contents.offeringList={};this.readChildNodes(node,contents.offeringList);},"ObservationOffering":function(node,offeringList){var id=this.getAttributeNS(node,this.namespaces.gml,"id");offeringList[id]={procedures:[],observedProperties:[],featureOfInterestIds:[],responseFormats:[],resultModels:[],responseModes:[]};this.readChildNodes(node,offeringList[id]);},"time":function(node,offering){offering.time={};this.readChildNodes(node,offering.time);},"procedure":function(node,offering){offering.procedures.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"observedProperty":function(node,offering){offering.observedProperties.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"featureOfInterest":function(node,offering){offering.featureOfInterestIds.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"responseFormat":function(node,offering){offering.responseFormats.push(this.getChildValue(node));},"resultModel":function(node,offering){offering.resultModels.push(this.getChildValue(node));},"responseMode":function(node,offering){offering.responseModes.push(this.getChildValue(node));;}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.SOSCapabilities.v1_0_0"});OpenLayers.Handler.Pinch=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:false,pinching:false,last:null,start:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},touchstart:function(evt){var propagate=true;this.pinching=false;if(OpenLayers.Event.isMultiTouch(evt)){this.started=true;this.last=this.start={distance:this.getDistance(evt.touches),delta:0,scale:1};this.callback("start",[evt,this.start]);propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;}
+OpenLayers.Event.stop(evt);return propagate;},touchmove:function(evt){if(this.started&&OpenLayers.Event.isMultiTouch(evt)){this.pinching=true;var current=this.getPinchData(evt);this.callback("move",[evt,current]);this.last=current;OpenLayers.Event.stop(evt);}
+return true;},touchend:function(evt){if(this.started){this.started=false;this.pinching=false;this.callback("done",[evt,this.start,this.last]);this.start=null;this.last=null;}
+return true;},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.pinching=false;activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.started=false;this.pinching=false;this.start=null;this.last=null;deactivated=true;}
+return deactivated;},getDistance:function(touches){var t0=touches[0];var t1=touches[1];return Math.sqrt(Math.pow(t0.clientX-t1.clientX,2)+
+Math.pow(t0.clientY-t1.clientY,2));},getPinchData:function(evt){var distance=this.getDistance(evt.touches);var scale=distance/this.start.distance;return{distance:distance,delta:this.last.distance-distance,scale:scale};},CLASS_NAME:"OpenLayers.Handler.Pinch"});OpenLayers.Control.NavToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation(),new OpenLayers.Control.ZoomBox()]);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);if(this.defaultControl===null){this.defaultControl=this.controls[0];}
+return div;},CLASS_NAME:"OpenLayers.Control.NavToolbar"});OpenLayers.Tile.WFS=OpenLayers.Class(OpenLayers.Tile,{features:null,url:null,request:null,initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.features=[];},destroy:function(){OpenLayers.Tile.prototype.destroy.apply(this,arguments);this.destroyAllFeatures();this.features=null;this.url=null;if(this.request){this.request.abort();this.request=null;}},clear:function(){this.destroyAllFeatures();},draw:function(){if(OpenLayers.Tile.prototype.draw.apply(this,arguments)){if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");}
+this.loadFeaturesForRegion(this.requestSuccess);}},loadFeaturesForRegion:function(success,failure){if(this.request){this.request.abort();}
+this.request=OpenLayers.Request.GET({url:this.url,success:success,failure:failure,scope:this});},requestSuccess:function(request){if(this.features){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(this.layer.vectorMode){this.layer.addFeatures(this.layer.formatObject.read(doc));}else{var xml=new OpenLayers.Format.XML();if(typeof doc=="string"){doc=xml.read(doc);}
+var resultFeatures=xml.getElementsByTagNameNS(doc,"http://www.opengis.net/gml","featureMember");this.addResults(resultFeatures);}}
+if(this.events){this.events.triggerEvent("loadend");}
+this.request=null;},addResults:function(results){for(var i=0;i<results.length;i++){var feature=new this.layer.featureClass(this.layer,results[i]);this.features.push(feature);}},destroyAllFeatures:function(){while(this.features.length>0){var feature=this.features.shift();feature.destroy();}},CLASS_NAME:"OpenLayers.Tile.WFS"});OpenLayers.Control.Geolocate=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["locationupdated","locationfailed","locationuncapable"],geolocation:navigator.geolocation,bind:true,watch:false,geolocationOptions:null,initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.Geolocate.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);this.geolocationOptions={};OpenLayers.Control.prototype.initialize.apply(this,[options]);},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){if(!this.geolocation){this.events.triggerEvent("locationuncapable");return false;}
+if(OpenLayers.Control.prototype.activate.apply(this,arguments)){if(this.watch){this.watchId=this.geolocation.watchPosition(OpenLayers.Function.bind(this.geolocate,this),OpenLayers.Function.bind(this.failure,this),this.geolocationOptions);}else{this.getCurrentLocation();}
+return true;}
+return false;},deactivate:function(){if(this.active&&this.watchId!==null){this.geolocation.clearWatch(this.watchId);}
+return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},geolocate:function(position){var center=new OpenLayers.LonLat(position.coords.longitude,position.coords.latitude).transform(new OpenLayers.Projection("EPSG:4326"),this.map.getProjectionObject());if(this.bind){this.map.setCenter(center);}
+this.events.triggerEvent("locationupdated",{position:position,point:new OpenLayers.Geometry.Point(center.lon,center.lat)});},getCurrentLocation:function(){if(!this.active||this.watch){return false;}
+this.geolocation.getCurrentPosition(OpenLayers.Function.bind(this.geolocate,this),OpenLayers.Function.bind(this.failure,this),this.geolocationOptions);return true;},failure:function(error){this.events.triggerEvent("locationfailed",{error:error});},CLASS_NAME:"OpenLayers.Control.Geolocate"});OpenLayers.Layer.ArcGIS93Rest=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{format:"png"},isBaseLayer:true,initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;}
+if(this.params.FORMAT=="jpg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"gif":"png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcGIS93Rest(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var projWords=this.projection.getCode().split(":");var srid=projWords[projWords.length-1];var imageSize=this.getImageSize();var newParams={'BBOX':bounds.toBBOX(),'SIZE':imageSize.w+","+imageSize.h,'F':"image",'BBOXSR':srid,'IMAGESR':srid};if(this.layerDefs){var layerDefStrList=[];var layerID;for(layerID in this.layerDefs){if(this.layerDefs.hasOwnProperty(layerID)){if(this.layerDefs[layerID]){layerDefStrList.push(layerID);layerDefStrList.push(":");layerDefStrList.push(this.layerDefs[layerID]);layerDefStrList.push(";");}}}
+if(layerDefStrList.length>0){newParams['LAYERDEFS']=layerDefStrList.join("");}}
+var requestString=this.getFullRequestString(newParams);return requestString;},setLayerFilter:function(id,queryDef){if(!this.layerDefs){this.layerDefs={};}
+if(queryDef){this.layerDefs[id]=queryDef;}else{delete this.layerDefs[id];}},clearLayerFilter:function(id){if(id){delete this.layerDefs[id];}else{delete this.layerDefs;}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},CLASS_NAME:"OpenLayers.Layer.ArcGIS93Rest"});OpenLayers.Layer.MapServer=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{mode:"map",map_imagetype:"png"},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.params.transparent!="true")&&(this.params.transparent!=true));}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var extent=[bounds.left,bounds.bottom,bounds.right,bounds.top];var imageSize=this.getImageSize();var url=this.getFullRequestString({mapext:extent,imgext:extent,map_size:[imageSize.w,imageSize.h],imgx:imageSize.w/2,imgy:imageSize.h/2,imgxy:[imageSize.w,imageSize.h]});return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(OpenLayers.Util.isArray(url)){url=this.selectUrl(paramsString,url);}
+var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
+paramsString=OpenLayers.Util.getParameterString(allParams);var requestString=url;paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}}
+return requestString;},CLASS_NAME:"OpenLayers.Layer.MapServer"});OpenLayers.Layer.MapServer.Untiled=OpenLayers.Class(OpenLayers.Layer.MapServer,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.MapServer.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.MapServer.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.MapServer class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer.Untiled(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.MapServer.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.MapServer.Untiled"});OpenLayers.Handler.Hover=OpenLayers.Class(OpenLayers.Handler,{delay:500,pixelTolerance:null,stopMove:false,px:null,timerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},mousemove:function(evt){if(this.passesTolerance(evt.xy)){this.clearTimer();this.callback('move',[evt]);this.px=evt.xy;evt=OpenLayers.Util.extend({},evt);this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);}
+return!this.stopMove;},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.eventsDiv)){this.clearTimer();this.callback('move',[evt]);}
+return true;},passesTolerance:function(px){var passes=true;if(this.pixelTolerance&&this.px){var dpx=Math.sqrt(Math.pow(this.px.x-px.x,2)+
+Math.pow(this.px.y-px.y,2));if(dpx<this.pixelTolerance){passes=false;}}
+return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}},delayedCall:function(evt){this.callback('pause',[evt]);},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();deactivated=true;}
+return deactivated;},CLASS_NAME:"OpenLayers.Handler.Hover"});OpenLayers.Control.GetFeature=OpenLayers.Class(OpenLayers.Control,{protocol:null,multipleKey:null,toggleKey:null,modifiers:null,multiple:false,click:true,single:true,clickout:true,toggle:false,clickTolerance:5,hover:false,box:false,maxFeatures:10,features:null,hoverFeature:null,handlerOptions:null,handlers:null,hoverResponse:null,filterType:OpenLayers.Filter.Spatial.BBOX,EVENT_TYPES:["featureselected","featuresselected","featureunselected","clickout","beforefeatureselected","beforefeaturesselected","hoverfeature","outfeature"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);this.features={};this.handlers={};if(this.click){this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.selectClick},this.handlerOptions.click||{});}
+if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},OpenLayers.Util.extend(this.handlerOptions.box,{boxDivClassName:"olHandlerBoxSelectFeature"}));}
+if(this.hover){this.handlers.hover=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.selectHover},OpenLayers.Util.extend(this.handlerOptions.hover,{'delay':250}));}},activate:function(){if(!this.active){for(var i in this.handlers){this.handlers[i].activate();}}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){for(var i in this.handlers){this.handlers[i].deactivate();}}
+return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},selectClick:function(evt){var bounds=this.pixelToBounds(evt.xy);this.setModifiers(evt);this.request(bounds,{single:this.single});},selectBox:function(position){var bounds;if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{if(this.click){return;}
+bounds=this.pixelToBounds(position);}
+this.setModifiers(this.handlers.box.dragHandler.evt);this.request(bounds);},selectHover:function(evt){var bounds=this.pixelToBounds(evt.xy);this.request(bounds,{single:true,hover:true});},cancelHover:function(){if(this.hoverResponse){this.protocol.abort(this.hoverResponse);this.hoverResponse=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");}},request:function(bounds,options){options=options||{};var filter=new OpenLayers.Filter.Spatial({type:this.filterType,value:bounds});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");var response=this.protocol.read({maxFeatures:options.single==true?this.maxFeatures:undefined,filter:filter,callback:function(result){if(result.success()){if(result.features.length){if(options.single==true){this.selectBestFeature(result.features,bounds.getCenterLonLat(),options);}else{this.select(result.features);}}else if(options.hover){this.hoverSelect();}else{this.events.triggerEvent("clickout");if(this.clickout){this.unselectAll();}}}
+OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},scope:this});if(options.hover==true){this.hoverResponse=response;}},selectBestFeature:function(features,clickPosition,options){options=options||{};if(features.length){var point=new OpenLayers.Geometry.Point(clickPosition.lon,clickPosition.lat);var feature,resultFeature,dist;var minDist=Number.MAX_VALUE;for(var i=0;i<features.length;++i){feature=features[i];if(feature.geometry){dist=point.distanceTo(feature.geometry,{edge:false});if(dist<minDist){minDist=dist;resultFeature=feature;if(minDist==0){break;}}}}
+if(options.hover==true){this.hoverSelect(resultFeature);}else{this.select(resultFeature||features);}}},setModifiers:function(evt){this.modifiers={multiple:this.multiple||(this.multipleKey&&evt[this.multipleKey]),toggle:this.toggle||(this.toggleKey&&evt[this.toggleKey])};},select:function(features){if(!this.modifiers.multiple&&!this.modifiers.toggle){this.unselectAll();}
+if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var cont=this.events.triggerEvent("beforefeaturesselected",{features:features});if(cont!==false){var selectedFeatures=[];var feature;for(var i=0,len=features.length;i<len;++i){feature=features[i];if(this.features[feature.fid||feature.id]){if(this.modifiers.toggle){this.unselect(this.features[feature.fid||feature.id]);}}else{cont=this.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){this.features[feature.fid||feature.id]=feature;selectedFeatures.push(feature);this.events.triggerEvent("featureselected",{feature:feature});}}}
+this.events.triggerEvent("featuresselected",{features:selectedFeatures});}},hoverSelect:function(feature){var fid=feature?feature.fid||feature.id:null;var hfid=this.hoverFeature?this.hoverFeature.fid||this.hoverFeature.id:null;if(hfid&&hfid!=fid){this.events.triggerEvent("outfeature",{feature:this.hoverFeature});this.hoverFeature=null;}
+if(fid&&fid!=hfid){this.events.triggerEvent("hoverfeature",{feature:feature});this.hoverFeature=feature;}},unselect:function(feature){delete this.features[feature.fid||feature.id];this.events.triggerEvent("featureunselected",{feature:feature});},unselectAll:function(){for(var fid in this.features){this.unselect(this.features[fid]);}},setMap:function(map){for(var i in this.handlers){this.handlers[i].setMap(map);}
+OpenLayers.Control.prototype.setMap.apply(this,arguments);},pixelToBounds:function(pixel){var llPx=pixel.add(-this.clickTolerance/2,this.clickTolerance/2);var urPx=pixel.add(this.clickTolerance/2,-this.clickTolerance/2);var ll=this.map.getLonLatFromPixel(llPx);var ur=this.map.getLonLatFromPixel(urPx);return new OpenLayers.Bounds(ll.lon,ll.lat,ur.lon,ur.lat);},CLASS_NAME:"OpenLayers.Control.GetFeature"});OpenLayers.Format.QueryStringFilter=(function(){var cmpToStr={};cmpToStr[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";cmpToStr[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN]="lt";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";cmpToStr[OpenLayers.Filter.Comparison.LIKE]="ilike";function regex2value(value){value=value.replace(/%/g,"\\%");value=value.replace(/\\\\\.(\*)?/g,function($0,$1){return $1?$0:"\\\\_";});value=value.replace(/\\\\\.\*/g,"\\\\%");value=value.replace(/(\\)?\.(\*)?/g,function($0,$1,$2){return $1||$2?$0:"_";});value=value.replace(/(\\)?\.\*/g,function($0,$1){return $1?$0:"%";});value=value.replace(/\\\./g,".");value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"*";});return value;}
+return OpenLayers.Class(OpenLayers.Format,{wildcarded:false,srsInBBOX:false,write:function(filter,params){params=params||{};var className=filter.CLASS_NAME;var filterType=className.substring(className.lastIndexOf(".")+1);switch(filterType){case"Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:params.bbox=filter.value.toArray();if(this.srsInBBOX&&filter.projection){params.bbox.push(filter.projection.getCode());}
+break;case OpenLayers.Filter.Spatial.DWITHIN:params.tolerance=filter.distance;case OpenLayers.Filter.Spatial.WITHIN:params.lon=filter.value.x;params.lat=filter.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+filter.type);}
+break;case"Comparison":var op=cmpToStr[filter.type];if(op!==undefined){var value=filter.value;if(filter.type==OpenLayers.Filter.Comparison.LIKE){value=regex2value(value);if(this.wildcarded){value="%"+value+"%";}}
+params[filter.property+"__"+op]=value;params.queryable=params.queryable||[];params.queryable.push(filter.property);}else{OpenLayers.Console.warn("Unknown comparison filter type "+filter.type);}
+break;case"Logical":if(filter.type===OpenLayers.Filter.Logical.AND){for(var i=0,len=filter.filters.length;i<len;i++){params=this.write(filter.filters[i],params);}}else{OpenLayers.Console.warn("Unsupported logical filter type "+filter.type);}
+break;default:OpenLayers.Console.warn("Unknown filter type "+filterType);}
+return params;},CLASS_NAME:"OpenLayers.Format.QueryStringFilter"});})();OpenLayers.Control.MousePosition=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,element:null,prefix:'',separator:', ',suffix:'',numDigits:5,granularity:10,emptyString:null,lastXy:null,displayProjection:null,destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.events.register('mousemove',this,this.redraw);this.map.events.register('mouseout',this,this.reset);this.redraw();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.map.events.unregister('mousemove',this,this.redraw);this.map.events.unregister('mouseout',this,this.reset);this.element.innerHTML="";return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.div.left="";this.div.top="";this.element=this.div;}
+return this.div;},redraw:function(evt){var lonLat;if(evt==null){this.reset();return;}else{if(this.lastXy==null||Math.abs(evt.xy.x-this.lastXy.x)>this.granularity||Math.abs(evt.xy.y-this.lastXy.y)>this.granularity)
+{this.lastXy=evt.xy;return;}
+lonLat=this.map.getLonLatFromPixel(evt.xy);if(!lonLat){return;}
+if(this.displayProjection){lonLat.transform(this.map.getProjectionObject(),this.displayProjection);}
+this.lastXy=evt.xy;}
+var newHtml=this.formatOutput(lonLat);if(newHtml!=this.element.innerHTML){this.element.innerHTML=newHtml;}},reset:function(evt){if(this.emptyString!=null){this.element.innerHTML=this.emptyString;}},formatOutput:function(lonLat){var digits=parseInt(this.numDigits);var newHtml=this.prefix+
+lonLat.lon.toFixed(digits)+
+this.separator+
+lonLat.lat.toFixed(digits)+
+this.suffix;return newHtml;},CLASS_NAME:"OpenLayers.Control.MousePosition"});OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:false,wildcarded:false,srsInBBOX:false,initialize:function(options){options=options||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var format=new OpenLayers.Format.QueryStringFilter({wildcarded:this.wildcarded,srsInBBOX:this.srsInBBOX});this.filterToParams=function(filter,params){return format.write(filter,params);}}},destroy:function(){this.params=null;this.headers=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=options||{};options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);options=OpenLayers.Util.applyDefaults(options,this.options);if(options.filter&&this.filterToParams){options.params=this.filterToParams(options.filter,options.params);}
+var readWithPOST=(options.readWithPOST!==undefined)?options.readWithPOST:this.readWithPOST;var resp=new OpenLayers.Protocol.Response({requestType:"read"});if(readWithPOST){resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,resp,options),data:OpenLayers.Util.getParameterString(options.params),headers:{"Content-Type":"application/x-www-form-urlencoded"}});}else{resp.priv=OpenLayers.Request.GET({url:options.url,callback:this.createCallback(this.handleRead,resp,options),params:options.params,headers:options.headers});}
+return resp;},handleRead:function(resp,options){this.handleResponse(resp,options);},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:features,requestType:"create"});resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleCreate,resp,options),headers:options.headers,data:this.format.write(features)});return resp;},handleCreate:function(resp,options){this.handleResponse(resp,options);},update:function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"update"});resp.priv=OpenLayers.Request.PUT({url:url,callback:this.createCallback(this.handleUpdate,resp,options),headers:options.headers,data:this.format.write(feature)});return resp;},handleUpdate:function(resp,options){this.handleResponse(resp,options);},"delete":function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"delete"});resp.priv=OpenLayers.Request.DELETE({url:url,callback:this.createCallback(this.handleDelete,resp,options),headers:options.headers});return resp;},handleDelete:function(resp,options){this.handleResponse(resp,options);},handleResponse:function(resp,options){var request=resp.priv;if(options.callback){if(request.status>=200&&request.status<300){if(resp.requestType!="delete"){resp.features=this.parseFeatures(request);}
+resp.code=OpenLayers.Protocol.Response.SUCCESS;}else{resp.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,resp);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+return this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=[],nResponses=0;var types={};types[OpenLayers.State.INSERT]=[];types[OpenLayers.State.UPDATE]=[];types[OpenLayers.State.DELETE]=[];var feature,list,requestFeatures=[];for(var i=0,len=features.length;i<len;++i){feature=features[i];list=types[feature.state];if(list){list.push(feature);requestFeatures.push(feature);}}
+var nRequests=(types[OpenLayers.State.INSERT].length>0?1:0)+
+types[OpenLayers.State.UPDATE].length+
+types[OpenLayers.State.DELETE].length;var success=true;var finalResponse=new OpenLayers.Protocol.Response({reqFeatures:requestFeatures});function insertCallback(response){var len=response.features?response.features.length:0;var fids=new Array(len);for(var i=0;i<len;++i){fids[i]=response.features[i].fid;}
+finalResponse.insertIds=fids;callback.apply(this,[response]);}
+function callback(response){this.callUserCallback(response,options);success=success&&response.success();nResponses++;if(nResponses>=nRequests){if(options.callback){finalResponse.code=success?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.apply(options.scope,[finalResponse]);}}}
+var queue=types[OpenLayers.State.INSERT];if(queue.length>0){resp.push(this.create(queue,OpenLayers.Util.applyDefaults({callback:insertCallback,scope:this},options.create)));}
+queue=types[OpenLayers.State.UPDATE];for(var i=queue.length-1;i>=0;--i){resp.push(this.update(queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options.update)));}
+queue=types[OpenLayers.State.DELETE];for(var i=queue.length-1;i>=0;--i){resp.push(this["delete"](queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options["delete"])));}
+return resp;},abort:function(response){if(response){response.priv.abort();}},callUserCallback:function(resp,options){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}},CLASS_NAME:"OpenLayers.Protocol.HTTP"});OpenLayers.Control.Button=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){},CLASS_NAME:"OpenLayers.Control.Button"});OpenLayers.Strategy.Cluster=OpenLayers.Class(OpenLayers.Strategy,{distance:20,threshold:null,features:null,clusters:null,clustering:false,resolution:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});}
+return deactivated;},cacheFeatures:function(event){var propagate=true;if(!this.clustering){this.clearCache();this.features=event.features;this.cluster();propagate=false;}
+return propagate;},clearCache:function(){this.features=null;},cluster:function(event){if((!event||event.zoomChanged)&&this.features){var resolution=this.layer.map.getResolution();if(resolution!=this.resolution||!this.clustersExist()){this.resolution=resolution;var clusters=[];var feature,clustered,cluster;for(var i=0;i<this.features.length;++i){feature=this.features[i];if(feature.geometry){clustered=false;for(var j=clusters.length-1;j>=0;--j){cluster=clusters[j];if(this.shouldCluster(cluster,feature)){this.addToCluster(cluster,feature);clustered=true;break;}}
+if(!clustered){clusters.push(this.createCluster(this.features[i]));}}}
+this.layer.removeAllFeatures();if(clusters.length>0){if(this.threshold>1){var clone=clusters.slice();clusters=[];var candidate;for(var i=0,len=clone.length;i<len;++i){candidate=clone[i];if(candidate.attributes.count<this.threshold){Array.prototype.push.apply(clusters,candidate.cluster);}else{clusters.push(candidate);}}}
+this.clustering=true;this.layer.addFeatures(clusters);this.clustering=false;}
+this.clusters=clusters;}}},clustersExist:function(){var exist=false;if(this.clusters&&this.clusters.length>0&&this.clusters.length==this.layer.features.length){exist=true;for(var i=0;i<this.clusters.length;++i){if(this.clusters[i]!=this.layer.features[i]){exist=false;break;}}}
+return exist;},shouldCluster:function(cluster,feature){var cc=cluster.geometry.getBounds().getCenterLonLat();var fc=feature.geometry.getBounds().getCenterLonLat();var distance=(Math.sqrt(Math.pow((cc.lon-fc.lon),2)+Math.pow((cc.lat-fc.lat),2))/this.resolution);return(distance<=this.distance);},addToCluster:function(cluster,feature){cluster.cluster.push(feature);cluster.attributes.count+=1;},createCluster:function(feature){var center=feature.geometry.getBounds().getCenterLonLat();var cluster=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(center.lon,center.lat),{count:1});cluster.cluster=[feature];return cluster;},CLASS_NAME:"OpenLayers.Strategy.Cluster"});OpenLayers.Protocol.SOS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.SOS.DEFAULTS);var cls=OpenLayers.Protocol.SOS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported SOS version: "+options.version;}
+return new cls(options);};OpenLayers.Protocol.SOS.DEFAULTS={"version":"1.0.0"};OpenLayers.Format.GeoRSS=OpenLayers.Class(OpenLayers.Format.XML,{rssns:"http://backend.userland.com/rss2",featureNS:"http://mapserver.gis.umn.edu/mapserver",georssns:"http://www.georss.org/georss",geons:"http://www.w3.org/2003/01/geo/wgs84_pos#",featureTitle:"Untitled",featureDescription:"No Description",gmlParser:null,xy:false,createGeometryFromItem:function(item){var point=this.getElementsByTagNameNS(item,this.georssns,"point");var lat=this.getElementsByTagNameNS(item,this.geons,'lat');var lon=this.getElementsByTagNameNS(item,this.geons,'long');var line=this.getElementsByTagNameNS(item,this.georssns,"line");var polygon=this.getElementsByTagNameNS(item,this.georssns,"polygon");var where=this.getElementsByTagNameNS(item,this.georssns,"where");var box=this.getElementsByTagNameNS(item,this.georssns,"box");if(point.length>0||(lat.length>0&&lon.length>0)){var location;if(point.length>0){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s+/);if(location.length!=2){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s*,\s*/);}}else{location=[parseFloat(lat[0].firstChild.nodeValue),parseFloat(lon[0].firstChild.nodeValue)];}
+var geometry=new OpenLayers.Geometry.Point(parseFloat(location[1]),parseFloat(location[0]));}else if(line.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(line[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);}
+geometry=new OpenLayers.Geometry.LineString(components);}else if(polygon.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(polygon[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);}
+geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);}else if(where.length>0){if(!this.gmlParser){this.gmlParser=new OpenLayers.Format.GML({'xy':this.xy});}
+var feature=this.gmlParser.parseFeature(where[0]);geometry=feature.geometry;}else if(box.length>0){var coords=OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/);var components=[];var point;if(coords.length>3){point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);}
+geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);}
+if(geometry&&this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
+return geometry;},createFeatureFromItem:function(item){var geometry=this.createGeometryFromItem(item);var title=this.getChildValue(item,"*","title",this.featureTitle);var description=this.getChildValue(item,"*","description",this.getChildValue(item,"*","content",this.getChildValue(item,"*","summary",this.featureDescription)));var link=this.getChildValue(item,"*","link");if(!link){try{link=this.getElementsByTagNameNS(item,"*","link")[0].getAttribute("href");}catch(e){link=null;}}
+var id=this.getChildValue(item,"*","id",null);var data={"title":title,"description":description,"link":link};var feature=new OpenLayers.Feature.Vector(geometry,data);feature.fid=id;return feature;},getChildValue:function(node,nsuri,name,def){var value;var eles=this.getElementsByTagNameNS(node,nsuri,name);if(eles&&eles[0]&&eles[0].firstChild&&eles[0].firstChild.nodeValue){value=OpenLayers.Format.XML.prototype.getChildValue(eles[0]);}else{value=(def==undefined)?"":def;}
+return value;},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
+var itemlist=null;itemlist=this.getElementsByTagNameNS(doc,'*','item');if(itemlist.length==0){itemlist=this.getElementsByTagNameNS(doc,'*','entry');}
+var numItems=itemlist.length;var features=new Array(numItems);for(var i=0;i<numItems;i++){features[i]=this.createFeatureFromItem(itemlist[i]);}
+return features;},write:function(features){var georss;if(OpenLayers.Util.isArray(features)){georss=this.createElementNS(this.rssns,"rss");for(var i=0,len=features.length;i<len;i++){georss.appendChild(this.createFeatureXML(features[i]));}}else{georss=this.createFeatureXML(features);}
+return OpenLayers.Format.XML.prototype.write.apply(this,[georss]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var featureNode=this.createElementNS(this.rssns,"item");var titleNode=this.createElementNS(this.rssns,"title");titleNode.appendChild(this.createTextNode(feature.attributes.title?feature.attributes.title:""));var descNode=this.createElementNS(this.rssns,"description");descNode.appendChild(this.createTextNode(feature.attributes.description?feature.attributes.description:""));featureNode.appendChild(titleNode);featureNode.appendChild(descNode);if(feature.attributes.link){var linkNode=this.createElementNS(this.rssns,"link");linkNode.appendChild(this.createTextNode(feature.attributes.link));featureNode.appendChild(linkNode);}
+for(var attr in feature.attributes){if(attr=="link"||attr=="title"||attr=="description"){continue;}
+var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];}
+var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureNode.appendChild(attrContainer);}
+featureNode.appendChild(geometryNode);return featureNode;},buildGeometryNode:function(geometry){if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var node;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){node=this.createElementNS(this.georssns,'georss:polygon');node.appendChild(this.buildCoordinatesNode(geometry.components[0]));}
+else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){node=this.createElementNS(this.georssns,'georss:line');node.appendChild(this.buildCoordinatesNode(geometry));}
+else if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){node=this.createElementNS(this.georssns,'georss:point');node.appendChild(this.buildCoordinatesNode(geometry));}else{throw"Couldn't parse "+geometry.CLASS_NAME;}
+return node;},buildCoordinatesNode:function(geometry){var points=null;if(geometry.components){points=geometry.components;}
+var path;if(points){var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;i++){parts[i]=points[i].y+" "+points[i].x;}
+path=parts.join(" ");}else{path=geometry.y+" "+geometry.x;}
+return this.createTextNode(path);},CLASS_NAME:"OpenLayers.Format.GeoRSS"});OpenLayers.Format.WPSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.WPSCapabilities"});OpenLayers.Format.WPSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows/1.1",wps:"http://www.opengis.net/wps/1.0.0",xlink:"http://www.w3.org/1999/xlink"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var capabilities={};this.readNode(data,capabilities);return capabilities;},readers:{"wps":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"ProcessOfferings":function(node,obj){obj.processOfferings={};this.readChildNodes(node,obj.processOfferings);},"Process":function(node,processOfferings){var processVersion=this.getAttributeNS(node,this.namespaces.wps,"processVersion");var process={processVersion:processVersion};this.readChildNodes(node,process);processOfferings[process.identifier]=process;},"Languages":function(node,obj){obj.languages=[];this.readChildNodes(node,obj.languages);},"Default":function(node,languages){var language={isDefault:true};this.readChildNodes(node,language);languages.push(language);},"Supported":function(node,languages){var language={};this.readChildNodes(node,language);languages.push(language);}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.WPSCapabilities.v1_0_0"});OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,containerOrigin:null,pinchOrigin:null,currentCenter:null,autoActivate:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions);},activate:function(){var activated=OpenLayers.Control.prototype.activate.apply(this,arguments);if(activated){this.map.events.on({moveend:this.updateContainerOrigin,scope:this});this.updateContainerOrigin();}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.apply(this,arguments);if(this.map&&this.map.events){this.map.events.un({moveend:this.updateContainerOrigin,scope:this});}
+return deactivated;},updateContainerOrigin:function(){var container=this.map.layerContainerDiv;this.containerOrigin={x:parseInt(container.style.left,10),y:parseInt(container.style.top,10)};},pinchStart:function(evt,pinchData){this.pinchOrigin=evt.xy;this.currentCenter=evt.xy;},pinchMove:function(evt,pinchData){var scale=pinchData.scale;var containerOrigin=this.containerOrigin;var pinchOrigin=this.pinchOrigin;var current=evt.xy;var dx=Math.round((current.x-pinchOrigin.x)+(scale-1)*(containerOrigin.x-pinchOrigin.x));var dy=Math.round((current.y-pinchOrigin.y)+(scale-1)*(containerOrigin.y-pinchOrigin.y));this.applyTransform("translate("+dx+"px, "+dy+"px) scale("+scale+")");this.currentCenter=current;},applyTransform:function(transform){var style=this.map.layerContainerDiv.style;style['-webkit-transform']=transform;style['-moz-transform']=transform;},pinchDone:function(evt,start,last){this.applyTransform("");var zoom=this.map.getZoomForResolution(this.map.getResolution()/last.scale,true);if(zoom!==this.map.getZoom()||!this.currentCenter.equals(this.pinchOrigin)){var resolution=this.map.getResolutionForZoom(zoom);var location=this.map.getLonLatFromPixel(this.pinchOrigin);var zoomPixel=this.currentCenter;var size=this.map.getSize();location.lon+=resolution*((size.w/2)-zoomPixel.x);location.lat-=resolution*((size.h/2)-zoomPixel.y);this.map.setCenter(location,zoom);}},CLASS_NAME:"OpenLayers.Control.PinchZoom"});OpenLayers.Control.TouchNavigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,pinchZoom:null,pinchZoomOptions:null,clickHandlerOptions:null,documentDrag:false,autoActivate:true,initialize:function(options){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();if(this.dragPan){this.dragPan.destroy();}
+this.dragPan=null;if(this.pinchZoom){this.pinchZoom.destroy();delete this.pinchZoom;}
+OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.dragPan.activate();this.handlers.click.activate();this.pinchZoom.activate();return true;}
+return false;},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.dragPan.deactivate();this.handlers.click.deactivate();this.pinchZoom.deactivate();return true;}
+return false;},draw:function(){var clickCallbacks={click:this.defaultClick,dblclick:this.defaultDblClick};var clickOptions=OpenLayers.Util.extend({"double":true,stopDouble:true,pixelTolerance:2},this.clickHandlerOptions);this.handlers.click=new OpenLayers.Handler.Click(this,clickCallbacks,clickOptions);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,documentDrag:this.documentDrag},this.dragPanOptions));this.dragPan.draw();this.pinchZoom=new OpenLayers.Control.PinchZoom(OpenLayers.Util.extend({map:this.map},this.pinchZoomOptions));},defaultClick:function(evt){if(evt.lastTouches&&evt.lastTouches.length==2){this.map.zoomOut();}},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);},CLASS_NAME:"OpenLayers.Control.TouchNavigation"});if(!OpenLayers.Format.GML){OpenLayers.Format.GML={};}
+OpenLayers.Format.GML.Base=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs"},defaultPrefix:"gml",schemaLocation:null,featureType:null,featureNS:null,geometryName:"geometry",extractAttributes:true,srsName:null,xy:true,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g),featureMember:(/^(.*:)?featureMembers?$/)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.setGeometryTypes();if(options&&options.featureNS){this.setNamespace("feature",options.featureNS);}
+this.singleFeatureType=!options||(typeof options.featureType==="string");},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+if(data&&data.nodeType==9){data=data.documentElement;}
+var features=[];this.readNode(data,{features:features},true);if(features.length==0){var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMember");if(elements.length){for(var i=0,len=elements.length;i<len;++i){this.readNode(elements[i],{features:features},true);}}else{var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMembers");if(elements.length){this.readNode(elements[0],{features:features},true);}}}
+return features;},readNode:function(node,obj,first){if(first===true&&this.autoConfig===true){this.featureType=null;delete this.namespaceAlias[this.featureNS];delete this.namespaces["feature"];this.featureNS=null;}
+if(!this.featureNS&&(!(node.prefix in this.namespaces)&&node.parentNode.namespaceURI==this.namespaces["gml"]&&this.regExes.featureMember.test(node.parentNode.nodeName))){this.featureType=node.nodeName.split(":").pop();this.setNamespace("feature",node.namespaceURI);this.featureNS=node.namespaceURI;this.autoConfig=true;}
+return OpenLayers.Format.XML.prototype.readNode.apply(this,[node,obj]);},readers:{"gml":{"featureMember":function(node,obj){this.readChildNodes(node,obj);},"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"name":function(node,obj){obj.name=this.getChildValue(node);},"boundedBy":function(node,obj){var container={};this.readChildNodes(node,container);if(container.components&&container.components.length>0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");if(this.xy){points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{points[i]=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+obj.points=points;},"coord":function(node,obj){var coord={};this.readChildNodes(node,coord);if(!obj.points){obj.points=[];}
+obj.points.push(new OpenLayers.Geometry.Point(coord.x,coord.y,coord.z));},"X":function(node,coord){coord.x=this.getChildValue(node);},"Y":function(node,coord){coord.y=this.getChildValue(node);},"Z":function(node,coord){coord.z=this.getChildValue(node);},"MultiPoint":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPoint(obj.components)];},"pointMember":function(node,obj){this.readChildNodes(node,obj);},"LineString":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"MultiLineString":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];},"lineStringMember":function(node,obj){this.readChildNodes(node,obj);},"Polygon":function(node,container){var obj={outer:null,inner:[]};this.readChildNodes(node,obj);obj.inner.unshift(obj.outer);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.Polygon(obj.inner));},"LinearRing":function(node,obj){var container={};this.readChildNodes(node,container);obj.components=[new OpenLayers.Geometry.LinearRing(container.points)];},"MultiPolygon":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];},"polygonMember":function(node,obj){this.readChildNodes(node,obj);},"GeometryCollection":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.Collection(obj.components)];},"geometryMember":function(node,obj){this.readChildNodes(node,obj);}},"feature":{"*":function(node,obj){var name;var local=node.localName||node.nodeName.split(":").pop();if(obj.features){if(!this.singleFeatureType&&(OpenLayers.Util.indexOf(this.featureType,local)!==-1)){name="_typeName";}else if(local===this.featureType){name="_typeName";}}else{if(node.childNodes.length==0||(node.childNodes.length==1&&node.firstChild.nodeType==3)){if(this.extractAttributes){name="_attribute";}}else{name="_geometry";}}
+if(name){this.readers.feature[name].apply(this,[node,obj]);}},"_typeName":function(node,obj){var container={components:[],attributes:{}};this.readChildNodes(node,container);if(container.name){container.attributes.name=container.name;}
+var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);if(!this.singleFeatureType){feature.type=node.nodeName.split(":").pop();feature.namespace=node.namespaceURI;}
+var fid=node.getAttribute("fid")||this.getAttributeNS(node,this.namespaces["gml"],"id");if(fid){feature.fid=fid;}
+if(this.internalProjection&&this.externalProjection&&feature.geometry){feature.geometry.transform(this.externalProjection,this.internalProjection);}
+if(container.bounds){feature.bounds=container.bounds;}
+obj.features.push(feature);},"_geometry":function(node,obj){if(!this.geometryName){this.geometryName=node.nodeName.split(":").pop();}
+this.readChildNodes(node,obj);},"_attribute":function(node,obj){var local=node.localName||node.nodeName.split(":").pop();var value=this.getChildValue(node);if(!obj.attributes[local]){obj.attributes[local]=value;}else{obj.attributes[local]=obj.attributes[local]+", "+value;}}},"wfs":{"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);}}},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":{"featureMember":function(feature){var node=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",feature,node);return node;},"MultiPoint":function(geometry){var node=this.createElementNSPlus("gml:MultiPoint");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("pointMember",components[i],node);}
+return node;},"pointMember":function(geometry){var node=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",geometry,node);return node;},"MultiLineString":function(geometry){var node=this.createElementNSPlus("gml:MultiLineString");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("lineStringMember",components[i],node);}
+return node;},"lineStringMember":function(geometry){var node=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",geometry,node);return node;},"MultiPolygon":function(geometry){var node=this.createElementNSPlus("gml:MultiPolygon");var components=geometry.components||[geometry];for(var i=0,ii=components.length;i<ii;++i){this.writeNode("polygonMember",components[i],node);}
+return node;},"polygonMember":function(geometry){var node=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",geometry,node);return node;},"GeometryCollection":function(geometry){var node=this.createElementNSPlus("gml:GeometryCollection");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("geometryMember",geometry.components[i],node);}
+return node;},"geometryMember":function(geometry){var node=this.createElementNSPlus("gml:geometryMember");var child=this.writeNode("feature:_geometry",geometry);node.appendChild(child.firstChild);return node;}},"feature":{"_typeName":function(feature){var node=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:feature.fid}});if(feature.geometry){this.writeNode("feature:_geometry",feature.geometry,node);}
+for(var name in feature.attributes){var value=feature.attributes[name];if(value!=null){this.writeNode("feature:_attribute",{name:name,value:value},node);}}
+return node;},"_geometry":function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone().transform(this.internalProjection,this.externalProjection);}
+var node=this.createElementNSPlus("feature:"+this.geometryName);var type=this.geometryTypes[geometry.CLASS_NAME];var child=this.writeNode("gml:"+type,geometry,node);if(this.srsName){child.setAttribute("srsName",this.srsName);}
+return node;},"_attribute":function(obj){return this.createElementNSPlus("feature:"+obj.name,{value:obj.value});}},"wfs":{"FeatureCollection":function(features){var node=this.createElementNSPlus("wfs:FeatureCollection");for(var i=0,len=features.length;i<len;++i){this.writeNode("gml:featureMember",features[i],node);}
+return node;}}},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":"LineString","OpenLayers.Geometry.MultiLineString":"MultiLineString","OpenLayers.Geometry.Polygon":"Polygon","OpenLayers.Geometry.MultiPolygon":"MultiPolygon","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.Base"});OpenLayers.Style2=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,initialize:function(config){OpenLayers.Util.extend(this,config);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();}
+delete this.rules;},clone:function(){var config=OpenLayers.Util.extend({},this);if(this.rules){config.rules=[];for(var i=0,len=this.rules.length;i<len;++i){config.rules.push(this.rules[i].clone());}}
+return new OpenLayers.Style2(config);},CLASS_NAME:"OpenLayers.Style2"});OpenLayers.Layer.Boxes=OpenLayers.Class(OpenLayers.Layer.Markers,{initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);},drawMarker:function(marker){var bounds=marker.bounds;var topleft=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.left,bounds.top));var botright=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.right,bounds.bottom));if(botright==null||topleft==null){marker.display(false);}else{var sz=new OpenLayers.Size(Math.max(1,botright.x-topleft.x),Math.max(1,botright.y-topleft.y));var markerDiv=marker.draw(topleft,sz);if(!marker.drawn){this.div.appendChild(markerDiv);marker.drawn=true;}}},removeMarker:function(marker){OpenLayers.Util.removeItem(this.markers,marker);if((marker.div!=null)&&(marker.div.parentNode==this.div)){this.div.removeChild(marker.div);}},CLASS_NAME:"OpenLayers.Layer.Boxes"});OpenLayers.Format.WFSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},read_cap_Service:function(capabilities,node){var service={};this.runChildNodes(service,node);capabilities.service=service;},read_cap_Fees:function(service,node){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){service.fees=fees;}},read_cap_AccessConstraints:function(service,node){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){service.accessConstraints=constraints;}},read_cap_OnlineResource:function(service,node){var onlineResource=this.getChildValue(node);if(onlineResource&&onlineResource.toLowerCase()!="none"){service.onlineResource=onlineResource;}},read_cap_Keywords:function(service,node){var keywords=this.getChildValue(node);if(keywords&&keywords.toLowerCase()!="none"){service.keywords=keywords.split(', ');}},read_cap_Capability:function(capabilities,node){var capability={};this.runChildNodes(capability,node);capabilities.capability=capability;},read_cap_Request:function(obj,node){var request={};this.runChildNodes(request,node);obj.request=request;},read_cap_GetFeature:function(request,node){var getfeature={href:{},formats:[]};this.runChildNodes(getfeature,node);request.getfeature=getfeature;},read_cap_ResultFormat:function(obj,node){var children=node.childNodes;var childNode;for(var i=0;i<children.length;i++){childNode=children[i];if(childNode.nodeType==1){obj.formats.push(childNode.nodeName);}}},read_cap_DCPType:function(obj,node){this.runChildNodes(obj,node);},read_cap_HTTP:function(obj,node){this.runChildNodes(obj.href,node);},read_cap_Get:function(obj,node){obj.get=node.getAttribute("onlineResource");},read_cap_Post:function(obj,node){obj.post=node.getAttribute("onlineResource");},read_cap_SRS:function(obj,node){var srs=this.getChildValue(node);if(srs){obj.srs=srs;}},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_0_0"});OpenLayers.Format.WMSCapabilities.v1_3=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"LayerLimit":function(node,obj){obj.layerLimit=parseInt(this.getChildValue(node));},"MaxWidth":function(node,obj){obj.maxWidth=parseInt(this.getChildValue(node));},"MaxHeight":function(node,obj){obj.maxHeight=parseInt(this.getChildValue(node));},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("CRS");obj.bbox[bbox.srs]=bbox;},"CRS":function(node,obj){this.readers.wms.SRS.apply(this,[node,obj]);},"EX_GeographicBoundingBox":function(node,obj){obj.llbbox=[];this.readChildNodes(node,obj.llbbox);},"westBoundLongitude":function(node,obj){obj[0]=this.getChildValue(node);},"eastBoundLongitude":function(node,obj){obj[2]=this.getChildValue(node);},"southBoundLatitude":function(node,obj){obj[1]=this.getChildValue(node);},"northBoundLatitude":function(node,obj){obj[3]=this.getChildValue(node);},"MinScaleDenominator":function(node,obj){obj.maxScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"MaxScaleDenominator":function(node,obj){obj.minScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol"),nearestVal:node.getAttribute("nearestValue")==="1",multipleVal:node.getAttribute("multipleValues")==="1","default":node.getAttribute("default")||"",current:node.getAttribute("current")==="1",values:this.getChildValue(node).split(",")};obj.dimensions[dim.name]=dim;},"Keyword":function(node,obj){var keyword={value:this.getChildValue(node),vocabulary:node.getAttribute("vocabulary")};if(obj.keywords){obj.keywords.push(keyword);}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),"sld":{"UserDefinedSymbolization":function(node,obj){this.readers.wms.UserDefinedSymbolization.apply(this,[node,obj]);obj.userSymbols.inlineFeature=parseInt(node.getAttribute("InlineFeature"))==1;obj.userSymbols.remoteWCS=parseInt(node.getAttribute("RemoteWCS"))==1;},"DescribeLayer":function(node,obj){this.readers.wms.DescribeLayer.apply(this,[node,obj]);},"GetLegendGraphic":function(node,obj){this.readers.wms.GetLegendGraphic.apply(this,[node,obj]);}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3"});OpenLayers.Layer.Yahoo=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031],type:null,wrapDateLine:true,sphericalMercator:false,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject=new YMap(this.div,this.type,size);this.mapObject.disableKeyControls();this.mapObject.disableDragMap();if(!this.mapObject.moveByXY||(typeof this.mapObject.moveByXY!="function")){this.dragPanMapObject=null;}}catch(e){}},onMapResize:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject.resizeTo(size);}catch(e){}},setMap:function(map){OpenLayers.Layer.EventPane.prototype.setMap.apply(this,arguments);this.map.events.register("moveend",this,this.fixYahooEventPane);},fixYahooEventPane:function(){var yahooEventPane=OpenLayers.Util.getElement("ygddfdiv");if(yahooEventPane!=null){if(yahooEventPane.parentNode!=null){yahooEventPane.parentNode.removeChild(yahooEventPane);}
+this.map.events.unregister("moveend",this,this.fixYahooEventPane);}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'Yahoo','layerLib':'Yahoo'});},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getOLZoomFromMapObjectZoom.apply(this,[moZoom]);zoom=18-zoom;}
+return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getMapObjectZoomFromOLZoom.apply(this,[olZoom]);zoom=18-zoom;}
+return zoom;},setMapObjectCenter:function(center,zoom){this.mapObject.drawZoomAndCenter(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCenterLatLon();},dragPanMapObject:function(dX,dY){this.mapObject.moveByXY({'x':-dX,'y':dY});},getMapObjectZoom:function(){return this.mapObject.getZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.convertXYLatLon(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.convertLatLonXY(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lon:moLonLat.Lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lat:moLonLat.Lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var yLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);yLatLong=new YGeoPoint(lonlat.lat,lonlat.lon);}else{yLatLong=new YGeoPoint(lat,lon);}
+return yLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new YCoordPoint(x,y);},getMapObjectSizeFromOLSize:function(olSize){return new YSize(olSize.w,olSize.h);},CLASS_NAME:"OpenLayers.Layer.Yahoo"});OpenLayers.Layer.PointGrid=OpenLayers.Class(OpenLayers.Layer.Vector,{dx:null,dy:null,ratio:1.5,maxFeatures:250,rotation:0,origin:null,gridBounds:null,initialize:function(config){config=config||{};OpenLayers.Layer.Vector.prototype.initialize.apply(this,[config.name,config]);},setMap:function(map){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);map.events.register("moveend",this,this.onMoveEnd);},removeMap:function(map){map.events.unregister("moveend",this,this.onMoveEnd);OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments);},setRatio:function(ratio){this.ratio=ratio;this.updateGrid(true);},setMaxFeatures:function(maxFeatures){this.maxFeatures=maxFeatures;this.updateGrid(true);},setSpacing:function(dx,dy){this.dx=dx;this.dy=dy||dx;this.updateGrid(true);},setOrigin:function(origin){this.origin=origin;this.updateGrid(true);},getOrigin:function(){if(!this.origin){this.origin=this.map.getExtent().getCenterLonLat();}
+return this.origin;},setRotation:function(rotation){this.rotation=rotation;this.updateGrid(true);},onMoveEnd:function(){this.updateGrid();},getViewBounds:function(){var bounds=this.map.getExtent();if(this.rotation){var origin=this.getOrigin();var rotationOrigin=new OpenLayers.Geometry.Point(origin.lon,origin.lat);var rect=bounds.toGeometry();rect.rotate(-this.rotation,rotationOrigin);bounds=rect.getBounds();}
+return bounds;},updateGrid:function(force){if(force||this.invalidBounds()){var viewBounds=this.getViewBounds();var origin=this.getOrigin();var rotationOrigin=new OpenLayers.Geometry.Point(origin.lon,origin.lat);var viewBoundsWidth=viewBounds.getWidth();var viewBoundsHeight=viewBounds.getHeight();var aspectRatio=viewBoundsWidth/viewBoundsHeight;var maxHeight=Math.sqrt(this.dx*this.dy*this.maxFeatures/aspectRatio);var maxWidth=maxHeight*aspectRatio;var gridWidth=Math.min(viewBoundsWidth*this.ratio,maxWidth);var gridHeight=Math.min(viewBoundsHeight*this.ratio,maxHeight);var center=viewBounds.getCenterLonLat();this.gridBounds=new OpenLayers.Bounds(center.lon-(gridWidth/2),center.lat-(gridHeight/2),center.lon+(gridWidth/2),center.lat+(gridHeight/2));var rows=Math.floor(gridHeight/this.dy);var cols=Math.floor(gridWidth/this.dx);var gridLeft=origin.lon+(this.dx*Math.ceil((this.gridBounds.left-origin.lon)/this.dx));var gridBottom=origin.lat+(this.dy*Math.ceil((this.gridBounds.bottom-origin.lat)/this.dy));var features=new Array(rows*cols);var x,y,point;for(var i=0;i<cols;++i){x=gridLeft+(i*this.dx);for(var j=0;j<rows;++j){y=gridBottom+(j*this.dy);point=new OpenLayers.Geometry.Point(x,y);if(this.rotation){point.rotate(this.rotation,rotationOrigin);}
+features[(i*rows)+j]=new OpenLayers.Feature.Vector(point);}}
+this.destroyFeatures(this.features,{silent:true});this.addFeatures(features,{silent:true});}},invalidBounds:function(){return!this.gridBounds||!this.gridBounds.containsBounds(this.getViewBounds());},CLASS_NAME:"OpenLayers.Layer.PointGrid"});OpenLayers.Layer.Zoomify=OpenLayers.Class(OpenLayers.Layer.Grid,{url:null,size:null,isBaseLayer:true,standardTileSize:256,tileOriginCorner:"tl",numberOfTiers:0,tileCountUpToTier:new Array(),tierSizeInTiles:new Array(),tierImageSize:new Array(),initialize:function(name,url,size,options){this.initializeZoomify(size);var newArguments=[];newArguments.push(name,url,size,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},initializeZoomify:function(size){var imageSize=size.clone();var tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);while(imageSize.w>this.standardTileSize||imageSize.h>this.standardTileSize){imageSize=new OpenLayers.Size(Math.floor(imageSize.w/2),Math.floor(imageSize.h/2));tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);}
+this.tierSizeInTiles.reverse();this.tierImageSize.reverse();this.numberOfTiers=this.tierSizeInTiles.length;this.tileCountUpToTier[0]=0;for(var i=1;i<this.numberOfTiers;i++){this.tileCountUpToTier.push(this.tierSizeInTiles[i-1].w*this.tierSizeInTiles[i-1].h+
+this.tileCountUpToTier[i-1]);}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);this.tileCountUpToTier.length=0;this.tierSizeInTiles.length=0;this.tierImageSize.length=0;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Zoomify(this.name,this.url,this.size,this.options);}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var tileIndex=x+y*this.tierSizeInTiles[z].w+this.tileCountUpToTier[z];var path="TileGroup"+Math.floor((tileIndex)/256)+"/"+z+"-"+x+"-"+y+".jpg";var url=this.url;if(OpenLayers.Util.isArray(url)){url=this.selectUrl(path,url);}
+return url+path;},getImageSize:function(){if(arguments.length>0){var bounds=this.adjustBounds(arguments[0]);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var w=this.standardTileSize;var h=this.standardTileSize;if(x==this.tierSizeInTiles[z].w-1){var w=this.tierImageSize[z].w%this.standardTileSize;};if(y==this.tierSizeInTiles[z].h-1){var h=this.tierImageSize[z].h%this.standardTileSize;};return(new OpenLayers.Size(w,h));}else{return this.tileSize;}},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.top);},calculateGridLayout:function(bounds,origin,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-origin.lon;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=origin.lon+tilecol*tilelon;var offsetlat=origin.lat-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=origin.lat-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.Zoomify"});OpenLayers.Format.CQL=(function(){var tokens=["PROPERTY","COMPARISON","VALUE","LOGICAL"],patterns={PROPERTY:/^[_a-zA-Z]\w*/,COMPARISON:/^(=|<>|<=|<|>=|>|LIKE)/i,COMMA:/^,/,LOGICAL:/^(AND|OR)/i,VALUE:/^('\w+'|\d+(\.\d*)?|\.\d+)/,LPAREN:/^\(/,RPAREN:/^\)/,SPATIAL:/^(BBOX|INTERSECTS|DWITHIN|WITHIN|CONTAINS)/i,NOT:/^NOT/i,BETWEEN:/^BETWEEN/i,GEOMETRY:function(text){var type=/^(POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)/.exec(text);if(type){var len=text.length;var idx=text.indexOf("(",type[0].length);if(idx>-1){var depth=1;while(idx<len&&depth>0){idx++;switch(text.charAt(idx)){case'(':depth++;break;case')':depth--;break;default:}}}
+return[text.substr(0,idx+1)];}},END:/^$/},follows={LPAREN:['GEOMETRY','SPATIAL','PROPERTY','VALUE','LPAREN'],RPAREN:['NOT','LOGICAL','END','RPAREN'],PROPERTY:['COMPARISON','BETWEEN','COMMA'],BETWEEN:['VALUE'],COMPARISON:['VALUE'],COMMA:['GEOMETRY','VALUE','PROPERTY'],VALUE:['LOGICAL','COMMA','RPAREN','END'],SPATIAL:['LPAREN'],LOGICAL:['NOT','VALUE','SPATIAL','PROPERTY','LPAREN'],NOT:['PROPERTY','LPAREN'],GEOMETRY:['COMMA','RPAREN']},operators={'=':OpenLayers.Filter.Comparison.EQUAL_TO,'<>':OpenLayers.Filter.Comparison.NOT_EQUAL_TO,'<':OpenLayers.Filter.Comparison.LESS_THAN,'<=':OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,'>':OpenLayers.Filter.Comparison.GREATER_THAN,'>=':OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,'LIKE':OpenLayers.Filter.Comparison.LIKE,'BETWEEN':OpenLayers.Filter.Comparison.BETWEEN},operatorReverse={},logicals={'AND':OpenLayers.Filter.Logical.AND,'OR':OpenLayers.Filter.Logical.OR},logicalReverse={},precedence={'RPAREN':3,'LOGICAL':2,'COMPARISON':1};var i;for(i in operators){if(operators.hasOwnProperty(i)){operatorReverse[operators[i]]=i;}}
+for(i in logicals){if(logicals.hasOwnProperty(i)){logicalReverse[logicals[i]]=i;}}
+function tryToken(text,pattern){if(pattern instanceof RegExp){return pattern.exec(text);}else{return pattern(text);}}
+function nextToken(text,tokens){var i,token,len=tokens.length;for(i=0;i<len;i++){token=tokens[i];var pat=patterns[token];var matches=tryToken(text,pat);if(matches){var match=matches[0];var remainder=text.substr(match.length).replace(/^\s*/,"");return{type:token,text:match,remainder:remainder};}}
+var msg="ERROR: In parsing: ["+text+"], expected one of: ";for(i=0;i<len;i++){token=tokens[i];msg+="\n    "+token+": "+patterns[token];}
+throw new Error(msg);}
+function tokenize(text){var results=[];var token,expect=["NOT","GEOMETRY","SPATIAL","PROPERTY","LPAREN"];do{token=nextToken(text,expect);text=token.remainder;expect=follows[token.type];if(token.type!="END"&&!expect){throw new Error("No follows list for "+token.type);}
+results.push(token);}while(token.type!="END");return results;}
+function buildAst(tokens){var operatorStack=[],postfix=[];while(tokens.length){var tok=tokens.shift();switch(tok.type){case"PROPERTY":case"GEOMETRY":case"VALUE":postfix.push(tok);break;case"COMPARISON":case"BETWEEN":case"LOGICAL":var p=precedence[tok.type];while(operatorStack.length>0&&(precedence[operatorStack[operatorStack.length-1].type]<=p)){postfix.push(operatorStack.pop());}
+operatorStack.push(tok);break;case"SPATIAL":case"NOT":case"LPAREN":operatorStack.push(tok);break;case"RPAREN":while(operatorStack.length>0&&(operatorStack[operatorStack.length-1].type!="LPAREN")){postfix.push(operatorStack.pop());}
+operatorStack.pop();if(operatorStack.length>0&&operatorStack[operatorStack.length-1].type=="SPATIAL"){postfix.push(operatorStack.pop());}
+case"COMMA":case"END":break;default:throw new Error("Unknown token type "+tok.type);}}
+while(operatorStack.length>0){postfix.push(operatorStack.pop());}
+function buildTree(){var tok=postfix.pop();switch(tok.type){case"LOGICAL":var rhs=buildTree(),lhs=buildTree();return new OpenLayers.Filter.Logical({filters:[lhs,rhs],type:logicals[tok.text.toUpperCase()]});case"NOT":var operand=buildTree();return new OpenLayers.Filter.Logical({filters:[operand],type:OpenLayers.Filter.Logical.NOT});case"BETWEEN":var min,max,property;postfix.pop();max=buildTree();min=buildTree();property=buildTree();return new OpenLayers.Filter.Comparison({property:property,lowerBoundary:min,upperBoundary:max,type:OpenLayers.Filter.Comparison.BETWEEN});case"COMPARISON":var value=buildTree(),property=buildTree();return new OpenLayers.Filter.Comparison({property:property,value:value,type:operators[tok.text.toUpperCase()]});case"VALUE":if((/^'.*'$/).test(tok.text)){return tok.text.substr(1,tok.text.length-2);}else{return Number(tok.text);}
+case"SPATIAL":switch(tok.text.toUpperCase()){case"BBOX":var maxy=buildTree(),maxx=buildTree(),miny=buildTree(),minx=buildTree(),prop=buildTree();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:prop,value:OpenLayers.Bounds.fromArray([minx,miny,maxx,maxy])});case"INTERSECTS":var value=buildTree(),property=buildTree();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:property,value:value});case"WITHIN":var value=buildTree(),property=buildTree();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.WITHIN,property:property,value:value});case"CONTAINS":var value=buildTree(),property=buildTree();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.CONTAINS,property:property,value:value});case"DWITHIN":var distance=buildTree(),value=buildTree(),property=buildTree();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,value:value,property:property,distance:Number(distance)});}
+case"GEOMETRY":return OpenLayers.Geometry.fromWKT(tok.text);default:return tok.text;}}
+var result=buildTree();if(postfix.length>0){var msg="Remaining tokens after building AST: \n";for(var i=postfix.length-1;i>=0;i--){msg+=postfix[i].type+": "+postfix[i].text+"\n";}
+throw new Error(msg);}
+return result;}
+return OpenLayers.Class(OpenLayers.Format,{read:function(text){var result=buildAst(tokenize(text));if(this.keepData){this.data=result;};return result;},write:function(filter){if(filter instanceof OpenLayers.Geometry){return filter.toString();}
+switch(filter.CLASS_NAME){case"OpenLayers.Filter.Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:return"BBOX("+
+filter.property+","+
+filter.value.toBBOX()+")";case OpenLayers.Filter.Spatial.DWITHIN:return"DWITHIN("+
+filter.property+", "+
+this.write(filter.value)+", "+
+filter.distance+")";case OpenLayers.Filter.Spatial.WITHIN:return"WITHIN("+
+filter.property+", "+
+this.write(filter.value)+")";case OpenLayers.Filter.Spatial.INTERSECTS:return"INTERSECTS("+
+filter.property+", "+
+this.write(filter.value)+")";case OpenLayers.Filter.Spatial.CONTAINS:return"CONTAINS("+
+filter.property+", "+
+this.write(filter.value)+")";default:throw new Error("Unknown spatial filter type: "+filter.type);}
+case"OpenLayers.Filter.Logical":if(filter.type==OpenLayers.Filter.Logical.NOT){return"NOT ("+this.write(filter.filters[0])+")";}else{var res="(";var first=true;for(var i=0;i<filter.filters.length;i++){if(first){first=false;}else{res+=") "+logicalReverse[filter.type]+" (";}
+res+=this.write(filter.filters[i]);}
+return res+")";}
+case"OpenLayers.Filter.Comparison":if(filter.type==OpenLayers.Filter.Comparison.BETWEEN){return filter.property+" BETWEEN "+
+this.write(filter.lowerBoundary)+" AND "+
+this.write(filter.upperBoundary);}else{return filter.property+" "+operatorReverse[filter.type]+" "+
+this.write(filter.value);}
+case undefined:if(typeof filter==="string"){return"'"+filter+"'";}else if(typeof filter==="number"){return String(filter);}
+default:throw new Error("Can't encode: "+filter.CLASS_NAME+" "+filter);}},CLASS_NAME:"OpenLayers.Format.CQL"});})();OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;}
+if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);var style=document.createStyleSheet();var shapes=['shape','rect','oval','fill','stroke','imagedata','group','textbox'];for(var i=0,len=shapes.length;i<len;i++){style.addRule('olv\\:'+shapes[i],"behavior: url(#default#VML); "+"position: absolute; display: inline-block;");}}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);},supported:function(){return!!(document.namespaces);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=(extent.left/resolution)|0;var top=(extent.top/resolution-this.size.h)|0;if(resolutionChanged||!this.offset){this.offset={x:left,y:top};left=0;top=0;}else{left=left-this.offset.x;top=top-this.offset.y;}
+var org=left+" "+top;this.root.coordorigin=org;var roots=[this.root,this.vectorRoot,this.textRoot];var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];var size=this.size.w+" "+this.size.h;root.coordsize=size;}
+this.root.style.flip="y";return true;},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);var roots=[this.rendererRoot,this.root,this.vectorRoot,this.textRoot];var w=this.size.w+"px";var h=this.size.h+"px";var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];root.style.width=w;root.style.height=h;}},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="olv:rect";}else if(this.isComplexSymbol(style.graphicName)){nodeType="olv:shape";}else{nodeType="olv:oval";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="olv:rect";break;case"OpenLayers.Geometry.LineString":case"OpenLayers.Geometry.LinearRing":case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="olv:shape";break;default:break;}
+return nodeType;},setStyle:function(node,style,options,geometry){style=style||node._style;options=options||node._options;var fillColor=style.fillColor;if(node._geometryClass==="OpenLayers.Geometry.Point"){if(style.externalGraphic){options.isFilled=true;if(style.graphicTitle){node.title=style.graphicTitle;}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var resolution=this.getResolution();var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);node.style.left=(((geometry.x/resolution-this.offset.x)+xOffset)|0)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)-(yOffset+height))|0)+"px";node.style.width=width+"px";node.style.height=height+"px";node.style.flip="y";fillColor="none";options.isStroked=false;}else if(this.isComplexSymbol(style.graphicName)){var cache=this.importSymbol(style.graphicName);node.path=cache.path;node.coordorigin=cache.left+","+cache.bottom;var size=cache.size;node.coordsize=size+","+size;this.drawCircle(node,geometry,style.pointRadius);node.style.flip="y";}else{this.drawCircle(node,geometry,style.pointRadius);}}
+if(options.isFilled){node.fillcolor=fillColor;}else{node.filled="false";}
+var fills=node.getElementsByTagName("fill");var fill=(fills.length==0)?null:fills[0];if(!options.isFilled){if(fill){node.removeChild(fill);}}else{if(!fill){fill=this.createNode('olv:fill',node.id+"_fill");}
+fill.opacity=style.fillOpacity;if(node._geometryClass==="OpenLayers.Geometry.Point"&&style.externalGraphic){if(style.graphicOpacity){fill.opacity=style.graphicOpacity;}
+fill.src=style.externalGraphic;fill.type="frame";if(!(style.graphicWidth&&style.graphicHeight)){fill.aspect="atmost";}}
+if(fill.parentNode!=node){node.appendChild(fill);}}
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)){node._rotation=rotation;if(style.externalGraphic){this.graphicRotate(node,xOffset,yOffset,style);fill.opacity=0;}else if(node._geometryClass==="OpenLayers.Geometry.Point"){node.style.rotation=rotation||0;}}
+var strokes=node.getElementsByTagName("stroke");var stroke=(strokes.length==0)?null:strokes[0];if(!options.isStroked){node.stroked=false;if(stroke){stroke.on=false;}}else{if(!stroke){stroke=this.createNode('olv:stroke',node.id+"_stroke");node.appendChild(stroke);}
+stroke.on=true;stroke.color=style.strokeColor;stroke.weight=style.strokeWidth+"px";stroke.opacity=style.strokeOpacity;stroke.endcap=style.strokeLinecap=='butt'?'flat':(style.strokeLinecap||'round');if(style.strokeDashstyle){stroke.dashstyle=this.dashStyle(style);}}
+if(style.cursor!="inherit"&&style.cursor!=null){node.style.cursor=style.cursor;}
+return node;},graphicRotate:function(node,xOffset,yOffset,style){var style=style||node._style;var rotation=style.rotation||0;var aspectRatio,size;if(!(style.graphicWidth&&style.graphicHeight)){var img=new Image();img.onreadystatechange=OpenLayers.Function.bind(function(){if(img.readyState=="complete"||img.readyState=="interactive"){aspectRatio=img.width/img.height;size=Math.max(style.pointRadius*2,style.graphicWidth||0,style.graphicHeight||0);xOffset=xOffset*aspectRatio;style.graphicWidth=size*aspectRatio;style.graphicHeight=size;this.graphicRotate(node,xOffset,yOffset,style);}},this);img.src=style.externalGraphic;return;}else{size=Math.max(style.graphicWidth,style.graphicHeight);aspectRatio=style.graphicWidth/style.graphicHeight;}
+var width=Math.round(style.graphicWidth||size*aspectRatio);var height=Math.round(style.graphicHeight||size);node.style.width=width+"px";node.style.height=height+"px";var image=document.getElementById(node.id+"_image");if(!image){image=this.createNode("olv:imagedata",node.id+"_image");node.appendChild(image);}
+image.style.width=width+"px";image.style.height=height+"px";image.src=style.externalGraphic;image.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader("+"src='', sizingMethod='scale')";var rot=rotation*Math.PI/180;var sintheta=Math.sin(rot);var costheta=Math.cos(rot);var filter="progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')\n";var opacity=style.graphicOpacity||style.fillOpacity;if(opacity&&opacity!=1){filter+="progid:DXImageTransform.Microsoft.BasicImage(opacity="+
+opacity+")\n";}
+node.style.filter=filter;var centerPoint=new OpenLayers.Geometry.Point(-xOffset,-yOffset);var imgBox=new OpenLayers.Bounds(0,0,width,height).toGeometry();imgBox.rotate(style.rotation,centerPoint);var imgBounds=imgBox.getBounds();node.style.left=Math.round(parseInt(node.style.left)+imgBounds.left)+"px";node.style.top=Math.round(parseInt(node.style.top)-imgBounds.bottom)+"px";},postDraw:function(node){node.style.visibility="visible";var fillColor=node._style.fillColor;var strokeColor=node._style.strokeColor;if(fillColor=="none"&&node.fillcolor!=fillColor){node.fillcolor=fillColor;}
+if(strokeColor=="none"&&node.strokecolor!=strokeColor){node.strokecolor=strokeColor;}},setNodeDimension:function(node,geometry){var bbox=geometry.getBounds();if(bbox){var resolution=this.getResolution();var scaledBox=new OpenLayers.Bounds((bbox.left/resolution-this.offset.x)|0,(bbox.bottom/resolution-this.offset.y)|0,(bbox.right/resolution-this.offset.x)|0,(bbox.top/resolution-this.offset.y)|0);node.style.left=scaledBox.left+"px";node.style.top=scaledBox.top+"px";node.style.width=scaledBox.getWidth()+"px";node.style.height=scaledBox.getHeight()+"px";node.coordorigin=scaledBox.left+" "+scaledBox.top;node.coordsize=scaledBox.getWidth()+" "+scaledBox.getHeight();}},dashStyle:function(style){var dash=style.strokeDashstyle;switch(dash){case'solid':case'dot':case'dash':case'dashdot':case'longdash':case'longdashdot':return dash;default:var parts=dash.split(/[ ,]/);if(parts.length==2){if(1*parts[0]>=2*parts[1]){return"longdash";}
+return(parts[0]==1||parts[1]==1)?"dot":"dash";}else if(parts.length==4){return(1*parts[0]>=2*parts[1])?"longdashdot":"dashdot";}
+return"solid";}},createNode:function(type,id){var node=document.createElement(type);if(id){node.id=id;}
+node.unselectable='on';node.onselectstart=OpenLayers.Function.False;return node;},nodeTypeCompare:function(node,type){var subType=type;var splitIndex=subType.indexOf(":");if(splitIndex!=-1){subType=subType.substr(splitIndex+1);}
+var nodeName=node.nodeName;splitIndex=nodeName.indexOf(":");if(splitIndex!=-1){nodeName=nodeName.substr(splitIndex+1);}
+return(subType==nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_vmlRoot","div");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"olv:group");},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){if(!isNaN(geometry.x)&&!isNaN(geometry.y)){var resolution=this.getResolution();node.style.left=(((geometry.x/resolution-this.offset.x)|0)-radius)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)|0)-radius)+"px";var diameter=radius*2;node.style.width=diameter+"px";node.style.height=diameter+"px";return node;}
+return false;},drawLineString:function(node,geometry){return this.drawLine(node,geometry,false);},drawLinearRing:function(node,geometry){return this.drawLine(node,geometry,true);},drawLine:function(node,geometry,closeLine){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var numComponents=geometry.components.length;var parts=new Array(numComponents);var comp,x,y;for(var i=0;i<numComponents;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;parts[i]=" "+x+","+y+" l ";}
+var end=(closeLine)?" x e":" e";node.path="m"+parts.join("")+end;return node;},drawPolygon:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var j,jj,points,area,first,second,i,ii,comp,pathComp,x,y;for(j=0,jj=geometry.components.length;j<jj;j++){path.push("m");points=geometry.components[j].components;area=(j===0);first=null;second=null;for(i=0,ii=points.length;i<ii;i++){comp=points[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;pathComp=" "+x+","+y;path.push(pathComp);if(i==0){path.push(" l");}
+if(!area){if(!first){first=pathComp;}else if(first!=pathComp){if(!second){second=pathComp;}else if(second!=pathComp){area=true;}}}}
+path.push(area?" x ":" ");}
+path.push("e");node.path=path.join("");return node;},drawRectangle:function(node,geometry){var resolution=this.getResolution();node.style.left=((geometry.x/resolution-this.offset.x)|0)+"px";node.style.top=((geometry.y/resolution-this.offset.y)|0)+"px";node.style.width=((geometry.width/resolution)|0)+"px";node.style.height=((geometry.height/resolution)|0)+"px";return node;},drawText:function(featureId,style,location){var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"olv:rect");var textbox=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_textbox","olv:textbox");var resolution=this.getResolution();label.style.left=((location.x/resolution-this.offset.x)|0)+"px";label.style.top=((location.y/resolution-this.offset.y)|0)+"px";label.style.flip="y";textbox.innerText=style.label;if(style.cursor!="inherit"&&style.cursor!=null){textbox.style.cursor=style.cursor;}
+if(style.fontColor){textbox.style.color=style.fontColor;}
+if(style.fontOpacity){textbox.style.filter='alpha(opacity='+(style.fontOpacity*100)+')';}
+if(style.fontFamily){textbox.style.fontFamily=style.fontFamily;}
+if(style.fontSize){textbox.style.fontSize=style.fontSize;}
+if(style.fontWeight){textbox.style.fontWeight=style.fontWeight;}
+if(style.fontStyle){textbox.style.fontStyle=style.fontStyle;}
+if(style.labelSelect===true){label._featureId=featureId;textbox._featureId=featureId;textbox._geometry=location;textbox._geometryClass=location.CLASS_NAME;}
+textbox.style.whiteSpace="nowrap";textbox.inset="1px,0px,0px,0px";if(!label.parentNode){label.appendChild(textbox);this.textRoot.appendChild(label);}
+var align=style.labelAlign||"cm";if(align.length==1){align+="m";}
+var xshift=textbox.clientWidth*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);var yshift=textbox.clientHeight*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);label.style.left=parseInt(label.style.left)-xshift-1+"px";label.style.top=parseInt(label.style.top)+yshift+"px";},drawSurface:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var comp,x,y;for(var i=0,len=geometry.components.length;i<len;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;if((i%3)==0&&(i/3)==0){path.push("m");}else if((i%3)==1){path.push(" c");}
+path.push(" "+x+","+y);}
+path.push(" x e");node.path=path.join("");return node;},moveRoot:function(renderer){var layer=this.map.getLayer(renderer.container.id);if(layer instanceof OpenLayers.Layer.Vector.RootContainer){layer=this.map.getLayer(this.container.id);}
+layer&&layer.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this,arguments);layer&&layer.redraw();},importSymbol:function(graphicName){var id=this.container.id+"-"+graphicName;var cache=this.symbolCache[id];if(cache){return cache;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var pathitems=["m"];for(var i=0;i<symbol.length;i=i+2){var x=symbol[i];var y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);pathitems.push(x);pathitems.push(y);if(i==0){pathitems.push("l");}}
+pathitems.push("x e");var path=pathitems.join(" ");var diff=(symbolExtent.getWidth()-symbolExtent.getHeight())/2;if(diff>0){symbolExtent.bottom=symbolExtent.bottom-diff;symbolExtent.top=symbolExtent.top+diff;}else{symbolExtent.left=symbolExtent.left+diff;symbolExtent.right=symbolExtent.right-diff;}
+cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Layer.MultiMap=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[9,1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125],type:null,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();this.RESOLUTIONS.unshift(10);}},loadMapObject:function(){try{this.mapObject=new MultimapViewer(this.div);}catch(e){}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':"MM",'layerLib':"MultiMap"});},setMapObjectCenter:function(center,zoom){this.mapObject.goToPosition(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCurrentPosition();},getMapObjectZoom:function(){return this.mapObject.getZoomFactor();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){moPixel.x=moPixel.x-(this.map.getSize().w/2);moPixel.y=moPixel.y-(this.map.getSize().h/2);return this.mapObject.getMapPositionAt(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.geoPosToContainerPixels(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lon:moLonLat.lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lat:moLonLat.lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var mmLatLon;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);mmLatLon=new MMLatLon(lonlat.lat,lonlat.lon);}else{mmLatLon=new MMLatLon(lat,lon);}
+return mmLatLon;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new MMPoint(x,y);},CLASS_NAME:"OpenLayers.Layer.MultiMap"});OpenLayers.Protocol.WFS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.0.0",CLASS_NAME:"OpenLayers.Protocol.WFS.v1_0_0"});OpenLayers.Control.WMTSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,requestEncoding:"KVP",drillDown:false,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:true,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","getfeatureinfo","exception"],pending:0,initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMTSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);}
+if(this.drillDown===true){this.hover=false;}
+if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{delay:250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},getInfoForClick:function(evt){this.request(evt.xy,{});},getInfoForHover:function(evt){this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;}
+this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer;for(var i=candidates.length-1;i>=0;--i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMTS&&layer.requestEncoding===this.requestEncoding&&(!this.queryVisible||layer.getVisibility())){layers.push(layer);if(!this.drillDown||this.hover){break;}}}
+return layers;},buildRequestOptions:function(layer,xy){var loc=this.map.getLonLatFromPixel(xy);var getTileUrl=layer.getURL(new OpenLayers.Bounds(loc.lon,loc.lat,loc.lon,loc.lat));var params=OpenLayers.Util.getParameters(getTileUrl);var tileInfo=layer.getTileInfo(loc);OpenLayers.Util.extend(params,{service:"WMTS",version:layer.version,request:"GetFeatureInfo",infoFormat:this.infoFormat,i:tileInfo.i,j:tileInfo.j});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:OpenLayers.Util.isArray(layer.url)?layer.url[0]:layer.url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(xy,request,layer);},scope:this};},request:function(xy,options){options=options||{};var layers=this.findLayers();if(layers.length>0){var issue,layer;for(var i=0,len=layers.length;i<len;i++){layer=layers[i];issue=this.events.triggerEvent("beforegetfeatureinfo",{xy:xy,layer:layer});if(issue!==false){++this.pending;var requestOptions=this.buildRequestOptions(layer,xy);var request=OpenLayers.Request.GET(requestOptions);if(options.hover===true){this.hoverRequest=request;}}}
+if(this.pending>0){OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");}}},handleResponse:function(xy,request,layer){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;}
+if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("exception",{xy:xy,request:request,layer:layer});}else{var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+var features,except;try{features=this.format.read(doc);}catch(error){except=true;this.events.triggerEvent("exception",{xy:xy,request:request,error:error,layer:layer});}
+if(!except){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy,layer:layer});}}},CLASS_NAME:"OpenLayers.Control.WMTSGetFeatureInfo"});OpenLayers.Format.WFST.v1_1_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_1_0,OpenLayers.Format.WFST.v1,{version:"1.1.0",schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readNode:function(node,obj,first){return OpenLayers.Format.GML.v3.prototype.readNode.apply(this,[node,obj]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){obj.numberOfFeatures=parseInt(node.getAttribute("numberOfFeatures"));OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(this,arguments);},"member":function(node,obj){this.readChildNodes(node,obj);},"TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"TransactionSummary":function(node,obj){obj.success=true;},"InsertResults":function(node,obj){this.readChildNodes(node,obj);},"Feature":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"gml32":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"],"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"GetFeature":function(options){var node=OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this,arguments);options&&this.setAttributes(node,{resultType:options.resultType,startIndex:options.startIndex,count:options.count});return node;},"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName},options);var prefix=options.featurePrefix;var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(prefix?prefix+":":"")+
+options.featureType,srsName:options.srsName}});if(options.featureNS){node.setAttribute("xmlns:"+prefix,options.featureNS);}
+if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("wfs:PropertyName",{property:options.propertyNames[i]},node);}}
+if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);}
+return node;},"PropertyName":function(obj){return this.createElementNSPlus("wfs:PropertyName",{value:obj.property});}},OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.writers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.WFST.v1_1_0"});OpenLayers.Control.Graticule=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,intervals:[45,30,20,10,5,2,1,0.5,0.2,0.1,0.05,0.01,0.005,0.002,0.001],displayInLayerSwitcher:true,visible:true,numPoints:50,targetSize:200,layerName:null,labelled:true,labelFormat:'dm',lineSymbolizer:{strokeColor:"#333",strokeWidth:1,strokeOpacity:0.5},labelSymbolizer:{},gratLayer:null,initialize:function(options){options=options||{};options.layerName=options.layerName||OpenLayers.i18n("Graticule");OpenLayers.Control.prototype.initialize.apply(this,[options]);this.labelSymbolizer.stroke=false;this.labelSymbolizer.fill=false;this.labelSymbolizer.label="${label}";this.labelSymbolizer.labelAlign="${labelAlign}";this.labelSymbolizer.labelXOffset="${xOffset}";this.labelSymbolizer.labelYOffset="${yOffset}";},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.gratLayer){this.gratLayer.destroy();this.gratLayer=null;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.gratLayer){var gratStyle=new OpenLayers.Style({},{rules:[new OpenLayers.Rule({'symbolizer':{"Point":this.labelSymbolizer,"Line":this.lineSymbolizer}})]});this.gratLayer=new OpenLayers.Layer.Vector(this.layerName,{styleMap:new OpenLayers.StyleMap({'default':gratStyle}),visibility:this.visible,displayInLayerSwitcher:this.displayInLayerSwitcher});}
+return this.div;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.addLayer(this.gratLayer);this.map.events.register('moveend',this,this.update);this.update();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.map.events.unregister('moveend',this,this.update);this.map.removeLayer(this.gratLayer);return true;}else{return false;}},update:function(){var mapBounds=this.map.getExtent();if(!mapBounds){return;}
+this.gratLayer.destroyFeatures();var llProj=new OpenLayers.Projection("EPSG:4326");var mapProj=this.map.getProjectionObject();var mapRes=this.map.getResolution();if(mapProj.proj&&mapProj.proj.projName=="longlat"){this.numPoints=1;}
+var mapCenter=this.map.getCenter();var mapCenterLL=new OpenLayers.Pixel(mapCenter.lon,mapCenter.lat);OpenLayers.Projection.transform(mapCenterLL,mapProj,llProj);var testSq=this.targetSize*mapRes;testSq*=testSq;var llInterval;for(var i=0;i<this.intervals.length;++i){llInterval=this.intervals[i];var delta=llInterval/2;var p1=mapCenterLL.offset(new OpenLayers.Pixel(-delta,-delta));var p2=mapCenterLL.offset(new OpenLayers.Pixel(delta,delta));OpenLayers.Projection.transform(p1,llProj,mapProj);OpenLayers.Projection.transform(p2,llProj,mapProj);var distSq=(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);if(distSq<=testSq){break;}}
+mapCenterLL.x=Math.floor(mapCenterLL.x/llInterval)*llInterval;mapCenterLL.y=Math.floor(mapCenterLL.y/llInterval)*llInterval;var iter=0;var centerLonPoints=[mapCenterLL.clone()];var newPoint=mapCenterLL.clone();var mapXY;do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,-llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);iter=0;var centerLatPoints=[mapCenterLL.clone()];newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(-llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);var lines=[];for(var i=0;i<centerLatPoints.length;++i){var lon=centerLatPoints[i].x;var pointList=[];var labelPoint=null;var latEnd=Math.min(centerLonPoints[0].y,90);var latStart=Math.max(centerLonPoints[centerLonPoints.length-1].y,-90);var latDelta=(latEnd-latStart)/this.numPoints;var lat=latStart;for(var j=0;j<=this.numPoints;++j){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lat+=latDelta;if(gridPoint.y>=mapBounds.bottom&&!labelPoint){labelPoint=gridPoint;}}
+if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(labelPoint.x,mapBounds.bottom);var labelAttrs={value:lon,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lon,"lon",this.labelFormat):"",labelAlign:"cb",xOffset:0,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));}
+var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));}
+for(var j=0;j<centerLonPoints.length;++j){lat=centerLonPoints[j].y;if(lat<-90||lat>90){continue;}
+var pointList=[];var lonStart=centerLatPoints[0].x;var lonEnd=centerLatPoints[centerLatPoints.length-1].x;var lonDelta=(lonEnd-lonStart)/this.numPoints;var lon=lonStart;var labelPoint=null;for(var i=0;i<=this.numPoints;++i){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lon+=lonDelta;if(gridPoint.x<mapBounds.right){labelPoint=gridPoint;}}
+if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(mapBounds.right,labelPoint.y);var labelAttrs={value:lat,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lat,"lat",this.labelFormat):"",labelAlign:"rb",xOffset:-2,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));}
+var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));}
+this.gratLayer.addFeatures(lines);},CLASS_NAME:"OpenLayers.Control.Graticule"});OpenLayers.Control.NavigationHistory=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOGGLE,previous:null,previousOptions:null,next:null,nextOptions:null,limit:50,autoActivate:true,clearOnDeactivate:false,registry:null,nextStack:null,previousStack:null,listeners:null,restoring:false,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.registry=OpenLayers.Util.extend({"moveend":this.getState},this.registry);var previousOptions={trigger:OpenLayers.Function.bind(this.previousTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Previous"};OpenLayers.Util.extend(previousOptions,this.previousOptions);this.previous=new OpenLayers.Control.Button(previousOptions);var nextOptions={trigger:OpenLayers.Function.bind(this.nextTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Next"};OpenLayers.Util.extend(nextOptions,this.nextOptions);this.next=new OpenLayers.Control.Button(nextOptions);this.clear();},onPreviousChange:function(state,length){if(state&&!this.previous.active){this.previous.activate();}else if(!state&&this.previous.active){this.previous.deactivate();}},onNextChange:function(state,length){if(state&&!this.next.active){this.next.activate();}else if(!state&&this.next.active){this.next.deactivate();}},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this);this.previous.destroy();this.next.destroy();this.deactivate();for(var prop in this){this[prop]=null;}},setMap:function(map){this.map=map;this.next.setMap(map);this.previous.setMap(map);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.next.draw();this.previous.draw();},previousTrigger:function(){var current=this.previousStack.shift();var state=this.previousStack.shift();if(state!=undefined){this.nextStack.unshift(current);this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}else{this.previousStack.unshift(current);}
+return state;},nextTrigger:function(){var state=this.nextStack.shift();if(state!=undefined){this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}
+return state;},clear:function(){this.previousStack=[];this.previous.deactivate();this.nextStack=[];this.next.deactivate();},getState:function(){return{center:this.map.getCenter(),resolution:this.map.getResolution(),projection:this.map.getProjectionObject(),units:this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units};},restore:function(state){var center,zoom;if(this.map.getProjectionObject()==state.projection){zoom=this.map.getZoomForResolution(state.resolution);center=state.center;}else{center=state.center.clone();center.transform(state.projection,this.map.getProjectionObject());var sourceUnits=state.units;var targetUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;zoom=this.map.getZoomForResolution(resolutionFactor*state.resolution);}
+this.map.setCenter(center,zoom);},setListeners:function(){this.listeners={};for(var type in this.registry){this.listeners[type]=OpenLayers.Function.bind(function(){if(!this.restoring){var state=this.registry[type].apply(this,arguments);this.previousStack.unshift(state);if(this.previousStack.length>1){this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}
+if(this.previousStack.length>(this.limit+1)){this.previousStack.pop();}
+if(this.nextStack.length>0){this.nextStack=[];this.onNextChange(null,0);}}
+return true;},this);}},activate:function(){var activated=false;if(this.map){if(OpenLayers.Control.prototype.activate.apply(this)){if(this.listeners==null){this.setListeners();}
+for(var type in this.listeners){this.map.events.register(type,this,this.listeners[type]);}
+activated=true;if(this.previousStack.length==0){this.initStack();}}}
+return activated;},initStack:function(){if(this.map.getCenter()){this.listeners.moveend();}},deactivate:function(){var deactivated=false;if(this.map){if(OpenLayers.Control.prototype.deactivate.apply(this)){for(var type in this.listeners){this.map.events.unregister(type,this,this.listeners[type]);}
+if(this.clearOnDeactivate){this.clear();}
+deactivated=true;}}
+return deactivated;},CLASS_NAME:"OpenLayers.Control.NavigationHistory"});OpenLayers.Layer.WMS.Post=OpenLayers.Class(OpenLayers.Layer.WMS,{unsupportedBrowsers:["mozilla","firefox","opera"],SUPPORTED_TRANSITIONS:[],usePost:null,initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.WMS.prototype.initialize.apply(this,newArguments);this.usePost=OpenLayers.Util.indexOf(this.unsupportedBrowsers,OpenLayers.BROWSER_NAME)==-1;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize,{maxGetUrlLength:this.usePost?0:null});},CLASS_NAME:'OpenLayers.Layer.WMS.Post'});OpenLayers.Control.TransformFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesetfeature","setfeature","beforetransform","transform","transformcomplete"],geometryTypes:null,layer:null,preserveAspectRatio:false,rotate:true,feature:null,renderIntent:"temporary",rotationHandleSymbolizer:null,box:null,center:null,scale:1,ratio:1,rotation:0,handles:null,rotationHandles:null,dragControl:null,initialize:function(layer,options){this.EVENT_TYPES=OpenLayers.Control.TransformFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;if(!this.rotationHandleSymbolizer){this.rotationHandleSymbolizer={stroke:false,pointRadius:10,fillOpacity:0,cursor:"pointer"};}
+this.createBox();this.createControl();},activate:function(){var activated=false;if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.dragControl.activate();this.layer.addFeatures([this.box]);this.rotate&&this.layer.addFeatures(this.rotationHandles);this.layer.addFeatures(this.handles);activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.handles);this.rotate&&this.layer.removeFeatures(this.rotationHandles);this.layer.removeFeatures([this.box]);this.dragControl.deactivate();deactivated=true;}
+if(deactivated){this.unsetFeature();}
+return deactivated;},setMap:function(map){this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},setFeature:function(feature,initialParams){initialParams=OpenLayers.Util.applyDefaults(initialParams,{rotation:0,scale:1,ratio:1});var oldRotation=this.rotation;var oldCenter=this.center;OpenLayers.Util.extend(this,initialParams);var cont=this.events.triggerEvent("beforesetfeature",{feature:feature});if(cont===false){return;}
+this.feature=feature;this.activate();this._setfeature=true;var featureBounds=this.feature.geometry.getBounds();this.box.move(featureBounds.getCenterLonLat());this.box.geometry.rotate(-oldRotation,oldCenter);this._angle=0;var ll;if(this.rotation){var geom=feature.geometry.clone();geom.rotate(-this.rotation,this.center);var box=new OpenLayers.Feature.Vector(geom.getBounds().toGeometry());box.geometry.rotate(this.rotation,this.center);this.box.geometry.rotate(this.rotation,this.center);this.box.move(box.geometry.getBounds().getCenterLonLat());var llGeom=box.geometry.components[0].components[0];ll=llGeom.getBounds().getCenterLonLat();}else{ll=new OpenLayers.LonLat(featureBounds.left,featureBounds.bottom);}
+this.handles[0].move(ll);delete this._setfeature;this.events.triggerEvent("setfeature",{feature:feature});},unsetFeature:function(){if(this.active){this.deactivate();}else{this.feature=null;this.rotation=0;this.scale=1;this.ratio=1;}},createBox:function(){var control=this;this.center=new OpenLayers.Geometry.Point(0,0);var box=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([new OpenLayers.Geometry.Point(-1,-1),new OpenLayers.Geometry.Point(0,-1),new OpenLayers.Geometry.Point(1,-1),new OpenLayers.Geometry.Point(1,0),new OpenLayers.Geometry.Point(1,1),new OpenLayers.Geometry.Point(0,1),new OpenLayers.Geometry.Point(-1,1),new OpenLayers.Geometry.Point(-1,0),new OpenLayers.Geometry.Point(-1,-1)]),null,typeof this.renderIntent=="string"?null:this.renderIntent);box.geometry.move=function(x,y){control._moving=true;OpenLayers.Geometry.LineString.prototype.move.apply(this,arguments);control.center.move(x,y);delete control._moving;};var vertexMoveFn=function(x,y){OpenLayers.Geometry.Point.prototype.move.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.move(x,y);this._handle.geometry.move(x,y);};var vertexResizeFn=function(scale,center,ratio){OpenLayers.Geometry.Point.prototype.resize.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.resize(scale,center,ratio);this._handle.geometry.resize(scale,center,ratio);};var vertexRotateFn=function(angle,center){OpenLayers.Geometry.Point.prototype.rotate.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.rotate(angle,center);this._handle.geometry.rotate(angle,center);};var handleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
+var evt=control.dragControl.handlers.drag.evt;var preserveAspectRatio=!control._setfeature&&control.preserveAspectRatio;var reshape=!preserveAspectRatio&&!(evt&&evt.shiftKey);var oldGeom=new OpenLayers.Geometry.Point(oldX,oldY);var centerGeometry=control.center;this.rotate(-control.rotation,centerGeometry);oldGeom.rotate(-control.rotation,centerGeometry);var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-(this.x-oldGeom.x);var dy0=dy1-(this.y-oldGeom.y);this.x=oldX;this.y=oldY;var scale,ratio=1;if(reshape){scale=Math.abs(dy0)<0.00001?1:dy1/dy0;ratio=(Math.abs(dx0)<0.00001?1:(dx1/dx0))/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;}
+control._moving=true;control.box.geometry.rotate(-control.rotation,centerGeometry);delete control._moving;control.box.geometry.resize(scale,centerGeometry,ratio);control.box.geometry.rotate(control.rotation,centerGeometry);control.transformFeature({scale:scale,ratio:ratio});};var rotationHandleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
+var evt=control.dragControl.handlers.drag.evt;var constrain=(evt&&evt.shiftKey)?45:1;var centerGeometry=control.center;var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-x;var dy0=dy1-y;this.x=oldX;this.y=oldY;var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;control._angle=(control._angle+angle)%360;var diff=control.rotation%constrain;if(Math.abs(control._angle)>=constrain||diff!==0){angle=Math.round(control._angle/constrain)*constrain-
+diff;control._angle=0;control.box.geometry.rotate(angle,centerGeometry);control.transformFeature({rotation:angle});}};var handles=new Array(8);var rotationHandles=new Array(4);var geom,handle,rotationHandle;for(var i=0;i<8;++i){geom=box.geometry.components[i];handle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.renderIntent=="string"?null:this.renderIntent);if(i%2==0){rotationHandle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.rotationHandleSymbolizer=="string"?null:this.rotationHandleSymbolizer);rotationHandle.geometry.move=rotationHandleMoveFn;geom._rotationHandle=rotationHandle;rotationHandles[i/2]=rotationHandle;}
+geom.move=vertexMoveFn;geom.resize=vertexResizeFn;geom.rotate=vertexRotateFn;handle.geometry.move=handleMoveFn;geom._handle=handle;handles[i]=handle;}
+this.box=box;this.rotationHandles=rotationHandles;this.handles=handles;},createControl:function(){var control=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:true,moveFeature:function(pixel){if(this.feature===control.feature){this.feature=control.box;}
+OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments);},onDrag:function(feature,pixel){if(feature===control.box){control.transformFeature({center:control.center});control.drawHandles();}},onStart:function(feature,pixel){var eligible=!control.geometryTypes||OpenLayers.Util.indexOf(control.geometryTypes,feature.geometry.CLASS_NAME)!==-1;var i=OpenLayers.Util.indexOf(control.handles,feature);i+=OpenLayers.Util.indexOf(control.rotationHandles,feature);if(feature!==control.feature&&feature!==control.box&&i==-2&&eligible){control.setFeature(feature);}},onComplete:function(feature,pixel){control.events.triggerEvent("transformcomplete",{feature:control.feature});}});},drawHandles:function(){var layer=this.layer;for(var i=0;i<8;++i){if(this.rotate&&i%2===0){layer.drawFeature(this.rotationHandles[i/2],this.rotationHandleSymbolizer);}
+layer.drawFeature(this.handles[i],this.renderIntent);}},transformFeature:function(mods){if(!this._setfeature){this.scale*=(mods.scale||1);this.ratio*=(mods.ratio||1);var oldRotation=this.rotation;this.rotation=(this.rotation+(mods.rotation||0))%360;if(this.events.triggerEvent("beforetransform",mods)!==false){var feature=this.feature;var geom=feature.geometry;var center=this.center;geom.rotate(-oldRotation,center);if(mods.scale||mods.ratio){geom.resize(mods.scale,center,mods.ratio);}else if(mods.center){feature.move(mods.center.getBounds().getCenterLonLat());}
+geom.rotate(this.rotation,center);this.layer.drawFeature(feature);feature.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",mods);}}
+this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles();},destroy:function(){var geom;for(var i=0;i<8;++i){geom=this.box.geometry.components[i];geom._handle.destroy();geom._handle=null;geom._rotationHandle&&geom._rotationHandle.destroy();geom._rotationHandle=null;}
+this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Layer.ArcGISCache=OpenLayers.Class(OpenLayers.Layer.XYZ,{url:null,tileOrigin:null,tileSize:new OpenLayers.Size(256,256),useArcGISServer:true,type:'png',useScales:false,overrideDPI:false,initialize:function(name,url,options){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);if(this.resolutions){this.serverResolutions=this.resolutions;this.maxExtent=this.getMaxExtentForResolution(this.resolutions[0]);}
+if(this.layerInfo){var info=this.layerInfo;var startingTileExtent=new OpenLayers.Bounds(info.fullExtent.xmin,info.fullExtent.ymin,info.fullExtent.xmax,info.fullExtent.ymax);this.projection='EPSG:'+info.spatialReference.wkid;this.sphericalMercator=(info.spatialReference.wkid==102100);this.units=(info.units=="esriFeet")?'ft':'m';if(!!info.tileInfo){this.tileSize=new OpenLayers.Size(info.tileInfo.width||info.tileInfo.cols,info.tileInfo.height||info.tileInfo.rows);this.tileOrigin=new OpenLayers.LonLat(info.tileInfo.origin.x,info.tileInfo.origin.y);var upperLeft=new OpenLayers.Geometry.Point(startingTileExtent.left,startingTileExtent.top);var bottomRight=new OpenLayers.Geometry.Point(startingTileExtent.right,startingTileExtent.bottom);if(this.useScales){this.scales=[];}else{this.resolutions=[];}
+this.lods=[];for(var key in info.tileInfo.lods){if(info.tileInfo.lods.hasOwnProperty(key)){var lod=info.tileInfo.lods[key];if(this.useScales){this.scales.push(lod.scale);}else{this.resolutions.push(lod.resolution);}
+var start=this.getContainingTileCoords(upperLeft,lod.resolution);lod.startTileCol=start.x;lod.startTileRow=start.y;var end=this.getContainingTileCoords(bottomRight,lod.resolution);lod.endTileCol=end.x;lod.endTileRow=end.y;this.lods.push(lod);}}
+this.maxExtent=this.calculateMaxExtentWithLOD(this.lods[0]);this.serverResolutions=this.resolutions;if(this.overrideDPI&&info.tileInfo.dpi){OpenLayers.DOTS_PER_INCH=info.tileInfo.dpi;}}}},getContainingTileCoords:function(point,res){return new OpenLayers.Pixel(Math.max(Math.floor((point.x-this.tileOrigin.lon)/(this.tileSize.w*res)),0),Math.max(Math.floor((this.tileOrigin.lat-point.y)/(this.tileSize.h*res)),0));},calculateMaxExtentWithLOD:function(lod){var numTileCols=(lod.endTileCol-lod.startTileCol)+1;var numTileRows=(lod.endTileRow-lod.startTileRow)+1;var minX=this.tileOrigin.lon+(lod.startTileCol*this.tileSize.w*lod.resolution);var maxX=minX+(numTileCols*this.tileSize.w*lod.resolution);var maxY=this.tileOrigin.lat-(lod.startTileRow*this.tileSize.h*lod.resolution);var minY=maxY-(numTileRows*this.tileSize.h*lod.resolution);return new OpenLayers.Bounds(minX,minY,maxX,maxY);},calculateMaxExtentWithExtent:function(extent,res){var upperLeft=new OpenLayers.Geometry.Point(extent.left,extent.top);var bottomRight=new OpenLayers.Geometry.Point(extent.right,extent.bottom);var start=this.getContainingTileCoords(upperLeft,res);var end=this.getContainingTileCoords(bottomRight,res);var lod={resolution:res,startTileCol:start.x,startTileRow:start.y,endTileCol:end.x,endTileRow:end.y};return this.calculateMaxExtentWithLOD(lod);},getUpperLeftTileCoord:function(res){var upperLeft=new OpenLayers.Geometry.Point(this.maxExtent.left,this.maxExtent.top);return this.getContainingTileCoords(upperLeft,res);},getLowerRightTileCoord:function(res){var bottomRight=new OpenLayers.Geometry.Point(this.maxExtent.right,this.maxExtent.bottom);return this.getContainingTileCoords(bottomRight,res);},getMaxExtentForResolution:function(res){var start=this.getUpperLeftTileCoord(res);var end=this.getLowerRightTileCoord(res);var numTileCols=(end.x-start.x)+1;var numTileRows=(end.y-start.y)+1;var minX=this.tileOrigin.lon+(start.x*this.tileSize.w*res);var maxX=minX+(numTileCols*this.tileSize.w*res);var maxY=this.tileOrigin.lat-(start.y*this.tileSize.h*res);var minY=maxY-(numTileRows*this.tileSize.h*res);return new OpenLayers.Bounds(minX,minY,maxX,maxY);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcGISCache(this.name,this.url,this.options);}
+return OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);},getMaxExtent:function(){var resolution=this.map.getResolution();return this.maxExtent=this.getMaxExtentForResolution(resolution);},getTileOrigin:function(){var extent=this.getMaxExtent();return new OpenLayers.LonLat(extent.left,extent.bottom);},getURL:function(bounds){var res=this.getResolution();var originTileX=(this.tileOrigin.lon+(res*this.tileSize.w/2));var originTileY=(this.tileOrigin.lat-(res*this.tileSize.h/2));var center=bounds.getCenterLonLat();var point={x:center.lon,y:center.lat};var x=(Math.round(Math.abs((center.lon-originTileX)/(res*this.tileSize.w))));var y=(Math.round(Math.abs((originTileY-center.lat)/(res*this.tileSize.h))));var z=this.map.getZoom();if(this.lods){var lod=this.lods[this.map.getZoom()];if((x<lod.startTileCol||x>lod.endTileCol)||(y<lod.startTileRow||y>lod.endTileRow)){return null;}}
+else{var start=this.getUpperLeftTileCoord(res);var end=this.getLowerRightTileCoord(res);if((x<start.x||x>=end.x)||(y<start.y||y>=end.y)){return null;}}
+var url=this.url;var s=''+x+y+z;if(OpenLayers.Util.isArray(url)){url=this.selectUrl(s,url);}
+if(this.useArcGISServer){url=url+'/tile/${z}/${y}/${x}';}else{x='C'+this.zeroPad(x,8,16);y='R'+this.zeroPad(y,8,16);z='L'+this.zeroPad(z,2,16);url=url+'/${z}/${y}/${x}.'+this.type;}
+url=OpenLayers.String.format(url,{'x':x,'y':y,'z':z});return url;},zeroPad:function(num,len,radix){var str=num.toString(radix||10);while(str.length<len){str="0"+str;}
+return str;},CLASS_NAME:'OpenLayers.Layer.ArcGISCache'});OpenLayers.Control.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,drillDown:false,maxFeatures:10,clickCallback:"click",output:"features",layers:null,queryVisible:false,url:null,layerUrls:null,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","nogetfeatureinfo","getfeatureinfo"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);}
+if(this.drillDown===true){this.hover=false;}
+if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{'delay':250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},activate:function(){if(!this.active){this.handler.activate();}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},getInfoForClick:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");this.request(evt.xy,{});},getInfoForHover:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer,url;for(var i=0,len=candidates.length;i<len;++i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMS&&(!this.queryVisible||layer.getVisibility())){url=OpenLayers.Util.isArray(layer.url)?layer.url[0]:layer.url;if(this.drillDown===false&&!this.url){this.url=url;}
+if(this.drillDown===true||this.urlMatches(url)){layers.push(layer);}}}
+return layers;},urlMatches:function(url){var matches=OpenLayers.Util.isEquivalentUrl(this.url,url);if(!matches&&this.layerUrls){for(var i=0,len=this.layerUrls.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[i],url)){matches=true;break;}}}
+return matches;},buildWMSOptions:function(url,layers,clickPosition,format){var layerNames=[],styleNames=[];for(var i=0,len=layers.length;i<len;i++){layerNames=layerNames.concat(layers[i].params.LAYERS);styleNames=styleNames.concat(this.getStyleNames(layers[i]));}
+var firstLayer=layers[0];var projection=this.map.getProjection();var layerProj=firstLayer.projection;if(layerProj&&layerProj.equals(this.map.getProjectionObject())){projection=layerProj.getCode();}
+var params=OpenLayers.Util.extend({service:"WMS",version:firstLayer.params.VERSION,request:"GetFeatureInfo",layers:layerNames,query_layers:layerNames,styles:styleNames,bbox:this.map.getExtent().toBBOX(null,firstLayer.reverseAxisOrder()),feature_count:this.maxFeatures,height:this.map.getSize().h,width:this.map.getSize().w,format:format,info_format:firstLayer.params.INFO_FORMAT||this.infoFormat},(parseFloat(firstLayer.params.VERSION)>=1.3)?{crs:projection,i:parseInt(clickPosition.x),j:parseInt(clickPosition.y)}:{srs:projection,x:parseInt(clickPosition.x),y:parseInt(clickPosition.y)});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(clickPosition,request,url);},scope:this};},getStyleNames:function(layer){var styleNames;if(layer.params.STYLES){styleNames=layer.params.STYLES;}else{if(OpenLayers.Util.isArray(layer.params.LAYERS)){styleNames=new Array(layer.params.LAYERS.length);}else{styleNames=layer.params.LAYERS.replace(/[^,]/g,"");}}
+return styleNames;},request:function(clickPosition,options){var layers=this.findLayers();if(layers.length==0){this.events.triggerEvent("nogetfeatureinfo");OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");return;}
+options=options||{};if(this.drillDown===false){var wmsOptions=this.buildWMSOptions(this.url,layers,clickPosition,layers[0].params.FORMAT);var request=OpenLayers.Request.GET(wmsOptions);if(options.hover===true){this.hoverRequest=request;}}else{this._requestCount=0;this._numRequests=0;this.features=[];var services={},url;for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var service,found=false;url=OpenLayers.Util.isArray(layer.url)?layer.url[0]:layer.url;if(url in services){services[url].push(layer);}else{this._numRequests++;services[url]=[layer];}}
+var layers;for(var url in services){layers=services[url];var wmsOptions=this.buildWMSOptions(url,layers,clickPosition,layers[0].params.FORMAT);OpenLayers.Request.GET(wmsOptions);}}},triggerGetFeatureInfo:function(request,xy,features){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy});OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},handleResponse:function(xy,request,url){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+var features=this.format.read(doc);if(this.drillDown===false){this.triggerGetFeatureInfo(request,xy,features);}else{this._requestCount++;if(this.output==="object"){this._features=(this._features||[]).concat({url:url,features:features});}else{this._features=(this._features||[]).concat(features);}
+if(this._requestCount===this._numRequests){this.triggerGetFeatureInfo(request,xy,this._features.concat());delete this._features;delete this._requestCount;delete this._numRequests;}}},CLASS_NAME:"OpenLayers.Control.WMSGetFeatureInfo"});OpenLayers.Format.WMSCapabilities.v1_3_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_3,{version:"1.3.0",CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3_0"});OpenLayers.Control.Split=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesplit","split","aftersplit"],layer:null,source:null,sourceOptions:null,tolerance:null,edge:true,deferDelete:false,mutual:true,targetFilter:null,sourceFilter:null,handler:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.source){this.setSource(this.options.source);}},setSource:function(layer){if(this.active){this.deactivate();if(this.handler){this.handler.destroy();delete this.handler;}
+this.source=layer;this.activate();}else{this.source=layer;}},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(!this.source){if(!this.handler){this.handler=new OpenLayers.Handler.Path(this,{done:function(geometry){this.onSketchComplete({feature:new OpenLayers.Feature.Vector(geometry)});}},{layerOptions:this.sourceOptions});}
+this.handler.activate();}else if(this.source.events){this.source.events.on({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.source&&this.source.events){this.layer.events.un({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}}
+return deactivated;},onSketchComplete:function(event){this.feature=null;return!this.considerSplit(event.feature);},afterFeatureModified:function(event){if(event.modified){var feature=event.feature;if(feature.geometry instanceof OpenLayers.Geometry.LineString||feature.geometry instanceof OpenLayers.Geometry.MultiLineString){this.feature=event.feature;this.considerSplit(event.feature);}}},removeByGeometry:function(features,geometry){for(var i=0,len=features.length;i<len;++i){if(features[i].geometry===geometry){features.splice(i,1);break;}}},isEligible:function(target){return(target.state!==OpenLayers.State.DELETE)&&(target.geometry instanceof OpenLayers.Geometry.LineString||target.geometry instanceof OpenLayers.Geometry.MultiLineString)&&(this.feature!==target)&&(!this.targetFilter||this.targetFilter.evaluate(target.attributes));},considerSplit:function(feature){var sourceSplit=false;var targetSplit=false;if(!this.sourceFilter||this.sourceFilter.evaluate(feature.attributes)){var features=this.layer&&this.layer.features||[];var target,results,proceed;var additions=[],removals=[];var mutual=(this.layer===this.source)&&this.mutual;var options={edge:this.edge,tolerance:this.tolerance,mutual:mutual};var sourceParts=[feature.geometry];var targetFeature,targetParts;var source,parts;for(var i=0,len=features.length;i<len;++i){targetFeature=features[i];if(this.isEligible(targetFeature)){targetParts=[targetFeature.geometry];for(var j=0;j<sourceParts.length;++j){source=sourceParts[j];for(var k=0;k<targetParts.length;++k){target=targetParts[k];if(source.getBounds().intersectsBounds(target.getBounds())){results=source.split(target,options);if(results){proceed=this.events.triggerEvent("beforesplit",{source:feature,target:targetFeature});if(proceed!==false){if(mutual){parts=results[0];if(parts.length>1){parts.unshift(j,1);Array.prototype.splice.apply(sourceParts,parts);j+=parts.length-3;}
+results=results[1];}
+if(results.length>1){results.unshift(k,1);Array.prototype.splice.apply(targetParts,results);k+=results.length-3;}}}}}}
+if(targetParts&&targetParts.length>1){this.geomsToFeatures(targetFeature,targetParts);this.events.triggerEvent("split",{original:targetFeature,features:targetParts});Array.prototype.push.apply(additions,targetParts);removals.push(targetFeature);targetSplit=true;}}}
+if(sourceParts&&sourceParts.length>1){this.geomsToFeatures(feature,sourceParts);this.events.triggerEvent("split",{original:feature,features:sourceParts});Array.prototype.push.apply(additions,sourceParts);removals.push(feature);sourceSplit=true;}
+if(sourceSplit||targetSplit){if(this.deferDelete){var feat,destroys=[];for(var i=0,len=removals.length;i<len;++i){feat=removals[i];if(feat.state===OpenLayers.State.INSERT){destroys.push(feat);}else{feat.state=OpenLayers.State.DELETE;this.layer.drawFeature(feat);}}
+this.layer.destroyFeatures(destroys,{silent:true});for(var i=0,len=additions.length;i<len;++i){additions[i].state=OpenLayers.State.INSERT;}}else{this.layer.destroyFeatures(removals,{silent:true});}
+this.layer.addFeatures(additions,{silent:true});this.events.triggerEvent("aftersplit",{source:feature,features:additions});}}
+return sourceSplit;},geomsToFeatures:function(feature,geoms){var clone=feature.clone();delete clone.geometry;var newFeature;for(var i=0,len=geoms.length;i<len;++i){newFeature=clone.clone();newFeature.geometry=geoms[i];newFeature.state=OpenLayers.State.INSERT;geoms[i]=newFeature;}},destroy:function(){if(this.active){this.deactivate();}
+OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Split"});OpenLayers.Layer.WMTS=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,version:"1.0.0",requestEncoding:"KVP",url:null,layer:null,matrixSet:null,style:null,format:"image/jpeg",tileOrigin:null,tileFullExtent:null,formatSuffix:null,matrixIds:null,dimensions:null,params:null,zoomOffset:0,formatSuffixMap:{"image/png":"png","image/png8":"png","image/png24":"png","image/png32":"png","png":"png","image/jpeg":"jpg","image/jpg":"jpg","jpeg":"jpg","jpg":"jpg"},matrix:null,initialize:function(config){var required={url:true,layer:true,style:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}}
+config.params=OpenLayers.Util.upperCaseObject(config.params);var args=[config.name,config.url,config.params,config];OpenLayers.Layer.Grid.prototype.initialize.apply(this,args);if(!this.formatSuffix){this.formatSuffix=this.formatSuffixMap[this.format]||this.format.split("/").pop();}
+if(this.matrixIds){var len=this.matrixIds.length;if(len&&typeof this.matrixIds[0]==="string"){var ids=this.matrixIds;this.matrixIds=new Array(len);for(var i=0;i<len;++i){this.matrixIds[i]={identifier:ids[i]};}}}},setMap:function(){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.updateMatrixProperties();},updateMatrixProperties:function(){this.matrix=this.getMatrix();if(this.matrix){if(this.matrix.topLeftCorner){this.tileOrigin=this.matrix.topLeftCorner;}
+if(this.matrix.tileWidth&&this.matrix.tileHeight){this.tileSize=new OpenLayers.Size(this.matrix.tileWidth,this.matrix.tileHeight);}
+if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.top);}
+if(!this.tileFullExtent){this.tileFullExtent=this.maxExtent;}}},moveTo:function(bounds,zoomChanged,dragging){if(zoomChanged||!this.matrix){this.updateMatrixProperties();}
+return OpenLayers.Layer.Grid.prototype.moveTo.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMTS(this.options);}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getMatrix:function(){var matrix;if(!this.matrixIds||this.matrixIds.length===0){matrix={identifier:this.map.getZoom()+this.zoomOffset};}else{if("scaleDenominator"in this.matrixIds[0]){var denom=OpenLayers.METERS_PER_INCH*OpenLayers.INCHES_PER_UNIT[this.units]*this.map.getResolution()/0.28E-3;var diff=Number.POSITIVE_INFINITY;var delta;for(var i=0,ii=this.matrixIds.length;i<ii;++i){delta=Math.abs(1-(this.matrixIds[i].scaleDenominator/denom));if(delta<diff){diff=delta;matrix=this.matrixIds[i];}}}else{matrix=this.matrixIds[this.map.getZoom()+this.zoomOffset];}}
+return matrix;},getTileInfo:function(loc){var res=this.map.getResolution();var fx=(loc.lon-this.tileOrigin.lon)/(res*this.tileSize.w);var fy=(this.tileOrigin.lat-loc.lat)/(res*this.tileSize.h);var col=Math.floor(fx);var row=Math.floor(fy);return{col:col,row:row,i:Math.floor((fx-col)*this.tileSize.w),j:Math.floor((fy-row)*this.tileSize.h)};},getURL:function(bounds){bounds=this.adjustBounds(bounds);var url="";if(!this.tileFullExtent||this.tileFullExtent.intersectsBounds(bounds)){var center=bounds.getCenterLonLat();var info=this.getTileInfo(center);var matrixId=this.matrix.identifier;if(this.requestEncoding.toUpperCase()==="REST"){var path=this.version+"/"+this.layer+"/"+this.style+"/";if(this.dimensions){for(var i=0;i<this.dimensions.length;i++){if(this.params[this.dimensions[i]]){path=path+this.params[this.dimensions[i]]+"/";}}}
+path=path+this.matrixSet+"/"+this.matrix.identifier+"/"+info.row+"/"+info.col+"."+this.formatSuffix;if(OpenLayers.Util.isArray(this.url)){url=this.selectUrl(path,this.url);}else{url=this.url;}
+if(!url.match(/\/$/)){url=url+"/";}
+url=url+path;}else if(this.requestEncoding.toUpperCase()==="KVP"){var params={SERVICE:"WMTS",REQUEST:"GetTile",VERSION:this.version,LAYER:this.layer,STYLE:this.style,TILEMATRIXSET:this.matrixSet,TILEMATRIX:this.matrix.identifier,TILEROW:info.row,TILECOL:info.col,FORMAT:this.format};url=OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,[params]);}}
+return url;},mergeNewParams:function(newParams){if(this.requestEncoding.toUpperCase()==="KVP"){return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,[OpenLayers.Util.upperCaseObject(newParams)]);}},CLASS_NAME:"OpenLayers.Layer.WMTS"});OpenLayers.Protocol.SOS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol,{fois:null,formatOptions:null,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=new OpenLayers.Format.SOSGetFeatureOfInterest(this.formatOptions);}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();}
+this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var format=this.format;var data=OpenLayers.Format.XML.prototype.write.apply(format,[format.writeNode("sos:GetFeatureOfInterest",{fois:this.fois})]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),data:data});return response;},handleRead:function(response,options){if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){response.features=this.parseFeatures(request);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,response);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+return this.format.read(doc);},CLASS_NAME:"OpenLayers.Protocol.SOS.v1_0_0"});OpenLayers.Layer.KaMapCache=OpenLayers.Class(OpenLayers.Layer.KaMap,{IMAGE_EXTENSIONS:{'jpeg':'jpg','gif':'gif','png':'png','png8':'png','png24':'png','dithered':'png'},DEFAULT_FORMAT:'jpeg',initialize:function(name,url,params,options){OpenLayers.Layer.KaMap.prototype.initialize.apply(this,arguments);this.extension=this.IMAGE_EXTENSIONS[this.params.i.toLowerCase()||DEFAULT_FORMAT];},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);var metaX=Math.floor(pX/this.tileSize.w/this.params.metaTileSize.w)*this.tileSize.w*this.params.metaTileSize.w;var metaY=Math.floor(pY/this.tileSize.h/this.params.metaTileSize.h)*this.tileSize.h*this.params.metaTileSize.h;var url=this.url;if(OpenLayers.Util.isArray(url)){url=this.selectUrl(paramsString,url);}
+var components=[url,"/",this.params.map,"/",scale,"/",this.params.g.replace(/\s/g,'_'),"/def/t",metaY,"/l",metaX,"/t",pY,"l",pX,".",this.extension];return components.join("");},CLASS_NAME:"OpenLayers.Layer.KaMapCache"});OpenLayers.Control.PanZoomBar=OpenLayers.Class(OpenLayers.Control.PanZoom,{zoomStopWidth:18,zoomStopHeight:11,slider:null,sliderEvents:null,zoombarDiv:null,divEvents:null,zoomWorldIcon:false,panIcons:true,forceFixedZoomLevel:false,mouseDragStart:null,deltaY:null,zoomStart:null,destroy:function(){this._removeZoomBar();this.map.events.un({"changebaselayer":this.redraw,scope:this});OpenLayers.Control.PanZoom.prototype.destroy.apply(this,arguments);delete this.mouseDragStart;delete this.zoomStart;},setMap:function(map){OpenLayers.Control.PanZoom.prototype.setMap.apply(this,arguments);this.map.events.register("changebaselayer",this,this.redraw);},redraw:function(){if(this.div!=null){this.removeButtons();this._removeZoomBar();}
+this.draw();},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position.clone();this.buttons=[];var sz=new OpenLayers.Size(18,18);if(this.panIcons){var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);var wposition=sz.w;if(this.zoomWorldIcon){centered=new OpenLayers.Pixel(px.x+sz.w,px.y);}
+this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);if(this.zoomWorldIcon){this._addButton("zoomworld","zoom-world-mini.png",px.add(sz.w,0),sz);wposition*=2;}
+this._addButton("panright","east-mini.png",px.add(wposition,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);centered=this._addZoomBar(centered.add(0,sz.h*4+5));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);}
+else{this._addButton("zoomin","zoom-plus-mini.png",px,sz);centered=this._addZoomBar(px.add(0,sz.h));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);if(this.zoomWorldIcon){centered=centered.add(0,sz.h+3);this._addButton("zoomworld","zoom-world-mini.png",centered,sz);}}
+return this.div;},_addZoomBar:function(centered){var imgLocation=OpenLayers.Util.getImagesLocation();var id=this.id+"_"+this.map.id;var zoomsToEnd=this.map.getNumZoomLevels()-1-this.map.getZoom();var slider=OpenLayers.Util.createAlphaImageDiv(id,centered.add(-1,zoomsToEnd*this.zoomStopHeight),new OpenLayers.Size(20,9),imgLocation+"slider.png","absolute");slider.style.cursor="move";this.slider=slider;this.sliderEvents=new OpenLayers.Events(this,slider,null,true,{includeXY:true});this.sliderEvents.on({"touchstart":this.zoomBarDown,"touchmove":this.zoomBarDrag,"touchend":this.zoomBarUp,"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});var sz=new OpenLayers.Size();sz.h=this.zoomStopHeight*this.map.getNumZoomLevels();sz.w=this.zoomStopWidth;var div=null;if(OpenLayers.Util.alphaHack()){var id=this.id+"_"+this.map.id;div=OpenLayers.Util.createAlphaImageDiv(id,centered,new OpenLayers.Size(sz.w,this.zoomStopHeight),imgLocation+"zoombar.png","absolute",null,"crop");div.style.height=sz.h+"px";}else{div=OpenLayers.Util.createDiv('OpenLayers_Control_PanZoomBar_Zoombar'+this.map.id,centered,sz,imgLocation+"zoombar.png");}
+div.style.cursor="pointer";this.zoombarDiv=div;this.divEvents=new OpenLayers.Events(this,div,null,true,{includeXY:true});this.divEvents.on({"touchmove":this.passEventToSlider,"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.div.appendChild(div);this.startTop=parseInt(div.style.top);this.div.appendChild(slider);this.map.events.register("zoomend",this,this.moveZoomBar);centered=centered.add(0,this.zoomStopHeight*this.map.getNumZoomLevels());return centered;},_removeZoomBar:function(){this.sliderEvents.un({"touchmove":this.zoomBarDrag,"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});this.sliderEvents.destroy();this.divEvents.un({"touchmove":this.passEventToSlider,"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.divEvents.destroy();this.div.removeChild(this.zoombarDiv);this.zoombarDiv=null;this.div.removeChild(this.slider);this.slider=null;this.map.events.unregister("zoomend",this,this.moveZoomBar);},passEventToSlider:function(evt){this.sliderEvents.handleBrowserEvent(evt);},divClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
+var levels=evt.xy.y/this.zoomStopHeight;if(this.forceFixedZoomLevel||!this.map.fractionalZoom){levels=Math.floor(levels);}
+var zoom=(this.map.getNumZoomLevels()-1)-levels;zoom=Math.min(Math.max(zoom,0),this.map.getNumZoomLevels()-1);this.map.zoomTo(zoom);OpenLayers.Event.stop(evt);},zoomBarDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)&&!OpenLayers.Event.isSingleTouch(evt)){return;}
+this.map.events.on({"touchmove":this.passEventToSlider,"mousemove":this.passEventToSlider,"mouseup":this.passEventToSlider,scope:this});this.mouseDragStart=evt.xy.clone();this.zoomStart=evt.xy.clone();this.div.style.cursor="move";this.zoombarDiv.offsets=null;OpenLayers.Event.stop(evt);},zoomBarDrag:function(evt){if(this.mouseDragStart!=null){var deltaY=this.mouseDragStart.y-evt.xy.y;var offsets=OpenLayers.Util.pagePosition(this.zoombarDiv);if((evt.clientY-offsets[1])>0&&(evt.clientY-offsets[1])<parseInt(this.zoombarDiv.style.height)-2){var newTop=parseInt(this.slider.style.top)-deltaY;this.slider.style.top=newTop+"px";this.mouseDragStart=evt.xy.clone();}
+this.deltaY=this.zoomStart.y-evt.xy.y;OpenLayers.Event.stop(evt);}},zoomBarUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)&&evt.type!=="touchend"){return;}
+if(this.mouseDragStart){this.div.style.cursor="";this.map.events.un({"touchmove":this.passEventToSlider,"mouseup":this.passEventToSlider,"mousemove":this.passEventToSlider,scope:this});var zoomLevel=this.map.zoom;if(!this.forceFixedZoomLevel&&this.map.fractionalZoom){zoomLevel+=this.deltaY/this.zoomStopHeight;zoomLevel=Math.min(Math.max(zoomLevel,0),this.map.getNumZoomLevels()-1);}else{zoomLevel+=this.deltaY/this.zoomStopHeight;zoomLevel=Math.max(Math.round(zoomLevel),0);}
+this.map.zoomTo(zoomLevel);this.mouseDragStart=null;this.zoomStart=null;this.deltaY=0;OpenLayers.Event.stop(evt);}},moveZoomBar:function(){var newTop=((this.map.getNumZoomLevels()-1)-this.map.getZoom())*this.zoomStopHeight+this.startTop+1;this.slider.style.top=newTop+"px";},CLASS_NAME:"OpenLayers.Control.PanZoomBar"});OpenLayers.Format.GML.v3=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",curve:false,multiCurve:true,surface:false,multiSurface:true,initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"FeatureCollection":function(node,obj){obj.features=[];this.readChildNodes(node,obj);},"Curve":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"segments":function(node,obj){this.readChildNodes(node,obj);},"LineStringSegment":function(node,container){var obj={};this.readChildNodes(node,obj);if(obj.points){Array.prototype.push.apply(container.points,obj.points);}},"pos":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var point;if(this.xy){point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{point=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}
+obj.points=[point];},"posList":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var dim=parseInt(node.getAttribute("dimension"))||2;var j,x,y,z;var numPoints=coords.length/dim;var points=new Array(numPoints);for(var i=0,len=coords.length;i<len;i+=dim){x=coords[i];y=coords[i+1];z=(dim==2)?undefined:coords[i+2];if(this.xy){points[i/dim]=new OpenLayers.Geometry.Point(x,y,z);}else{points[i/dim]=new OpenLayers.Geometry.Point(y,x,z);}}
+obj.points=points;},"Surface":function(node,obj){this.readChildNodes(node,obj);},"patches":function(node,obj){this.readChildNodes(node,obj);},"PolygonPatch":function(node,obj){this.readers.gml.Polygon.apply(this,[node,obj]);},"exterior":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"interior":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"MultiCurve":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];}},"curveMember":function(node,obj){this.readChildNodes(node,obj);},"MultiSurface":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];}},"surfaceMember":function(node,obj){this.readChildNodes(node,obj);},"surfaceMembers":function(node,obj){this.readChildNodes(node,obj);},"pointMembers":function(node,obj){this.readChildNodes(node,obj);},"lineStringMembers":function(node,obj){this.readChildNodes(node,obj);},"polygonMembers":function(node,obj){this.readChildNodes(node,obj);},"geometryMembers":function(node,obj){this.readChildNodes(node,obj);},"Envelope":function(node,container){var obj={points:new Array(2)};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));},"lowerCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[0]=obj.points[0];},"upperCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[1]=obj.points[0];}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Util.applyDefaults({"member":function(node,container){this.readChildNodes(node,obj);}},OpenLayers.Format.GML.Base.prototype.readers["wfs"])},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(features){var node=this.createElementNSPlus("gml:featureMembers");for(var i=0,len=features.length;i<len;++i){this.writeNode("feature:_typeName",features[i],node);}
+return node;},"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("pos",geometry,node);return node;},"pos":function(point){var pos=(this.xy)?(point.x+" "+point.y):(point.y+" "+point.x);return this.createElementNSPlus("gml:pos",{value:pos});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("posList",geometry.components,node);return node;},"Curve":function(geometry){var node=this.createElementNSPlus("gml:Curve");this.writeNode("segments",geometry,node);return node;},"segments":function(geometry){var node=this.createElementNSPlus("gml:segments");this.writeNode("LineStringSegment",geometry,node);return node;},"LineStringSegment":function(geometry){var node=this.createElementNSPlus("gml:LineStringSegment");this.writeNode("posList",geometry.components,node);return node;},"posList":function(points){var len=points.length;var parts=new Array(len);var point;for(var i=0;i<len;++i){point=points[i];if(this.xy){parts[i]=point.x+" "+point.y;}else{parts[i]=point.y+" "+point.x;}}
+return this.createElementNSPlus("gml:posList",{value:parts.join(" ")});},"Surface":function(geometry){var node=this.createElementNSPlus("gml:Surface");this.writeNode("patches",geometry,node);return node;},"patches":function(geometry){var node=this.createElementNSPlus("gml:patches");this.writeNode("PolygonPatch",geometry,node);return node;},"PolygonPatch":function(geometry){var node=this.createElementNSPlus("gml:PolygonPatch",{attributes:{interpolation:"planar"}});this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
+return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
+return node;},"exterior":function(ring){var node=this.createElementNSPlus("gml:exterior");this.writeNode("LinearRing",ring,node);return node;},"interior":function(ring){var node=this.createElementNSPlus("gml:interior");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("posList",ring.components,node);return node;},"MultiCurve":function(geometry){var node=this.createElementNSPlus("gml:MultiCurve");var components=geometry.components||[geometry];for(var i=0,len=components.length;i<len;++i){this.writeNode("curveMember",components[i],node);}
+return node;},"curveMember":function(geometry){var node=this.createElementNSPlus("gml:curveMember");if(this.curve){this.writeNode("Curve",geometry,node);}else{this.writeNode("LineString",geometry,node);}
+return node;},"MultiSurface":function(geometry){var node=this.createElementNSPlus("gml:MultiSurface");var components=geometry.components||[geometry];for(var i=0,len=components.length;i<len;++i){this.writeNode("surfaceMember",components[i],node);}
+return node;},"surfaceMember":function(polygon){var node=this.createElementNSPlus("gml:surfaceMember");if(this.surface){this.writeNode("Surface",polygon,node);}else{this.writeNode("Polygon",polygon,node);}
+return node;},"Envelope":function(bounds){var node=this.createElementNSPlus("gml:Envelope");this.writeNode("lowerCorner",bounds,node);this.writeNode("upperCorner",bounds,node);if(this.srsName){node.setAttribute("srsName",this.srsName);}
+return node;},"lowerCorner":function(bounds){var pos=(this.xy)?(bounds.left+" "+bounds.bottom):(bounds.bottom+" "+bounds.left);return this.createElementNSPlus("gml:lowerCorner",{value:pos});},"upperCorner":function(bounds){var pos=(this.xy)?(bounds.right+" "+bounds.top):(bounds.top+" "+bounds.right);return this.createElementNSPlus("gml:upperCorner",{value:pos});}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":(this.curve===true)?"Curve":"LineString","OpenLayers.Geometry.MultiLineString":(this.multiCurve===false)?"MultiLineString":"MultiCurve","OpenLayers.Geometry.Polygon":(this.surface===true)?"Surface":"Polygon","OpenLayers.Geometry.MultiPolygon":(this.multiSurface===false)?"MultiPolygon":"MultiSurface","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.v3"});OpenLayers.Layer.TileCache=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,format:'image/png',serverResolutions:null,initialize:function(name,url,layername,options){this.layername=layername;OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,{},options]);this.extension=this.format.split('/')[1].toLowerCase();this.extension=(this.extension=='jpg')?'jpeg':this.extension;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TileCache(this.name,this.url,this.layername,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var res=this.map.getResolution();var bbox=this.maxExtent;var size=this.tileSize;var tileX=Math.round((bounds.left-bbox.left)/(res*size.w));var tileY=Math.round((bounds.bottom-bbox.bottom)/(res*size.h));var tileZ=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom();function zeroPad(number,length){number=String(number);var zeros=[];for(var i=0;i<length;++i){zeros.push('0');}
+return zeros.join('').substring(0,length-number.length)+number;}
+var components=[this.layername,zeroPad(tileZ,2),zeroPad(parseInt(tileX/1000000),3),zeroPad((parseInt(tileX/1000)%1000),3),zeroPad((parseInt(tileX)%1000),3),zeroPad(parseInt(tileY/1000000),3),zeroPad((parseInt(tileY/1000)%1000),3),zeroPad((parseInt(tileY)%1000),3)+'.'+this.extension];var path=components.join('/');var url=this.url;if(OpenLayers.Util.isArray(url)){url=this.selectUrl(path,url);}
+url=(url.charAt(url.length-1)=='/')?url:url+'/';return url+path;},CLASS_NAME:"OpenLayers.Layer.TileCache"});OpenLayers.Format.WMSCapabilities.v1_1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.1",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1"});OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1_1,{version:"1.1.1",profile:"WMSC",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"VendorSpecificCapabilities":function(node,obj){obj.vendorSpecific={tileSets:[]};this.readChildNodes(node,obj.vendorSpecific);},"TileSet":function(node,vendorSpecific){var tileset={srs:{},bbox:{},resolutions:[]};this.readChildNodes(node,tileset);vendorSpecific.tileSets.push(tileset);},"Resolutions":function(node,tileset){var res=this.getChildValue(node).split(" ");for(var i=0,len=res.length;i<len;i++){if(res[i]!=""){tileset.resolutions.push(parseFloat(res[i]));}}},"Width":function(node,tileset){tileset.width=parseInt(this.getChildValue(node));},"Height":function(node,tileset){tileset.height=parseInt(this.getChildValue(node));},"Layers":function(node,tileset){tileset.layers=this.getChildValue(node);},"Styles":function(node,tileset){tileset.styles=this.getChildValue(node);}},OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC"});OpenLayers.Layer.WFS=OpenLayers.Class(OpenLayers.Layer.Vector,OpenLayers.Layer.Markers,{isBaseLayer:false,tile:null,ratio:2,DEFAULT_PARAMS:{service:"WFS",version:"1.0.0",request:"GetFeature"},featureClass:null,format:null,formatObject:null,formatOptions:null,vectorMode:true,encodeBBOX:false,extractAttributes:false,initialize:function(name,url,params,options){if(options==undefined){options={};}
+if(options.featureClass||!OpenLayers.Layer.Vector||!OpenLayers.Feature.Vector){this.vectorMode=false;}
+params=OpenLayers.Util.upperCaseObject(params);OpenLayers.Util.extend(options,{'reportError':false});var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);if(!this.renderer||!this.vectorMode){this.vectorMode=false;if(!options.featureClass){options.featureClass=OpenLayers.Feature.WFS;}
+OpenLayers.Layer.Markers.prototype.initialize.apply(this,newArguments);}
+if(this.params&&this.params.typename&&!this.options.typename){this.options.typename=this.params.typename;}
+if(!this.options.geometry_column){this.options.geometry_column="the_geom";}
+this.params=OpenLayers.Util.applyDefaults(params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));this.url=url;},destroy:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.destroy.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);}
+if(this.tile){this.tile.destroy();}
+this.tile=null;this.ratio=null;this.featureClass=null;this.format=null;if(this.formatObject&&this.formatObject.destroy){this.formatObject.destroy();}
+this.formatObject=null;this.formatOptions=null;this.vectorMode=null;this.encodeBBOX=null;this.extractAttributes=null;},setMap:function(map){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);var options={'extractAttributes':this.extractAttributes};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
+this.formatObject=this.format?new this.format(options):new OpenLayers.Format.GML(options);}else{OpenLayers.Layer.Markers.prototype.setMap.apply(this,arguments);}},moveTo:function(bounds,zoomChanged,dragging){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);}
+if(dragging){return false;}
+if(zoomChanged){if(this.vectorMode){this.renderer.clear();}}
+if(this.options.minZoomLevel){OpenLayers.Console.warn(OpenLayers.i18n('minZoomLevelError'));if(this.map.getZoom()<this.options.minZoomLevel){return null;}}
+if(bounds==null){bounds=this.map.getExtent();}
+var firstRendering=(this.tile==null);var outOfBounds=(!firstRendering&&!this.tile.bounds.containsBounds(bounds));if(zoomChanged||firstRendering||(!dragging&&outOfBounds)){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var tileSize=this.map.getSize();tileSize.w=tileSize.w*this.ratio;tileSize.h=tileSize.h*this.ratio;var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var pos=this.map.getLayerPxFromLonLat(ul);var url=this.getFullRequestString();var params=null;var filter=this.params.filter||this.params.FILTER;if(filter){params={FILTER:filter};}
+else{params={BBOX:this.encodeBBOX?tileBounds.toBBOX():tileBounds.toArray()};}
+if(this.map&&!this.projection.equals(this.map.getProjectionObject())){var projectedBounds=tileBounds.clone();projectedBounds.transform(this.map.getProjectionObject(),this.projection);if(!filter){params.BBOX=this.encodeBBOX?projectedBounds.toBBOX():projectedBounds.toArray();}}
+url+="&"+OpenLayers.Util.getParameterString(params);if(!this.tile){this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}else{if(this.vectorMode){this.destroyFeatures();this.renderer.clear();}else{this.clearMarkers();}
+this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}}},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("loadstart");}};tile.events.register("loadstart",tile,tile.onLoadStart);tile.onLoadEnd=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("tileloaded");this.layer.events.triggerEvent("loadend");}};tile.events.register("loadend",tile,tile.onLoadEnd);tile.events.register("unload",tile,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:tile});},onMapResize:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.onMapResize.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.onMapResize.apply(this,arguments);}},display:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.display.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.display.apply(this,arguments);}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WFS(this.name,this.url,this.params,this.getOptions());}
+if(this.vectorMode){obj=OpenLayers.Layer.Vector.prototype.clone.apply(this,[obj]);}else{obj=OpenLayers.Layer.Markers.prototype.clone.apply(this,[obj]);}
+return obj;},getFullRequestString:function(newParams,altUrl){var projectionCode=this.projection.getCode()||this.map.getProjection();this.params.SRS=(projectionCode=="none")?null:projectionCode;return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},commit:function(){if(!this.writer){var options={};if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
+this.writer=new OpenLayers.Format.WFS(options,this);}
+var data=this.writer.write(this.features);OpenLayers.Request.POST({url:this.url,data:data,success:this.commitSuccess,failure:this.commitFailure,scope:this});},commitSuccess:function(request){var response=request.responseText;if(response.indexOf('SUCCESS')!=-1){this.commitReport(OpenLayers.i18n("commitSuccess",{'response':response}));for(var i=0;i<this.features.length;i++){this.features[i].state=null;}}else if(response.indexOf('FAILED')!=-1||response.indexOf('Exception')!=-1){this.commitReport(OpenLayers.i18n("commitFailed",{'response':response}));}},commitFailure:function(request){},commitReport:function(string,response){OpenLayers.Console.userError(string);},refresh:function(){if(this.tile){if(this.vectorMode){this.renderer.clear();this.features.length=0;}else{this.clearMarkers();this.markers.length=0;}
+this.tile.draw();}},getDataExtent:function(){var extent;if(this.vectorMode){extent=OpenLayers.Layer.Vector.prototype.getDataExtent.apply(this);}else{extent=OpenLayers.Layer.Markers.prototype.getDataExtent.apply(this);}
+return extent;},setOpacity:function(opacity){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setOpacity.apply(this,[opacity]);}else{OpenLayers.Layer.Markers.prototype.setOpacity.apply(this,[opacity]);}},CLASS_NAME:"OpenLayers.Layer.WFS"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{roundedCorner:true,roundedCornerColor:"darkblue",layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[];},destroy:function(){OpenLayers.Event.stopObservingElement(this.div);OpenLayers.Event.stopObservingElement(this.minimizeDiv);OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.on({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();if(!this.outsideViewport){this.minimizeControl();}
+this.redraw();return this.div;},clearLayersArray:function(layersType){var layers=this[layersType+"Layers"];if(layers){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];OpenLayers.Event.stopObservingElement(layer.inputElem);OpenLayers.Event.stopObservingElement(layer.labelSpan);}}
+this[layersType+"LayersDiv"].innerHTML="";this[layersType+"Layers"]=[];},checkRedraw:function(){var redraw=false;if(!this.layerStates.length||(this.map.layers.length!=this.layerStates.length)){redraw=true;}else{for(var i=0,len=this.layerStates.length;i<len;i++){var layerState=this.layerStates[i];var layer=this.map.layers[i];if((layerState.name!=layer.name)||(layerState.inRange!=layer.inRange)||(layerState.id!=layer.id)||(layerState.visibility!=layer.visibility)){redraw=true;break;}}}
+return redraw;},redraw:function(){if(!this.checkRedraw()){return this.div;}
+this.clearLayersArray("base");this.clearLayersArray("data");var containsOverlays=false;var containsBaseLayers=false;var len=this.map.layers.length;this.layerStates=new Array(len);for(var i=0;i<len;i++){var layer=this.map.layers[i];this.layerStates[i]={'name':layer.name,'visibility':layer.visibility,'inRange':layer.inRange,'id':layer.id};}
+var layers=this.map.layers.slice();if(!this.ascending){layers.reverse();}
+for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var baseLayer=layer.isBaseLayer;if(layer.displayInLayerSwitcher){if(baseLayer){containsBaseLayers=true;}else{containsOverlays=true;}
+var checked=(baseLayer)?(layer==this.map.baseLayer):layer.getVisibility();var inputElem=document.createElement("input");inputElem.id=this.id+"_input_"+layer.name;inputElem.name=(baseLayer)?this.id+"_baseLayers":layer.name;inputElem.type=(baseLayer)?"radio":"checkbox";inputElem.value=layer.name;inputElem.checked=checked;inputElem.defaultChecked=checked;if(!baseLayer&&!layer.inRange){inputElem.disabled=true;}
+var context={'inputElem':inputElem,'layer':layer,'layerSwitcher':this};OpenLayers.Event.observe(inputElem,"mouseup",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var labelSpan=document.createElement("span");OpenLayers.Element.addClass(labelSpan,"labelSpan");if(!baseLayer&&!layer.inRange){labelSpan.style.color="gray";}
+labelSpan.innerHTML=layer.name;labelSpan.style.verticalAlign=(baseLayer)?"bottom":"baseline";OpenLayers.Event.observe(labelSpan,"click",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var br=document.createElement("br");var groupArray=(baseLayer)?this.baseLayers:this.dataLayers;groupArray.push({'layer':layer,'inputElem':inputElem,'labelSpan':labelSpan});var groupDiv=(baseLayer)?this.baseLayersDiv:this.dataLayersDiv;groupDiv.appendChild(inputElem);groupDiv.appendChild(labelSpan);groupDiv.appendChild(br);}}
+this.dataLbl.style.display=(containsOverlays)?"":"none";this.baseLbl.style.display=(containsBaseLayers)?"":"none";return this.div;},onInputClick:function(e){if(!this.inputElem.disabled){if(this.inputElem.type=="radio"){this.inputElem.checked=true;this.layer.map.setBaseLayer(this.layer);}else{this.inputElem.checked=!this.inputElem.checked;this.layerSwitcher.updateMap();}}
+OpenLayers.Event.stop(e);},onLayerClick:function(e){this.updateMap();},updateMap:function(){for(var i=0,len=this.baseLayers.length;i<len;i++){var layerEntry=this.baseLayers[i];if(layerEntry.inputElem.checked){this.map.setBaseLayer(layerEntry.layer,false);}}
+for(var i=0,len=this.dataLayers.length;i<len;i++){var layerEntry=this.dataLayers[i];layerEntry.layer.setVisibility(layerEntry.inputElem.checked);}},maximizeControl:function(e){this.div.style.width="";this.div.style.height="";this.showControls(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.div.style.width="0px";this.div.style.height="0px";this.showControls(true);if(e!=null){OpenLayers.Event.stop(e);}},showControls:function(minimize){this.maximizeDiv.style.display=minimize?"":"none";this.minimizeDiv.style.display=minimize?"none":"";this.layersDiv.style.display=minimize?"none":"";},loadContents:function(){OpenLayers.Event.observe(this.div,"mouseup",OpenLayers.Function.bindAsEventListener(this.mouseUp,this));OpenLayers.Event.observe(this.div,"click",this.ignoreEvent);OpenLayers.Event.observe(this.div,"mousedown",OpenLayers.Function.bindAsEventListener(this.mouseDown,this));OpenLayers.Event.observe(this.div,"dblclick",this.ignoreEvent);this.layersDiv=document.createElement("div");this.layersDiv.id=this.id+"_layersDiv";OpenLayers.Element.addClass(this.layersDiv,"layersDiv");this.baseLbl=document.createElement("div");this.baseLbl.innerHTML=OpenLayers.i18n("Base Layer");OpenLayers.Element.addClass(this.baseLbl,"baseLbl");this.baseLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.baseLayersDiv,"baseLayersDiv");this.dataLbl=document.createElement("div");this.dataLbl.innerHTML=OpenLayers.i18n("Overlays");OpenLayers.Element.addClass(this.dataLbl,"dataLbl");this.dataLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.dataLayersDiv,"dataLayersDiv");if(this.ascending){this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);}else{this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);}
+this.div.appendChild(this.layersDiv);if(this.roundedCorner){OpenLayers.Rico.Corner.round(this.div,{corners:"tl bl",bgColor:"transparent",color:this.roundedCornerColor,blend:false});OpenLayers.Rico.Corner.changeOpacity(this.layersDiv,0.75);}
+var imgLocation=OpenLayers.Util.getImagesLocation();var sz=new OpenLayers.Size(18,18);var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MaximizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.maximizeDiv,"maximizeDiv");this.maximizeDiv.style.display="none";OpenLayers.Event.observe(this.maximizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';var sz=new OpenLayers.Size(18,18);this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MinimizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.minimizeDiv,"minimizeDiv");this.minimizeDiv.style.display="none";OpenLayers.Event.observe(this.minimizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);},ignoreEvent:function(evt){OpenLayers.Event.stop(evt);},mouseDown:function(evt){this.isMouseDown=true;this.ignoreEvent(evt);},mouseUp:function(evt){if(this.isMouseDown){this.isMouseDown=false;this.ignoreEvent(evt);}},CLASS_NAME:"OpenLayers.Control.LayerSwitcher"});OpenLayers.Format.WFS=OpenLayers.Class(OpenLayers.Format.GML,{layer:null,wfsns:"http://www.opengis.net/wfs",ogcns:"http://www.opengis.net/ogc",initialize:function(options,layer){OpenLayers.Format.GML.prototype.initialize.apply(this,[options]);this.layer=layer;if(this.layer.featureNS){this.featureNS=this.layer.featureNS;}
+if(this.layer.options.geometry_column){this.geometryName=this.layer.options.geometry_column;}
+if(this.layer.options.typename){this.featureName=this.layer.options.typename;}},write:function(features){var transaction=this.createElementNS(this.wfsns,'wfs:Transaction');transaction.setAttribute("version","1.0.0");transaction.setAttribute("service","WFS");for(var i=0;i<features.length;i++){switch(features[i].state){case OpenLayers.State.INSERT:transaction.appendChild(this.insert(features[i]));break;case OpenLayers.State.UPDATE:transaction.appendChild(this.update(features[i]));break;case OpenLayers.State.DELETE:transaction.appendChild(this.remove(features[i]));break;}}
+return OpenLayers.Format.XML.prototype.write.apply(this,[transaction]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var geomContainer=this.createElementNS(this.featureNS,"feature:"+this.geometryName);geomContainer.appendChild(geometryNode);var featureContainer=this.createElementNS(this.featureNS,"feature:"+this.featureName);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];}
+var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);}
+return featureContainer;},insert:function(feature){var insertNode=this.createElementNS(this.wfsns,'wfs:Insert');insertNode.appendChild(this.createFeatureXML(feature));return insertNode;},update:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));}
+var updateNode=this.createElementNS(this.wfsns,'wfs:Update');updateNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);updateNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var propertyNode=this.createElementNS(this.wfsns,'wfs:Property');var nameNode=this.createElementNS(this.wfsns,'wfs:Name');var txtNode=this.createTextNode(this.geometryName);nameNode.appendChild(txtNode);propertyNode.appendChild(nameNode);var valueNode=this.createElementNS(this.wfsns,'wfs:Value');var geometryNode=this.buildGeometryNode(feature.geometry);if(feature.layer){geometryNode.setAttribute("srsName",feature.layer.projection.getCode());}
+valueNode.appendChild(geometryNode);propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);for(var propName in feature.attributes){propertyNode=this.createElementNS(this.wfsns,'wfs:Property');nameNode=this.createElementNS(this.wfsns,'wfs:Name');nameNode.appendChild(this.createTextNode(propName));propertyNode.appendChild(nameNode);valueNode=this.createElementNS(this.wfsns,'wfs:Value');valueNode.appendChild(this.createTextNode(feature.attributes[propName]));propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);}
+var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);updateNode.appendChild(filterNode);return updateNode;},remove:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));return false;}
+var deleteNode=this.createElementNS(this.wfsns,'wfs:Delete');deleteNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);deleteNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);deleteNode.appendChild(filterNode);return deleteNode;},destroy:function(){this.layer=null;},CLASS_NAME:"OpenLayers.Format.WFS"});OpenLayers.Format.Atom=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{atom:"http://www.w3.org/2005/Atom",georss:"http://www.georss.org/georss"},feedTitle:"untitled",defaultEntryTitle:"untitled",gmlParser:null,xy:false,read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
+return this.parseFeatures(doc);},write:function(features){var doc;if(OpenLayers.Util.isArray(features)){doc=this.createElementNSPlus("atom:feed");doc.appendChild(this.createElementNSPlus("atom:title",{value:this.feedTitle}));for(var i=0,ii=features.length;i<ii;i++){doc.appendChild(this.buildEntryNode(features[i]));}}
+else{doc=this.buildEntryNode(features);}
+return OpenLayers.Format.XML.prototype.write.apply(this,[doc]);},buildContentNode:function(content){var node=this.createElementNSPlus("atom:content",{attributes:{type:content.type||null}});if(content.src){node.setAttribute("src",content.src);}else{if(content.type=="text"||content.type==null){node.appendChild(this.createTextNode(content.value));}else if(content.type=="html"){if(typeof content.value!="string"){throw"HTML content must be in form of an escaped string";}
+node.appendChild(this.createTextNode(content.value));}else if(content.type=="xhtml"){node.appendChild(content.value);}else if(content.type=="xhtml"||content.type.match(/(\+|\/)xml$/)){node.appendChild(content.value);}
+else{node.appendChild(this.createTextNode(content.value));}}
+return node;},buildEntryNode:function(feature){var attrib=feature.attributes;var atomAttrib=attrib.atom||{};var entryNode=this.createElementNSPlus("atom:entry");if(atomAttrib.authors){var authors=OpenLayers.Util.isArray(atomAttrib.authors)?atomAttrib.authors:[atomAttrib.authors];for(var i=0,ii=authors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("author",authors[i]));}}
+if(atomAttrib.categories){var categories=OpenLayers.Util.isArray(atomAttrib.categories)?atomAttrib.categories:[atomAttrib.categories];var category;for(var i=0,ii=categories.length;i<ii;i++){category=categories[i];entryNode.appendChild(this.createElementNSPlus("atom:category",{attributes:{term:category.term,scheme:category.scheme||null,label:category.label||null}}));}}
+if(atomAttrib.content){entryNode.appendChild(this.buildContentNode(atomAttrib.content));}
+if(atomAttrib.contributors){var contributors=OpenLayers.Util.isArray(atomAttrib.contributors)?atomAttrib.contributors:[atomAttrib.contributors];for(var i=0,ii=contributors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("contributor",contributors[i]));}}
+if(feature.fid){entryNode.appendChild(this.createElementNSPlus("atom:id",{value:feature.fid}));}
+if(atomAttrib.links){var links=OpenLayers.Util.isArray(atomAttrib.links)?atomAttrib.links:[atomAttrib.links];var link;for(var i=0,ii=links.length;i<ii;i++){link=links[i];entryNode.appendChild(this.createElementNSPlus("atom:link",{attributes:{href:link.href,rel:link.rel||null,type:link.type||null,hreflang:link.hreflang||null,title:link.title||null,length:link.length||null}}));}}
+if(atomAttrib.published){entryNode.appendChild(this.createElementNSPlus("atom:published",{value:atomAttrib.published}));}
+if(atomAttrib.rights){entryNode.appendChild(this.createElementNSPlus("atom:rights",{value:atomAttrib.rights}));}
+if(atomAttrib.summary||attrib.description){entryNode.appendChild(this.createElementNSPlus("atom:summary",{value:atomAttrib.summary||attrib.description}));}
+entryNode.appendChild(this.createElementNSPlus("atom:title",{value:atomAttrib.title||attrib.title||this.defaultEntryTitle}));if(atomAttrib.updated){entryNode.appendChild(this.createElementNSPlus("atom:updated",{value:atomAttrib.updated}));}
+if(feature.geometry){var whereNode=this.createElementNSPlus("georss:where");whereNode.appendChild(this.buildGeometryNode(feature.geometry));entryNode.appendChild(whereNode);}
+return entryNode;},initGmlParser:function(){this.gmlParser=new OpenLayers.Format.GML.v3({xy:this.xy,featureNS:"http://example.com#feature",internalProjection:this.internalProjection,externalProjection:this.externalProjection});},buildGeometryNode:function(geometry){if(!this.gmlParser){this.initGmlParser();}
+var node=this.gmlParser.writeNode("feature:_geometry",geometry);return node.firstChild;},buildPersonConstructNode:function(name,value){var oNames=["uri","email"];var personNode=this.createElementNSPlus("atom:"+name);personNode.appendChild(this.createElementNSPlus("atom:name",{value:value.name}));for(var i=0,ii=oNames.length;i<ii;i++){if(value[oNames[i]]){personNode.appendChild(this.createElementNSPlus("atom:"+oNames[i],{value:value[oNames[i]]}));}}
+return personNode;},getFirstChildValue:function(node,nsuri,name,def){var value;var nodes=this.getElementsByTagNameNS(node,nsuri,name);if(nodes&&nodes.length>0){value=this.getChildValue(nodes[0],def);}else{value=def;}
+return value;},parseFeature:function(node){var atomAttrib={};var value=null;var nodes=null;var attval=null;var atomns=this.namespaces.atom;this.parsePersonConstructs(node,"author",atomAttrib);nodes=this.getElementsByTagNameNS(node,atomns,"category");if(nodes.length>0){atomAttrib.categories=[];}
+for(var i=0,ii=nodes.length;i<ii;i++){value={};value.term=nodes[i].getAttribute("term");attval=nodes[i].getAttribute("scheme");if(attval){value.scheme=attval;}
+attval=nodes[i].getAttribute("label");if(attval){value.label=attval;}
+atomAttrib.categories.push(value);}
+nodes=this.getElementsByTagNameNS(node,atomns,"content");if(nodes.length>0){value={};attval=nodes[0].getAttribute("type");if(attval){value.type=attval;}
+attval=nodes[0].getAttribute("src");if(attval){value.src=attval;}else{if(value.type=="text"||value.type=="html"||value.type==null){value.value=this.getFirstChildValue(node,atomns,"content",null);}else if(value.type=="xhtml"||value.type.match(/(\+|\/)xml$/)){value.value=this.getChildEl(nodes[0]);}else{value.value=this.getFirstChildValue(node,atomns,"content",null);}
+atomAttrib.content=value;}}
+this.parsePersonConstructs(node,"contributor",atomAttrib);atomAttrib.id=this.getFirstChildValue(node,atomns,"id",null);nodes=this.getElementsByTagNameNS(node,atomns,"link");if(nodes.length>0){atomAttrib.links=new Array(nodes.length);}
+var oAtts=["rel","type","hreflang","title","length"];for(var i=0,ii=nodes.length;i<ii;i++){value={};value.href=nodes[i].getAttribute("href");for(var j=0,jj=oAtts.length;j<jj;j++){attval=nodes[i].getAttribute(oAtts[j]);if(attval){value[oAtts[j]]=attval;}}
+atomAttrib.links[i]=value;}
+value=this.getFirstChildValue(node,atomns,"published",null);if(value){atomAttrib.published=value;}
+value=this.getFirstChildValue(node,atomns,"rights",null);if(value){atomAttrib.rights=value;}
+value=this.getFirstChildValue(node,atomns,"summary",null);if(value){atomAttrib.summary=value;}
+atomAttrib.title=this.getFirstChildValue(node,atomns,"title",null);atomAttrib.updated=this.getFirstChildValue(node,atomns,"updated",null);var featureAttrib={title:atomAttrib.title,description:atomAttrib.summary,atom:atomAttrib};var geometry=this.parseLocations(node)[0];var feature=new OpenLayers.Feature.Vector(geometry,featureAttrib);feature.fid=atomAttrib.id;return feature;},parseFeatures:function(node){var features=[];var entries=this.getElementsByTagNameNS(node,this.namespaces.atom,"entry");if(entries.length==0){entries=[node];}
+for(var i=0,ii=entries.length;i<ii;i++){features.push(this.parseFeature(entries[i]));}
+return features;},parseLocations:function(node){var georssns=this.namespaces.georss;var locations={components:[]};var where=this.getElementsByTagNameNS(node,georssns,"where");if(where&&where.length>0){if(!this.gmlParser){this.initGmlParser();}
+for(var i=0,ii=where.length;i<ii;i++){this.gmlParser.readChildNodes(where[i],locations);}}
+var components=locations.components;var point=this.getElementsByTagNameNS(node,georssns,"point");if(point&&point.length>0){for(var i=0,ii=point.length;i<ii;i++){var xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s+/);if(xy.length!=2){xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s*,\s*/);}
+components.push(new OpenLayers.Geometry.Point(parseFloat(xy[1]),parseFloat(xy[0])));}}
+var line=this.getElementsByTagNameNS(node,georssns,"line");if(line&&line.length>0){var coords;var p;var points;for(var i=0,ii=line.length;i<ii;i++){coords=OpenLayers.String.trim(line[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);}
+components.push(new OpenLayers.Geometry.LineString(points));}}
+var polygon=this.getElementsByTagNameNS(node,georssns,"polygon");if(polygon&&polygon.length>0){var coords;var p;var points;for(var i=0,ii=polygon.length;i<ii;i++){coords=OpenLayers.String.trim(polygon[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);}
+components.push(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]));}}
+if(this.internalProjection&&this.externalProjection){for(var i=0,ii=components.length;i<ii;i++){if(components[i]){components[i].transform(this.externalProjection,this.internalProjection);}}}
+return components;},parsePersonConstructs:function(node,name,data){var persons=[];var atomns=this.namespaces.atom;var nodes=this.getElementsByTagNameNS(node,atomns,name);var oAtts=["uri","email"];for(var i=0,ii=nodes.length;i<ii;i++){var value={};value.name=this.getFirstChildValue(nodes[i],atomns,"name",null);for(var j=0,jj=oAtts.length;j<jj;j++){var attval=this.getFirstChildValue(nodes[i],atomns,oAtts[j],null);if(attval){value[oAtts[j]]=attval;}}
+persons.push(value);}
+if(persons.length>0){data[name+"s"]=persons;}},CLASS_NAME:"OpenLayers.Format.Atom"});OpenLayers.Control.KeyboardDefaults=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,slideFactor:75,draw:function(){this.handler=new OpenLayers.Handler.Keyboard(this,{"keydown":this.defaultKeyPress});},defaultKeyPress:function(evt){switch(evt.keyCode){case OpenLayers.Event.KEY_LEFT:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Event.KEY_RIGHT:this.map.pan(this.slideFactor,0);break;case OpenLayers.Event.KEY_UP:this.map.pan(0,-this.slideFactor);break;case OpenLayers.Event.KEY_DOWN:this.map.pan(0,this.slideFactor);break;case 33:var size=this.map.getSize();this.map.pan(0,-0.75*size.h);break;case 34:var size=this.map.getSize();this.map.pan(0,0.75*size.h);break;case 35:var size=this.map.getSize();this.map.pan(0.75*size.w,0);break;case 36:var size=this.map.getSize();this.map.pan(-0.75*size.w,0);break;case 43:case 61:case 187:case 107:this.map.zoomIn();break;case 45:case 109:case 189:case 95:this.map.zoomOut();break;}},CLASS_NAME:"OpenLayers.Control.KeyboardDefaults"});OpenLayers.Feature.WFS=OpenLayers.Class(OpenLayers.Feature,{initialize:function(layer,xmlNode){var newArguments=arguments;var data=this.processXMLNode(xmlNode);newArguments=new Array(layer,data.lonlat,data);OpenLayers.Feature.prototype.initialize.apply(this,newArguments);this.createMarker();this.layer.addMarker(this.marker);},destroy:function(){if(this.marker!=null){this.layer.removeMarker(this.marker);}
+OpenLayers.Feature.prototype.destroy.apply(this,arguments);},processXMLNode:function(xmlNode){var point=OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,"http://www.opengis.net/gml","gml","Point");var text=OpenLayers.Util.getXmlNodeValue(OpenLayers.Ajax.getElementsByTagNameNS(point[0],"http://www.opengis.net/gml","gml","coordinates")[0]);var floats=text.split(",");return{lonlat:new OpenLayers.LonLat(parseFloat(floats[0]),parseFloat(floats[1])),id:null};},CLASS_NAME:"OpenLayers.Feature.WFS"});
\ No newline at end of file
diff --git a/src/main/webapp/lib/openlayers/img/blank.gif b/src/main/webapp/lib/openlayers/img/blank.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4bcc753a12e9854923af4b9b5b9a4b76f1bc53a6
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/blank.gif differ
diff --git a/src/main/webapp/lib/openlayers/img/cloud-popup-relative.png b/src/main/webapp/lib/openlayers/img/cloud-popup-relative.png
new file mode 100755
index 0000000000000000000000000000000000000000..c9fd4c411c041fb1efb2f288d509fd4c425fcfa1
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/cloud-popup-relative.png differ
diff --git a/src/main/webapp/lib/openlayers/img/drag-rectangle-off.png b/src/main/webapp/lib/openlayers/img/drag-rectangle-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..382a81d9a1af6e7c2b822f8d1edb5684a55b14df
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/drag-rectangle-off.png differ
diff --git a/src/main/webapp/lib/openlayers/img/drag-rectangle-on.png b/src/main/webapp/lib/openlayers/img/drag-rectangle-on.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ed2d5b088366d411a609fa43650f5bcc7a823f4
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/drag-rectangle-on.png differ
diff --git a/src/main/webapp/lib/openlayers/img/east-mini.png b/src/main/webapp/lib/openlayers/img/east-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..ecedc5ef9f2ea756eaebb78e187b543c221760b2
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/east-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/layer-switcher-maximize.png b/src/main/webapp/lib/openlayers/img/layer-switcher-maximize.png
new file mode 100644
index 0000000000000000000000000000000000000000..f346086b38eb98effa931eb7c50ab5a221cf06c0
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/layer-switcher-maximize.png differ
diff --git a/src/main/webapp/lib/openlayers/img/layer-switcher-minimize.png b/src/main/webapp/lib/openlayers/img/layer-switcher-minimize.png
new file mode 100644
index 0000000000000000000000000000000000000000..b4aab0bf784076f86893d0c28a8cae36ec6c113e
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/layer-switcher-minimize.png differ
diff --git a/src/main/webapp/lib/openlayers/img/marker-blue.png b/src/main/webapp/lib/openlayers/img/marker-blue.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5b4efcfe120ebd4f7d96b22e1972b48d0cc6655
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/marker-blue.png differ
diff --git a/src/main/webapp/lib/openlayers/img/marker-gold.png b/src/main/webapp/lib/openlayers/img/marker-gold.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b62f9618ace58d9dac39832a6fe506ab1cfbad8
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/marker-gold.png differ
diff --git a/src/main/webapp/lib/openlayers/img/marker-green.png b/src/main/webapp/lib/openlayers/img/marker-green.png
new file mode 100644
index 0000000000000000000000000000000000000000..c36b164b55b241b3f67a3323e4c8a3fa660371d3
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/marker-green.png differ
diff --git a/src/main/webapp/lib/openlayers/img/marker.png b/src/main/webapp/lib/openlayers/img/marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..ea3e59a560adcaea8b1610034f80b35a980c5c50
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/marker.png differ
diff --git a/src/main/webapp/lib/openlayers/img/measuring-stick-off.png b/src/main/webapp/lib/openlayers/img/measuring-stick-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..efbf63fb3084ef001da436fe4fa98265f0173257
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/measuring-stick-off.png differ
diff --git a/src/main/webapp/lib/openlayers/img/measuring-stick-on.png b/src/main/webapp/lib/openlayers/img/measuring-stick-on.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d41c84e817d1df8137182cc85e73da050732f8a
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/measuring-stick-on.png differ
diff --git a/src/main/webapp/lib/openlayers/img/north-mini.png b/src/main/webapp/lib/openlayers/img/north-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfd7211ffc7bf3ec82c490c7e9f522a872eb5c2b
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/north-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/panning-hand-off.png b/src/main/webapp/lib/openlayers/img/panning-hand-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1c593e1df5900ffc37e749d748065635e9d6e43
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/panning-hand-off.png differ
diff --git a/src/main/webapp/lib/openlayers/img/panning-hand-on.png b/src/main/webapp/lib/openlayers/img/panning-hand-on.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b7e0646d74e76ebff18d2c2646bd5db1c79db68
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/panning-hand-on.png differ
diff --git a/src/main/webapp/lib/openlayers/img/slider.png b/src/main/webapp/lib/openlayers/img/slider.png
new file mode 100644
index 0000000000000000000000000000000000000000..433536422ead435c8e9e5b9dd1f209c7087994c3
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/slider.png differ
diff --git a/src/main/webapp/lib/openlayers/img/south-mini.png b/src/main/webapp/lib/openlayers/img/south-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..2970875c4c2588c1345cc2c782cc40e7dfb667e3
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/south-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/west-mini.png b/src/main/webapp/lib/openlayers/img/west-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..363cd3d7b2e9aaa24625d57fb59293a063a55158
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/west-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/zoom-minus-mini.png b/src/main/webapp/lib/openlayers/img/zoom-minus-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f0d77fff1cc3f68b512dce21bd789d7f59f2f62
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/zoom-minus-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/zoom-plus-mini.png b/src/main/webapp/lib/openlayers/img/zoom-plus-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..a73ab4e951b38fde6f1f39124efb1fa01fdc01b2
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/zoom-plus-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/zoom-world-mini.png b/src/main/webapp/lib/openlayers/img/zoom-world-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..aebf22d95e8225bf127954281349c54f0b596f04
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/zoom-world-mini.png differ
diff --git a/src/main/webapp/lib/openlayers/img/zoombar.png b/src/main/webapp/lib/openlayers/img/zoombar.png
new file mode 100644
index 0000000000000000000000000000000000000000..47110ab3e5a5e3e9d01a9f6ad1ae4aa08d4e3a28
Binary files /dev/null and b/src/main/webapp/lib/openlayers/img/zoombar.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/framedCloud.css b/src/main/webapp/lib/openlayers/theme/default/framedCloud.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/webapp/lib/openlayers/theme/default/google.css b/src/main/webapp/lib/openlayers/theme/default/google.css
new file mode 100644
index 0000000000000000000000000000000000000000..3ee757c478428ceefa8af5f231731f9b9f362365
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/google.css
@@ -0,0 +1,17 @@
+.olLayerGoogleCopyright {
+    right: 3px;
+    bottom: 2px;
+    left: auto;  
+}
+.olLayerGoogleV3.olLayerGoogleCopyright {
+    bottom: 0px;
+    right: 0px !important;
+}
+.olLayerGooglePoweredBy {
+    left: 2px;
+    bottom: 2px;   
+}
+.olLayerGoogleV3.olLayerGooglePoweredBy {
+    bottom: 0px !important;
+}
+
diff --git a/src/main/webapp/lib/openlayers/theme/default/google.tidy.css b/src/main/webapp/lib/openlayers/theme/default/google.tidy.css
new file mode 100644
index 0000000000000000000000000000000000000000..4ba0cd8452b6ec41579bba1060168695e3647cbb
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/google.tidy.css
@@ -0,0 +1 @@
+.olLayerGoogleCopyright{right:3px;bottom:2px;left:auto;}.olLayerGoogleV3.olLayerGoogleCopyright{bottom:0;right:0!important;}.olLayerGooglePoweredBy{left:2px;bottom:2px;}.olLayerGoogleV3.olLayerGooglePoweredBy{bottom:0!important;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/openlayers/theme/default/ie6-style.css b/src/main/webapp/lib/openlayers/theme/default/ie6-style.css
new file mode 100755
index 0000000000000000000000000000000000000000..a0fd7c63920dc3d088c99665009301aa1e92305e
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/ie6-style.css
@@ -0,0 +1,10 @@
+.olControlZoomPanel div {
+    background-image: url(img/zoom-panel-NOALPHA.png);
+}
+.olControlPanPanel div {
+    background-image: url(img/pan-panel-NOALPHA.png);
+}
+.olControlEditingToolbar {
+    width: 200px;
+}
+
diff --git a/src/main/webapp/lib/openlayers/theme/default/ie6-style.tidy.css b/src/main/webapp/lib/openlayers/theme/default/ie6-style.tidy.css
new file mode 100644
index 0000000000000000000000000000000000000000..7a23bbc7806968802bc089446ef6877957506b60
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/ie6-style.tidy.css
@@ -0,0 +1 @@
+.olControlZoomPanel div{background-image:url(img/zoom-panel-NOALPHA.png);}.olControlPanPanel div{background-image:url(img/pan-panel-NOALPHA.png);}.olControlEditingToolbar{width:200px;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/add_point_off.png b/src/main/webapp/lib/openlayers/theme/default/img/add_point_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..26c023309a83e6487e7d4893a0071384dcc13cdc
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/add_point_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/add_point_on.png b/src/main/webapp/lib/openlayers/theme/default/img/add_point_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..1294a2c160af789cf615576f8e23ac32c7c736d3
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/add_point_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/blank.gif b/src/main/webapp/lib/openlayers/theme/default/img/blank.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4bcc753a12e9854923af4b9b5b9a4b76f1bc53a6
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/blank.gif differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/close.gif b/src/main/webapp/lib/openlayers/theme/default/img/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a8958de9b429ae00f56bb282c4b133ecbaf334bd
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/close.gif differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-off.png b/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..382a81d9a1af6e7c2b822f8d1edb5684a55b14df
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-on.png b/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-on.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ed2d5b088366d411a609fa43650f5bcc7a823f4
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/drag-rectangle-on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_line_off.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_line_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4d67b3b97802b8a2ca281f82351da5d5ab98f81
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_line_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_line_on.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_line_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..90dcf3e35f963efb4a948bb618921bf25dde49df
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_line_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_point_off.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_point_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..56334072a886b0c32d35d33a1bf77e43567c8f25
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_point_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_point_on.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_point_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..fff50b7b0ed8f74272310a17a0e3910087a1e939
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_point_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_off.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..917af3597b67c353025191184572e460ec08754a
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_on.png b/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..05a2cc5a8c5fe75aa0de1b99cef405dc6732d704
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/draw_polygon_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/editing_tool_bar.png b/src/main/webapp/lib/openlayers/theme/default/img/editing_tool_bar.png
new file mode 100644
index 0000000000000000000000000000000000000000..5977856cf7cd3ee88f8c98fd4722a166636eba6d
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/editing_tool_bar.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/move_feature_off.png b/src/main/webapp/lib/openlayers/theme/default/img/move_feature_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed4472dd8971c49f17a1f9bf972a04f0b9bca523
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/move_feature_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/move_feature_on.png b/src/main/webapp/lib/openlayers/theme/default/img/move_feature_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..62226a2d71adbde8377b7ff7df08349e23f48546
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/move_feature_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/navigation_history.png b/src/main/webapp/lib/openlayers/theme/default/img/navigation_history.png
new file mode 100644
index 0000000000000000000000000000000000000000..84e3489852eba0359b7eb48e520798b442897b55
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/navigation_history.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/overview_replacement.gif b/src/main/webapp/lib/openlayers/theme/default/img/overview_replacement.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a82cf5fc54cc0064099720322d62e9bf4dde05c9
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/overview_replacement.gif differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/pan-panel-NOALPHA.png b/src/main/webapp/lib/openlayers/theme/default/img/pan-panel-NOALPHA.png
new file mode 100755
index 0000000000000000000000000000000000000000..6987268840f5325b526364a929132c55c63e2f7c
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/pan-panel-NOALPHA.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/pan-panel.png b/src/main/webapp/lib/openlayers/theme/default/img/pan-panel.png
new file mode 100755
index 0000000000000000000000000000000000000000..dfe67481ca1b7e781ff179f1243396c93e459f38
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/pan-panel.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/pan_off.png b/src/main/webapp/lib/openlayers/theme/default/img/pan_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..30b2aed4d94eee3d9cd12469e71e35a6889db174
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/pan_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/pan_on.png b/src/main/webapp/lib/openlayers/theme/default/img/pan_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3953a82488fb1363e074aad3dab3ef10665265d
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/pan_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-off.png b/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1c593e1df5900ffc37e749d748065635e9d6e43
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-on.png b/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-on.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b7e0646d74e76ebff18d2c2646bd5db1c79db68
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/panning-hand-on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/remove_point_off.png b/src/main/webapp/lib/openlayers/theme/default/img/remove_point_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..76c8606f550c1d95cb9df2e8b8656447e8a9e58d
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/remove_point_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/remove_point_on.png b/src/main/webapp/lib/openlayers/theme/default/img/remove_point_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc8d7b2c679d5b2588363020226523f455cb50e3
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/remove_point_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/ruler.png b/src/main/webapp/lib/openlayers/theme/default/img/ruler.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa4883bcd458311d93861a9a9d7574a53b979e97
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/ruler.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/save_features_off.png b/src/main/webapp/lib/openlayers/theme/default/img/save_features_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d305b622a6afc555ef30e0cd140460c15031fdd
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/save_features_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/save_features_on.png b/src/main/webapp/lib/openlayers/theme/default/img/save_features_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..5640ae888ba2bee0e9758d24e2cf144db4cf685f
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/save_features_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/view_next_off.png b/src/main/webapp/lib/openlayers/theme/default/img/view_next_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..9149a24209a235c1681e032de44bcd2d0b340a90
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/view_next_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/view_next_on.png b/src/main/webapp/lib/openlayers/theme/default/img/view_next_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..e41fb7bddfa186b688e88991fe805c70c7158608
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/view_next_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/view_previous_off.png b/src/main/webapp/lib/openlayers/theme/default/img/view_previous_off.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a9ef2179068162b995102feba2a248d53136484
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/view_previous_off.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/view_previous_on.png b/src/main/webapp/lib/openlayers/theme/default/img/view_previous_on.png
new file mode 100644
index 0000000000000000000000000000000000000000..c009c255ef8f129ad1b562f1f699de02fcb3c2a5
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/view_previous_on.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel-NOALPHA.png b/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel-NOALPHA.png
new file mode 100755
index 0000000000000000000000000000000000000000..cdde6fc7ee621e569bd7f0e62eabf756ed9b8367
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel-NOALPHA.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel.png b/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel.png
new file mode 100755
index 0000000000000000000000000000000000000000..c91a4ef3c935bd5540c8997341cdff48b3376cc4
Binary files /dev/null and b/src/main/webapp/lib/openlayers/theme/default/img/zoom-panel.png differ
diff --git a/src/main/webapp/lib/openlayers/theme/default/style.css b/src/main/webapp/lib/openlayers/theme/default/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..3aeac29c2e8505be73beed1c196eee944490a141
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/style.css
@@ -0,0 +1,433 @@
+div.olMap {
+    z-index: 0;
+    padding: 0 !important;
+    margin: 0 !important;
+    cursor: default;
+}
+
+div.olMapViewport {
+    text-align: left;
+}
+
+div.olLayerDiv {
+   -moz-user-select: none;
+   -khtml-user-select: none;
+}
+
+.olLayerGoogleCopyright {
+    left: 2px;
+    bottom: 2px;
+}
+.olLayerGoogleV3.olLayerGoogleCopyright {
+    right: auto !important;
+}
+.olLayerGooglePoweredBy {
+    left: 2px;
+    bottom: 15px;   
+}
+.olLayerGoogleV3.olLayerGooglePoweredBy {
+    bottom: 15px !important;
+}
+.olControlAttribution {
+    font-size: smaller; 
+    right: 3px; 
+    bottom: 4.5em; 
+    position: absolute; 
+    display: block;
+}
+.olControlScale {
+    right: 3px;
+    bottom: 3em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+}
+.olControlScaleLine {
+   display: block;
+   position: absolute;
+   left: 10px;
+   bottom: 15px;
+   font-size: xx-small;
+}
+.olControlScaleLineBottom {
+   border: solid 2px black;
+   border-bottom: none;
+   margin-top:-2px;
+   text-align: center;
+}
+.olControlScaleLineTop {
+   border: solid 2px black;
+   border-top: none;
+   text-align: center;
+}
+
+.olControlPermalink {
+    right: 3px;
+    bottom: 1.5em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+} 
+
+div.olControlMousePosition {
+    bottom: 0em;
+    right: 3px;
+    display: block;
+    position: absolute;
+    font-family: Arial;
+    font-size: smaller;
+}
+
+.olControlOverviewMapContainer {
+    position: absolute;
+    bottom: 0;
+    right: 0;
+}
+
+.olControlOverviewMapElement {
+    padding: 10px 18px 10px 10px;
+    background-color: #00008B;
+    -moz-border-radius: 1em 0 0 0;
+}
+
+.olControlOverviewMapMinimizeButton {
+    right: 0;
+    bottom: 80px;
+    cursor: pointer;
+}    
+
+.olControlOverviewMapMaximizeButton {
+    right: 0;
+    bottom: 80px;
+    cursor: pointer;
+}
+
+.olControlOverviewMapExtentRectangle {
+    overflow: hidden;
+    background-image: url("img/blank.gif");
+    cursor: move;
+    border: 2px dotted red;
+}
+.olControlOverviewMapRectReplacement {
+    overflow: hidden;
+    cursor: move;
+    background-image: url("img/overview_replacement.gif");
+    background-repeat: no-repeat;
+    background-position: center;
+}
+
+.olLayerGeoRSSDescription {
+    float:left;
+    width:100%;
+    overflow:auto;
+    font-size:1.0em;
+}
+.olLayerGeoRSSClose {
+    float:right;
+    color:gray;
+    font-size:1.2em;
+    margin-right:6px;
+    font-family:sans-serif;
+}
+.olLayerGeoRSSTitle {
+    float:left;font-size:1.2em;
+}
+
+.olPopupContent {
+    padding:5px;
+    overflow: auto;
+}    
+
+.olControlNavigationHistory {
+   background-image: url("img/navigation_history.png");
+   background-repeat: no-repeat;
+   width:  24px;
+   height: 24px;
+
+}
+.olControlNavigationHistoryPreviousItemActive { 
+  background-position: 0 0;
+}
+.olControlNavigationHistoryPreviousItemInactive { 
+   background-position: 0 -24px;
+}
+.olControlNavigationHistoryNextItemActive { 
+   background-position: -24px 0;
+}
+.olControlNavigationHistoryNextItemInactive { 
+   background-position: -24px -24px;
+}
+
+div.olControlSaveFeaturesItemActive { 
+    background-image: url(img/save_features_on.png);
+    background-repeat: no-repeat;
+    background-position: 0 1px;
+}
+div.olControlSaveFeaturesItemInactive { 
+    background-image: url(img/save_features_off.png);
+    background-repeat: no-repeat;
+    background-position: 0 1px;
+}
+
+.olHandlerBoxZoomBox {
+    border: 2px solid red;
+    position: absolute;
+    background-color: white;
+    opacity: 0.50;
+    font-size: 1px;
+    filter: alpha(opacity=50);
+}
+.olHandlerBoxSelectFeature {
+    border: 2px solid blue;
+    position: absolute;
+    background-color: white;
+    opacity: 0.50;
+    font-size: 1px;
+    filter: alpha(opacity=50);
+}   
+
+.olControlPanPanel {
+    top: 10px;
+    left: 5px;
+}  
+
+.olControlPanPanel div {
+    background-image: url(img/pan-panel.png);
+    height: 18px;
+    width: 18px;
+    cursor: pointer;
+    position: absolute;
+}
+
+.olControlPanPanel .olControlPanNorthItemInactive {
+    top: 0;
+    left: 9px;
+    background-position: 0 0;
+}
+.olControlPanPanel .olControlPanSouthItemInactive {
+    top: 36px;
+    left: 9px;
+    background-position: 18px 0;
+}
+.olControlPanPanel .olControlPanWestItemInactive {
+    position: absolute;
+    top: 18px;
+    left: 0;
+    background-position: 0 18px;
+}
+.olControlPanPanel .olControlPanEastItemInactive {
+    top: 18px;
+    left: 18px;
+    background-position: 18px 18px;
+}
+
+.olControlZoomPanel {
+    top: 71px;
+    left: 14px;
+} 
+
+.olControlZoomPanel div {
+    background-image: url(img/zoom-panel.png);
+    position: absolute;
+    height: 18px;
+    width: 18px;
+    cursor: pointer;
+}
+
+.olControlZoomPanel .olControlZoomInItemInactive {
+    top: 0;
+    left: 0;
+    background-position: 0 0;
+}
+
+.olControlZoomPanel .olControlZoomToMaxExtentItemInactive {
+    top: 18px;
+    left: 0;
+    background-position: 0 -18px;
+}
+
+.olControlZoomPanel .olControlZoomOutItemInactive {
+    top: 36px;
+    left: 0;
+    background-position: 0 18px;
+}
+
+/* 
+ * When a potential text is bigger than the image it move the image
+ * with some headers (closes #3154) 
+ */
+.olControlPanZoomBar div {
+    font-size: 1px;
+}
+
+.olPopupCloseBox {
+  background: url("img/close.gif") no-repeat;
+  cursor: pointer;
+}
+
+.olFramedCloudPopupContent {
+    padding: 5px;
+    overflow: auto;
+}
+
+.olControlNoSelect {
+ -moz-user-select: none;
+ -khtml-user-select: none;
+}
+
+.olImageLoadError {
+    background-color: pink;
+    opacity: 0.5;
+    filter: alpha(opacity=50); /* IE */
+}
+
+/**
+ * Cursor styles
+ */
+
+.olCursorWait {
+    cursor: wait;
+}
+.olDragDown {
+    cursor: move;
+}
+.olDrawBox {
+    cursor: crosshair;
+}
+.olControlDragFeatureOver {
+    cursor: move;
+}
+.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown {
+    cursor: -moz-grabbing;
+}
+
+/**
+ * Layer switcher
+ */
+.olControlLayerSwitcher {
+    position: absolute;
+    top: 25px;
+    right: 0;
+    width: 20em;
+    font-family: sans-serif;
+    font-weight: bold;
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+    font-size: smaller;
+    color: white;
+    background-color: transparent;
+}
+
+.olControlLayerSwitcher .layersDiv {
+    padding-top: 5px;
+    padding-left: 10px;
+    padding-bottom: 5px;
+    padding-right: 75px;
+    background-color: darkblue;
+    width: 100%;
+    height: 100%;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLbl,
+.olControlLayerSwitcher .layersDiv .dataLbl {
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLayersDiv,
+.olControlLayerSwitcher .layersDiv .dataLayersDiv {
+    padding-left: 10px;
+}
+
+.olControlLayerSwitcher .maximizeDiv,
+.olControlLayerSwitcher .minimizeDiv {
+    top: 5px;
+    right: 0;
+    cursor: pointer;
+}
+
+.olBingAttribution {
+    color: #DDD;
+}
+.olBingAttribution.road {
+    color: #333;
+}
+
+.olGoogleAttribution.hybrid, .olGoogleAttribution.satellite {
+    color: #EEE;
+}
+.olGoogleAttribution {
+    color: #333;
+}
+span.olGoogleAttribution a {
+    color: #77C;
+}
+span.olGoogleAttribution.hybrid a, span.olGoogleAttribution.satellite a {
+    color: #EEE;
+}
+
+/**
+ * Editing and navigation icons.
+ * (using the editing_tool_bar.png sprint image)
+ */
+.olControlNavToolbar ,
+.olControlEditingToolbar {
+    margin: 5px 5px 0 0;
+}
+.olControlNavToolbar div,
+.olControlEditingToolbar div {
+    background-image: url("img/editing_tool_bar.png");
+    background-repeat: no-repeat;
+    margin: 0 0 5px 5px;
+    width: 24px;
+    height: 22px;
+    cursor: pointer
+}
+/* positions */
+.olControlEditingToolbar {
+    right: 0;
+    top: 0;
+}
+.olControlNavToolbar {
+    top: 295px;
+    left: 9px;
+}
+/* layouts */
+.olControlEditingToolbar div {
+    float: right;
+}
+/* individual controls */
+.olControlNavToolbar .olControlNavigationItemInactive,
+.olControlEditingToolbar .olControlNavigationItemInactive {
+    background-position: -103px -1px;
+}
+.olControlNavToolbar .olControlNavigationItemActive ,
+.olControlEditingToolbar .olControlNavigationItemActive  {
+    background-position: -103px -24px;
+}
+.olControlNavToolbar .olControlZoomBoxItemInactive {
+    background-position: -128px -1px;
+}
+.olControlNavToolbar .olControlZoomBoxItemActive  {
+    background-position: -128px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemInactive {
+    background-position: -77px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemActive {
+    background-position: -77px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemInactive {
+    background-position: -51px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemActive {
+    background-position: -51px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive{
+    background-position: -26px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive {
+    background-position: -26px -24px;
+}
diff --git a/src/main/webapp/lib/openlayers/theme/default/style.tidy.css b/src/main/webapp/lib/openlayers/theme/default/style.tidy.css
new file mode 100644
index 0000000000000000000000000000000000000000..b3a73b3fc7f72f21291b05b90dbe840f418fef1b
--- /dev/null
+++ b/src/main/webapp/lib/openlayers/theme/default/style.tidy.css
@@ -0,0 +1 @@
+div.olMap{z-index:0;cursor:default;margin:0!important;padding:0!important;}div.olMapViewport{text-align:left;}.olLayerGoogleCopyright{left:2px;bottom:2px;}.olLayerGoogleV3.olLayerGoogleCopyright{right:auto!important;}.olLayerGooglePoweredBy{left:2px;bottom:15px;}.olLayerGoogleV3.olLayerGooglePoweredBy{bottom:15px!important;}.olControlAttribution{font-size:smaller;right:3px;bottom:4.5em;position:absolute;display:block;}.olControlScale{right:3px;bottom:3em;display:block;position:absolute;font-size:smaller;}.olControlScaleLine{display:block;position:absolute;left:10px;bottom:15px;font-size:xx-small;}.olControlScaleLineBottom{border:solid 2px #000;border-bottom:none;margin-top:-2px;text-align:center;}.olControlScaleLineTop{border:solid 2px #000;border-top:none;text-align:center;}.olControlPermalink{right:3px;bottom:1.5em;display:block;position:absolute;font-size:smaller;}div.olControlMousePosition{bottom:0;right:3px;display:block;position:absolute;font-family:Arial;font-size:smaller;}.olControlOverviewMapContainer{position:absolute;bottom:0;right:0;}.olControlOverviewMapElement{background-color:#00008B;-moz-border-radius:1em 0 0;padding:10px 18px 10px 10px;}.olControlOverviewMapExtentRectangle{overflow:hidden;background-image:url(img/blank.gif);cursor:move;border:2px dotted red;}.olControlOverviewMapRectReplacement{overflow:hidden;cursor:move;background-image:url(img/overview_replacement.gif);background-repeat:no-repeat;background-position:center;}.olLayerGeoRSSDescription{float:left;width:100%;overflow:auto;font-size:1em;}.olLayerGeoRSSClose{float:right;color:gray;font-size:1.2em;margin-right:6px;font-family:sans-serif;}.olLayerGeoRSSTitle{float:left;font-size:1.2em;}.olControlNavigationHistory{background-image:url(img/navigation_history.png);background-repeat:no-repeat;width:24px;height:24px;}.olControlNavigationHistoryPreviousItemActive{background-position:0 0;}.olControlNavigationHistoryPreviousItemInactive{background-position:0 -24px;}.olControlNavigationHistoryNextItemActive{background-position:-24px 0;}.olControlNavigationHistoryNextItemInactive{background-position:-24px -24px;}div.olControlSaveFeaturesItemActive{background-image:url(img/save_features_on.png);background-repeat:no-repeat;background-position:0 1px;}div.olControlSaveFeaturesItemInactive{background-image:url(img/save_features_off.png);background-repeat:no-repeat;background-position:0 1px;}.olHandlerBoxZoomBox{border:2px solid red;position:absolute;background-color:#FFF;opacity:.5;font-size:1px;filter:alpha(opacity=50);}.olHandlerBoxSelectFeature{border:2px solid blue;position:absolute;background-color:#FFF;opacity:.5;font-size:1px;filter:alpha(opacity=50);}.olControlPanPanel{top:10px;left:5px;}.olControlPanPanel div{background-image:url(img/pan-panel.png);height:18px;width:18px;cursor:pointer;position:absolute;}.olControlPanPanel .olControlPanNorthItemInactive{top:0;left:9px;background-position:0 0;}.olControlPanPanel .olControlPanSouthItemInactive{top:36px;left:9px;background-position:18px 0;}.olControlPanPanel .olControlPanWestItemInactive{position:absolute;top:18px;left:0;background-position:0 18px;}.olControlPanPanel .olControlPanEastItemInactive{top:18px;left:18px;background-position:18px 18px;}.olControlZoomPanel{top:71px;left:14px;}.olControlZoomPanel div{background-image:url(img/zoom-panel.png);position:absolute;height:18px;width:18px;cursor:pointer;}.olControlZoomPanel .olControlZoomInItemInactive{top:0;left:0;background-position:0 0;}.olControlZoomPanel .olControlZoomToMaxExtentItemInactive{top:18px;left:0;background-position:0 -18px;}.olControlZoomPanel .olControlZoomOutItemInactive{top:36px;left:0;background-position:0 18px;}.olControlPanZoomBar div{font-size:1px;}.olPopupCloseBox{background:url(img/close.gif) no-repeat;cursor:pointer;}.olImageLoadError{background-color:#FFC0CB;opacity:.5;filter:alpha(opacity=50);}.olCursorWait{cursor:wait;}.olDrawBox{cursor:crosshair;}.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown{cursor:0;}.olControlLayerSwitcher{position:absolute;top:25px;right:0;width:20em;font-family:sans-serif;font-weight:700;margin-top:3px;margin-left:3px;margin-bottom:3px;font-size:smaller;color:#FFF;background-color:transparent;}.olControlLayerSwitcher .layersDiv{background-color:#00008B;width:100%;height:100%;padding:5px 75px 5px 10px;}.olControlLayerSwitcher .layersDiv .baseLbl,.olControlLayerSwitcher .layersDiv .dataLbl{margin-top:3px;margin-left:3px;margin-bottom:3px;}.olControlLayerSwitcher .layersDiv .baseLayersDiv,.olControlLayerSwitcher .layersDiv .dataLayersDiv{padding-left:10px;}.olControlLayerSwitcher .maximizeDiv,.olControlLayerSwitcher .minimizeDiv{top:5px;right:0;cursor:pointer;}.olBingAttribution{color:#DDD;}span.olGoogleAttribution a{color:#77C;}.olControlNavToolbar,.olControlEditingToolbar{margin:5px 5px 0 0;}.olControlNavToolbar div,.olControlEditingToolbar div{background-image:url(img/editing_tool_bar.png);background-repeat:no-repeat;width:24px;height:22px;cursor:pointer;margin:0 0 5px 5px;}.olControlEditingToolbar{right:0;top:0;}.olControlNavToolbar{top:295px;left:9px;}.olControlEditingToolbar div{float:right;}.olControlNavToolbar .olControlNavigationItemInactive,.olControlEditingToolbar .olControlNavigationItemInactive{background-position:-103px -1px;}.olControlNavToolbar .olControlNavigationItemActive,.olControlEditingToolbar .olControlNavigationItemActive{background-position:-103px -24px;}.olControlNavToolbar .olControlZoomBoxItemInactive{background-position:-128px -1px;}.olControlNavToolbar .olControlZoomBoxItemActive{background-position:-128px -24px;}.olControlEditingToolbar .olControlDrawFeaturePointItemInactive{background-position:-77px -1px;}.olControlEditingToolbar .olControlDrawFeaturePointItemActive{background-position:-77px -24px;}.olControlEditingToolbar .olControlDrawFeaturePathItemInactive{background-position:-51px -1px;}.olControlEditingToolbar .olControlDrawFeaturePathItemActive{background-position:-51px -24px;}.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive{background-position:-26px -1px;}.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive{background-position:-26px -24px;}div.olLayerDiv,.olControlNoSelect{-khtml-user-select:none;-moz-user-select:none;}.olControlOverviewMapMinimizeButton,.olControlOverviewMapMaximizeButton{bottom:80px;cursor:pointer;right:0;}.olPopupContent,.olFramedCloudPopupContent{overflow:auto;padding:5px;}.olDragDown,.olControlDragFeatureOver{cursor:move;}.olBingAttribution.road,.olGoogleAttribution{color:#333;}.olGoogleAttribution.hybrid,.olGoogleAttribution.satellite,span.olGoogleAttribution.hybrid a,span.olGoogleAttribution.satellite a{color:#EEE;}
\ No newline at end of file
diff --git a/src/main/webapp/lib/org/cometd.js b/src/main/webapp/lib/org/cometd.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba924d6a6f9556729e7480a61f0d3c52b1231acd
--- /dev/null
+++ b/src/main/webapp/lib/org/cometd.js
@@ -0,0 +1,3039 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Namespaces for the cometd implementation
+this.org = this.org || {};
+org.cometd = {};
+
+org.cometd.JSON = {};
+org.cometd.JSON.toJSON = org.cometd.JSON.fromJSON = function(object)
+{
+    throw 'Abstract';
+};
+
+org.cometd.Utils = {};
+
+org.cometd.Utils.isString = function(value)
+{
+    if (value === undefined || value === null)
+    {
+        return false;
+    }
+    return typeof value === 'string' ||  value instanceof String;
+};
+
+org.cometd.Utils.isArray = function(value)
+{
+    if (value === undefined || value === null)
+    {
+        return false;
+    }
+    return value instanceof Array;
+};
+
+/**
+ * Returns whether the given element is contained into the given array.
+ * @param element the element to check presence for
+ * @param array the array to check for the element presence
+ * @return the index of the element, if present, or a negative index if the element is not present
+ */
+org.cometd.Utils.inArray = function(element, array)
+{
+    for (var i = 0; i < array.length; ++i)
+    {
+        if (element === array[i])
+        {
+            return i;
+        }
+    }
+    return -1;
+};
+
+org.cometd.Utils.setTimeout = function(cometd, funktion, delay)
+{
+    return window.setTimeout(function()
+    {
+        try
+        {
+            funktion();
+        }
+        catch (x)
+        {
+            cometd._debug('Exception invoking timed function', funktion, x);
+        }
+    }, delay);
+};
+
+org.cometd.Utils.clearTimeout = function(timeoutHandle)
+{
+    window.clearTimeout(timeoutHandle);
+};
+
+/**
+ * A registry for transports used by the Cometd object.
+ */
+org.cometd.TransportRegistry = function()
+{
+    var _types = [];
+    var _transports = {};
+
+    this.getTransportTypes = function()
+    {
+        return _types.slice(0);
+    };
+
+    this.findTransportTypes = function(version, crossDomain, url)
+    {
+        var result = [];
+        for (var i = 0; i < _types.length; ++i)
+        {
+            var type = _types[i];
+            if (_transports[type].accept(version, crossDomain, url) === true)
+            {
+                result.push(type);
+            }
+        }
+        return result;
+    };
+
+    this.negotiateTransport = function(types, version, crossDomain, url)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            var type = _types[i];
+            for (var j = 0; j < types.length; ++j)
+            {
+                if (type === types[j])
+                {
+                    var transport = _transports[type];
+                    if (transport.accept(version, crossDomain, url) === true)
+                    {
+                        return transport;
+                    }
+                }
+            }
+        }
+        return null;
+    };
+
+    this.add = function(type, transport, index)
+    {
+        var existing = false;
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                existing = true;
+                break;
+            }
+        }
+
+        if (!existing)
+        {
+            if (typeof index !== 'number')
+            {
+                _types.push(type);
+            }
+            else
+            {
+                _types.splice(index, 0, type);
+            }
+            _transports[type] = transport;
+        }
+
+        return !existing;
+    };
+
+    this.find = function(type)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                return _transports[type];
+            }
+        }
+        return null;
+    };
+
+    this.remove = function(type)
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            if (_types[i] === type)
+            {
+                _types.splice(i, 1);
+                var transport = _transports[type];
+                delete _transports[type];
+                return transport;
+            }
+        }
+        return null;
+    };
+
+    this.clear = function()
+    {
+        _types = [];
+        _transports = {};
+    };
+
+    this.reset = function()
+    {
+        for (var i = 0; i < _types.length; ++i)
+        {
+            _transports[_types[i]].reset();
+        }
+    };
+};
+
+/**
+ * Base object with the common functionality for transports.
+ */
+org.cometd.Transport = function()
+{
+    var _type;
+    var _cometd;
+
+    /**
+     * Function invoked just after a transport has been successfully registered.
+     * @param type the type of transport (for example 'long-polling')
+     * @param cometd the cometd object this transport has been registered to
+     * @see #unregistered()
+     */
+    this.registered = function(type, cometd)
+    {
+        _type = type;
+        _cometd = cometd;
+    };
+
+    /**
+     * Function invoked just after a transport has been successfully unregistered.
+     * @see #registered(type, cometd)
+     */
+    this.unregistered = function()
+    {
+        _type = null;
+        _cometd = null;
+    };
+
+    this._debug = function()
+    {
+        _cometd._debug.apply(_cometd, arguments);
+    };
+
+    this._mixin = function()
+    {
+        return _cometd._mixin.apply(_cometd, arguments);
+    };
+
+    this.getConfiguration = function()
+    {
+        return _cometd.getConfiguration();
+    };
+
+    this.getAdvice = function()
+    {
+        return _cometd.getAdvice();
+    };
+
+    this.setTimeout = function(funktion, delay)
+    {
+        return org.cometd.Utils.setTimeout(_cometd, funktion, delay);
+    };
+
+    this.clearTimeout = function(handle)
+    {
+        org.cometd.Utils.clearTimeout(handle);
+    };
+
+    /**
+     * Converts the given response into an array of bayeux messages
+     * @param response the response to convert
+     * @return an array of bayeux messages obtained by converting the response
+     */
+    this.convertToMessages = function (response)
+    {
+        if (org.cometd.Utils.isString(response))
+        {
+            try
+            {
+                return org.cometd.JSON.fromJSON(response);
+            }
+            catch(x)
+            {
+                this._debug('Could not convert to JSON the following string', '"' + response + '"');
+                throw x;
+            }
+        }
+        if (org.cometd.Utils.isArray(response))
+        {
+            return response;
+        }
+        if (response === undefined || response === null)
+        {
+            return [];
+        }
+        if (response instanceof Object)
+        {
+            return [response];
+        }
+        throw 'Conversion Error ' + response + ', typeof ' + (typeof response);
+    };
+
+    /**
+     * Returns whether this transport can work for the given version and cross domain communication case.
+     * @param version a string indicating the transport version
+     * @param crossDomain a boolean indicating whether the communication is cross domain
+     * @return true if this transport can work for the given version and cross domain communication case,
+     * false otherwise
+     */
+    this.accept = function(version, crossDomain, url)
+    {
+        throw 'Abstract';
+    };
+
+    /**
+     * Returns the type of this transport.
+     * @see #registered(type, cometd)
+     */
+    this.getType = function()
+    {
+        return _type;
+    };
+
+    this.send = function(envelope, metaConnect)
+    {
+        throw 'Abstract';
+    };
+
+    this.reset = function()
+    {
+        this._debug('Transport', _type, 'reset');
+    };
+
+    this.abort = function()
+    {
+        this._debug('Transport', _type, 'aborted');
+    };
+
+    this.toString = function()
+    {
+        return this.getType();
+    };
+};
+
+org.cometd.Transport.derive = function(baseObject)
+{
+    function F() {}
+    F.prototype = baseObject;
+    return new F();
+};
+
+/**
+ * Base object with the common functionality for transports based on requests.
+ * The key responsibility is to allow at most 2 outstanding requests to the server,
+ * to avoid that requests are sent behind a long poll.
+ * To achieve this, we have one reserved request for the long poll, and all other
+ * requests are serialized one after the other.
+ */
+org.cometd.RequestTransport = function()
+{
+    var _super = new org.cometd.Transport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _requestIds = 0;
+    var _metaConnectRequest = null;
+    var _requests = [];
+    var _envelopes = [];
+
+    function _coalesceEnvelopes(envelope)
+    {
+        while (_envelopes.length > 0)
+        {
+            var envelopeAndRequest = _envelopes[0];
+            var newEnvelope = envelopeAndRequest[0];
+            var newRequest = envelopeAndRequest[1];
+            if (newEnvelope.url === envelope.url &&
+                    newEnvelope.sync === envelope.sync)
+            {
+                _envelopes.shift();
+                envelope.messages = envelope.messages.concat(newEnvelope.messages);
+                this._debug('Coalesced', newEnvelope.messages.length, 'messages from request', newRequest.id);
+                continue;
+            }
+            break;
+        }
+    }
+
+    function _transportSend(envelope, request)
+    {
+        this.transportSend(envelope, request);
+        request.expired = false;
+
+        if (!envelope.sync)
+        {
+            var maxDelay = this.getConfiguration().maxNetworkDelay;
+            var delay = maxDelay;
+            if (request.metaConnect === true)
+            {
+                delay += this.getAdvice().timeout;
+            }
+
+            this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for the response, maxNetworkDelay', maxDelay);
+
+            var self = this;
+            request.timeout = this.setTimeout(function()
+            {
+                request.expired = true;
+                if (request.xhr)
+                {
+                    request.xhr.abort();
+                }
+                var errorMessage = 'Request ' + request.id + ' of transport ' + self.getType() + ' exceeded ' + delay + ' ms max network delay';
+                self._debug(errorMessage);
+                self.complete(request, false, request.metaConnect);
+                envelope.onFailure(request.xhr, envelope.messages, 'timeout', errorMessage);
+            }, delay);
+        }
+    }
+
+    function _queueSend(envelope)
+    {
+        var requestId = ++_requestIds;
+        var request = {
+            id: requestId,
+            metaConnect: false
+        };
+
+        // Consider the metaConnect requests which should always be present
+        if (_requests.length < this.getConfiguration().maxConnections - 1)
+        {
+            _requests.push(request);
+            _transportSend.call(this, envelope, request);
+        }
+        else
+        {
+            this._debug('Transport', this.getType(), 'queueing request', requestId, 'envelope', envelope);
+            _envelopes.push([envelope, request]);
+        }
+    }
+
+    function _metaConnectComplete(request)
+    {
+        var requestId = request.id;
+        this._debug('Transport', this.getType(), 'metaConnect complete, request', requestId);
+        if (_metaConnectRequest !== null && _metaConnectRequest.id !== requestId)
+        {
+            throw 'Longpoll request mismatch, completing request ' + requestId;
+        }
+
+        // Reset metaConnect request
+        _metaConnectRequest = null;
+    }
+
+    function _complete(request, success)
+    {
+        var index = org.cometd.Utils.inArray(request, _requests);
+        // The index can be negative if the request has been aborted
+        if (index >= 0)
+        {
+            _requests.splice(index, 1);
+        }
+
+        if (_envelopes.length > 0)
+        {
+            var envelopeAndRequest = _envelopes.shift();
+            var nextEnvelope = envelopeAndRequest[0];
+            var nextRequest = envelopeAndRequest[1];
+            this._debug('Transport dequeued request', nextRequest.id);
+            if (success)
+            {
+                if (this.getConfiguration().autoBatch)
+                {
+                    _coalesceEnvelopes.call(this, nextEnvelope);
+                }
+                _queueSend.call(this, nextEnvelope);
+                this._debug('Transport completed request', request.id, nextEnvelope);
+            }
+            else
+            {
+                // Keep the semantic of calling response callbacks asynchronously after the request
+                var self = this;
+                this.setTimeout(function()
+                {
+                    self.complete(nextRequest, false, nextRequest.metaConnect);
+                    nextEnvelope.onFailure(nextRequest.xhr, nextEnvelope.messages, 'error', 'Previous request failed');
+                }, 0);
+            }
+        }
+    }
+
+    _self.complete = function(request, success, metaConnect)
+    {
+        if (metaConnect)
+        {
+            _metaConnectComplete.call(this, request);
+        }
+        else
+        {
+            _complete.call(this, request, success);
+        }
+    };
+
+    /**
+     * Performs the actual send depending on the transport type details.
+     * @param envelope the envelope to send
+     * @param request the request information
+     */
+    _self.transportSend = function(envelope, request)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSuccess = function(envelope, request, responses)
+    {
+        if (!request.expired)
+        {
+            this.clearTimeout(request.timeout);
+            this.complete(request, true, request.metaConnect);
+            if (responses && responses.length > 0)
+            {
+                envelope.onSuccess(responses);
+            }
+            else
+            {
+                envelope.onFailure(request.xhr, envelope.messages, 'Empty HTTP response');
+            }
+        }
+    };
+
+    _self.transportFailure = function(envelope, request, reason, exception)
+    {
+        if (!request.expired)
+        {
+            this.clearTimeout(request.timeout);
+            this.complete(request, false, request.metaConnect);
+            envelope.onFailure(request.xhr, envelope.messages, reason, exception);
+        }
+    };
+
+    function _metaConnectSend(envelope)
+    {
+        if (_metaConnectRequest !== null)
+        {
+            throw 'Concurrent metaConnect requests not allowed, request id=' + _metaConnectRequest.id + ' not yet completed';
+        }
+
+        var requestId = ++_requestIds;
+        this._debug('Transport', this.getType(), 'metaConnect send, request', requestId, 'envelope', envelope);
+        var request = {
+            id: requestId,
+            metaConnect: true
+        };
+        _transportSend.call(this, envelope, request);
+        _metaConnectRequest = request;
+    }
+
+    _self.send = function(envelope, metaConnect)
+    {
+        if (metaConnect)
+        {
+            _metaConnectSend.call(this, envelope);
+        }
+        else
+        {
+            _queueSend.call(this, envelope);
+        }
+    };
+
+    _self.abort = function()
+    {
+        _super.abort();
+        for (var i = 0; i < _requests.length; ++i)
+        {
+            var request = _requests[i];
+            this._debug('Aborting request', request);
+            if (request.xhr)
+            {
+                request.xhr.abort();
+            }
+        }
+        if (_metaConnectRequest)
+        {
+            this._debug('Aborting metaConnect request', _metaConnectRequest);
+            if (_metaConnectRequest.xhr)
+            {
+                _metaConnectRequest.xhr.abort();
+            }
+        }
+        this.reset();
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        _metaConnectRequest = null;
+        _requests = [];
+        _envelopes = [];
+    };
+
+    return _self;
+};
+
+org.cometd.LongPollingTransport = function()
+{
+    var _super = new org.cometd.RequestTransport();
+    var _self = org.cometd.Transport.derive(_super);
+    // By default, support cross domain
+    var _supportsCrossDomain = true;
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        return _supportsCrossDomain || !crossDomain;
+    };
+
+    _self.xhrSend = function(packet)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSend = function(envelope, request)
+    {
+        this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelope);
+
+        var self = this;
+        try
+        {
+            var sameStack = true;
+            request.xhr = this.xhrSend({
+                transport: this,
+                url: envelope.url,
+                sync: envelope.sync,
+                headers: this.getConfiguration().requestHeaders,
+                body: org.cometd.JSON.toJSON(envelope.messages),
+                onSuccess: function(response)
+                {
+                    self._debug('Transport', self.getType(), 'received response', response);
+                    var success = false;
+                    try
+                    {
+                        var received = self.convertToMessages(response);
+                        if (received.length === 0)
+                        {
+                            _supportsCrossDomain = false;
+                            self.transportFailure(envelope, request, 'no response', null);
+                        }
+                        else
+                        {
+                            success = true;
+                            self.transportSuccess(envelope, request, received);
+                        }
+                    }
+                    catch(x)
+                    {
+                        self._debug(x);
+                        if (!success)
+                        {
+                            _supportsCrossDomain = false;
+                            self.transportFailure(envelope, request, 'bad response', x);
+                        }
+                    }
+                },
+                onError: function(reason, exception)
+                {
+                    _supportsCrossDomain = false;
+                    if (sameStack)
+                    {
+                        // Keep the semantic of calling response callbacks asynchronously after the request
+                        self.setTimeout(function()
+                        {
+                            self.transportFailure(envelope, request, reason, exception);
+                        }, 0);
+                    }
+                    else
+                    {
+                        self.transportFailure(envelope, request, reason, exception);
+                    }
+                }
+            });
+            sameStack = false;
+        }
+        catch (x)
+        {
+            _supportsCrossDomain = false;
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                self.transportFailure(envelope, request, 'error', x);
+            }, 0);
+        }
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        _supportsCrossDomain = true;
+    };
+
+    return _self;
+};
+
+org.cometd.CallbackPollingTransport = function()
+{
+    var _super = new org.cometd.RequestTransport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _maxLength = 2000;
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        return true;
+    };
+
+    _self.jsonpSend = function(packet)
+    {
+        throw 'Abstract';
+    };
+
+    _self.transportSend = function(envelope, request)
+    {
+        var self = this;
+
+        // Microsoft Internet Explorer has a 2083 URL max length
+        // We must ensure that we stay within that length
+        var start = 0;
+        var length = envelope.messages.length;
+        var lengths = [];
+        while (length > 0)
+        {
+            // Encode the messages because all brackets, quotes, commas, colons, etc
+            // present in the JSON will be URL encoded, taking many more characters
+            var json = org.cometd.JSON.toJSON(envelope.messages.slice(start, start + length));
+            var urlLength = envelope.url.length + encodeURI(json).length;
+
+            // Let's stay on the safe side and use 2000 instead of 2083
+            // also because we did not count few characters among which
+            // the parameter name 'message' and the parameter 'jsonp',
+            // which sum up to about 50 chars
+            if (urlLength > _maxLength)
+            {
+                if (length === 1)
+                {
+                    var x = 'Bayeux message too big (' + urlLength + ' bytes, max is ' + _maxLength + ') ' +
+                            'for transport ' + this.getType();
+                    // Keep the semantic of calling response callbacks asynchronously after the request
+                    this.setTimeout(function()
+                    {
+                        self.transportFailure(envelope, request, 'error', x);
+                    }, 0);
+                    return;
+                }
+
+                --length;
+                continue;
+            }
+
+            lengths.push(length);
+            start += length;
+            length = envelope.messages.length - start;
+        }
+
+        // Here we are sure that the messages can be sent within the URL limit
+
+        var envelopeToSend = envelope;
+        if (lengths.length > 1)
+        {
+            var begin = 0;
+            var end = lengths[0];
+            this._debug('Transport', this.getType(), 'split', envelope.messages.length, 'messages into', lengths.join(' + '));
+            envelopeToSend = this._mixin(false, {}, envelope);
+            envelopeToSend.messages = envelope.messages.slice(begin, end);
+            envelopeToSend.onSuccess = envelope.onSuccess;
+            envelopeToSend.onFailure = envelope.onFailure;
+
+            for (var i = 1; i < lengths.length; ++i)
+            {
+                var nextEnvelope = this._mixin(false, {}, envelope);
+                begin = end;
+                end += lengths[i];
+                nextEnvelope.messages = envelope.messages.slice(begin, end);
+                nextEnvelope.onSuccess = envelope.onSuccess;
+                nextEnvelope.onFailure = envelope.onFailure;
+                this.send(nextEnvelope, request.metaConnect);
+            }
+        }
+
+        this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelopeToSend);
+
+        try
+        {
+            var sameStack = true;
+            this.jsonpSend({
+                transport: this,
+                url: envelopeToSend.url,
+                sync: envelopeToSend.sync,
+                headers: this.getConfiguration().requestHeaders,
+                body: org.cometd.JSON.toJSON(envelopeToSend.messages),
+                onSuccess: function(responses)
+                {
+                    var success = false;
+                    try
+                    {
+                        var received = self.convertToMessages(responses);
+                        if (received.length === 0)
+                        {
+                            self.transportFailure(envelopeToSend, request, 'no response');
+                        }
+                        else
+                        {
+                            success=true;
+                            self.transportSuccess(envelopeToSend, request, received);
+                        }
+                    }
+                    catch (x)
+                    {
+                        self._debug(x);
+                        if (!success)
+                        {
+                            self.transportFailure(envelopeToSend, request, 'bad response', x);
+                        }
+                    }
+                },
+                onError: function(reason, exception)
+                {
+                    if (sameStack)
+                    {
+                        // Keep the semantic of calling response callbacks asynchronously after the request
+                        self.setTimeout(function()
+                        {
+                            self.transportFailure(envelopeToSend, request, reason, exception);
+                        }, 0);
+                    }
+                    else
+                    {
+                        self.transportFailure(envelopeToSend, request, reason, exception);
+                    }
+                }
+            });
+            sameStack = false;
+        }
+        catch (xx)
+        {
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                self.transportFailure(envelopeToSend, request, 'error', xx);
+            }, 0);
+        }
+    };
+
+    return _self;
+};
+
+org.cometd.WebSocketTransport = function()
+{
+    var _super = new org.cometd.Transport();
+    var _self = org.cometd.Transport.derive(_super);
+    var _cometd;
+    // By default, support WebSocket
+    var _supportsWebSocket = true;
+    // Whether we were able to establish a WebSocket connection
+    var _webSocketSupported = false;
+    // Envelopes that have been sent
+    var _envelopes = {};
+    // Timeouts for messages that have been sent
+    var _timeouts = {};
+    var _webSocket = null;
+    var _opened = false;
+    var _connected = false;
+    var _successCallback;
+
+    function _websocketConnect()
+    {
+        // Mangle the URL, changing the scheme from 'http' to 'ws'
+        var url = _cometd.getURL().replace(/^http/, 'ws');
+        this._debug('Transport', this.getType(), 'connecting to URL', url);
+
+        var self = this;
+        var connectTimer = null;
+
+        var connectTimeout = _cometd.getConfiguration().connectTimeout;
+        if (connectTimeout > 0)
+        {
+            connectTimer = this.setTimeout(function()
+            {
+                connectTimer = null;
+                if (!_opened)
+                {
+                    self._debug('Transport', self.getType(), 'timed out while connecting to URL', url, ':', connectTimeout, 'ms');
+                    self.onClose(1002, 'Connect Timeout');
+                }
+            }, connectTimeout);
+        }
+
+        var webSocket = new org.cometd.WebSocket(url);
+        webSocket.onopen = function()
+        {
+            self._debug('WebSocket opened', webSocket);
+            if (connectTimer)
+            {
+                self.clearTimeout(connectTimer);
+                connectTimer = null;
+            }
+            if (webSocket !== _webSocket)
+            {
+                // It's possible that the onopen callback is invoked
+                // with a delay so that we have already reconnected
+                self._debug('Ignoring open event, WebSocket', _webSocket);
+                return;
+            }
+            self.onOpen();
+        };
+        webSocket.onclose = function(event)
+        {
+            var code = event ? event.code : 1000;
+            var reason = event ? event.reason : undefined;
+            self._debug('WebSocket closed', code, '/', reason, webSocket);
+            if (connectTimer)
+            {
+                self.clearTimeout(connectTimer);
+                connectTimer = null;
+            }
+            if (webSocket !== _webSocket)
+            {
+                // The onclose callback may be invoked when the server sends
+                // the close message reply, but after we have already reconnected
+                self._debug('Ignoring close event, WebSocket', _webSocket);
+                return;
+            }
+            self.onClose(code, reason);
+        };
+        webSocket.onerror = function()
+        {
+            webSocket.onclose({ code: 1002 });
+        };
+        webSocket.onmessage = function(message)
+        {
+            self._debug('WebSocket message', message, webSocket);
+            if (webSocket !== _webSocket)
+            {
+                self._debug('Ignoring message event, WebSocket', _webSocket);
+                return;
+            }
+            self.onMessage(message);
+        };
+
+        _webSocket = webSocket;
+        this._debug('Transport', this.getType(), 'configured callbacks on', webSocket);
+    }
+
+    function _webSocketSend(envelope, metaConnect)
+    {
+        var json = org.cometd.JSON.toJSON(envelope.messages);
+
+        _webSocket.send(json);
+        this._debug('Transport', this.getType(), 'sent', envelope, 'metaConnect =', metaConnect);
+
+        // Manage the timeout waiting for the response
+        var maxDelay = this.getConfiguration().maxNetworkDelay;
+        var delay = maxDelay;
+        if (metaConnect)
+        {
+            delay += this.getAdvice().timeout;
+            _connected = true;
+        }
+
+        var messageIds = [];
+        for (var i = 0; i < envelope.messages.length; ++i)
+        {
+            var message = envelope.messages[i];
+            if (message.id)
+            {
+                messageIds.push(message.id);
+                var self = this;
+                _timeouts[message.id] = this.setTimeout(function()
+                {
+                    if (_webSocket)
+                    {
+                        _webSocket.close(1000, 'Timeout');
+                    }
+                }, delay);
+            }
+        }
+
+        this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for messages', messageIds, 'maxNetworkDelay', maxDelay, ', timeouts:', _timeouts);
+    }
+
+    function _send(envelope, metaConnect)
+    {
+        try
+        {
+            if (_webSocket === null)
+            {
+                _websocketConnect.call(this);
+            }
+            // We may have a non-null _webSocket, but not be open yet so
+            // to avoid out of order deliveries, we check if we are open
+            else if (_opened)
+            {
+                _webSocketSend.call(this, envelope, metaConnect);
+            }
+        }
+        catch (x)
+        {
+            // Keep the semantic of calling response callbacks asynchronously after the request
+            this.setTimeout(function()
+            {
+                envelope.onFailure(_webSocket, envelope.messages, 'error', x);
+            }, 0);
+        }
+    }
+
+    _self.onOpen = function()
+    {
+        this._debug('Transport', this.getType(), 'opened', _webSocket);
+        _opened = true;
+        _webSocketSupported = true;
+
+        this._debug('Sending pending messages', _envelopes);
+        for (var key in _envelopes)
+        {
+            var element = _envelopes[key];
+            var envelope = element[0];
+            var metaConnect = element[1];
+            // Store the success callback, which is independent from the envelope,
+            // so that it can be used to notify arrival of messages.
+            _successCallback = envelope.onSuccess;
+            _webSocketSend.call(this, envelope, metaConnect);
+        }
+    };
+
+    _self.onMessage = function(wsMessage)
+    {
+        this._debug('Transport', this.getType(), 'received websocket message', wsMessage, _webSocket);
+
+        var close = false;
+        var messages = this.convertToMessages(wsMessage.data);
+        var messageIds = [];
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+
+            // Detect if the message is a response to a request we made.
+            // If it's a meta message, for sure it's a response;
+            // otherwise it's a publish message and publish responses lack the data field
+            if (/^\/meta\//.test(message.channel) || message.data === undefined)
+            {
+                if (message.id)
+                {
+                    messageIds.push(message.id);
+
+                    var timeout = _timeouts[message.id];
+                    if (timeout)
+                    {
+                        this.clearTimeout(timeout);
+                        delete _timeouts[message.id];
+                        this._debug('Transport', this.getType(), 'removed timeout for message', message.id, ', timeouts', _timeouts);
+                    }
+                }
+            }
+
+            if ('/meta/connect' === message.channel)
+            {
+                _connected = false;
+            }
+            if ('/meta/disconnect' === message.channel && !_connected)
+            {
+                close = true;
+            }
+        }
+
+        // Remove the envelope corresponding to the messages
+        var removed = false;
+        for (var j = 0; j < messageIds.length; ++j)
+        {
+            var id = messageIds[j];
+            for (var key in _envelopes)
+            {
+                var ids = key.split(',');
+                var index = org.cometd.Utils.inArray(id, ids);
+                if (index >= 0)
+                {
+                    removed = true;
+                    ids.splice(index, 1);
+                    var envelope = _envelopes[key][0];
+                    var metaConnect = _envelopes[key][1];
+                    delete _envelopes[key];
+                    if (ids.length > 0)
+                    {
+                        _envelopes[ids.join(',')] = [envelope, metaConnect];
+                    }
+                    break;
+                }
+            }
+        }
+        if (removed)
+        {
+            this._debug('Transport', this.getType(), 'removed envelope, envelopes', _envelopes);
+        }
+
+        _successCallback.call(this, messages);
+
+        if (close)
+        {
+            _webSocket.close(1000, 'Disconnect');
+        }
+    };
+
+    _self.onClose = function(code, reason)
+    {
+        this._debug('Transport', this.getType(), 'closed', code, reason, _webSocket);
+
+        // Remember if we were able to connect
+        // This close event could be due to server shutdown, and if it restarts we want to try websocket again
+        _supportsWebSocket = _webSocketSupported;
+
+        for (var id in _timeouts)
+        {
+            this.clearTimeout(_timeouts[id]);
+        }
+        _timeouts = {};
+
+        for (var key in _envelopes)
+        {
+            var envelope = _envelopes[key][0];
+            var metaConnect = _envelopes[key][1];
+            if (metaConnect)
+            {
+                _connected = false;
+            }
+            envelope.onFailure(_webSocket, envelope.messages, 'closed ' + code + '/' + reason);
+        }
+        _envelopes = {};
+
+        if (_webSocket !== null && _opened)
+        {
+            _webSocket.close(1000, 'Close');
+        }
+        _opened = false;
+        _webSocket = null;
+    };
+
+    _self.registered = function(type, cometd)
+    {
+        _super.registered(type, cometd);
+        _cometd = cometd;
+    };
+
+    _self.accept = function(version, crossDomain, url)
+    {
+        // Using !! to return a boolean (and not the WebSocket object)
+        return _supportsWebSocket && !!org.cometd.WebSocket && _cometd.websocketEnabled !== false;
+    };
+
+    _self.send = function(envelope, metaConnect)
+    {
+        this._debug('Transport', this.getType(), 'sending', envelope, 'metaConnect =', metaConnect);
+
+        // Store the envelope in any case; if the websocket cannot be opened, we fail it in close()
+        var messageIds = [];
+        for (var i = 0; i < envelope.messages.length; ++i)
+        {
+            var message = envelope.messages[i];
+            if (message.id)
+            {
+                messageIds.push(message.id);
+            }
+        }
+        _envelopes[messageIds.join(',')] = [envelope, metaConnect];
+        this._debug('Transport', this.getType(), 'stored envelope, envelopes', _envelopes);
+
+        _send.call(this, envelope, metaConnect);
+    };
+
+    _self.abort = function()
+    {
+        _super.abort();
+        if (_webSocket !== null)
+        {
+            try
+            {
+                _webSocket.close(1001);
+            }
+            catch (x)
+            {
+                // Firefox may throw, just ignore
+                this._debug(x);
+            }
+        }
+        this.reset();
+    };
+
+    _self.reset = function()
+    {
+        _super.reset();
+        if (_webSocket !== null && _opened)
+        {
+            _webSocket.close(1000, 'Reset');
+        }
+        _supportsWebSocket = true;
+        _webSocketSupported = false;
+        _timeouts = {};
+        _envelopes = {};
+        _webSocket = null;
+        _opened = false;
+        _successCallback = null;
+    };
+
+    return _self;
+};
+
+/**
+ * The constructor for a Cometd object, identified by an optional name.
+ * The default name is the string 'default'.
+ * In the rare case a page needs more than one Bayeux conversation,
+ * a new instance can be created via:
+ * <pre>
+ * var bayeuxUrl2 = ...;
+ *
+ * // Dojo style
+ * var cometd2 = new dojox.Cometd('another_optional_name');
+ *
+ * // jQuery style
+ * var cometd2 = new $.Cometd('another_optional_name');
+ *
+ * cometd2.init({url: bayeuxUrl2});
+ * </pre>
+ * @param name the optional name of this cometd object
+ */
+// IMPLEMENTATION NOTES:
+// Be very careful in not changing the function order and pass this file every time through JSLint (http://jslint.com)
+// The only implied globals must be "dojo", "org" and "window", and check that there are no "unused" warnings
+// Failing to pass JSLint may result in shrinkers/minifiers to create an unusable file.
+org.cometd.Cometd = function(name)
+{
+    var _cometd = this;
+    var _name = name || 'default';
+    var _crossDomain = false;
+    var _transports = new org.cometd.TransportRegistry();
+    var _transport;
+    var _status = 'disconnected';
+    var _messageId = 0;
+    var _clientId = null;
+    var _batch = 0;
+    var _messageQueue = [];
+    var _internalBatch = false;
+    var _listeners = {};
+    var _backoff = 0;
+    var _scheduledSend = null;
+    var _extensions = [];
+    var _advice = {};
+    var _handshakeProps;
+    var _publishCallbacks = {};
+    var _reestablish = false;
+    var _connected = false;
+    var _config = {
+        connectTimeout: 0,
+        maxConnections: 2,
+        backoffIncrement: 1000,
+        maxBackoff: 60000,
+        logLevel: 'info',
+        reverseIncomingExtensions: true,
+        maxNetworkDelay: 10000,
+        requestHeaders: {},
+        appendMessageTypeToURL: true,
+        autoBatch: false,
+        advice: {
+            timeout: 60000,
+            interval: 0,
+            reconnect: 'retry'
+        }
+    };
+
+    /**
+     * Mixes in the given objects into the target object by copying the properties.
+     * @param deep if the copy must be deep
+     * @param target the target object
+     * @param objects the objects whose properties are copied into the target
+     */
+    this._mixin = function(deep, target, objects)
+    {
+        var result = target || {};
+
+        // Skip first 2 parameters (deep and target), and loop over the others
+        for (var i = 2; i < arguments.length; ++i)
+        {
+            var object = arguments[i];
+
+            if (object === undefined || object === null)
+            {
+                continue;
+            }
+
+            for (var propName in object)
+            {
+                var prop = object[propName];
+                var targ = result[propName];
+
+                // Avoid infinite loops
+                if (prop === target)
+                {
+                    continue;
+                }
+                // Do not mixin undefined values
+                if (prop === undefined)
+                {
+                    continue;
+                }
+
+                if (deep && typeof prop === 'object' && prop !== null)
+                {
+                    if (prop instanceof Array)
+                    {
+                        result[propName] = this._mixin(deep, targ instanceof Array ? targ : [], prop);
+                    }
+                    else
+                    {
+                        var source = typeof targ === 'object' && !(targ instanceof Array) ? targ : {};
+                        result[propName] = this._mixin(deep, source, prop);
+                    }
+                }
+                else
+                {
+                    result[propName] = prop;
+                }
+            }
+        }
+
+        return result;
+    };
+
+    function _isString(value)
+    {
+        return org.cometd.Utils.isString(value);
+    }
+
+    function _isFunction(value)
+    {
+        if (value === undefined || value === null)
+        {
+            return false;
+        }
+        return typeof value === 'function';
+    }
+
+    function _log(level, args)
+    {
+        if (window.console)
+        {
+            var logger = window.console[level];
+            if (_isFunction(logger))
+            {
+                logger.apply(window.console, args);
+            }
+        }
+    }
+
+    this._warn = function()
+    {
+        _log('warn', arguments);
+    };
+
+    this._info = function()
+    {
+        if (_config.logLevel !== 'warn')
+        {
+            _log('info', arguments);
+        }
+    };
+
+    this._debug = function()
+    {
+        if (_config.logLevel === 'debug')
+        {
+            _log('debug', arguments);
+        }
+    };
+
+    /**
+     * Returns whether the given hostAndPort is cross domain.
+     * The default implementation checks against window.location.host
+     * but this function can be overridden to make it work in non-browser
+     * environments.
+     *
+     * @param hostAndPort the host and port in format host:port
+     * @return whether the given hostAndPort is cross domain
+     */
+    this._isCrossDomain = function(hostAndPort)
+    {
+        return hostAndPort && hostAndPort !== window.location.host;
+    };
+
+    function _configure(configuration)
+    {
+        _cometd._debug('Configuring cometd object with', configuration);
+        // Support old style param, where only the Bayeux server URL was passed
+        if (_isString(configuration))
+        {
+            configuration = { url: configuration };
+        }
+        if (!configuration)
+        {
+            configuration = {};
+        }
+
+        _config = _cometd._mixin(false, _config, configuration);
+
+        if (!_config.url)
+        {
+            throw 'Missing required configuration parameter \'url\' specifying the Bayeux server URL';
+        }
+
+        // Check if we're cross domain
+        // [1] = protocol://, [2] = host:port, [3] = host, [4] = IPv6_host, [5] = IPv4_host, [6] = :port, [7] = port, [8] = uri, [9] = rest
+        var urlParts = /(^https?:\/\/)?(((\[[^\]]+\])|([^:\/\?#]+))(:(\d+))?)?([^\?#]*)(.*)?/.exec(_config.url);
+        var hostAndPort = urlParts[2];
+        var uri = urlParts[8];
+        var afterURI = urlParts[9];
+        _crossDomain = _cometd._isCrossDomain(hostAndPort);
+
+        // Check if appending extra path is supported
+        if (_config.appendMessageTypeToURL)
+        {
+            if (afterURI !== undefined && afterURI.length > 0)
+            {
+                _cometd._info('Appending message type to URI ' + uri + afterURI + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
+                _config.appendMessageTypeToURL = false;
+            }
+            else
+            {
+                var uriSegments = uri.split('/');
+                var lastSegmentIndex = uriSegments.length - 1;
+                if (uri.match(/\/$/))
+                {
+                    lastSegmentIndex -= 1;
+                }
+                if (uriSegments[lastSegmentIndex].indexOf('.') >= 0)
+                {
+                    // Very likely the CometD servlet's URL pattern is mapped to an extension, such as *.cometd
+                    // It will be difficult to add the extra path in this case
+                    _cometd._info('Appending message type to URI ' + uri + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
+                    _config.appendMessageTypeToURL = false;
+                }
+            }
+        }
+    }
+
+    function _clearSubscriptions()
+    {
+        for (var channel in _listeners)
+        {
+            var subscriptions = _listeners[channel];
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                var subscription = subscriptions[i];
+                if (subscription && !subscription.listener)
+                {
+                    delete subscriptions[i];
+                    _cometd._debug('Removed subscription', subscription, 'for channel', channel);
+                }
+            }
+        }
+    }
+
+    function _setStatus(newStatus)
+    {
+        if (_status !== newStatus)
+        {
+            _cometd._debug('Status', _status, '->', newStatus);
+            _status = newStatus;
+        }
+    }
+
+    function _isDisconnected()
+    {
+        return _status === 'disconnecting' || _status === 'disconnected';
+    }
+
+    function _nextMessageId()
+    {
+        return ++_messageId;
+    }
+
+    function _applyExtension(scope, callback, name, message, outgoing)
+    {
+        try
+        {
+            return callback.call(scope, message);
+        }
+        catch (x)
+        {
+            _cometd._debug('Exception during execution of extension', name, x);
+            var exceptionCallback = _cometd.onExtensionException;
+            if (_isFunction(exceptionCallback))
+            {
+                _cometd._debug('Invoking extension exception callback', name, x);
+                try
+                {
+                    exceptionCallback.call(_cometd, x, name, outgoing, message);
+                }
+                catch(xx)
+                {
+                    _cometd._info('Exception during execution of exception callback in extension', name, xx);
+                }
+            }
+            return message;
+        }
+    }
+
+    function _applyIncomingExtensions(message)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            if (message === undefined || message === null)
+            {
+                break;
+            }
+
+            var index = _config.reverseIncomingExtensions ? _extensions.length - 1 - i : i;
+            var extension = _extensions[index];
+            var callback = extension.extension.incoming;
+            if (_isFunction(callback))
+            {
+                var result = _applyExtension(extension.extension, callback, extension.name, message, false);
+                message = result === undefined ? message : result;
+            }
+        }
+        return message;
+    }
+
+    function _applyOutgoingExtensions(message)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            if (message === undefined || message === null)
+            {
+                break;
+            }
+
+            var extension = _extensions[i];
+            var callback = extension.extension.outgoing;
+            if (_isFunction(callback))
+            {
+                var result = _applyExtension(extension.extension, callback, extension.name, message, true);
+                message = result === undefined ? message : result;
+            }
+        }
+        return message;
+    }
+
+    function _notify(channel, message)
+    {
+        var subscriptions = _listeners[channel];
+        if (subscriptions && subscriptions.length > 0)
+        {
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                var subscription = subscriptions[i];
+                // Subscriptions may come and go, so the array may have 'holes'
+                if (subscription)
+                {
+                    try
+                    {
+                        subscription.callback.call(subscription.scope, message);
+                    }
+                    catch (x)
+                    {
+                        _cometd._debug('Exception during notification', subscription, message, x);
+                        var listenerCallback = _cometd.onListenerException;
+                        if (_isFunction(listenerCallback))
+                        {
+                            _cometd._debug('Invoking listener exception callback', subscription, x);
+                            try
+                            {
+                                listenerCallback.call(_cometd, x, subscription.handle, subscription.listener, message);
+                            }
+                            catch (xx)
+                            {
+                                _cometd._info('Exception during execution of listener callback', subscription, xx);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    function _notifyListeners(channel, message)
+    {
+        // Notify direct listeners
+        _notify(channel, message);
+
+        // Notify the globbing listeners
+        var channelParts = channel.split('/');
+        var last = channelParts.length - 1;
+        for (var i = last; i > 0; --i)
+        {
+            var channelPart = channelParts.slice(0, i).join('/') + '/*';
+            // We don't want to notify /foo/* if the channel is /foo/bar/baz,
+            // so we stop at the first non recursive globbing
+            if (i === last)
+            {
+                _notify(channelPart, message);
+            }
+            // Add the recursive globber and notify
+            channelPart += '*';
+            _notify(channelPart, message);
+        }
+    }
+
+    function _cancelDelayedSend()
+    {
+        if (_scheduledSend !== null)
+        {
+            org.cometd.Utils.clearTimeout(_scheduledSend);
+        }
+        _scheduledSend = null;
+    }
+
+    function _delayedSend(operation)
+    {
+        _cancelDelayedSend();
+        var delay = _advice.interval + _backoff;
+        _cometd._debug('Function scheduled in', delay, 'ms, interval =', _advice.interval, 'backoff =', _backoff, operation);
+        _scheduledSend = org.cometd.Utils.setTimeout(_cometd, operation, delay);
+    }
+
+    // Needed to break cyclic dependencies between function definitions
+    var _handleMessages;
+    var _handleFailure;
+
+    /**
+     * Delivers the messages to the CometD server
+     * @param messages the array of messages to send
+     * @param longpoll true if this send is a long poll
+     */
+    function _send(sync, messages, longpoll, extraPath)
+    {
+        // We must be sure that the messages have a clientId.
+        // This is not guaranteed since the handshake may take time to return
+        // (and hence the clientId is not known yet) and the application
+        // may create other messages.
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+            message.id = '' + _nextMessageId();
+
+            if (_clientId)
+            {
+                message.clientId = _clientId;
+            }
+
+            var callback = undefined;
+            if (_isFunction(message._callback))
+            {
+                callback = message._callback;
+                // Remove the publish callback before calling the extensions
+                delete message._callback;
+            }
+
+            message = _applyOutgoingExtensions(message);
+            if (message !== undefined && message !== null)
+            {
+                messages[i] = message;
+                if (callback)
+                    _publishCallbacks[message.id] = callback;
+            }
+            else
+            {
+                messages.splice(i--, 1);
+            }
+        }
+
+        if (messages.length === 0)
+        {
+            return;
+        }
+
+        var url = _config.url;
+        if (_config.appendMessageTypeToURL)
+        {
+            // If url does not end with '/', then append it
+            if (!url.match(/\/$/))
+            {
+                url = url + '/';
+            }
+            if (extraPath)
+            {
+                url = url + extraPath;
+            }
+        }
+
+        var envelope = {
+            url: url,
+            sync: sync,
+            messages: messages,
+            onSuccess: function(rcvdMessages)
+            {
+                try
+                {
+                    _handleMessages.call(_cometd, rcvdMessages);
+                }
+                catch (x)
+                {
+                    _cometd._debug('Exception during handling of messages', x);
+                }
+            },
+            onFailure: function(conduit, messages, reason, exception)
+            {
+                try
+                {
+                    _handleFailure.call(_cometd, conduit, messages, reason, exception);
+                }
+                catch (x)
+                {
+                    _cometd._debug('Exception during handling of failure', x);
+                }
+            }
+        };
+        _cometd._debug('Send', envelope);
+        _transport.send(envelope, longpoll);
+    }
+
+    function _queueSend(message)
+    {
+        if (_batch > 0 || _internalBatch === true)
+        {
+            _messageQueue.push(message);
+        }
+        else
+        {
+            _send(false, [message], false);
+        }
+    }
+
+    /**
+     * Sends a complete bayeux message.
+     * This method is exposed as a public so that extensions may use it
+     * to send bayeux message directly, for example in case of re-sending
+     * messages that have already been sent but that for some reason must
+     * be resent.
+     */
+    this.send = _queueSend;
+
+    function _resetBackoff()
+    {
+        _backoff = 0;
+    }
+
+    function _increaseBackoff()
+    {
+        if (_backoff < _config.maxBackoff)
+        {
+            _backoff += _config.backoffIncrement;
+        }
+    }
+
+    /**
+     * Starts a the batch of messages to be sent in a single request.
+     * @see #_endBatch(sendMessages)
+     */
+    function _startBatch()
+    {
+        ++_batch;
+    }
+
+    function _flushBatch()
+    {
+        var messages = _messageQueue;
+        _messageQueue = [];
+        if (messages.length > 0)
+        {
+            _send(false, messages, false);
+        }
+    }
+
+    /**
+     * Ends the batch of messages to be sent in a single request,
+     * optionally sending messages present in the message queue depending
+     * on the given argument.
+     * @see #_startBatch()
+     */
+    function _endBatch()
+    {
+        --_batch;
+        if (_batch < 0)
+        {
+            throw 'Calls to startBatch() and endBatch() are not paired';
+        }
+
+        if (_batch === 0 && !_isDisconnected() && !_internalBatch)
+        {
+            _flushBatch();
+        }
+    }
+
+    /**
+     * Sends the connect message
+     */
+    function _connect()
+    {
+        if (!_isDisconnected())
+        {
+            var message = {
+                channel: '/meta/connect',
+                connectionType: _transport.getType()
+            };
+
+            // In case of reload or temporary loss of connection
+            // we want the next successful connect to return immediately
+            // instead of being held by the server, so that connect listeners
+            // can be notified that the connection has been re-established
+            if (!_connected)
+            {
+                message.advice = { timeout: 0 };
+            }
+
+            _setStatus('connecting');
+            _cometd._debug('Connect sent', message);
+            _send(false, [message], true, 'connect');
+            _setStatus('connected');
+        }
+    }
+
+    function _delayedConnect()
+    {
+        _setStatus('connecting');
+        _delayedSend(function()
+        {
+            _connect();
+        });
+    }
+
+    function _updateAdvice(newAdvice)
+    {
+        if (newAdvice)
+        {
+            _advice = _cometd._mixin(false, {}, _config.advice, newAdvice);
+            _cometd._debug('New advice', _advice);
+        }
+    }
+
+    function _disconnect(abort)
+    {
+        _cancelDelayedSend();
+        if (abort)
+        {
+            _transport.abort();
+        }
+        _clientId = null;
+        _setStatus('disconnected');
+        _batch = 0;
+        _resetBackoff();
+
+        // Fail any existing queued message
+        if (_messageQueue.length > 0)
+        {
+            _handleFailure.call(_cometd, undefined, _messageQueue, 'error', 'Disconnected');
+            _messageQueue = [];
+        }
+    }
+
+    /**
+     * Sends the initial handshake message
+     */
+    function _handshake(handshakeProps)
+    {
+        _clientId = null;
+
+        _clearSubscriptions();
+
+        // Reset the transports if we're not retrying the handshake
+        if (_isDisconnected())
+        {
+            _transports.reset();
+            _updateAdvice(_config.advice);
+        }
+        else
+        {
+            // We are retrying the handshake, either because another handshake failed
+            // and we're backing off, or because the server timed us out and asks us to
+            // re-handshake: in both cases, make sure that if the handshake succeeds
+            // the next action is a connect.
+            _updateAdvice(_cometd._mixin(false, _advice, {reconnect: 'retry'}));
+        }
+
+        _batch = 0;
+
+        // Mark the start of an internal batch.
+        // This is needed because handshake and connect are async.
+        // It may happen that the application calls init() then subscribe()
+        // and the subscribe message is sent before the connect message, if
+        // the subscribe message is not held until the connect message is sent.
+        // So here we start a batch to hold temporarily any message until
+        // the connection is fully established.
+        _internalBatch = true;
+
+        // Save the properties provided by the user, so that
+        // we can reuse them during automatic re-handshake
+        _handshakeProps = handshakeProps;
+
+        var version = '1.0';
+
+        // Figure out the transports to send to the server
+        var transportTypes = _transports.findTransportTypes(version, _crossDomain, _config.url);
+
+        var bayeuxMessage = {
+            version: version,
+            minimumVersion: '0.9',
+            channel: '/meta/handshake',
+            supportedConnectionTypes: transportTypes,
+            advice: {
+                timeout: _advice.timeout,
+                interval: _advice.interval
+            }
+        };
+        // Do not allow the user to mess with the required properties,
+        // so merge first the user properties and *then* the bayeux message
+        var message = _cometd._mixin(false, {}, _handshakeProps, bayeuxMessage);
+
+        // Pick up the first available transport as initial transport
+        // since we don't know if the server supports it
+        _transport = _transports.negotiateTransport(transportTypes, version, _crossDomain, _config.url);
+        _cometd._debug('Initial transport is', _transport.getType());
+
+        // We started a batch to hold the application messages,
+        // so here we must bypass it and send immediately.
+        _setStatus('handshaking');
+        _cometd._debug('Handshake sent', message);
+        _send(false, [message], false, 'handshake');
+    }
+
+    function _delayedHandshake()
+    {
+        _setStatus('handshaking');
+
+        // We will call _handshake() which will reset _clientId, but we want to avoid
+        // that between the end of this method and the call to _handshake() someone may
+        // call publish() (or other methods that call _queueSend()).
+        _internalBatch = true;
+
+        _delayedSend(function()
+        {
+            _handshake(_handshakeProps);
+        });
+    }
+
+    function _failHandshake(message)
+    {
+        _notifyListeners('/meta/handshake', message);
+        _notifyListeners('/meta/unsuccessful', message);
+
+        // Only try again if we haven't been disconnected and
+        // the advice permits us to retry the handshake
+        var retry = !_isDisconnected() && _advice.reconnect !== 'none';
+        if (retry)
+        {
+            _increaseBackoff();
+            _delayedHandshake();
+        }
+        else
+        {
+            _disconnect(false);
+        }
+    }
+
+    function _handshakeResponse(message)
+    {
+        if (message.successful)
+        {
+            // Save clientId, figure out transport, then follow the advice to connect
+            _clientId = message.clientId;
+
+            var newTransport = _transports.negotiateTransport(message.supportedConnectionTypes, message.version, _crossDomain, _config.url);
+            if (newTransport === null)
+            {
+                throw 'Could not negotiate transport with server; client ' +
+                      _transports.findTransportTypes(message.version, _crossDomain, _config.url) +
+                      ', server ' + message.supportedConnectionTypes;
+            }
+            else if (_transport !== newTransport)
+            {
+                _cometd._debug('Transport', _transport, '->', newTransport);
+                _transport = newTransport;
+            }
+
+            // End the internal batch and allow held messages from the application
+            // to go to the server (see _handshake() where we start the internal batch).
+            _internalBatch = false;
+            _flushBatch();
+
+            // Here the new transport is in place, as well as the clientId, so
+            // the listeners can perform a publish() if they want.
+            // Notify the listeners before the connect below.
+            message.reestablish = _reestablish;
+            _reestablish = true;
+            _notifyListeners('/meta/handshake', message);
+
+            var action = _isDisconnected() ? 'none' : _advice.reconnect;
+            switch (action)
+            {
+                case 'retry':
+                    _resetBackoff();
+                    _delayedConnect();
+                    break;
+                case 'none':
+                    _disconnect(false);
+                    break;
+                default:
+                    throw 'Unrecognized advice action ' + action;
+            }
+        }
+        else
+        {
+            _failHandshake(message);
+        }
+    }
+
+    function _handshakeFailure(xhr, message)
+    {
+        _failHandshake({
+            successful: false,
+            failure: true,
+            channel: '/meta/handshake',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'retry',
+                interval: _backoff
+            }
+        });
+    }
+
+    function _failConnect(message)
+    {
+        // Notify the listeners after the status change but before the next action
+        _notifyListeners('/meta/connect', message);
+        _notifyListeners('/meta/unsuccessful', message);
+
+        // This may happen when the server crashed, the current clientId
+        // will be invalid, and the server will ask to handshake again
+        // Listeners can call disconnect(), so check the state after they run
+        var action = _isDisconnected() ? 'none' : _advice.reconnect;
+        switch (action)
+        {
+            case 'retry':
+                _delayedConnect();
+                _increaseBackoff();
+                break;
+            case 'handshake':
+                // The current transport may be failed (e.g. network disconnection)
+                // Reset the transports so the new handshake picks up the right one
+                _transports.reset();
+                _resetBackoff();
+                _delayedHandshake();
+                break;
+            case 'none':
+                _disconnect(false);
+                break;
+            default:
+                throw 'Unrecognized advice action' + action;
+        }
+    }
+
+    function _connectResponse(message)
+    {
+        _connected = message.successful;
+
+        if (_connected)
+        {
+            _notifyListeners('/meta/connect', message);
+
+            // Normally, the advice will say "reconnect: 'retry', interval: 0"
+            // and the server will hold the request, so when a response returns
+            // we immediately call the server again (long polling)
+            // Listeners can call disconnect(), so check the state after they run
+            var action = _isDisconnected() ? 'none' : _advice.reconnect;
+            switch (action)
+            {
+                case 'retry':
+                    _resetBackoff();
+                    _delayedConnect();
+                    break;
+                case 'none':
+                    _disconnect(false);
+                    break;
+                default:
+                    throw 'Unrecognized advice action ' + action;
+            }
+        }
+        else
+        {
+            _failConnect(message);
+        }
+    }
+
+    function _connectFailure(xhr, message)
+    {
+        _connected = false;
+        _failConnect({
+            successful: false,
+            failure: true,
+            channel: '/meta/connect',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'retry',
+                interval: _backoff
+            }
+        });
+    }
+
+    function _failDisconnect(message)
+    {
+        _disconnect(true);
+        _notifyListeners('/meta/disconnect', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _disconnectResponse(message)
+    {
+        if (message.successful)
+        {
+            _disconnect(false);
+            _notifyListeners('/meta/disconnect', message);
+        }
+        else
+        {
+            _failDisconnect(message);
+        }
+    }
+
+    function _disconnectFailure(xhr, message)
+    {
+        _failDisconnect({
+            successful: false,
+            failure: true,
+            channel: '/meta/disconnect',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _failSubscribe(message)
+    {
+        _notifyListeners('/meta/subscribe', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _subscribeResponse(message)
+    {
+        if (message.successful)
+        {
+            _notifyListeners('/meta/subscribe', message);
+        }
+        else
+        {
+            _failSubscribe(message);
+        }
+    }
+
+    function _subscribeFailure(xhr, message)
+    {
+        _failSubscribe({
+            successful: false,
+            failure: true,
+            channel: '/meta/subscribe',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _failUnsubscribe(message)
+    {
+        _notifyListeners('/meta/unsubscribe', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _unsubscribeResponse(message)
+    {
+        if (message.successful)
+        {
+            _notifyListeners('/meta/unsubscribe', message);
+        }
+        else
+        {
+            _failUnsubscribe(message);
+        }
+    }
+
+    function _unsubscribeFailure(xhr, message)
+    {
+        _failUnsubscribe({
+            successful: false,
+            failure: true,
+            channel: '/meta/unsubscribe',
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _handlePublishCallback(message)
+    {
+        var callback = _publishCallbacks[message.id];
+        if (_isFunction(callback))
+        {
+            delete _publishCallbacks[message.id];
+            callback.call(_cometd, message);
+        }
+    }
+
+    function _failMessage(message)
+    {
+        _handlePublishCallback(message);
+        _notifyListeners('/meta/publish', message);
+        _notifyListeners('/meta/unsuccessful', message);
+    }
+
+    function _messageResponse(message)
+    {
+        if (message.successful === undefined)
+        {
+            if (message.data)
+            {
+                // It is a plain message, and not a bayeux meta message
+                _notifyListeners(message.channel, message);
+            }
+            else
+            {
+                _cometd._debug('Unknown message', message);
+            }
+        }
+        else
+        {
+            if (message.successful)
+            {
+                _handlePublishCallback(message);
+                _notifyListeners('/meta/publish', message);
+            }
+            else
+            {
+                _failMessage(message);
+            }
+        }
+    }
+
+    function _messageFailure(xhr, message)
+    {
+        _failMessage({
+            successful: false,
+            failure: true,
+            channel: message.channel,
+            request: message,
+            xhr: xhr,
+            advice: {
+                reconnect: 'none',
+                interval: 0
+            }
+        });
+    }
+
+    function _receive(message)
+    {
+        message = _applyIncomingExtensions(message);
+        if (message === undefined || message === null)
+        {
+            return;
+        }
+
+        _updateAdvice(message.advice);
+
+        var channel = message.channel;
+        switch (channel)
+        {
+            case '/meta/handshake':
+                _handshakeResponse(message);
+                break;
+            case '/meta/connect':
+                _connectResponse(message);
+                break;
+            case '/meta/disconnect':
+                _disconnectResponse(message);
+                break;
+            case '/meta/subscribe':
+                _subscribeResponse(message);
+                break;
+            case '/meta/unsubscribe':
+                _unsubscribeResponse(message);
+                break;
+            default:
+                _messageResponse(message);
+                break;
+        }
+    }
+
+    /**
+     * Receives a message.
+     * This method is exposed as a public so that extensions may inject
+     * messages simulating that they had been received.
+     */
+    this.receive = _receive;
+
+    _handleMessages = function(rcvdMessages)
+    {
+        _cometd._debug('Received', rcvdMessages);
+
+        for (var i = 0; i < rcvdMessages.length; ++i)
+        {
+            var message = rcvdMessages[i];
+            _receive(message);
+        }
+    };
+
+    _handleFailure = function(conduit, messages, reason, exception)
+    {
+        _cometd._debug('handleFailure', conduit, messages, reason, exception);
+
+        for (var i = 0; i < messages.length; ++i)
+        {
+            var message = messages[i];
+            var channel = message.channel;
+            switch (channel)
+            {
+                case '/meta/handshake':
+                    _handshakeFailure(conduit, message);
+                    break;
+                case '/meta/connect':
+                    _connectFailure(conduit, message);
+                    break;
+                case '/meta/disconnect':
+                    _disconnectFailure(conduit, message);
+                    break;
+                case '/meta/subscribe':
+                    _subscribeFailure(conduit, message);
+                    break;
+                case '/meta/unsubscribe':
+                    _unsubscribeFailure(conduit, message);
+                    break;
+                default:
+                    _messageFailure(conduit, message);
+                    break;
+            }
+        }
+    };
+
+    function _hasSubscriptions(channel)
+    {
+        var subscriptions = _listeners[channel];
+        if (subscriptions)
+        {
+            for (var i = 0; i < subscriptions.length; ++i)
+            {
+                if (subscriptions[i])
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    function _resolveScopedCallback(scope, callback)
+    {
+        var delegate = {
+            scope: scope,
+            method: callback
+        };
+        if (_isFunction(scope))
+        {
+            delegate.scope = undefined;
+            delegate.method = scope;
+        }
+        else
+        {
+            if (_isString(callback))
+            {
+                if (!scope)
+                {
+                    throw 'Invalid scope ' + scope;
+                }
+                delegate.method = scope[callback];
+                if (!_isFunction(delegate.method))
+                {
+                    throw 'Invalid callback ' + callback + ' for scope ' + scope;
+                }
+            }
+            else if (!_isFunction(callback))
+            {
+                throw 'Invalid callback ' + callback;
+            }
+        }
+        return delegate;
+    }
+
+    function _addListener(channel, scope, callback, isListener)
+    {
+        // The data structure is a map<channel, subscription[]>, where each subscription
+        // holds the callback to be called and its scope.
+
+        var delegate = _resolveScopedCallback(scope, callback);
+        _cometd._debug('Adding listener on', channel, 'with scope', delegate.scope, 'and callback', delegate.method);
+
+        var subscription = {
+            channel: channel,
+            scope: delegate.scope,
+            callback: delegate.method,
+            listener: isListener
+        };
+
+        var subscriptions = _listeners[channel];
+        if (!subscriptions)
+        {
+            subscriptions = [];
+            _listeners[channel] = subscriptions;
+        }
+
+        // Pushing onto an array appends at the end and returns the id associated with the element increased by 1.
+        // Note that if:
+        // a.push('a'); var hb=a.push('b'); delete a[hb-1]; var hc=a.push('c');
+        // then:
+        // hc==3, a.join()=='a',,'c', a.length==3
+        var subscriptionID = subscriptions.push(subscription) - 1;
+        subscription.id = subscriptionID;
+        subscription.handle = [channel, subscriptionID];
+
+        _cometd._debug('Added listener', subscription, 'for channel', channel, 'having id =', subscriptionID);
+
+        // The subscription to allow removal of the listener is made of the channel and the index
+        return subscription.handle;
+    }
+
+    function _removeListener(subscription)
+    {
+        var subscriptions = _listeners[subscription[0]];
+        if (subscriptions)
+        {
+            delete subscriptions[subscription[1]];
+            _cometd._debug('Removed listener', subscription);
+        }
+    }
+
+    //
+    // PUBLIC API
+    //
+
+    /**
+     * Registers the given transport under the given transport type.
+     * The optional index parameter specifies the "priority" at which the
+     * transport is registered (where 0 is the max priority).
+     * If a transport with the same type is already registered, this function
+     * does nothing and returns false.
+     * @param type the transport type
+     * @param transport the transport object
+     * @param index the index at which this transport is to be registered
+     * @return true if the transport has been registered, false otherwise
+     * @see #unregisterTransport(type)
+     */
+    this.registerTransport = function(type, transport, index)
+    {
+        var result = _transports.add(type, transport, index);
+        if (result)
+        {
+            this._debug('Registered transport', type);
+
+            if (_isFunction(transport.registered))
+            {
+                transport.registered(type, this);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @return an array of all registered transport types
+     */
+    this.getTransportTypes = function()
+    {
+        return _transports.getTransportTypes();
+    };
+
+    /**
+     * Unregisters the transport with the given transport type.
+     * @param type the transport type to unregister
+     * @return the transport that has been unregistered,
+     * or null if no transport was previously registered under the given transport type
+     */
+    this.unregisterTransport = function(type)
+    {
+        var transport = _transports.remove(type);
+        if (transport !== null)
+        {
+            this._debug('Unregistered transport', type);
+
+            if (_isFunction(transport.unregistered))
+            {
+                transport.unregistered();
+            }
+        }
+        return transport;
+    };
+
+    this.unregisterTransports = function()
+    {
+        _transports.clear();
+    };
+
+    this.findTransport = function(name)
+    {
+        return _transports.find(name);
+    };
+
+    /**
+     * Configures the initial Bayeux communication with the Bayeux server.
+     * Configuration is passed via an object that must contain a mandatory field <code>url</code>
+     * of type string containing the URL of the Bayeux server.
+     * @param configuration the configuration object
+     */
+    this.configure = function(configuration)
+    {
+        _configure.call(this, configuration);
+    };
+
+    /**
+     * Configures and establishes the Bayeux communication with the Bayeux server
+     * via a handshake and a subsequent connect.
+     * @param configuration the configuration object
+     * @param handshakeProps an object to be merged with the handshake message
+     * @see #configure(configuration)
+     * @see #handshake(handshakeProps)
+     */
+    this.init = function(configuration, handshakeProps)
+    {
+        this.configure(configuration);
+        this.handshake(handshakeProps);
+    };
+
+    /**
+     * Establishes the Bayeux communication with the Bayeux server
+     * via a handshake and a subsequent connect.
+     * @param handshakeProps an object to be merged with the handshake message
+     */
+    this.handshake = function(handshakeProps)
+    {
+        _setStatus('disconnected');
+        _reestablish = false;
+        _handshake(handshakeProps);
+    };
+
+    /**
+     * Disconnects from the Bayeux server.
+     * It is possible to suggest to attempt a synchronous disconnect, but this feature
+     * may only be available in certain transports (for example, long-polling may support
+     * it, callback-polling certainly does not).
+     * @param sync whether attempt to perform a synchronous disconnect
+     * @param disconnectProps an object to be merged with the disconnect message
+     */
+    this.disconnect = function(sync, disconnectProps)
+    {
+        if (_isDisconnected())
+        {
+            return;
+        }
+
+        if (disconnectProps === undefined)
+        {
+            if (typeof sync !== 'boolean')
+            {
+                disconnectProps = sync;
+                sync = false;
+            }
+        }
+
+        var bayeuxMessage = {
+            channel: '/meta/disconnect'
+        };
+        var message = this._mixin(false, {}, disconnectProps, bayeuxMessage);
+        _setStatus('disconnecting');
+        _send(sync === true, [message], false, 'disconnect');
+    };
+
+    /**
+     * Marks the start of a batch of application messages to be sent to the server
+     * in a single request, obtaining a single response containing (possibly) many
+     * application reply messages.
+     * Messages are held in a queue and not sent until {@link #endBatch()} is called.
+     * If startBatch() is called multiple times, then an equal number of endBatch()
+     * calls must be made to close and send the batch of messages.
+     * @see #endBatch()
+     */
+    this.startBatch = function()
+    {
+        _startBatch();
+    };
+
+    /**
+     * Marks the end of a batch of application messages to be sent to the server
+     * in a single request.
+     * @see #startBatch()
+     */
+    this.endBatch = function()
+    {
+        _endBatch();
+    };
+
+    /**
+     * Executes the given callback in the given scope, surrounded by a {@link #startBatch()}
+     * and {@link #endBatch()} calls.
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to be executed within {@link #startBatch()} and {@link #endBatch()} calls
+     */
+    this.batch = function(scope, callback)
+    {
+        var delegate = _resolveScopedCallback(scope, callback);
+        this.startBatch();
+        try
+        {
+            delegate.method.call(delegate.scope);
+            this.endBatch();
+        }
+        catch (x)
+        {
+            this._debug('Exception during execution of batch', x);
+            this.endBatch();
+            throw x;
+        }
+    };
+
+    /**
+     * Adds a listener for bayeux messages, performing the given callback in the given scope
+     * when a message for the given channel arrives.
+     * @param channel the channel the listener is interested to
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to call when a message is sent to the channel
+     * @returns the subscription handle to be passed to {@link #removeListener(object)}
+     * @see #removeListener(subscription)
+     */
+    this.addListener = function(channel, scope, callback)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+
+        return _addListener(channel, scope, callback, true);
+    };
+
+    /**
+     * Removes the subscription obtained with a call to {@link #addListener(string, object, function)}.
+     * @param subscription the subscription to unsubscribe.
+     * @see #addListener(channel, scope, callback)
+     */
+    this.removeListener = function(subscription)
+    {
+        if (!org.cometd.Utils.isArray(subscription))
+        {
+            throw 'Invalid argument: expected subscription, not ' + subscription;
+        }
+
+        _removeListener(subscription);
+    };
+
+    /**
+     * Removes all listeners registered with {@link #addListener(channel, scope, callback)} or
+     * {@link #subscribe(channel, scope, callback)}.
+     */
+    this.clearListeners = function()
+    {
+        _listeners = {};
+    };
+
+    /**
+     * Subscribes to the given channel, performing the given callback in the given scope
+     * when a message for the channel arrives.
+     * @param channel the channel to subscribe to
+     * @param scope the scope of the callback, may be omitted
+     * @param callback the callback to call when a message is sent to the channel
+     * @param subscribeProps an object to be merged with the subscribe message
+     * @return the subscription handle to be passed to {@link #unsubscribe(object)}
+     */
+    this.subscribe = function(channel, scope, callback, subscribeProps)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        // Normalize arguments
+        if (_isFunction(scope))
+        {
+            subscribeProps = callback;
+            callback = scope;
+            scope = undefined;
+        }
+
+        // Only send the message to the server if this client has not yet subscribed to the channel
+        var send = !_hasSubscriptions(channel);
+
+        var subscription = _addListener(channel, scope, callback, false);
+
+        if (send)
+        {
+            // Send the subscription message after the subscription registration to avoid
+            // races where the server would send a message to the subscribers, but here
+            // on the client the subscription has not been added yet to the data structures
+            var bayeuxMessage = {
+                channel: '/meta/subscribe',
+                subscription: channel
+            };
+            var message = this._mixin(false, {}, subscribeProps, bayeuxMessage);
+            _queueSend(message);
+        }
+
+        return subscription;
+    };
+
+    /**
+     * Unsubscribes the subscription obtained with a call to {@link #subscribe(string, object, function)}.
+     * @param subscription the subscription to unsubscribe.
+     */
+    this.unsubscribe = function(subscription, unsubscribeProps)
+    {
+        if (arguments.length < 1)
+        {
+            throw 'Illegal arguments number: required 1, got ' + arguments.length;
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        // Remove the local listener before sending the message
+        // This ensures that if the server fails, this client does not get notifications
+        this.removeListener(subscription);
+
+        var channel = subscription[0];
+        // Only send the message to the server if this client unsubscribes the last subscription
+        if (!_hasSubscriptions(channel))
+        {
+            var bayeuxMessage = {
+                channel: '/meta/unsubscribe',
+                subscription: channel
+            };
+            var message = this._mixin(false, {}, unsubscribeProps, bayeuxMessage);
+            _queueSend(message);
+        }
+    };
+
+    /**
+     * Removes all subscriptions added via {@link #subscribe(channel, scope, callback, subscribeProps)},
+     * but does not remove the listeners added via {@link addListener(channel, scope, callback)}.
+     */
+    this.clearSubscriptions = function()
+    {
+        _clearSubscriptions();
+    };
+
+    /**
+     * Publishes a message on the given channel, containing the given content.
+     * @param channel the channel to publish the message to
+     * @param content the content of the message
+     * @param publishProps an object to be merged with the publish message
+     */
+    this.publish = function(channel, content, publishProps, publishCallback)
+    {
+        if (arguments.length < 1)
+        {
+            throw 'Illegal arguments number: required 1, got ' + arguments.length;
+        }
+        if (!_isString(channel))
+        {
+            throw 'Illegal argument type: channel must be a string';
+        }
+        if (_isDisconnected())
+        {
+            throw 'Illegal state: already disconnected';
+        }
+
+        if (_isFunction(content))
+        {
+            publishCallback = content;
+            content = publishProps = {};
+        }
+        else if (_isFunction(publishProps))
+        {
+            publishCallback = publishProps;
+            publishProps = {};
+        }
+
+        var bayeuxMessage = {
+            channel: channel,
+            data: content,
+            _callback: publishCallback
+        };
+        var message = this._mixin(false, {}, publishProps, bayeuxMessage);
+        _queueSend(message);
+    };
+
+    /**
+     * Returns a string representing the status of the bayeux communication with the Bayeux server.
+     */
+    this.getStatus = function()
+    {
+        return _status;
+    };
+
+    /**
+     * Returns whether this instance has been disconnected.
+     */
+    this.isDisconnected = _isDisconnected;
+
+    /**
+     * Sets the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
+     * Default value is 1 second, which means if there is a persistent failure the retries will happen
+     * after 1 second, then after 2 seconds, then after 3 seconds, etc. So for example with 15 seconds of
+     * elapsed time, there will be 5 retries (at 1, 3, 6, 10 and 15 seconds elapsed).
+     * @param period the backoff period to set
+     * @see #getBackoffIncrement()
+     */
+    this.setBackoffIncrement = function(period)
+    {
+        _config.backoffIncrement = period;
+    };
+
+    /**
+     * Returns the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
+     * @see #setBackoffIncrement(period)
+     */
+    this.getBackoffIncrement = function()
+    {
+        return _config.backoffIncrement;
+    };
+
+    /**
+     * Returns the backoff period to wait before retrying an unsuccessful or failed message.
+     */
+    this.getBackoffPeriod = function()
+    {
+        return _backoff;
+    };
+
+    /**
+     * Sets the log level for console logging.
+     * Valid values are the strings 'error', 'warn', 'info' and 'debug', from
+     * less verbose to more verbose.
+     * @param level the log level string
+     */
+    this.setLogLevel = function(level)
+    {
+        _config.logLevel = level;
+    };
+
+    /**
+     * Registers an extension whose callbacks are called for every incoming message
+     * (that comes from the server to this client implementation) and for every
+     * outgoing message (that originates from this client implementation for the
+     * server).
+     * The format of the extension object is the following:
+     * <pre>
+     * {
+     *     incoming: function(message) { ... },
+     *     outgoing: function(message) { ... }
+     * }
+     * </pre>
+     * Both properties are optional, but if they are present they will be called
+     * respectively for each incoming message and for each outgoing message.
+     * @param name the name of the extension
+     * @param extension the extension to register
+     * @return true if the extension was registered, false otherwise
+     * @see #unregisterExtension(name)
+     */
+    this.registerExtension = function(name, extension)
+    {
+        if (arguments.length < 2)
+        {
+            throw 'Illegal arguments number: required 2, got ' + arguments.length;
+        }
+        if (!_isString(name))
+        {
+            throw 'Illegal argument type: extension name must be a string';
+        }
+
+        var existing = false;
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var existingExtension = _extensions[i];
+            if (existingExtension.name === name)
+            {
+                existing = true;
+                break;
+            }
+        }
+        if (!existing)
+        {
+            _extensions.push({
+                name: name,
+                extension: extension
+            });
+            this._debug('Registered extension', name);
+
+            // Callback for extensions
+            if (_isFunction(extension.registered))
+            {
+                extension.registered(name, this);
+            }
+
+            return true;
+        }
+        else
+        {
+            this._info('Could not register extension with name', name, 'since another extension with the same name already exists');
+            return false;
+        }
+    };
+
+    /**
+     * Unregister an extension previously registered with
+     * {@link #registerExtension(name, extension)}.
+     * @param name the name of the extension to unregister.
+     * @return true if the extension was unregistered, false otherwise
+     */
+    this.unregisterExtension = function(name)
+    {
+        if (!_isString(name))
+        {
+            throw 'Illegal argument type: extension name must be a string';
+        }
+
+        var unregistered = false;
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var extension = _extensions[i];
+            if (extension.name === name)
+            {
+                _extensions.splice(i, 1);
+                unregistered = true;
+                this._debug('Unregistered extension', name);
+
+                // Callback for extensions
+                var ext = extension.extension;
+                if (_isFunction(ext.unregistered))
+                {
+                    ext.unregistered();
+                }
+
+                break;
+            }
+        }
+        return unregistered;
+    };
+
+    /**
+     * Find the extension registered with the given name.
+     * @param name the name of the extension to find
+     * @return the extension found or null if no extension with the given name has been registered
+     */
+    this.getExtension = function(name)
+    {
+        for (var i = 0; i < _extensions.length; ++i)
+        {
+            var extension = _extensions[i];
+            if (extension.name === name)
+            {
+                return extension.extension;
+            }
+        }
+        return null;
+    };
+
+    /**
+     * Returns the name assigned to this Cometd object, or the string 'default'
+     * if no name has been explicitly passed as parameter to the constructor.
+     */
+    this.getName = function()
+    {
+        return _name;
+    };
+
+    /**
+     * Returns the clientId assigned by the Bayeux server during handshake.
+     */
+    this.getClientId = function()
+    {
+        return _clientId;
+    };
+
+    /**
+     * Returns the URL of the Bayeux server.
+     */
+    this.getURL = function()
+    {
+        return _config.url;
+    };
+
+    this.getTransport = function()
+    {
+        return _transport;
+    };
+
+    this.getConfiguration = function()
+    {
+        return this._mixin(true, {}, _config);
+    };
+
+    this.getAdvice = function()
+    {
+        return this._mixin(true, {}, _advice);
+    };
+
+    // WebSocket handling for Firefox, which deploys WebSocket
+    // under the name of MozWebSocket in Firefox 6, 7, 8 and 9
+    org.cometd.WebSocket = window.WebSocket;
+    if (!org.cometd.WebSocket)
+    {
+        org.cometd.WebSocket = window.MozWebSocket;
+    }
+};
+
+if (typeof define === 'function' && define.amd)
+{
+    define(function()
+    {
+        return org.cometd;
+    });
+}
+
diff --git a/src/main/webapp/lib/org/cometd/AckExtension.js b/src/main/webapp/lib/org/cometd/AckExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..3b547a67ca45410eb46036691a8aa495941f121e
--- /dev/null
+++ b/src/main/webapp/lib/org/cometd/AckExtension.js
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * This client-side extension enables the client to acknowledge to the server
+         * the messages that the client has received.
+         * For the acknowledgement to work, the server must be configured with the
+         * correspondent server-side ack extension. If both client and server support
+         * the ack extension, then the ack functionality will take place automatically.
+         * By enabling this extension, all messages arriving from the server will arrive
+         * via the long poll, so the comet communication will be slightly chattier.
+         * The fact that all messages will return via long poll means also that the
+         * messages will arrive with total order, which is not guaranteed if messages
+         * can arrive via both long poll and normal response.
+         * Messages are not acknowledged one by one, but instead a group of messages is
+         * acknowledged when long poll returns.
+         */
+        return org_cometd.AckExtension = function()
+        {
+            var _cometd;
+            var _serverSupportsAcks = false;
+            var _ackId = -1;
+
+            function _debug(text, args)
+            {
+                _cometd._debug(text, args);
+            }
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _debug('AckExtension: executing registration callback');
+            };
+
+            this.unregistered = function()
+            {
+                _debug('AckExtension: executing unregistration callback');
+                _cometd = null;
+            };
+
+            this.incoming = function(message)
+            {
+                var channel = message.channel;
+                if (channel == '/meta/handshake')
+                {
+                    _serverSupportsAcks = message.ext && message.ext.ack;
+                    _debug('AckExtension: server supports acks', _serverSupportsAcks);
+                }
+                else if (_serverSupportsAcks && channel == '/meta/connect' && message.successful)
+                {
+                    var ext = message.ext;
+                    if (ext && typeof ext.ack === 'number')
+                    {
+                        _ackId = ext.ack;
+                        _debug('AckExtension: server sent ack id', _ackId);
+                    }
+                }
+                return message;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+                if (channel == '/meta/handshake')
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.ack = _cometd && _cometd.ackEnabled !== false;
+                    _ackId = -1;
+                }
+                else if (_serverSupportsAcks && channel == '/meta/connect')
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.ack = _ackId;
+                    _debug('AckExtension: client sending ack id', _ackId);
+                }
+                return message;
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/org/cometd/ReloadExtension.js b/src/main/webapp/lib/org/cometd/ReloadExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef6de781554f6a9067666b85e2d32966871068eb
--- /dev/null
+++ b/src/main/webapp/lib/org/cometd/ReloadExtension.js
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        if (!org_cometd.COOKIE)
+        {
+            org_cometd.COOKIE = {};
+            org_cometd.COOKIE.set = function(name, value, options)
+            {
+                throw 'Abstract';
+            };
+            org_cometd.COOKIE.get = function(name)
+            {
+                throw 'Abstract';
+            };
+        }
+
+        /**
+         * The reload extension allows a page to be loaded (or reloaded)
+         * without having to re-handshake in the new (or reloaded) page,
+         * therefore resuming the existing cometd connection.
+         *
+         * When the reload() method is called, the state of the cometd
+         * connection and of the cometd subscriptions is stored in a cookie
+         * with a short max-age.
+         * The reload() method must therefore be called by page unload
+         * handlers, often provided by JavaScript toolkits.
+         *
+         * When the page is (re)loaded, this extension checks the cookie
+         * and restores the cometd connection and the cometd subscriptions.
+         */
+        return org_cometd.ReloadExtension = function(configuration)
+        {
+            var _cometd;
+            var _debug;
+            var _state = null;
+            var _cookieName = 'org.cometd.reload';
+            var _cookiePath = '/';
+            var _cookieMaxAge = 5;
+            var _batch = false;
+
+            function _reload(config)
+            {
+                if (_state && _state.handshakeResponse !== null)
+                {
+                    _configure(config);
+                    _state.cookiePath = _cookiePath;
+                    var cookie = org_cometd.JSON.toJSON(_state);
+                    _debug('Reload extension saving cookie value', cookie);
+                    org_cometd.COOKIE.set(_cookieName, cookie, {
+                        'max-age': _cookieMaxAge,
+                        path: _cookiePath,
+                        expires: new Date(new Date().getTime() + _cookieMaxAge * 1000)
+                    });
+                }
+            }
+
+            function _similarState(oldState)
+            {
+                // We want to check here that the CometD object
+                // did not change much between reloads.
+                // We just check the URL for now, but in future
+                // further checks may involve the transport type
+                // and other configuration parameters.
+                return _state.url == oldState.url;
+            }
+
+            function _configure(config)
+            {
+                if (config)
+                {
+                    if (typeof config.cookieMaxAge === 'number')
+                    {
+                        _cookieMaxAge = config.cookieMaxAge;
+                    }
+                    if (typeof config.cookieName === 'string')
+                    {
+                        _cookieName = config.cookieName;
+                    }
+                    if (typeof config.cookiePath === 'string')
+                    {
+                        _cookiePath = config.cookiePath;
+                    }
+                }
+            }
+
+            this.configure = _configure;
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _cometd.reload = _reload;
+                _debug = _cometd._debug;
+            };
+
+            this.unregistered = function()
+            {
+                delete _cometd.reload;
+                _cometd = null;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+
+                if (channel == '/meta/handshake')
+                {
+                    _state = {};
+                    _state.url = _cometd.getURL();
+
+                    var cookie = org_cometd.COOKIE.get(_cookieName);
+                    _debug('Reload extension found cookie value', cookie);
+                    // Is there a saved handshake response from a prior load ?
+                    if (cookie)
+                    {
+                        try
+                        {
+                            var oldState = org_cometd.JSON.fromJSON(cookie);
+
+                            // Remove the cookie, not needed anymore
+                            org_cometd.COOKIE.set(_cookieName, '', {
+                                'max-age': -1,
+                                path: oldState.cookiePath,
+                                expires: -1
+                            });
+
+                            if (oldState.handshakeResponse && _similarState(oldState))
+                            {
+                                _debug('Reload extension restoring state', oldState);
+                                setTimeout(function()
+                                {
+                                    _debug('Reload extension replaying handshake response', oldState.handshakeResponse);
+                                    _state.handshakeResponse = oldState.handshakeResponse;
+                                    _state.transportType = oldState.transportType;
+                                    _state.reloading = true;
+                                    var response = _cometd._mixin(true, {}, _state.handshakeResponse, {ext: {reload: true}});
+                                    response.supportedConnectionTypes = [_state.transportType];
+                                    _cometd.receive(response);
+                                    _debug('Reload extension replayed handshake response', response);
+                                }, 0);
+
+                                // delay any sends until first connect is complete.
+                                if (!_batch)
+                                {
+                                    _batch = true;
+                                    _cometd.startBatch();
+                                }
+                                // This handshake is aborted, as we will replay the prior handshake response
+                                return null;
+                            }
+                            else
+                            {
+                                _debug('Reload extension could not restore state', oldState);
+                            }
+                        }
+                        catch(x)
+                        {
+                            _debug('Reload extension error while trying to restore cookie', x);
+                        }
+                    }
+                }
+                else if (channel == '/meta/connect')
+                {
+                    if (!_state.transportType)
+                    {
+                        _state.transportType = message.connectionType;
+                        _debug('Reload extension tracked transport type', _state.transportType);
+                    }
+                }
+                return message;
+            };
+
+            this.incoming = function(message)
+            {
+                if (message.successful)
+                {
+                    switch (message.channel)
+                    {
+                        case '/meta/handshake':
+                            // If the handshake response is already present, then we're replaying it.
+                            // Since the replay may have modified the handshake response, do not record it here.
+                            if (!_state.handshakeResponse)
+                            {
+                                // Save successful handshake response
+                                _state.handshakeResponse = message;
+                                _debug('Reload extension tracked handshake response', message);
+                            }
+                            break;
+                        case '/meta/disconnect':
+                            _state = null;
+                            break;
+                        case '/meta/connect':
+                            if (_batch)
+                            {
+                                _cometd.endBatch();
+                                _batch = false;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                return message;
+            };
+
+            _configure(configuration);
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/org/cometd/TimeStampExtension.js b/src/main/webapp/lib/org/cometd/TimeStampExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..8011a3a68e54ed9dae65583400421637a649cabf
--- /dev/null
+++ b/src/main/webapp/lib/org/cometd/TimeStampExtension.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * The timestamp extension adds the optional timestamp field to all outgoing messages.
+         */
+        return org_cometd.TimeStampExtension = function()
+        {
+            this.outgoing = function(message)
+            {
+                message.timestamp = new Date().toUTCString();
+                return message;
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+}());
diff --git a/src/main/webapp/lib/org/cometd/TimeSyncExtension.js b/src/main/webapp/lib/org/cometd/TimeSyncExtension.js
new file mode 100644
index 0000000000000000000000000000000000000000..506329830f9d486ceeb38a90b7054bfbf28d1dc3
--- /dev/null
+++ b/src/main/webapp/lib/org/cometd/TimeSyncExtension.js
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function()
+{
+    function bind(org_cometd)
+    {
+        /**
+         * With each handshake or connect, the extension sends timestamps within the
+         * ext field like: <code>{ext:{timesync:{tc:12345567890,l:23,o:4567},...},...}</code>
+         * where:<ul>
+         *  <li>tc is the client timestamp in ms since 1970 of when the message was sent.
+         *  <li>l is the network lag that the client has calculated.
+         *  <li>o is the clock offset that the client has calculated.
+         * </ul>
+         *
+         * <p>
+         * A cometd server that supports timesync, can respond with an ext
+         * field like: <code>{ext:{timesync:{tc:12345567890,ts:1234567900,p:123,a:3},...},...}</code>
+         * where:<ul>
+         *  <li>tc is the client timestamp of when the message was sent,
+         *  <li>ts is the server timestamp of when the message was received
+         *  <li>p is the poll duration in ms - ie the time the server took before sending the response.
+         *  <li>a is the measured accuracy of the calculated offset and lag sent by the client
+         * </ul>
+         *
+         * <p>
+         * The relationship between tc, ts & l is given by <code>ts=tc+o+l</code> (the
+         * time the server received the messsage is the client time plus the offset plus the
+         * network lag).   Thus the accuracy of the o and l settings can be determined with
+         * <code>a=(tc+o+l)-ts</code>.
+         * </p>
+         * <p>
+         * When the client has received the response, it can make a more accurate estimate
+         * of the lag as <code>l2=(now-tc-p)/2</code> (assuming symmetric lag).
+         * A new offset can then be calculated with the relationship on the client
+         * that <code>ts=tc+o2+l2</code>, thus <code>o2=ts-tc-l2</code>.
+         * </p>
+         * <p>
+         * Since the client also receives the a value calculated on the server, it
+         * should be possible to analyse this and compensate for some asymmetry
+         * in the lag. But the current client does not do this.
+         * </p>
+         *
+         * @param configuration
+         */
+        return org_cometd.TimeSyncExtension = function(configuration)
+        {
+            var _cometd;
+            var _maxSamples = configuration && configuration.maxSamples || 10;
+            var _lags = [];
+            var _offsets = [];
+            var _lag = 0;
+            var _offset = 0;
+
+            function _debug(text, args)
+            {
+                _cometd._debug(text, args);
+            }
+
+            this.registered = function(name, cometd)
+            {
+                _cometd = cometd;
+                _debug('TimeSyncExtension: executing registration callback');
+            };
+
+            this.unregistered = function()
+            {
+                _debug('TimeSyncExtension: executing unregistration callback');
+                _cometd = null;
+                _lags = [];
+                _offsets = [];
+            };
+
+            this.incoming = function(message)
+            {
+                var channel = message.channel;
+                if (channel && channel.indexOf('/meta/') === 0)
+                {
+                    if (message.ext && message.ext.timesync)
+                    {
+                        var timesync = message.ext.timesync;
+                        _debug('TimeSyncExtension: server sent timesync', timesync);
+
+                        var now = new Date().getTime();
+                        var l2 = (now - timesync.tc - timesync.p) / 2;
+                        var o2 = timesync.ts - timesync.tc - l2;
+
+                        _lags.push(l2);
+                        _offsets.push(o2);
+                        if (_offsets.length > _maxSamples)
+                        {
+                            _offsets.shift();
+                            _lags.shift();
+                        }
+
+                        var samples = _offsets.length;
+                        var lagsSum = 0;
+                        var offsetsSum = 0;
+                        for (var i = 0; i < samples; ++i)
+                        {
+                            lagsSum += _lags[i];
+                            offsetsSum += _offsets[i];
+                        }
+                        _lag = parseInt((lagsSum / samples).toFixed());
+                        _offset = parseInt((offsetsSum / samples).toFixed());
+                        _debug('TimeSyncExtension: network lag', _lag, 'ms, time offset with server', _offset, 'ms', _lag, _offset);
+                    }
+                }
+                return message;
+            };
+
+            this.outgoing = function(message)
+            {
+                var channel = message.channel;
+                if (channel && channel.indexOf('/meta/') === 0)
+                {
+                    if (!message.ext)
+                    {
+                        message.ext = {};
+                    }
+                    message.ext.timesync = {
+                        tc: new Date().getTime(),
+                        l: _lag,
+                        o: _offset
+                    };
+                    _debug('TimeSyncExtension: client sending timesync', org_cometd.JSON.toJSON(message.ext.timesync));
+                }
+                return message;
+            };
+
+            /**
+             * Get the estimated offset in ms from the clients clock to the
+             * servers clock.  The server time is the client time plus the offset.
+             */
+            this.getTimeOffset = function()
+            {
+                return _offset;
+            };
+
+            /**
+             * Get an array of multiple offset samples used to calculate
+             * the offset.
+             */
+            this.getTimeOffsetSamples = function()
+            {
+                return _offsets;
+            };
+
+            /**
+             * Get the estimated network lag in ms from the client to the server.
+             */
+            this.getNetworkLag = function()
+            {
+                return _lag;
+            };
+
+            /**
+             * Get the estimated server time in ms since the epoch.
+             */
+            this.getServerTime = function()
+            {
+                return new Date().getTime() + _offset;
+            };
+
+            /**
+             *
+             * Get the estimated server time as a Date object
+             */
+            this.getServerDate = function()
+            {
+                return new Date(this.getServerTime());
+            };
+
+            /**
+             * Set a timeout to expire at given time on the server.
+             * @param callback The function to call when the timer expires
+             * @param atServerTimeOrDate a js Time or Date object representing the
+             * server time at which the timeout should expire
+             */
+            this.setTimeout = function(callback, atServerTimeOrDate)
+            {
+                var ts = (atServerTimeOrDate instanceof Date) ? atServerTimeOrDate.getTime() : (0 + atServerTimeOrDate);
+                var tc = ts - _offset;
+                var interval = tc - new Date().getTime();
+                if (interval <= 0)
+                {
+                    interval = 1;
+                }
+                return org_cometd.Utils.setTimeout(_cometd, callback, interval);
+            };
+        };
+    }
+
+    if (typeof define === 'function' && define.amd)
+    {
+        define(['org/cometd'], bind);
+    }
+    else
+    {
+        bind(org.cometd);
+    }
+})();
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG102005.js b/src/main/webapp/lib/proj4js/defs/EPSG102005.js
new file mode 100755
index 0000000000000000000000000000000000000000..da707ba735ca1846c24dfee8bb2c943253ebecab
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG102005.js
@@ -0,0 +1,13 @@
+//
+//# USA Contiguous Equidistant Conic
+//<102005> +proj=eqdc +lat_0=0 +lon_0=0 +lat_1=33 +lat_2=45 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m 
+
+Proj4js.defs["EPSG:102005"] = "\
+  +title=USA Contiguous Equidistant Conic\
+  +proj=eqdc\
+  +lat_0=0 +lon_0=0 +lat_1=33 +lat_2=45 +x_0=0 +y_0=0   \
+  +lon_0=-90 +x_0=600000.0000000001 +y_0=0 \
+  +ellps=GRS80 +datum=NAD83 +units=m \
+  ";
+
+
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG102028.js b/src/main/webapp/lib/proj4js/defs/EPSG102028.js
new file mode 100755
index 0000000000000000000000000000000000000000..d6ea743b9b8e57c01c82c8b12d6f3675fe5af1a9
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG102028.js
@@ -0,0 +1,11 @@
+//# Asia South Albers Equal Area Conic
+//<102028> +proj=aea +lat_1=7 +lat_2=-32 +lat_0=-15 +lon_0=125 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m  no_defs <>
+
+Proj4js.defs["EPSG:102028"] = "\
+  +title=Asia South Albers Equal Area Conic EPSG:102028\
+  +proj=aea \
+ +lat_1=7 +lat_2=-32 +lat_0=-15 +lon_0=125 \
+  +x_0=0 +y_0=0 \
+  +ellps=WGS84 +datum=WGS84\
+  +units=m\
+";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG102582.js b/src/main/webapp/lib/proj4js/defs/EPSG102582.js
new file mode 100755
index 0000000000000000000000000000000000000000..61c469386747dba66105db882f2278af930d577b
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG102582.js
@@ -0,0 +1,5 @@
+/*# NTF France II degrees
+<102582> +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=2.337229166666667 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356514.999904194 +units=m  no_defs <>
+*/
+Proj4js.defs["EPSG:102582"] = "+title=NTF France II degrees EPSG:102582\
+	 +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=2.337229166666667 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356514.999904194 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG102757.js b/src/main/webapp/lib/proj4js/defs/EPSG102757.js
new file mode 100755
index 0000000000000000000000000000000000000000..4bb822b556a7e635a5f7b579e1edf90128fed892
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG102757.js
@@ -0,0 +1,6 @@
+Proj4js.defs["EPSG:102757"] = "+title=NAD 1983 StatePlane Wyoming West Central FIPS 4903 Feet\
+  +proj=tmerc \
+  +lat_0=40.5 +lon_0=-108.75 \
+  +x_0=600000.0 +y_0=0 +k=0.999938 \
+  +a=6378137.0  +b=6356752.3141403\
+  +to_meter=0.3048006096012192";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG102758.js b/src/main/webapp/lib/proj4js/defs/EPSG102758.js
new file mode 100755
index 0000000000000000000000000000000000000000..1fa49dfbbd501cbfc230c2227543f0c78b6fd36a
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG102758.js
@@ -0,0 +1,7 @@
+Proj4js.defs["EPSG:102758"] = "+title=NAD 1983 StatePlane Wyoming West FIPS 4904 Feet\
+  +proj=tmerc \
+  +proj=tmerc \
+  +lat_0=40.5 +lon_0=-108.75 \
+  +x_0=600000.0 +y_0=0 +k=0.999938 \
+  +a=6378137.0  +b=6356752.3141403\
+  +to_meter=0.3048006096012192";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG22195.js b/src/main/webapp/lib/proj4js/defs/EPSG22195.js
new file mode 100755
index 0000000000000000000000000000000000000000..1174e6000cd4ff6941905af2c86b9053252c2623
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG22195.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:22195"]= "+title=Campo Inchauspe / Argentina 5 epsg:22195 +proj=tmerc +lat_0=-90 +lon_0=-60 +k=1.000000 +x_0=5500000 +y_0=0 +ellps=intl +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG258320.js b/src/main/webapp/lib/proj4js/defs/EPSG258320.js
new file mode 100755
index 0000000000000000000000000000000000000000..86d3f6d259052511bf59aa491132f2f053c00a4d
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG258320.js
@@ -0,0 +1,43 @@
+/*
+ * This is the projection format used in the province Bozen/Bolzano /South-Tyrol/Italy.
+ * The format is very similar to EPSG:25832
+ * 
+ *  
+ **  Human-Readable OGC WKT **
+ PROJCS["ETRF_1989_UTM_Zone_32N",
+  GEOGCS["GCS_ETRF_1989",
+   DATUM["D_ETRF_1989",
+    SPHEROID["WGS_1984",6378137.0,298.257223563]
+   ],
+   PRIMEM["Greenwich",0.0],
+   UNIT["Degree",0.0174532925199433]
+  ],
+  PROJECTION["Transverse_Mercator"],
+  PARAMETER["False_Easting",500000.0],
+  PARAMETER["False_Northing",0.0],
+  PARAMETER["Central_Meridian",9.0],
+  PARAMETER["Scale_Factor",0.9996],
+  PARAMETER["Latitude_Of_Origin",0.0],
+  UNIT["Meter",1.0]
+ ]
+ *
+ ** Postgis insert statement
+ INSERT into spatial_ref_sys (srid, auth_name, auth_srid, proj4text, srtext) values ( 9258320, 'spatialreference.org', 258320, '+proj=utm +zone=32 +ellps=WGS84 +lat_0=0 +lon_0=21.45233333333333 +k=0.999600 +x_0=500000.0 +y_0=0 +pm=greenwich +units=m', 'PROJCS["ETRF_1989_UTM_Zone_32N",GEOGCS["GCS_ETRF_1989",DATUM["D_ETRF_1989",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]');
+ *
+ ** Proj4js format **
+ */
+Proj4js.defs["EPSG:258320"] = "\
+  +title=ETRF_1989_UTM_Zone_32N\
+  +proj=utm\
+  +zone=32\
+	+ellps=WGS84\
+	+lat_0=0\
+	+lon_0=21.45233333333333\
+	+k=0.999600\
+	+x_0=500000.0\
+	+y_0=0\
+	+pm=greenwich\
+	+units=m\
+ ";
+ 
+ //+title=ETRF_1989_UTM_Zone_32N +proj=utm +zone=32 +ellps=WGS84 +lat_0=0 +lon_0=21.45233333333333 +k=0.999600 +x_0=500000.0 +y_0=0 +pm=greenwich +units=m +towgs84=-104.1,-49.1,-9.9,-0.971,-2.917,0.714,-11.68 +no_defs
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG26591.js b/src/main/webapp/lib/proj4js/defs/EPSG26591.js
new file mode 100755
index 0000000000000000000000000000000000000000..a45c92ad21ef9c2e810945f2d7c73fe1ddaa57c0
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG26591.js
@@ -0,0 +1,6 @@
+Proj4js.defs["EPSG:26591"] = "+title= Monte Mario (Rome) / Italy zone 1 EPSG:26591\
++proj=tmerc\
++lat_0=0 +lon_0=-3.45233333333333 +from_greenwich=12.45233333333333\
++k=0.999600 +x_0=1500000 +y_0=0\
++a=6378388.0, +b=6356911.94612795\
++units=m";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG26912.js b/src/main/webapp/lib/proj4js/defs/EPSG26912.js
new file mode 100755
index 0000000000000000000000000000000000000000..ee8473c82c8381ea060b0943ab90b6c7d17428f7
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG26912.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG26912"] = "+title=NAD83 / UTM zone 12N +proj=utm +zone=12 +a=6378137.0 +b=6356752.3141403";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG26986.js b/src/main/webapp/lib/proj4js/defs/EPSG26986.js
new file mode 100755
index 0000000000000000000000000000000000000000..2d848021bfc818cebdac3c3c4d406709b7a8de01
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG26986.js
@@ -0,0 +1,14 @@
+//# NAD83 / Massachusetts Mainland, United States (USA) - Massachusetts - SPCS - mainland 
+
+//+proj=lcc +lat_1=42.68333333333333 +lat_2=41.71666666666667 +lat_0=41 +lon_0=-71.5 +x_0=200000 +y_0=750000 +ellps=GRS80 +datum=NAD83 +units=m +no_defs  <>
+
+
+Proj4js.defs["EPSG:26986"]= "\
+  +title=NAD 1983 StatePlane Wyoming West Central FIPS 4903 Feet\
+  +proj=lcc \
+  +lat_1=42.68333333333333 +lat_2=41.71666666666667 +lat_0=41 +lon_0=-71.5 \
+  +x_0=200000 +y_0=750000 \
+  +ellps=GRS80  \
+  +units=m +no_defs \
+";
+
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG27563.js b/src/main/webapp/lib/proj4js/defs/EPSG27563.js
new file mode 100755
index 0000000000000000000000000000000000000000..46abe8dbc301e36dcce9e318a309fd219ee1976d
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG27563.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:27563"]="+title=LAMB sud france  +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=2.33722917 +k_0=0.999877499 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG27582.js b/src/main/webapp/lib/proj4js/defs/EPSG27582.js
new file mode 100755
index 0000000000000000000000000000000000000000..da3fa9c42b97c07880ff64a6b419a29a446ae070
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG27582.js
@@ -0,0 +1,16 @@
+//
+//# USA Contiguous Equidistant Conic
+//<102005> +proj=eqdc +lat_0=0 +lon_0=0 +lat_1=33 +lat_2=45 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m 
+
+Proj4js.defs["EPSG:27582"] = "+proj=lcc \
+ +lat_1=46.8  \
+ +lat_0=46.8  +lon_0=0  \
+ +k_0=0.99987742  \
+ +x_0=600000  +y_0=2200000  \
+ +a=6378249.2  +b=6356515  \
+ +towgs84=-168,-60,320,0,0,0,0  \
+ +pm=paris  \
+ +units=m +no_defs  \
+  ";
+
+
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG27700.js b/src/main/webapp/lib/proj4js/defs/EPSG27700.js
new file mode 100755
index 0000000000000000000000000000000000000000..c8cdafbae2d368a3ed4fdc237cb9e7e82601570c
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG27700.js
@@ -0,0 +1,4 @@
+//# OSGB 1936 / British National Grid
+//<27700> +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.999601 +x_0=400000 +y_0=-100000 +ellps=airy +units=m +no_defs  no_defs <>
+Proj4js.defs["EPSG:27700"] = "+title=OSGB 1936 / British National Grid / EPSG:27700\
++proj=tmerc +lat_0=49 +lon_0=-2 +k=0.999601 +x_0=400000 +y_0=-100000 +ellps=airy +units=m ";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG28992.js b/src/main/webapp/lib/proj4js/defs/EPSG28992.js
new file mode 100755
index 0000000000000000000000000000000000000000..c72ce7c171a5eca788239bf421a203864db05804
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG28992.js
@@ -0,0 +1,3 @@
+//# Amersfoort / RD New
+//<28992> +proj=stere +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.999908 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +no_defs  no_defs <>
+Proj4js.defs["EPSG:28992"] = "+title=Amersfoort / RD New EPSG:28992 +proj=stere +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.999908 +x_0=155000 +y_0=463000 +ellps=bessel +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31281.js b/src/main/webapp/lib/proj4js/defs/EPSG31281.js
new file mode 100755
index 0000000000000000000000000000000000000000..1854c9fa8a071c821c1408949e788992d95c919a
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31281.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31281"] = "+title=MGI (Ferro) / Austria West Zone EPSG:31281 +proj=tmerc +lat_0=0 +lon_0=28 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31282.js b/src/main/webapp/lib/proj4js/defs/EPSG31282.js
new file mode 100755
index 0000000000000000000000000000000000000000..f7dce17465455d95b061ca48bcc0ffd51bc346bb
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31282.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31282"] = "+title=MGI (Ferro) / Austria Central Zone EPSG:31282 +proj=tmerc +lat_0=0 +lon_0=31 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31283.js b/src/main/webapp/lib/proj4js/defs/EPSG31283.js
new file mode 100755
index 0000000000000000000000000000000000000000..c6346bd9790419bf850ba0d53849264a9e371b60
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31283.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31283"] = "+title=MGI (Ferro) / Austria East Zone EPSG:31283 +proj=tmerc +lat_0=0 +lon_0=34 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31284.js b/src/main/webapp/lib/proj4js/defs/EPSG31284.js
new file mode 100755
index 0000000000000000000000000000000000000000..432d2ed73f3f57aa6a83c2c42b485f641d0bda3d
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31284.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31284"] = "+title=MGI / M31 EPSG:31284 +proj=tmerc +lat_0=0 +lon_0=10.33333333333333 +k=1.000000 +x_0=150000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31285.js b/src/main/webapp/lib/proj4js/defs/EPSG31285.js
new file mode 100755
index 0000000000000000000000000000000000000000..5130093347f6e16e32c4847d5d01adf1dfcff835
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31285.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31285"] = "+title=MGI / M31 EPSG:31285 +proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1.000000 +x_0=450000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31286.js b/src/main/webapp/lib/proj4js/defs/EPSG31286.js
new file mode 100755
index 0000000000000000000000000000000000000000..a65fa7f2bb1f1f30ec268fccda7475d0dc7703bd
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31286.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31286"] = "+title=MGI / M34 EPSG:31286 +proj=tmerc +lat_0=0 +lon_0=16.33333333333333 +k=1.000000 +x_0=750000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31287.js b/src/main/webapp/lib/proj4js/defs/EPSG31287.js
new file mode 100755
index 0000000000000000000000000000000000000000..46f11a279cde4063213fe9cfaeb3a8650757f813
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31287.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31287"] = "+title=MGI / Austria Lambert EPSG:31287 +proj=lcc +lat_1=49 +lat_2=46 +lat_0=47.5 +lon_0=13.33333333333333 +x_0=400000 +y_0=400000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31291.js b/src/main/webapp/lib/proj4js/defs/EPSG31291.js
new file mode 100755
index 0000000000000000000000000000000000000000..4a358f8d08018202197faad717e774a0de9dc9ad
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31291.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31291"] = "+title=MGI (Ferro) / Austria West Zone EPSG:31291 +proj=tmerc +lat_0=0 +lon_0=28 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31292.js b/src/main/webapp/lib/proj4js/defs/EPSG31292.js
new file mode 100755
index 0000000000000000000000000000000000000000..5adb7e08f83416a8bd861aac0d9f473a98683c91
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31292.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31292"] = "+title=MGI (Ferro) / Austria Central Zone EPSG:31292 +proj=tmerc +lat_0=0 +lon_0=31 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31293.js b/src/main/webapp/lib/proj4js/defs/EPSG31293.js
new file mode 100755
index 0000000000000000000000000000000000000000..55dadc310e6e2f5544af671004ec4ba6bccc72f3
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31293.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:31293"] = "+title=MGI (Ferro) / Austria East Zone EPSG:31293 +proj=tmerc +lat_0=0 +lon_0=34 +k=1.000000 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31294.js b/src/main/webapp/lib/proj4js/defs/EPSG31294.js
new file mode 100755
index 0000000000000000000000000000000000000000..c0d7ca94ff7d96e3d45900872a07cf991698df17
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31294.js
@@ -0,0 +1,3 @@
+//# MGI / M28
+//<31294> +proj=tmerc +lat_0=0 +lon_0=10.33333333333333 +k=1.000000 +x_0=150000 +y_0=0 +ellps=bessel +units=m +no_defs  <>
+Proj4js.defs["EPSG:31294"] = "+title=MGI / M31 EPSG:31294 +proj=tmerc +lat_0=0 +lon_0=10.33333333333333 +k=1.000000 +x_0=150000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31295.js b/src/main/webapp/lib/proj4js/defs/EPSG31295.js
new file mode 100755
index 0000000000000000000000000000000000000000..553d426a440ff254bc35fe8c0614883ce60b3207
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31295.js
@@ -0,0 +1,3 @@
+//# MGI / M31
+//<31295> +proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1.000000 +x_0=450000 +y_0=0 +ellps=bessel +units=m +no_defs  <>
+Proj4js.defs["EPSG:31295"] = "+title=MGI / M31 EPSG:31295 +proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1.000000 +x_0=450000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31296.js b/src/main/webapp/lib/proj4js/defs/EPSG31296.js
new file mode 100755
index 0000000000000000000000000000000000000000..42a801b03fa65865e942986a815bb5bbaa3a1cd0
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31296.js
@@ -0,0 +1,3 @@
+//# MGI / M34
+//<31296> +proj=tmerc +lat_0=0 +lon_0=16.33333333333333 +k=1.000000 +x_0=750000 +y_0=0 +ellps=bessel +units=m +no_defs  <>
+Proj4js.defs["EPSG:31296"] = "+title=MGI / M34 EPSG:31296 +proj=tmerc +lat_0=0 +lon_0=16.33333333333333 +k=1.000000 +x_0=750000 +y_0=0 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG31297.js b/src/main/webapp/lib/proj4js/defs/EPSG31297.js
new file mode 100755
index 0000000000000000000000000000000000000000..c7d23d5fdbe9f8021e957f93b05633208f4f4174
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG31297.js
@@ -0,0 +1,3 @@
+//# MGI / Austria Lambert
+//<31297> +proj=lcc +lat_1=49 +lat_2=46 +lat_0=47.5 +lon_0=13.33333333333333 +x_0=400000 +y_0=400000 +ellps=bessel +units=m +no_defs  <>
+Proj4js.defs["EPSG:31297"] = "+title=MGI / Austria Lambert EPSG:31297 +proj=lcc +lat_1=49 +lat_2=46 +lat_0=47.5 +lon_0=13.33333333333333 +x_0=400000 +y_0=400000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32611.js b/src/main/webapp/lib/proj4js/defs/EPSG32611.js
new file mode 100755
index 0000000000000000000000000000000000000000..cbe0408ddd9a9e9530146d6af84ce9ac89252daa
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32611.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32611"] = "+title=WGS 84 / UTM zone 11N epsg:32611 +proj=utm +zone=11 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32612.js b/src/main/webapp/lib/proj4js/defs/EPSG32612.js
new file mode 100755
index 0000000000000000000000000000000000000000..b7cd926beb0286dbadba9b909e1919edc5b68a68
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32612.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32612"] = "+title=WGS 84 / UTM zone 12N epsg:32612 +proj=utm +zone=12 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32613.js b/src/main/webapp/lib/proj4js/defs/EPSG32613.js
new file mode 100755
index 0000000000000000000000000000000000000000..b54e7259bfbb3b068b96b74293dcd1a7bcd8ff82
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32613.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32613"] = "+title=WGS 84 / UTM zone 13N epsg:32613 +proj=utm +zone=13 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32614.js b/src/main/webapp/lib/proj4js/defs/EPSG32614.js
new file mode 100755
index 0000000000000000000000000000000000000000..74c6d11d7dd8c2c2e79255444cd4af54e6b996b4
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32614.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32614"] = "+title=WGS 84 / UTM zone 14N epsg:32614 +proj=utm +zone=14 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32615.js b/src/main/webapp/lib/proj4js/defs/EPSG32615.js
new file mode 100755
index 0000000000000000000000000000000000000000..89f468d517da32914e260236b5e0ee6d133ef6ec
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32615.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32615"] = "+title=WGS 84 / UTM zone 15N epsg:32615 +proj=utm +zone=15 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32616.js b/src/main/webapp/lib/proj4js/defs/EPSG32616.js
new file mode 100755
index 0000000000000000000000000000000000000000..16a7796a1c3b1d91ae8c7af3410d99957221f4d5
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32616.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32616"] = "+title=WGS 84 / UTM zone 16N epsg:32616 +proj=utm +zone=16 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32620.js b/src/main/webapp/lib/proj4js/defs/EPSG32620.js
new file mode 100755
index 0000000000000000000000000000000000000000..ab210d053fe7001def8cbdf9df6f535ee3e9f32a
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32620.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32620"] = "+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32622.js b/src/main/webapp/lib/proj4js/defs/EPSG32622.js
new file mode 100755
index 0000000000000000000000000000000000000000..e8d55fc1f4ae991d0c9e68464ea7a36e4feebd3c
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32622.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32622"] = "+proj=utm +zone=22 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32705.js b/src/main/webapp/lib/proj4js/defs/EPSG32705.js
new file mode 100755
index 0000000000000000000000000000000000000000..dcb63f82ed2629f8cfbca75cdb5a5b6571fbb7e5
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32705.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32705"] = "+proj=utm +zone=5 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32706.js b/src/main/webapp/lib/proj4js/defs/EPSG32706.js
new file mode 100755
index 0000000000000000000000000000000000000000..00314e9231643d9e34b2aff74bc09fb575078b69
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32706.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32706"] = "+proj=utm +zone=6 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32738.js b/src/main/webapp/lib/proj4js/defs/EPSG32738.js
new file mode 100755
index 0000000000000000000000000000000000000000..71a782f9ee251106bedc966b76cde730868c7fdd
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32738.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32738"] = "+proj=utm +zone=38 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32740.js b/src/main/webapp/lib/proj4js/defs/EPSG32740.js
new file mode 100755
index 0000000000000000000000000000000000000000..360ac6469df3792ec97c367a768e58418965b103
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32740.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32740"] = "+proj=utm +zone=40 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG32758.js b/src/main/webapp/lib/proj4js/defs/EPSG32758.js
new file mode 100755
index 0000000000000000000000000000000000000000..cde7e9a399613f805d62262e806cdfd461994b2b
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG32758.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:32758"] = "+proj=utm +zone=58 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG41001.js b/src/main/webapp/lib/proj4js/defs/EPSG41001.js
new file mode 100755
index 0000000000000000000000000000000000000000..9e8e682541ae31968995ffefa01ef8f9e5cc19e3
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG41001.js
@@ -0,0 +1,2 @@
+Proj4js.defs["EPSG:41001"] = "+title=simple mercator EPSG:41001\
+  +proj=merc +lat_ts=0 +lon_0=0 +k=1.000000 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG4139.js b/src/main/webapp/lib/proj4js/defs/EPSG4139.js
new file mode 100755
index 0000000000000000000000000000000000000000..236736334686872731af9313d4df7659ccf02bfa
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG4139.js
@@ -0,0 +1,4 @@
+Proj4js.defs["EPSG:4139"] = "+title=Puerto Rico EPSG:4139 (3 param datum shift)\
+  +proj=longlat \
+  +towgs84 = 11,72,-101,0,0,0,0 \
+  +a=6378206.4 +b=6356583.8";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG4181.js b/src/main/webapp/lib/proj4js/defs/EPSG4181.js
new file mode 100755
index 0000000000000000000000000000000000000000..3b22d7c3bcbe30c890dfd8a234784b712bf36528
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG4181.js
@@ -0,0 +1,4 @@
+Proj4js.defs["EPSG:4181"] = "+title=Luxembourg 1930 EPSG:4181 (7 param datum shift)\
+  +proj=longlat \
+  +towgs84=-193,13.7,-39.3,-0.41,-2.933,2.688,0.43 \
+  +a=6378388.0, +b=6356911.94612795";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG42101.js b/src/main/webapp/lib/proj4js/defs/EPSG42101.js
new file mode 100755
index 0000000000000000000000000000000000000000..541d346152b2d8aa512df1cd4b997f358daf76a2
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG42101.js
@@ -0,0 +1,5 @@
+//## WGS84 / LCC Canada
+//<42101> +proj=lcc +ellps=WGS84 +lat_0=0 +lon_0=-95 +lat_1=49 +lat_2=77 +x_0=0 +y_0=-8000000.0 +datum=WGS84 +units=m no_defs <>
+Proj4js.defs["EPSG:42101"]= "+title=WGS84 / LCC Canada EPSG:42101\
+  +proj=lcc +ellps=WGS84 +lat_0=0 +lon_0=-95 +lat_1=49 +lat_2=77 +x_0=0 +y_0=-8000000.0 +datum=WGS84 +units=m\
+ ";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG42304.js b/src/main/webapp/lib/proj4js/defs/EPSG42304.js
new file mode 100755
index 0000000000000000000000000000000000000000..70768cf533e541caa8f55984927ecd5aaf97add5
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG42304.js
@@ -0,0 +1 @@
+Proj4js.defs["EPSG:42304"]="+proj=lcc +lat_1=49 +lat_2=77 +lat_0=49 +lon_0=-95 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs";
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG4302.js b/src/main/webapp/lib/proj4js/defs/EPSG4302.js
new file mode 100755
index 0000000000000000000000000000000000000000..e60fc3a7343802f5eceb7b6a61b5a14f44af2864
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG4302.js
@@ -0,0 +1,3 @@
+Proj4js.defs["EPSG:4302"] = "+title=Trinidad 1903 EPSG:4302 (7 param datum shift)\
+  +proj=longlat +a=6378293.63683822 +b=6356617.979337744 +towgs84=-61.702,284.488,472.052,0,0,0,0";
+  
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG54008.js b/src/main/webapp/lib/proj4js/defs/EPSG54008.js
new file mode 100755
index 0000000000000000000000000000000000000000..c7341926fad5d740486268f06ef55eefad693b03
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG54008.js
@@ -0,0 +1,9 @@
+// World Sinusoidal
+//<54008> +proj=sinu +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m  no_defs <>
+
+Proj4js.defs["EPSG:54008"]= "\
+  +title= World Sinusoïdal EPSG:54008\
+  +proj=sinu \
+  +lon_0=0 +x_0=0 +y_0=0 \
+  +ellps=WGS84 +datum=WGS84 +units=m \
+";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG54021.js b/src/main/webapp/lib/proj4js/defs/EPSG54021.js
new file mode 100755
index 0000000000000000000000000000000000000000..6158f5e28c13db0928454789b34134def86f91a2
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG54021.js
@@ -0,0 +1,7 @@
+//<54021> +proj=poly +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m 
+Proj4js.defs["EPSG:54021"]= "\
+  +title= World polyconic EPSG:54021\
+  +proj=poly \
+  +lon_0=0 +x_0=0 +y_0=0 \
+  +ellps=WGS84 +datum=WGS84 +units=m \
+";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG54029.js b/src/main/webapp/lib/proj4js/defs/EPSG54029.js
new file mode 100755
index 0000000000000000000000000000000000000000..a1c41572ce6c7e364668b8fae11def8bce511113
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG54029.js
@@ -0,0 +1,9 @@
+//# World Van der Grinten I
+//<54029> +proj=vandg +lon_0=0 +x_0=0 +y_0=0 +R_A +ellps=WGS84 +datum=WGS84 +units=m  no_defs <>
+
+Proj4js.defs["EPSG:54029"]= "\
+  +title= World  Van der Grinten I EPSG:54029\
+  +proj=vandg \
+  +lon_0=0 +x_0=0 +y_0=0 +R_A  \
+  +ellps=WGS84 +datum=WGS84 +units=m \
+";
diff --git a/src/main/webapp/lib/proj4js/defs/EPSG900913.js b/src/main/webapp/lib/proj4js/defs/EPSG900913.js
new file mode 100755
index 0000000000000000000000000000000000000000..809f50eae02b26051316854fe609771a29dde80c
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/EPSG900913.js
@@ -0,0 +1,11 @@
+// Google Mercator projection
+// Used in combination with GoogleMercator layer type in OpenLayers
+//+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs
+
+Proj4js.defs["EPSG:900913"]= "\
+  +title= Google Mercator EPSG:900913\
+  +proj=merc +a=6378137 +b=6378137 \
+  +lat_ts=0.0 +lon_0=0.0 \
+  +x_0=0.0 +y_0=0 +k=1.0 \
+  +units=m +nadgrids=@null +no_defs \
+";
diff --git a/src/main/webapp/lib/proj4js/defs/GOOGLE.js b/src/main/webapp/lib/proj4js/defs/GOOGLE.js
new file mode 100755
index 0000000000000000000000000000000000000000..5f926b7a77395e76e9eb83fcfd0a69f6fb78c339
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/defs/GOOGLE.js
@@ -0,0 +1,2 @@
+Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs";
+Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];
\ No newline at end of file
diff --git a/src/main/webapp/lib/proj4js/proj4js-combined.js b/src/main/webapp/lib/proj4js/proj4js-combined.js
new file mode 100755
index 0000000000000000000000000000000000000000..ad34dd5ea3dcbd2506b2f925db807dc021848181
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/proj4js-combined.js
@@ -0,0 +1,3714 @@
+/*
+  proj4js.js -- Javascript reprojection library. 
+  
+  Author:       Mike Adair madairATdmsolutions.ca
+                Richard Greenwood rich@greenwoodmap.com
+  License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html 
+                Note: This program is an almost direct port of the C library
+                Proj4.
+*/
+/* ======================================================================
+    proj4js.js
+   ====================================================================== */
+
+/*
+Author:       Mike Adair madairATdmsolutions.ca
+              Richard Greenwood rich@greenwoodmap.com
+License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
+              Note: This program is an almost direct port of the C library Proj4.
+$Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
+*/
+
+/**
+ * Provides methods for coordinate transformations between map projections and 
+ * longitude/latitude, including datum transformations.
+ * 
+ * Initialization of Proj objects is with a projection code, usually EPSG codes.
+ * The code passed in will be stripped of colons (':') and converted to uppercase
+ * for internal use.
+ * If you know what map projections your application will be dealing with, the
+ * definition for the projections can be included with the script tag when the 
+ * application is being coded.  Otherwise, practically any projection definition
+ * can be loaded dynamically at run-time with an AJAX request to a lookup service
+ * such as spatialreference.org.
+ * The actual code supporting the forward and inverse tansformations for each
+ * projection class is loaded dynamically at run-time.  These may also be 
+ * specified when the application is coded if the projections to be used are known
+ * beforehand.
+ * A projection object has properties for units and title strings.
+ * All coordinates are handled as points which is a 2 element array where x is
+ * the first element and y is the second.
+ * For the transform() method pass in mapXY and a destination projection object
+ * and it returns a map XY coordinate in the other projection
+ */
+
+/**
+ * Global namespace object for Proj4js library to use
+ */
+Proj4js = {
+
+    /**
+     * Property: defaultDatum
+     * The datum to use when no others a specified
+     */
+    defaultDatum: 'WGS84',                  //default datum
+
+    /**
+     * Property: proxyScript
+     * A proxy script to execute AJAX requests in other domains. 
+     */
+    proxyScript: null,  //TBD: customize this for spatialreference.org output
+
+    /**
+     * Property: defsLookupService
+     * AJAX service to retreive projection definition parameters from
+     */
+    defsLookupService: 'http://spatialreference.org/ref',
+
+    /**
+     * Property: libPath
+     * internal: http server path to library code.
+     * TBD figure this out automatically
+     */
+    libPath: '../lib/',
+
+    /** 
+    * Method: transform(source, dest, point)
+    * Transform a point coordinate from one map projection to another.
+    *
+    * Parameters:
+    * source - {Proj4js.Proj} source map projection for the transformation
+    * dest - {Proj4js.Proj} destination map projection for the transformation
+    * point - {Object} point to transform, may be geodetic (long, lat) or
+    *     projected Cartesian (x,y), but should always have x,y properties.
+    */
+    transform : function(source, dest, point) {
+        if (!source.readyToUse || !dest.readyToUse) {
+            this.reportError("Proj4js initialization for "+source.srsCode+" not yet complete");
+            return;
+        }
+        
+        if (point.transformed) {
+          this.log("point already transformed");
+          return;
+        }
+        
+        // Workaround for Spherical Mercator
+        if ((source.srsProjNumber =="900913" && dest.datumCode != "WGS84") ||
+            (dest.srsProjNumber == "900913" && source.datumCode != "WGS84")) {
+            var wgs84 = Proj4js.WGS84;
+            this.transform(source, wgs84, point);
+            point.transformed = false;
+            source = wgs84;
+        }
+
+        // Transform source points to long/lat, if they aren't already.
+        if ( source.projName=="longlat") {
+            point.x *= Proj4js.common.D2R;  // convert degrees to radians
+            point.y *= Proj4js.common.D2R;
+        } else {
+            if (source.to_meter) {
+                point.x *= source.to_meter;
+                point.y *= source.to_meter;
+            }
+            source.inverse(point); // Convert Cartesian to longlat
+        }
+
+        // Adjust for the prime meridian if necessary
+        if (source.from_greenwich) { 
+            point.x += source.from_greenwich; 
+        }
+
+        // Convert datums if needed, and if possible.
+        point = this.datum_transform( source.datum, dest.datum, point );
+
+        // Adjust for the prime meridian if necessary
+        if (dest.from_greenwich) { 
+            point.x -= dest.from_greenwich; 
+        }
+
+        if( dest.projName=="longlat" ) {             
+            // convert radians to decimal degrees
+            point.x *= Proj4js.common.R2D;
+            point.y *= Proj4js.common.R2D;
+        } else  {               // else project
+            dest.forward(point);
+            if (dest.to_meter) {
+                point.x /= dest.to_meter;
+                point.y /= dest.to_meter;
+            }
+        }
+        point.transformed = true;
+        return point;
+    }, // transform()
+
+    /** datum_transform()
+      source coordinate system definition,
+      destination coordinate system definition,
+      point to transform in geodetic coordinates (long, lat, height)
+    */
+    datum_transform : function( source, dest, point ) {
+
+      // Short cut if the datums are identical.
+      if( source.compare_datums( dest ) ) {
+          return point; // in this case, zero is sucess,
+                    // whereas cs_compare_datums returns 1 to indicate TRUE
+                    // confusing, should fix this
+      }
+      
+      // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
+      if( source.datum_type == Proj4js.common.PJD_NODATUM  
+          || dest.datum_type == Proj4js.common.PJD_NODATUM) {
+          return point; 
+      }
+      
+        // If this datum requires grid shifts, then apply it to geodetic coordinates.
+        if( source.datum_type == Proj4js.common.PJD_GRIDSHIFT )
+        {
+          alert("ERROR: Grid shift transformations are not implemented yet.");
+          /*
+            pj_apply_gridshift( pj_param(source.params,"snadgrids").s, 0,
+                                point_count, point_offset, x, y, z );
+            CHECK_RETURN;
+
+            src_a = SRS_WGS84_SEMIMAJOR;
+            src_es = 0.006694379990;
+          */
+        }
+
+        if( dest.datum_type == Proj4js.common.PJD_GRIDSHIFT )
+        {
+          alert("ERROR: Grid shift transformations are not implemented yet.");
+          /*
+            dst_a = ;
+            dst_es = 0.006694379990;
+          */
+        }
+
+        // Do we need to go through geocentric coordinates?
+        if( source.es != dest.es || source.a != dest.a 
+            || source.datum_type == Proj4js.common.PJD_3PARAM 
+            || source.datum_type == Proj4js.common.PJD_7PARAM
+            || dest.datum_type == Proj4js.common.PJD_3PARAM
+            || dest.datum_type == Proj4js.common.PJD_7PARAM)
+        {
+
+          // Convert to geocentric coordinates.
+          source.geodetic_to_geocentric( point );
+          // CHECK_RETURN;
+
+          // Convert between datums
+          if( source.datum_type == Proj4js.common.PJD_3PARAM || source.datum_type == Proj4js.common.PJD_7PARAM ) {
+            source.geocentric_to_wgs84(point);
+            // CHECK_RETURN;
+          }
+
+          if( dest.datum_type == Proj4js.common.PJD_3PARAM || dest.datum_type == Proj4js.common.PJD_7PARAM ) {
+            dest.geocentric_from_wgs84(point);
+            // CHECK_RETURN;
+          }
+
+          // Convert back to geodetic coordinates
+          dest.geocentric_to_geodetic( point );
+            // CHECK_RETURN;
+        }
+
+      // Apply grid shift to destination if required
+      if( dest.datum_type == Proj4js.common.PJD_GRIDSHIFT )
+      {
+        alert("ERROR: Grid shift transformations are not implemented yet.");
+        // pj_apply_gridshift( pj_param(dest.params,"snadgrids").s, 1, point);
+        // CHECK_RETURN;
+      }
+      return point;
+    }, // cs_datum_transform
+
+    /**
+     * Function: reportError
+     * An internal method to report errors back to user. Should be overridden
+     * by applications to deliver error messages.
+     */
+    reportError: function(msg) {
+    },
+
+    /**
+     * Function: log
+     * An internal method to log events. 
+     */
+    log: function(msg) {
+    },
+
+    loadProjDefinition : function(proj) {
+
+      //check in memory
+      if (this.defs[proj.srsCode]) return this.defs[proj.srsCode];
+
+      //set AJAX options
+      var options = {
+        method: 'get',
+        asynchronous: false,          //need to wait until defs are loaded before proceeding
+        onSuccess: this.defsLoadedFromDisk.bind(this,proj.srsCode)
+      }
+      
+      //else check for def on the server
+      var url = this.libPath + 'defs/' + proj.srsAuth.toUpperCase() + proj.srsProjNumber + '.js';
+      new OpenLayers.Ajax.Request(url, options);
+      if ( this.defs[proj.srsCode] ) return this.defs[proj.srsCode];
+
+      //else load from web service via AJAX request
+      if (this.proxyScript) {
+        var url = this.proxyScript + this.defsLookupService +'/' + proj.srsAuth +'/'+ proj.srsProjNumber + '/proj4';
+        options.onSuccess = this.defsLoadedFromService.bind(this,proj.srsCode)
+        options.onFailure = this.defsFailed.bind(this,proj.srsCode);
+        new OpenLayers.Ajax.Request(url, options);
+      }
+      
+      //may return null here if the defs are not found
+      return this.defs[proj.srsCode];
+    },
+
+    defsLoadedFromDisk: function(srsCode, transport) {
+      eval(transport.responseText);
+    },
+
+    defsLoadedFromService: function(srsCode, transport) {
+      this.defs[srsCode] = transport.responseText;
+      // save this also in the prototype, so we don't need to fetch it again
+      Proj4js.defs[srsCode] = transport.responseText;
+    },
+
+    defsFailed: function(srsCode) {
+      this.reportError('failed to load projection definition for: '+srsCode);
+      OpenLayers.Util.extend(this.defs[srsCode], this.defs['WGS84']);  //set it to something so it can at least continue
+    },
+
+    loadProjCode : function(projName) {
+      if (this.Proj[projName]) return;
+
+      //set AJAX options
+      var options = {
+        method: 'get',
+        asynchronous: false,          //need to wait until defs are loaded before proceeding
+        onSuccess: this.loadProjCodeSuccess.bind(this, projName),
+        onFailure: this.loadProjCodeFailure.bind(this, projName)
+      };
+      
+      //load the projection class 
+      var url = this.libPath + 'projCode/' + projName + '.js';
+      new OpenLayers.Ajax.Request(url, options);
+    },
+
+    loadProjCodeSuccess : function(projName, transport) {
+      eval(transport.responseText);
+      if (this.Proj[projName].dependsOn){
+        this.loadProjCode(this.Proj[projName].dependsOn);
+      }
+    },
+
+    loadProjCodeFailure : function(projName) {
+      Proj4js.reportError("failed to find projection file for: " + projName);
+      //TBD initialize with identity transforms so proj will still work
+    }
+
+};
+
+/**
+ * Class: Proj4js.Proj
+ * Projection objects provide coordinate transformation methods for point coordinates
+ * once they have been initialized with a projection code.
+ */
+Proj4js.Proj = OpenLayers.Class({
+
+  /**
+   * Property: readyToUse
+   * Flag to indicate if initialization is complete for this Proj object
+   */
+  readyToUse : false,   
+  
+  /**
+   * Property: title
+   * The title to describe the projection
+   */
+  title: null,  
+  
+  /**
+   * Property: projName
+   * The projection class for this projection, e.g. lcc (lambert conformal conic,
+   * or merc for mercator.  These are exactly equicvalent to their Proj4 
+   * counterparts.
+   */
+  projName: null,
+  /**
+   * Property: units
+   * The units of the projection.  Values include 'm' and 'degrees'
+   */
+  units: null,
+  /**
+   * Property: datum
+   * The datum specified for the projection
+   */
+  datum: null,
+
+  /**
+   * Constructor: initialize
+   * Constructor for Proj4js.Proj objects
+  *
+  * Parameters:
+  * srsCode - a code for map projection definition parameters.  These are usually
+  * (but not always) EPSG codes.
+  */
+  initialize : function(srsCode) {
+      this.srsCode = srsCode.toUpperCase();
+      if (this.srsCode.indexOf("EPSG") == 0) {
+          this.srsCode = this.srsCode;
+          this.srsAuth = 'epsg';
+          this.srsProjNumber = this.srsCode.substring(5);
+      } else {
+          this.srsAuth = '';
+          this.srsProjNumber = this.srsCode;
+      }
+
+      var defs = Proj4js.loadProjDefinition(this);
+      if (defs) {
+          this.parseDefs(defs);
+          Proj4js.loadProjCode(this.projName);
+          this.callInit();
+      }
+
+  },
+
+  callInit : function() {
+      Proj4js.log('projection script loaded for:' + this.projName);
+      OpenLayers.Util.extend(this, Proj4js.Proj[this.projName]);
+      this.init();
+      this.mapXYToLonLat = this.inverse;
+      this.lonLatToMapXY = this.forward;
+      this.readyToUse = true;
+  },
+
+  parseDefs : function(proj4opts) {
+      this.defData = proj4opts;
+      var paramName, paramVal;
+      var paramArray=this.defData.split("+");
+
+      for (var prop=0; prop<paramArray.length; prop++) {
+          var property = paramArray[prop].split("=");
+          paramName = property[0].toLowerCase();
+          paramVal = property[1];
+
+          switch (paramName.replace(/\s/gi,"")) {  // trim out spaces
+              case "": break;   // throw away nameless parameter
+              case "title":  this.title = paramVal; break;
+              case "proj":   this.projName =  paramVal.replace(/\s/gi,""); break;
+              case "units":  this.units = paramVal.replace(/\s/gi,""); break;
+              case "datum":  this.datumCode = paramVal.replace(/\s/gi,""); break;
+              case "nadgrids": this.nagrids = paramVal.replace(/\s/gi,""); break;
+              case "ellps":  this.ellps = paramVal.replace(/\s/gi,""); break;
+              case "a":      this.a =  parseFloat(paramVal); break;  // semi-major radius
+              case "b":      this.b =  parseFloat(paramVal); break;  // semi-minor radius
+              case "lat_0":  this.lat0 = paramVal*Proj4js.common.D2R; break;        // phi0, central latitude
+              case "lat_1":  this.lat1 = paramVal*Proj4js.common.D2R; break;        //standard parallel 1
+              case "lat_2":  this.lat2 = paramVal*Proj4js.common.D2R; break;        //standard parallel 2
+              case "lat_ts": this.lat_ts = paramVal*Proj4js.common.D2R; break;      //used in merc 
+              case "lon_0":  this.long0 = paramVal*Proj4js.common.D2R; break;       // lam0, central longitude
+              case "x_0":    this.x0 = parseFloat(paramVal); break;  // false easting
+              case "y_0":    this.y0 = parseFloat(paramVal); break;  // false northing
+              case "k_0":    this.k0 = parseFloat(paramVal); break;  // projection scale factor
+              case "k":      this.k0 = parseFloat(paramVal); break;  // both forms returned
+              case "R_A":    this.R = parseFloat(paramVal); break;   //Spheroid radius 
+              case "zone":   this.zone = parseInt(paramVal); break;  // UTM Zone
+              case "south":   this.utmSouth = true; break;  // UTM north/south
+              case "towgs84":this.datum_params = paramVal.split(","); break;
+              case "to_meter": this.to_meter = parseFloat(paramVal); break; // cartesian scaling
+              case "from_greenwich": this.from_greenwich = paramVal*Proj4js.common.D2R; break;
+              case "pm":     paramVal = paramVal.replace(/\s/gi,"");
+                             this.from_greenwich = Proj4js.PrimeMeridian[paramVal] ?
+                                Proj4js.PrimeMeridian[paramVal]*Proj4js.common.D2R : 0.0; break;
+              case "no_defs": break; 
+              default: Proj4js.log("Unrecognized parameter: " + paramName);
+          } // switch()
+      } // for paramArray
+      this.deriveConstants();
+  },
+
+  deriveConstants : function() {
+      if (this.nagrids == '@null') this.datumCode = 'none';
+      if (this.datumCode && this.datumCode != 'none') {
+        var datumDef = Proj4js.Datum[this.datumCode];
+        if (datumDef) {
+          this.datum_params = datumDef.towgs84.split(',');
+          this.ellps = datumDef.ellipse;
+          this.datumName = datumDef.datumName;
+        }
+      }
+      if (!this.a) {    // do we have an ellipsoid?
+          var ellipse = Proj4js.Ellipsoid[this.ellps] ? Proj4js.Ellipsoid[this.ellps] : Proj4js.Ellipsoid['WGS84'];
+          OpenLayers.Util.extend(this, ellipse);
+      }
+      if (this.rf && !this.b) this.b = (1.0 - 1.0/this.rf) * this.a;
+      if (Math.abs(this.a - this.b)<Proj4js.common.EPSLN) this.sphere = true;
+      this.a2 = this.a * this.a;          // used in geocentric
+      this.b2 = this.b * this.b;          // used in geocentric
+      this.es = (this.a2-this.b2)/this.a2;  // e ^ 2
+      //this.es=1-(Math.pow(this.b,2)/Math.pow(this.a,2));
+      this.e = Math.sqrt(this.es);        // eccentricity
+      this.ep2=(this.a2-this.b2)/this.b2; // used in geocentric
+      if (!this.k0) this.k0 = 1.0;    //default value
+
+      this.datum = new Proj4js.datum(this);
+  }
+});
+
+Proj4js.Proj.longlat = {
+  init : function() {
+    //no-op for longlat
+  },
+  forward : function(pt) {
+    //identity transform
+    return pt;
+  },
+  inverse : function(pt) {
+    //identity transform
+    return pt;
+  }
+};
+
+/**
+  Proj4js.defs is a collection of coordinate system definition objects in the 
+  Proj4 command line format.
+  Generally a def is added by means of a separate .js file for example:
+
+    <SCRIPT type="text/javascript" src="defs/EPSG26912.js"></SCRIPT>
+
+  def is a CS definition in PROJ.4 WKT format, for example:
+    +proj="tmerc"   //longlat, etc.
+    +a=majorRadius
+    +b=minorRadius
+    +lat0=somenumber
+    +long=somenumber
+*/
+Proj4js.defs = {
+  // These are so widely used, we'll go ahead and throw them in
+  // without requiring a separate .js file
+  'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84",
+  'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84",
+  'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83" 
+};
+//+a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84",
+Proj4js.common = {
+  PI : Math.PI,
+  HALF_PI : Math.PI*0.5,
+  TWO_PI : Math.PI*2,
+  FORTPI : 0.78539816339744833,
+  R2D : 57.2957795131,
+  D2R : 0.0174532925199,
+  SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
+  EPSLN : 1.0e-10,
+  MAX_ITER : 20,
+  // following constants from geocent.c
+  COS_67P5 : 0.38268343236508977,  /* cosine of 67.5 degrees */
+  AD_C : 1.0026000,                /* Toms region 1 constant */
+
+  /* datum_type values */
+  PJD_UNKNOWN  : 0,
+  PJD_3PARAM   : 1,
+  PJD_7PARAM   : 2,
+  PJD_GRIDSHIFT: 3,
+  PJD_WGS84    : 4,   // WGS84 or equivalent
+  PJD_NODATUM  : 5,   // WGS84 or equivalent
+  SRS_WGS84_SEMIMAJOR : 6378137.0,  // only used in grid shift transforms
+
+// Function to compute the constant small m which is the radius of
+//   a parallel of latitude, phi, divided by the semimajor axis.
+// -----------------------------------------------------------------
+  msfnz : function(eccent, sinphi, cosphi) {
+      var con = eccent * sinphi;
+      return cosphi/(Math.sqrt(1.0 - con * con));
+  },
+
+// Function to compute the constant small t for use in the forward
+//   computations in the Lambert Conformal Conic and the Polar
+//   Stereographic projections.
+// -----------------------------------------------------------------
+  tsfnz : function(eccent, phi, sinphi) {
+    var con = eccent * sinphi;
+    var com = .5 * eccent;
+    con = Math.pow(((1.0 - con) / (1.0 + con)), com);
+    return (Math.tan(.5 * (this.HALF_PI - phi))/con);
+  },
+
+// Function to compute the latitude angle, phi2, for the inverse of the
+//   Lambert Conformal Conic and Polar Stereographic projections.
+// ----------------------------------------------------------------
+  phi2z : function(eccent, ts) {
+    var eccnth = .5 * eccent;
+    var con, dphi;
+    var phi = this.HALF_PI - 2 * Math.atan(ts);
+    for (i = 0; i <= 15; i++) {
+      con = eccent * Math.sin(phi);
+      dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
+      phi += dphi;
+      if (Math.abs(dphi) <= .0000000001) return phi;
+    }
+    alert("phi2z has NoConvergence");
+    return (-9999);
+  },
+
+/* Function to compute constant small q which is the radius of a 
+   parallel of latitude, phi, divided by the semimajor axis. 
+------------------------------------------------------------*/
+  qsfnz : function(eccent,sinphi,cosphi) {
+    var con;
+    if (eccent > 1.0e-7) {
+      con = eccent * sinphi;
+      return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
+    } else {
+      return(2.0 * sinphi);
+    }
+  },
+
+/* Function to eliminate roundoff errors in asin
+----------------------------------------------*/
+  asinz : function(x) {
+    if (Math.abs(x)>1.0) {
+      x=(x>1.0)?1.0:-1.0;
+    }
+    return Math.asin(x);
+  },
+
+// following functions from gctpc cproj.c for transverse mercator projections
+  e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
+  e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
+  e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
+  e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
+  mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},
+
+  srat : function(esinp, exp) {
+    return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
+  },
+
+// Function to return the sign of an argument
+  sign : function(x) { if (x < 0.0) return(-1); else return(1);},
+
+// Function to adjust longitude to -180 to 180; input in radians
+  adjust_lon : function(x) {
+    x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
+    return x;
+  }
+
+};
+
+/** datum object
+*/
+Proj4js.datum = OpenLayers.Class({
+
+  initialize : function(proj) {
+    this.datum_type = Proj4js.common.PJD_WGS84;   //default setting
+    if (proj.datumCode && proj.datumCode == 'none') {
+      this.datum_type = Proj4js.common.PJD_NODATUM;
+    }
+    if (proj && proj.datum_params) {
+      for (var i=0; i<proj.datum_params.length; i++) {
+        proj.datum_params[i]=parseFloat(proj.datum_params[i]);
+      }
+      if (proj.datum_params[0] != 0 || proj.datum_params[1] != 0 || proj.datum_params[2] != 0 ) {
+        this.datum_type = Proj4js.common.PJD_3PARAM;
+      }
+      if (proj.datum_params.length > 3) {
+        if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
+            proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
+          this.datum_type = Proj4js.common.PJD_7PARAM;
+          proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
+          proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
+          proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
+          proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
+        }
+      }
+    }
+    if (proj) {
+      this.a = proj.a;    //datum object also uses these values
+      this.b = proj.b;
+      this.es = proj.es;
+      this.ep2 = proj.ep2;
+      this.datum_params = proj.datum_params;
+    }
+  },
+
+  /****************************************************************/
+  // cs_compare_datums()
+  //   Returns 1 (TRUE) if the two datums match, otherwise 0 (FALSE).
+  compare_datums : function( dest ) {
+    if( this.datum_type != dest.datum_type ) {
+      return false; // false, datums are not equal
+    } else if (this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050) {
+      // the tolerence for es is to ensure that GRS80 and WGS84
+      // are considered identical
+      return false;
+    } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
+      return (this.datum_params[0] == dest.datum_params[0]
+              && this.datum_params[1] == dest.datum_params[1]
+              && this.datum_params[2] == dest.datum_params[2]);
+    } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
+      return (this.datum_params[0] == dest.datum_params[0]
+              && this.datum_params[1] == dest.datum_params[1]
+              && this.datum_params[2] == dest.datum_params[2]
+              && this.datum_params[3] == dest.datum_params[3]
+              && this.datum_params[4] == dest.datum_params[4]
+              && this.datum_params[5] == dest.datum_params[5]
+              && this.datum_params[6] == dest.datum_params[6]);
+    } else if( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
+      return strcmp( pj_param(this.params,"snadgrids").s,
+                     pj_param(dest.params,"snadgrids").s ) == 0;
+    } else {
+      return true; // datums are equal
+    }
+  }, // cs_compare_datums()
+
+  /*
+   * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
+   * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
+   * according to the current ellipsoid parameters.
+   *
+   *    Latitude  : Geodetic latitude in radians                     (input)
+   *    Longitude : Geodetic longitude in radians                    (input)
+   *    Height    : Geodetic height, in meters                       (input)
+   *    X         : Calculated Geocentric X coordinate, in meters    (output)
+   *    Y         : Calculated Geocentric Y coordinate, in meters    (output)
+   *    Z         : Calculated Geocentric Z coordinate, in meters    (output)
+   *
+   */
+  geodetic_to_geocentric : function(p) {
+    var Longitude = p.x;
+    var Latitude = p.y;
+    var Height = p.z ? p.z : 0;   //Z value not always supplied
+    var X;  // output
+    var Y;
+    var Z;
+
+    var Error_Code=0;  //  GEOCENT_NO_ERROR;
+    var Rn;            /*  Earth radius at location  */
+    var Sin_Lat;       /*  Math.sin(Latitude)  */
+    var Sin2_Lat;      /*  Square of Math.sin(Latitude)  */
+    var Cos_Lat;       /*  Math.cos(Latitude)  */
+
+    /*
+    ** Don't blow up if Latitude is just a little out of the value
+    ** range as it may just be a rounding issue.  Also removed longitude
+    ** test, it should be wrapped by Math.cos() and Math.sin().  NFW for PROJ.4, Sep/2001.
+    */
+    if (Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
+        Latitude = -Proj4js.common.HALF_PI;
+    } else if (Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
+        Latitude = Proj4js.common.HALF_PI;
+    } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
+      /* Latitude out of range */
+      Proj4js.reportError('geocent:lat out of range:'+Latitude);
+      return null;
+    }
+
+    if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
+    Sin_Lat = Math.sin(Latitude);
+    Cos_Lat = Math.cos(Latitude);
+    Sin2_Lat = Sin_Lat * Sin_Lat;
+    Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
+    X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
+    Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
+    Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
+
+    p.x = X;
+    p.y = Y;
+    p.z = Z;
+    return Error_Code;
+  }, // cs_geodetic_to_geocentric()
+
+  geocentric_to_geodetic : function (p) {
+/* local defintions and variables */
+/* end-criterium of loop, accuracy of sin(Latitude) */
+var genau = 1.E-12;
+var genau2 = (genau*genau);
+var maxiter = 30;
+
+    var P;        /* distance between semi-minor axis and location */
+    var RR;       /* distance between center and location */
+    var CT;       /* sin of geocentric latitude */
+    var ST;       /* cos of geocentric latitude */
+    var RX;
+    var RK;
+    var RN;       /* Earth radius at location */
+    var CPHI0;    /* cos of start or old geodetic latitude in iterations */
+    var SPHI0;    /* sin of start or old geodetic latitude in iterations */
+    var CPHI;     /* cos of searched geodetic latitude */
+    var SPHI;     /* sin of searched geodetic latitude */
+    var SDPHI;    /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
+    var At_Pole;     /* indicates location is in polar region */
+    var iter;        /* # of continous iteration, max. 30 is always enough (s.a.) */
+
+    var X =p.x;
+    var Y = p.y;
+    var Z = p.z ? p.z : 0.0;   //Z value not always supplied
+    var Longitude;
+    var Latitude;
+    var Height;
+    
+    At_Pole = false;
+    P = Math.sqrt(X*X+Y*Y);
+    RR = Math.sqrt(X*X+Y*Y+Z*Z);
+
+/*  special cases for latitude and longitude */
+    if (P/this.a < genau) {
+
+/*  special case, if P=0. (X=0., Y=0.) */
+        At_Pole = true;
+        Longitude = 0.0;
+
+/*  if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
+ *  of ellipsoid (=center of mass), Latitude becomes PI/2 */
+        if (RR/this.a < genau) {
+            Latitude = Proj4js.common.HALF_PI;
+            Height   = -this.b;
+            return;
+        }
+    } else {
+/*  ellipsoidal (geodetic) longitude
+ *  interval: -PI < Longitude <= +PI */
+        Longitude=Math.atan2(Y,X);
+    }
+
+/* --------------------------------------------------------------
+ * Following iterative algorithm was developped by
+ * "Institut für Erdmessung", University of Hannover, July 1988.
+ * Internet: www.ife.uni-hannover.de
+ * Iterative computation of CPHI,SPHI and Height.
+ * Iteration of CPHI and SPHI to 10**-12 radian resp.
+ * 2*10**-7 arcsec.
+ * --------------------------------------------------------------
+ */
+    CT = Z/RR;
+    ST = P/RR;
+    RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
+    CPHI0 = ST*(1.0-this.es)*RX;
+    SPHI0 = CT*RX;
+    iter = 0;
+
+/* loop to find sin(Latitude) resp. Latitude
+ * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
+    do
+    {
+        iter++;
+        RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
+
+/*  ellipsoidal (geodetic) height */
+        Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
+
+        RK = this.es*RN/(RN+Height);
+        RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
+        CPHI = ST*(1.0-RK)*RX;
+        SPHI = CT*RX;
+        SDPHI = SPHI*CPHI0-CPHI*SPHI0;
+        CPHI0 = CPHI;
+        SPHI0 = SPHI;
+    }
+    while (SDPHI*SDPHI > genau2 && iter < maxiter);
+
+/*  ellipsoidal (geodetic) latitude */
+    Latitude=Math.atan(SPHI/Math.abs(CPHI));
+
+    p.x = Longitude;
+    p.y =Latitude;
+    p.z = Height;
+    return p;
+  },
+
+  /** Convert_Geocentric_To_Geodetic
+   * The method used here is derived from 'An Improved Algorithm for
+   * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
+   */
+  geocentric_to_geodetic_noniter : function (p) {
+    var X =p.x;
+    var Y = p.y;
+    var Z = p.z ? p.z : 0;   //Z value not always supplied
+    var Longitude;
+    var Latitude;
+    var Height;
+
+    var W;        /* distance from Z axis */
+    var W2;       /* square of distance from Z axis */
+    var T0;       /* initial estimate of vertical component */
+    var T1;       /* corrected estimate of vertical component */
+    var S0;       /* initial estimate of horizontal component */
+    var S1;       /* corrected estimate of horizontal component */
+    var Sin_B0;   /* Math.sin(B0), B0 is estimate of Bowring aux variable */
+    var Sin3_B0;  /* cube of Math.sin(B0) */
+    var Cos_B0;   /* Math.cos(B0) */
+    var Sin_p1;   /* Math.sin(phi1), phi1 is estimated latitude */
+    var Cos_p1;   /* Math.cos(phi1) */
+    var Rn;       /* Earth radius at location */
+    var Sum;      /* numerator of Math.cos(phi1) */
+    var At_Pole;  /* indicates location is in polar region */
+
+    X = parseFloat(X);  // cast from string to float
+    Y = parseFloat(Y);
+    Z = parseFloat(Z);
+
+    At_Pole = false;
+    if (X != 0.0)
+    {
+        Longitude = Math.atan2(Y,X);
+    }
+    else
+    {
+        if (Y > 0)
+        {
+            Longitude = Proj4js.common.HALF_PI;
+        }
+        else if (Y < 0)
+        {
+            Longitude = -Proj4js.common.HALF_PI;
+        }
+        else
+        {
+            At_Pole = true;
+            Longitude = 0.0;
+            if (Z > 0.0)
+            {  /* north pole */
+                Latitude = Proj4js.common.HALF_PI;
+            }
+            else if (Z < 0.0)
+            {  /* south pole */
+                Latitude = -Proj4js.common.HALF_PI;
+            }
+            else
+            {  /* center of earth */
+                Latitude = Proj4js.common.HALF_PI;
+                Height = -this.b;
+                return;
+            }
+        }
+    }
+    W2 = X*X + Y*Y;
+    W = Math.sqrt(W2);
+    T0 = Z * Proj4js.common.AD_C;
+    S0 = Math.sqrt(T0 * T0 + W2);
+    Sin_B0 = T0 / S0;
+    Cos_B0 = W / S0;
+    Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
+    T1 = Z + this.b * this.ep2 * Sin3_B0;
+    Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
+    S1 = Math.sqrt(T1*T1 + Sum * Sum);
+    Sin_p1 = T1 / S1;
+    Cos_p1 = Sum / S1;
+    Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
+    if (Cos_p1 >= Proj4js.common.COS_67P5)
+    {
+        Height = W / Cos_p1 - Rn;
+    }
+    else if (Cos_p1 <= -Proj4js.common.COS_67P5)
+    {
+        Height = W / -Cos_p1 - Rn;
+    }
+    else
+    {
+        Height = Z / Sin_p1 + Rn * (this.es - 1.0);
+    }
+    if (At_Pole == false)
+    {
+        Latitude = Math.atan(Sin_p1 / Cos_p1);
+    }
+
+    p.x = Longitude;
+    p.y =Latitude;
+    p.z = Height;
+    return p;
+  }, // cs_geocentric_to_geodetic()
+
+  /****************************************************************/
+  // pj_geocentic_to_wgs84( p )
+  //  p = point to transform in geocentric coordinates (x,y,z)
+  geocentric_to_wgs84 : function ( p ) {
+
+    if( this.datum_type == Proj4js.common.PJD_3PARAM )
+    {
+      // if( x[io] == HUGE_VAL )
+      //    continue;
+      p.x += this.datum_params[0];
+      p.y += this.datum_params[1];
+      p.z += this.datum_params[2];
+
+    }
+    else  // if( this.datum_type == Proj4js.common.PJD_7PARAM )
+    {
+      var Dx_BF =this.datum_params[0];
+      var Dy_BF =this.datum_params[1];
+      var Dz_BF =this.datum_params[2];
+      var Rx_BF =this.datum_params[3];
+      var Ry_BF =this.datum_params[4];
+      var Rz_BF =this.datum_params[5];
+      var M_BF  =this.datum_params[6];
+      // if( x[io] == HUGE_VAL )
+      //    continue;
+      var x_out = M_BF*(       p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
+      var y_out = M_BF*( Rz_BF*p.x +       p.y - Rx_BF*p.z) + Dy_BF;
+      var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y +       p.z) + Dz_BF;
+      p.x = x_out;
+      p.y = y_out;
+      p.z = z_out;
+    }
+  }, // cs_geocentric_to_wgs84
+
+  /****************************************************************/
+  // pj_geocentic_from_wgs84()
+  //  coordinate system definition,
+  //  point to transform in geocentric coordinates (x,y,z)
+  geocentric_from_wgs84 : function( p ) {
+
+    if( this.datum_type == Proj4js.common.PJD_3PARAM )
+    {
+      //if( x[io] == HUGE_VAL )
+      //    continue;
+      p.x -= this.datum_params[0];
+      p.y -= this.datum_params[1];
+      p.z -= this.datum_params[2];
+
+    }
+    else // if( this.datum_type == Proj4js.common.PJD_7PARAM )
+    {
+      var Dx_BF =this.datum_params[0];
+      var Dy_BF =this.datum_params[1];
+      var Dz_BF =this.datum_params[2];
+      var Rx_BF =this.datum_params[3];
+      var Ry_BF =this.datum_params[4];
+      var Rz_BF =this.datum_params[5];
+      var M_BF  =this.datum_params[6];
+      var x_tmp = (p.x - Dx_BF) / M_BF;
+      var y_tmp = (p.y - Dy_BF) / M_BF;
+      var z_tmp = (p.z - Dz_BF) / M_BF;
+      //if( x[io] == HUGE_VAL )
+      //    continue;
+
+      p.x =        x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
+      p.y = -Rz_BF*x_tmp +       y_tmp + Rx_BF*z_tmp;
+      p.z =  Ry_BF*x_tmp - Rx_BF*y_tmp +       z_tmp;
+    } //cs_geocentric_from_wgs84()
+  }
+});
+
+/** point object, nothing fancy, just allows values to be
+    passed back and forth by reference rather than by value.
+    Other point classes may be used as long as they have
+    x and y properties, which will get modified in the transform method.
+*/
+Proj4js.Point = OpenLayers.Class({
+
+    initialize : function(x,y,z) {
+      if (typeof x == 'object') {
+        this.x = x[0];
+        this.y = x[1];
+        this.z = x[2] || 0.0;
+      } else {
+        this.x = x;
+        this.y = y;
+        this.z = z || 0.0;
+      }
+    },
+
+    clone : function() {
+      return new Proj4js.Point(this.x, this.y, this.z);
+    },
+
+    /**
+     * Method: toString
+     * Return a readable string version of the lonlat
+     *
+     * Return:
+     * {String} String representation of Proj4js.Point object. 
+     *           (ex. <i>"x=5,y=42"</i>)
+     */
+    toString:function() {
+        return ("x=" + this.x + ",y=" + this.y);
+    },
+
+    /** 
+     * APIMethod: toShortString
+     * 
+     * Return:
+     * {String} Shortened String representation of Proj4js.Point object. 
+     *         (ex. <i>"5, 42"</i>)
+     */
+    toShortString:function() {
+        return (this.x + ", " + this.y);
+    }
+});
+
+Proj4js.PrimeMeridian = {
+    "greenwich": 0.0,               //"0dE",
+    "lisbon":     -9.131906111111,   //"9d07'54.862\"W",
+    "paris":       2.337229166667,   //"2d20'14.025\"E",
+    "bogota":    -74.080916666667,  //"74d04'51.3\"W",
+    "madrid":     -3.687938888889,  //"3d41'16.58\"W",
+    "rome":       12.452333333333,  //"12d27'8.4\"E",
+    "bern":        7.439583333333,  //"7d26'22.5\"E",
+    "jakarta":   106.807719444444,  //"106d48'27.79\"E",
+    "ferro":     -17.666666666667,  //"17d40'W",
+    "brussels":    4.367975,        //"4d22'4.71\"E",
+    "stockholm":  18.058277777778,  //"18d3'29.8\"E",
+    "athens":     23.7163375,       //"23d42'58.815\"E",
+    "oslo":       10.722916666667   //"10d43'22.5\"E"
+};
+
+Proj4js.Ellipsoid = {
+  "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"},
+  "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"},
+  "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"},
+  "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"},
+  "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"},
+  "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"},
+  "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"},
+  "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"},
+  "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"},
+  "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"},
+  "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"},
+  "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"},
+  "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"},
+  "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"},
+  "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."},
+  "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"},
+  "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"},
+  "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"},
+  "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"},
+  "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"},
+  "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"},
+  "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"},
+  "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"},
+  "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"},
+  "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"},
+  "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"},
+  "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"},
+  "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"},
+  "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"},
+  "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"},
+  "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"},
+  "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"},
+  "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"},
+  "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"},
+  "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"},
+  "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"},
+  "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"},
+  "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"},
+  "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"},
+  "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"},
+  "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"},
+  "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"}
+};
+
+Proj4js.Datum = {
+  "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: ""},
+  "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"},
+  "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"},
+  "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"},
+  "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"},
+  "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"},
+  "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"},
+  "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"},
+  "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"},
+  "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"}
+};
+
+Proj4js.WGS84 = new Proj4js.Proj('WGS84');
+Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org
+/* ======================================================================
+    projCode/sterea.js
+   ====================================================================== */
+
+
+Proj4js.Proj.sterea = {
+  dependsOn : 'gauss',
+
+  init : function() {
+    Proj4js.Proj['gauss'].init.apply(this);
+    if (!this.rc) {
+      Proj4js.reportError("sterea:init:E_ERROR_0");
+      return;
+    }
+    this.sinc0 = Math.sin(this.phic0);
+    this.cosc0 = Math.cos(this.phic0);
+    this.R2 = 2.0 * this.rc;
+    if (!this.title) this.title = "Oblique Stereographic Alternative";
+  },
+
+  forward : function(p) {
+    p.x = Proj4js.common.adjust_lon(p.x-this.long0); /* adjust del longitude */
+    Proj4js.Proj['gauss'].forward.apply(this, [p]);
+    sinc = Math.sin(p.y);
+    cosc = Math.cos(p.y);
+    cosl = Math.cos(p.x);
+    k = this.k0 * this.R2 / (1.0 + this.sinc0 * sinc + this.cosc0 * cosc * cosl);
+    p.x = k * cosc * Math.sin(p.x);
+    p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl);
+    p.x = this.a * p.x + this.x0;
+    p.y = this.a * p.y + this.y0;
+    return p;
+  },
+
+  inverse : function(p) {
+    var lon,lat;
+    p.x = (p.x - this.x0) / this.a; /* descale and de-offset */
+    p.y = (p.y - this.y0) / this.a;
+
+    p.x /= this.k0;
+    p.y /= this.k0;
+    if ( (rho = Math.sqrt(p.x*p.x + p.y*p.y)) ) {
+      c = 2.0 * Math.atan2(rho, this.R2);
+      sinc = Math.sin(c);
+      cosc = Math.cos(c);
+      lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho);
+      lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc);
+    } else {
+      lat = this.phic0;
+      lon = 0.;
+    }
+
+    p.x = lon;
+    p.y = lat;
+    Proj4js.Proj['gauss'].inverse.apply(this,[p]);
+    p.x = Proj4js.common.adjust_lon(p.x + this.long0); /* adjust longitude to CM */
+    return p;
+  }
+};
+
+/* ======================================================================
+    projCode/aea.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                     ALBERS CONICAL EQUAL AREA 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and Northing
+    for the Albers Conical Equal Area projection.  The longitude
+    and latitude must be in radians.  The Easting and Northing
+    values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan,        Feb, 1992
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+
+Proj4js.Proj.aea = {
+  init : function() {
+
+    if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
+       Proj4js.reportError("aeaInitEqualLatitudes");
+       return;
+    }
+    this.temp = this.b / this.a;
+    this.es = 1.0 - Math.pow(this.temp,2);
+    this.e3 = Math.sqrt(this.es);
+
+    this.sin_po=Math.sin(this.lat1);
+    this.cos_po=Math.cos(this.lat1);
+    this.t1=this.sin_po
+    this.con = this.sin_po;
+    this.ms1 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
+    this.qs1 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
+
+    this.sin_po=Math.sin(this.lat2);
+    this.cos_po=Math.cos(this.lat2);
+    this.t2=this.sin_po;
+    this.ms2 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
+    this.qs2 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
+
+    this.sin_po=Math.sin(this.lat0);
+    this.cos_po=Math.cos(this.lat0);
+    this.t3=this.sin_po;
+    this.qs0 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
+
+    if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
+      this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1);
+    } else {
+      this.ns0 = this.con;
+    }
+    this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1;
+    this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0;
+  },
+
+/* Albers Conical Equal Area forward equations--mapping lat,long to x,y
+  -------------------------------------------------------------------*/
+  forward: function(p){
+
+    var lon=p.x;
+    var lat=p.y;
+
+    this.sin_phi=Math.sin(lat);
+    this.cos_phi=Math.cos(lat);
+
+    var qs = Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi);
+    var rh1 =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0;
+    var theta = this.ns0 * Proj4js.common.adjust_lon(lon - this.long0); 
+    var x = rh1 * Math.sin(theta) + this.x0;
+    var y = this.rh - rh1 * Math.cos(theta) + this.y0;
+
+    p.x = x; 
+    p.y = y;
+    return p;
+  },
+
+
+  inverse: function(p) {
+    var rh1,qs,con,theta,lon,lat;
+
+    p.x -= this.x0;
+    p.y = this.rh - p.y + this.y0;
+    if (this.ns0 >= 0) {
+      rh1 = Math.sqrt(p.x *p.x + p.y * p.y);
+      con = 1.0;
+    } else {
+      rh1 = -Math.sqrt(p.x * p.x + p.y *p.y);
+      con = -1.0;
+    }
+    theta = 0.0;
+    if (rh1 != 0.0) {
+      theta = Math.atan2(con * p.x, con * p.y);
+    }
+    con = rh1 * this.ns0 / this.a;
+    qs = (this.c - con * con) / this.ns0;
+    if (this.e3 >= 1e-10) {
+      con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3;
+      if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) {
+          lat = this.phi1z(this.e3,qs);
+      } else {
+          if (qs >= 0) {
+             lat = .5 * PI;
+          } else {
+             lat = -.5 * PI;
+          }
+      }
+    } else {
+      lat = this.phi1z(e3,qs);
+    }
+
+    lon = Proj4js.common.adjust_lon(theta/this.ns0 + this.long0);
+    p.x = lon;
+    p.y = lat;
+    return p;
+  },
+  
+/* Function to compute phi1, the latitude for the inverse of the
+   Albers Conical Equal-Area projection.
+-------------------------------------------*/
+  phi1z: function (eccent,qs) {
+    var con, com, dphi;
+    var phi = Proj4js.common.asinz(.5 * qs);
+    if (eccent < Proj4js.common.EPSLN) return phi;
+    
+    var eccnts = eccent * eccent; 
+    for (var i = 1; i <= 25; i++) {
+        sinphi = Math.sin(phi);
+        cosphi = Math.cos(phi);
+        con = eccent * sinphi; 
+        com = 1.0 - con * con;
+        dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con)));
+        phi = phi + dphi;
+        if (Math.abs(dphi) <= 1e-7) return phi;
+    }
+    Proj4js.reportError("aea:phi1z:Convergence error");
+    return null;
+  }
+  
+};
+
+
+
+/* ======================================================================
+    projCode/poly.js
+   ====================================================================== */
+
+/* Function to compute, phi4, the latitude for the inverse of the
+   Polyconic projection.
+------------------------------------------------------------*/
+function phi4z (eccent,e0,e1,e2,e3,a,b,c,phi) {
+  var sinphi, sin2ph, tanph, ml, mlp, con1, con2, con3, dphi, i;
+
+  phi = a;
+  for (i = 1; i <= 15; i++) {
+    sinphi = Math.sin(phi);
+    tanphi = Math.tan(phi);
+    c = tanphi * Math.sqrt (1.0 - eccent * sinphi * sinphi);
+    sin2ph = Math.sin (2.0 * phi);
+    /*
+    ml = e0 * *phi - e1 * sin2ph + e2 * sin (4.0 *  *phi);
+    mlp = e0 - 2.0 * e1 * cos (2.0 *  *phi) + 4.0 * e2 *  cos (4.0 *  *phi);
+    */
+    ml = e0 * phi - e1 * sin2ph + e2 * Math.sin (4.0 *  phi) - e3 * Math.sin (6.0 * phi);
+    mlp = e0 - 2.0 * e1 * Math.cos (2.0 *  phi) + 4.0 * e2 * Math.cos (4.0 *  phi) - 6.0 * e3 * Math.cos (6.0 *  phi);
+    con1 = 2.0 * ml + c * (ml * ml + b) - 2.0 * a *  (c * ml + 1.0);
+    con2 = eccent * sin2ph * (ml * ml + b - 2.0 * a * ml) / (2.0 *c);
+    con3 = 2.0 * (a - ml) * (c * mlp - 2.0 / sin2ph) - 2.0 * mlp;
+    dphi = con1 / (con2 + con3);
+    phi += dphi;
+    if (Math.abs(dphi) <= .0000000001 ) return(phi);   
+  }
+  Proj4js.reportError("phi4z: No convergence");
+  return null;
+}
+
+
+/* Function to compute the constant e4 from the input of the eccentricity
+   of the spheroid, x.  This constant is used in the Polar Stereographic
+   projection.
+--------------------------------------------------------------------*/
+function e4fn(x) {
+  var con, com;
+  con = 1.0 + x;
+  com = 1.0 - x;
+  return (Math.sqrt((Math.pow(con,con))*(Math.pow(com,com))));
+}
+
+
+
+
+
+/*******************************************************************************
+NAME                             POLYCONIC 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Polyconic projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+Proj4js.Proj.poly = {
+
+  /* Initialize the POLYCONIC projection
+    ----------------------------------*/
+  init: function() {
+    var temp;     /* temporary variable   */
+    if (this.lat0=0) this.lat0=90;//this.lat0 ca
+
+    /* Place parameters in static storage for common use
+      -------------------------------------------------*/
+    this.temp = this.b / this.a;
+    this.es = 1.0 - Math.pow(this.temp,2);// devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles 
+    this.e = Math.sqrt(this.es);
+    this.e0 = Proj4js.common.e0fn(this.es);
+    this.e1 = Proj4js.common.e1fn(this.es);
+    this.e2 = Proj4js.common.e2fn(this.es);
+    this.e3 = Proj4js.common.e3fn(this.es);
+    this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this.e2, this.e3, this.lat0);//si que des zeros le calcul ne se fait pas
+    //if (!this.ml0) {this.ml0=0;}
+  },
+
+
+  /* Polyconic forward equations--mapping lat,long to x,y
+    ---------------------------------------------------*/
+  forward: function(p) {
+    var sinphi, cosphi; /* sin and cos value        */
+    var al;       /* temporary values       */
+    var c;        /* temporary values       */
+    var con, ml;    /* cone constant, small m     */
+    var ms;       /* small m          */
+    var x,y;
+
+    var lon=p.x;
+    var lat=p.y;  
+
+    con = Proj4js.common.adjust_lon(lon - this.long0);
+    if (Math.abs(lat) <= .0000001) {
+      x = this.x0 + this.a * con;
+      y = this.y0 - this.a * this.ml0;
+    } else {
+      sinphi = Math.sin(lat);
+      cosphi = Math.cos(lat);    
+
+      ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
+      ms = Proj4js.common.msfnz(this.e,sinphi,cosphi);
+      con = sinphi;
+      x = this.x0 + this.a * ms * Math.sin(con)/sinphi;
+      y = this.y0 + this.a * (ml - this.ml0 + ms * (1.0 - Math.cos(con))/sinphi);
+    }
+
+    p.x=x;
+    p.y=y;   
+    return p;
+  },
+
+
+  /* Inverse equations
+  -----------------*/
+  inverse: function(p) {
+    var sin_phi, cos_phi; /* sin and cos value        */
+    var al;         /* temporary values       */
+    var b;          /* temporary values       */
+    var c;          /* temporary values       */
+    var con, ml;      /* cone constant, small m     */
+    var iflg;       /* error flag         */
+    var lon,lat;
+    p.x -= this.x0;
+    p.y -= this.y0;
+    al = this.ml0 + p.y/this.a;
+    iflg = 0;
+
+    if (Math.abs(al) <= .0000001) {
+      lon = p.x/this.a + this.long0;
+      lat = 0.0;
+    } else {
+      b = al * al + (p.x/this.a) * (p.x/this.a);
+      iflg = phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat);
+      if (iflg != 1) return(iflg);
+      lon = Proj4js.common.adjust_lon((asinz(p.x * c / this.a) / Math.sin(lat)) + this.long0);
+    }
+
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+
+
+
+/* ======================================================================
+    projCode/equi.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                             EQUIRECTANGULAR 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Equirectangular projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+Proj4js.Proj.equi = {
+
+  init: function() {
+    if(!this.x0) this.x0=0;
+    if(!this.y0) this.y0=0;
+    if(!this.lat0) this.lat0=0;
+    if(!this.long0) this.long0=0;
+    ///this.t2;
+  },
+
+
+
+/* Equirectangular forward equations--mapping lat,long to x,y
+  ---------------------------------------------------------*/
+  forward: function(p) {
+
+    var lon=p.x;        
+    var lat=p.y;      
+
+    var dlon = Proj4js.common.adjust_lon(lon - this.long0);
+    var x = this.x0 +this. a * dlon *Math.cos(this.lat0);
+    var y = this.y0 + this.a * lat;
+
+    this.t1=x;
+    this.t2=Math.cos(this.lat0);
+    p.x=x;
+    p.y=y;
+    return p;
+  },  //equiFwd()
+
+
+
+/* Equirectangular inverse equations--mapping x,y to lat/long
+  ---------------------------------------------------------*/
+  inverse: function(p) {
+
+    p.x -= this.x0;
+    p.y -= this.y0;
+    var lat = p.y /this. a;
+
+    if ( Math.abs(lat) > Proj4js.common.HALF_PI) {
+        Proj4js.reportError("equi:Inv:DataError");
+    }
+    var lon = Proj4js.common.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0)));
+    p.x=lon;
+    p.y=lat;
+  }//equiInv()
+};
+
+
+/* ======================================================================
+    projCode/merc.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            MERCATOR
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Mercator projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+D. Steinwand, EROS      Nov, 1991
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+//static double r_major = a;       /* major axis        */
+//static double r_minor = b;       /* minor axis        */
+//static double lon_center = long0;    /* Center longitude (projection center) */
+//static double lat_origin =  lat0;    /* center latitude     */
+//static double e,es;              /* eccentricity constants    */
+//static double m1;                  /* small value m     */
+//static double false_northing = y0;   /* y offset in meters      */
+//static double false_easting = x0;    /* x offset in meters      */
+//scale_fact = k0 
+
+Proj4js.Proj.merc = {
+  init : function() {
+  //?this.temp = this.r_minor / this.r_major;
+  //this.temp = this.b / this.a;
+  //this.es = 1.0 - Math.sqrt(this.temp);
+  //this.e = Math.sqrt( this.es );
+  //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin)));
+  //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0)));
+    if (this.lat_ts) {
+      if (this.sphere) {
+        this.k0 = Math.cos(this.lat_ts);
+      } else {
+        this.k0 = Proj4js.common.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
+      }
+    }
+  },
+
+/* Mercator forward equations--mapping lat,long to x,y
+  --------------------------------------------------*/
+
+  forward : function(p) { 
+    //alert("ll2m coords : "+coords);
+    var lon = p.x;
+    var lat = p.y;
+    // convert to radians
+    if ( lat*Proj4js.common.R2D > 90.0 && 
+          lat*Proj4js.common.R2D < -90.0 && 
+          lon*Proj4js.common.R2D > 180.0 && 
+          lon*Proj4js.common.R2D < -180.0) {
+      Proj4js.reportError("merc:forward: llInputOutOfRange: "+ lon +" : " + lat);
+      return null;
+    }
+
+    var x,y;
+    if(Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI)  <= Proj4js.common.EPSLN) {
+      Proj4js.reportError("merc:forward: ll2mAtPoles");
+      return null;
+    } else {
+      if (this.sphere) {
+        x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
+        y = this.y0 + this.a * this.k0 * Math.log(Math.tan(Proj4js.common.FORTPI + 0.5*lat));
+      } else {
+        var sinphi = Math.sin(lat);
+        var ts = Proj4js.common.tsfnz(this.e,lat,sinphi);
+        x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
+        y = this.y0 - this.a * this.k0 * Math.log(ts);
+      }
+      p.x = x; 
+      p.y = y;
+      return p;
+    }
+  },
+
+
+  /* Mercator inverse equations--mapping x,y to lat/long
+  --------------------------------------------------*/
+  inverse : function(p) { 
+
+    var x = p.x - this.x0;
+    var y = p.y - this.y0;
+    var lon,lat;
+
+    if (this.sphere) {
+      lat = Proj4js.common.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0));
+    } else {
+      var ts = Math.exp(-y / (this.a * this.k0));
+      lat = Proj4js.common.phi2z(this.e,ts);
+      if(lat == -9999) {
+        Proj4js.reportError("merc:inverse: lat = -9999");
+        return null;
+      }
+    }
+    lon = Proj4js.common.adjust_lon(this.long0+ x / (this.a * this.k0));
+
+    p.x = lon;
+    p.y = lat;
+    return p;
+  }
+};
+
+
+/* ======================================================================
+    projCode/utm.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            TRANSVERSE MERCATOR
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Transverse Mercator projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+
+/**
+  Initialize Transverse Mercator projection
+*/
+
+Proj4js.Proj.utm = {
+  dependsOn : 'tmerc',
+
+  init : function() {
+    if (!this.zone) {
+      Proj4js.reportError("utm:init: zone must be specified for UTM");
+      return;
+    }
+    this.lat0 = 0.0;
+    this.long0 = ((6 * Math.abs(this.zone)) - 183) * Proj4js.common.D2R;
+    this.x0 = 500000.0;
+    this.y0 = this.utmSouth ? 10000000.0 : 0.0;
+    this.k0 = 0.9996;
+
+    Proj4js.Proj['tmerc'].init.apply(this);
+    this.forward = Proj4js.Proj['tmerc'].forward;
+    this.inverse = Proj4js.Proj['tmerc'].inverse;
+  }
+};
+/* ======================================================================
+    projCode/eqdc.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            EQUIDISTANT CONIC 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and Northing
+    for the Equidistant Conic projection.  The longitude and
+    latitude must be in radians.  The Easting and Northing values
+    will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+/* Variables common to all subroutines in this code file
+  -----------------------------------------------------*/
+
+Proj4js.Proj.eqdc = {
+
+/* Initialize the Equidistant Conic projection
+  ------------------------------------------*/
+  init: function() {
+
+    /* Place parameters in static storage for common use
+      -------------------------------------------------*/
+
+    if(!this.mode) this.mode=0;//chosen default mode
+    this.temp = this.b / this.a;
+    this.es = 1.0 - Math.pow(this.temp,2);
+    this.e = Math.sqrt(this.es);
+    this.e0 = Proj4js.common.e0fn(this.es);
+    this.e1 = Proj4js.common.e1fn(this.es);
+    this.e2 = Proj4js.common.e2fn(this.es);
+    this.e3 = Proj4js.common.e3fn(this.es);
+
+    this.sinphi=Math.sin(this.lat1);
+    this.cosphi=Math.cos(this.lat1);
+
+    this.ms1 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
+    this.ml1 = Proj4js.common.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1);
+
+    /* format B
+    ---------*/
+    if (this.mode != 0) {
+      if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
+            Proj4js.reportError("eqdc:Init:EqualLatitudes");
+            //return(81);
+       }
+       this.sinphi=Math.sin(this.lat2);
+       this.cosphi=Math.cos(this.lat2);   
+
+       this.ms2 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
+       this.ml2 = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2);
+       if (Math.abs(this.lat1 - this.lat2) >= Proj4js.common.EPSLN) {
+         this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1);
+       } else {
+          this.ns = this.sinphi;
+       }
+    } else {
+      this.ns = this.sinphi;
+    }
+    this.g = this.ml1 + this.ms1/this.ns;
+    this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0);
+    this.rh = this.a * (this.g - this.ml0);
+  },
+
+
+/* Equidistant Conic forward equations--mapping lat,long to x,y
+  -----------------------------------------------------------*/
+  forward: function(p) {
+    var lon=p.x;
+    var lat=p.y;
+
+    /* Forward equations
+      -----------------*/
+    var ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
+    var rh1 = this.a * (this.g - ml);
+    var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
+
+    var x = this.x0  + rh1 * Math.sin(theta);
+    var y = this.y0 + this.rh - rh1 * Math.cos(theta);
+    p.x=x;
+    p.y=y;
+    return p;
+  },
+
+/* Inverse equations
+  -----------------*/
+  inverse: function(p) {
+    p.x -= this.x0;
+    p.y  = this.rh - p.y + this.y0;
+    var con, rh1;
+    if (this.ns >= 0) {
+       var rh1 = Math.sqrt(p.x *p.x + p.y * p.y); 
+       var con = 1.0;
+    } else {
+       rh1 = -Math.sqrt(p.x *p. x +p. y * p.y); 
+       con = -1.0;
+    }
+    var theta = 0.0;
+    if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y);
+    var ml = this.g - rh1 /this.a;
+    var lat = this.phi3z(this.ml,this.e0,this.e1,this.e2,this.e3);
+    var lon = Proj4js.common.adjust_lon(this.long0 + theta / this.ns);
+
+     p.x=lon;
+     p.y=lat;  
+     return p;
+    },
+    
+/* Function to compute latitude, phi3, for the inverse of the Equidistant
+   Conic projection.
+-----------------------------------------------------------------*/
+  phi3z: function(ml,e0,e1,e2,e3) {
+    var phi;
+    var dphi;
+
+    phi = ml;
+    for (var i = 0; i < 15; i++) {
+      dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi;
+      phi += dphi;
+      if (Math.abs(dphi) <= .0000000001) {
+        return phi;
+      }
+    }
+    Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");
+    return null;
+  }
+
+    
+};
+/* ======================================================================
+    projCode/tmerc.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            TRANSVERSE MERCATOR
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Transverse Mercator projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+
+/**
+  Initialize Transverse Mercator projection
+*/
+
+Proj4js.Proj.tmerc = {
+  init : function() {
+    this.e0 = Proj4js.common.e0fn(this.es);
+    this.e1 = Proj4js.common.e1fn(this.es);
+    this.e2 = Proj4js.common.e2fn(this.es);
+    this.e3 = Proj4js.common.e3fn(this.es);
+    this.ml0 = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
+  },
+
+  /**
+    Transverse Mercator Forward  - long/lat to x/y
+    long/lat in radians
+  */
+  forward : function(p) {
+    var lon = p.x;
+    var lat = p.y;
+
+    var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude
+    var con;    // cone constant
+    var x, y;
+    var sin_phi=Math.sin(lat);
+    var cos_phi=Math.cos(lat);
+
+    if (this.sphere) {  /* spherical form */
+      var b = cos_phi * Math.sin(delta_lon);
+      if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001)  {
+        Proj4js.reportError("tmerc:forward: Point projects into infinity");
+        return(93);
+      } else {
+        x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b));
+        con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b));
+        if (lat < 0) con = - con;
+        y = this.a * this.k0 * (con - this.lat0);
+      }
+    } else {
+      var al  = cos_phi * delta_lon;
+      var als = Math.pow(al,2);
+      var c   = this.ep2 * Math.pow(cos_phi,2);
+      var tq  = Math.tan(lat);
+      var t   = Math.pow(tq,2);
+      con = 1.0 - this.es * Math.pow(sin_phi,2);
+      var n   = this.a / Math.sqrt(con);
+      var ml  = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
+
+      x = this.k0 * n * al * (1.0 + als / 6.0 * (1.0 - t + c + als / 20.0 * (5.0 - 18.0 * t + Math.pow(t,2) + 72.0 * c - 58.0 * this.ep2))) + this.x0;
+      y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24.0 * (5.0 - t + 9.0 * c + 4.0 * Math.pow(c,2) + als / 30.0 * (61.0 - 58.0 * t + Math.pow(t,2) + 600.0 * c - 330.0 * this.ep2))))) + this.y0;
+
+    }
+    p.x = x; p.y = y;
+    return p;
+  }, // tmercFwd()
+
+  /**
+    Transverse Mercator Inverse  -  x/y to long/lat
+  */
+  inverse : function(p) {
+    var con, phi;  /* temporary angles       */
+    var delta_phi; /* difference between longitudes    */
+    var i;
+    var max_iter = 6;      /* maximun number of iterations */
+    var lat, lon;
+
+    if (this.sphere) {   /* spherical form */
+      var f = Math.exp(p.x/(this.a * this.k0));
+      var g = .5 * (f - 1/f);
+      var temp = this.lat0 + p.y/(this.a * this.k0);
+      var h = Math.cos(temp);
+      con = Math.sqrt((1.0 - h * h)/(1.0 + g * g));
+      lat = Math.asinz(con);
+      if (temp < 0)
+        lat = -lat;
+      if ((g == 0) && (h == 0)) {
+        lon = this.long0;
+      } else {
+        lon = Proj4js.common.adjust_lon(Math.atan2(g,h) + this.long0);
+      }
+    } else {    // ellipsoidal form
+      var x = p.x - this.x0;
+      var y = p.y - this.y0;
+
+      con = (this.ml0 + y / this.k0) / this.a;
+      phi = con;
+      for (i=0;;i++) {
+        delta_phi=((con + this.e1 * Math.sin(2.0*phi) - this.e2 * Math.sin(4.0*phi) + this.e3 * Math.sin(6.0*phi)) / this.e0) - phi;
+        phi += delta_phi;
+        if (Math.abs(delta_phi) <= Proj4js.common.EPSLN) break;
+        if (i >= max_iter) {
+          Proj4js.reportError("tmerc:inverse: Latitude failed to converge");
+          return(95);
+        }
+      } // for()
+      if (Math.abs(phi) < Proj4js.common.HALF_PI) {
+        // sincos(phi, &sin_phi, &cos_phi);
+        var sin_phi=Math.sin(phi);
+        var cos_phi=Math.cos(phi);
+        var tan_phi = Math.tan(phi);
+        var c = this.ep2 * Math.pow(cos_phi,2);
+        var cs = Math.pow(c,2);
+        var t = Math.pow(tan_phi,2);
+        var ts = Math.pow(t,2);
+        con = 1.0 - this.es * Math.pow(sin_phi,2);
+        var n = this.a / Math.sqrt(con);
+        var r = n * (1.0 - this.es) / con;
+        var d = x / (n * this.k0);
+        var ds = Math.pow(d,2);
+        lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 * this.ep2 - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c + 45.0 * ts - 252.0 * this.ep2 - 3.0 * cs)));
+        lon = Proj4js.common.adjust_lon(this.long0 + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * this.ep2 + 24.0 * ts))) / cos_phi));
+      } else {
+        lat = Proj4js.common.HALF_PI * Proj4js.common.sign(y);
+        lon = this.long0;
+      }
+    }
+    p.x = lon;
+    p.y = lat;
+    return p;
+  } // tmercInv()
+};
+/* ======================================================================
+    defs/GOOGLE.js
+   ====================================================================== */
+
+Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs";
+Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];
+/* ======================================================================
+    projCode/ortho.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                             ORTHOGRAPHIC 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Orthographic projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+Proj4js.Proj.ortho = {
+
+  /* Initialize the Orthographic projection
+    -------------------------------------*/
+  init: function(def) {
+    //double temp;      /* temporary variable   */
+
+    /* Place parameters in static storage for common use
+      -------------------------------------------------*/;
+    this.sin_p14=Math.sin(this.lat0);
+    this.cos_p14=Math.cos(this.lat0); 
+  },
+
+
+  /* Orthographic forward equations--mapping lat,long to x,y
+    ---------------------------------------------------*/
+  forward: function(p) {
+    var sinphi, cosphi; /* sin and cos value        */
+    var dlon;   /* delta longitude value      */
+    var coslon;   /* cos of longitude       */
+    var ksp;    /* scale factor         */
+    var g;    
+    var lon=p.x;
+    var lat=p.y;  
+    /* Forward equations
+      -----------------*/
+    dlon = Proj4js.common.adjust_lon(lon - this.long0);
+
+    sinphi=Math.sin(lat);
+    cosphi=Math.cos(lat); 
+
+    coslon = Math.cos(dlon);
+    g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
+    ksp = 1.0;
+    if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) {
+      var x = this.a * ksp * cosphi * Math.sin(dlon);
+      var y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
+    } else {
+      Proj4js.reportError("orthoFwdPointError");
+    }
+    p.x=x;
+    p.y=y;
+    return p;
+  },
+
+
+  inverse: function(p) {
+    var rh;   /* height above ellipsoid     */
+    var z;    /* angle          */
+    var sinz,cosz;  /* sin of z and cos of z      */
+    var temp;
+    var con;
+    var lon , lat;
+    /* Inverse equations
+      -----------------*/
+    p.x -= this.x0;
+    p.y -= this.y0;
+    rh = Math.sqrt(p.x * p.x + p.y * p.y);
+    if (rh > this.a + .0000001) {
+      Proj4js.reportError("orthoInvDataError");
+    }
+    z = Proj4js.common.asinz(rh / this.a);
+
+    sinz=Math.sin(z);
+    cosi=Math.cos(z);
+
+    lon = this.long0;
+    if (Math.abs(rh) <= Proj4js.common.EPSLN) {
+      lat = this.lat0; 
+    }
+    lat = Proj4js.common.asinz(cosz * this.sin_p14 + (y * sinz * this.cos_p14)/rh);
+    con = Math.abs(lat0) - Proj4js.common.HALF_PI;
+    if (Math.abs(con) <= Proj4js.common.EPSLN) {
+       if (this.lat0 >= 0) {
+          lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
+       } else {
+          lon = Proj4js.common.adjust_lon(this.long0 -Math.atan2(-p.x, p.y));
+       }
+    }
+    con = cosz - this.sin_p14 * Math.sin(lat);
+    if ((Math.abs(con) >= Proj4js.common.EPSLN) || (Math.abs(x) >= Proj4js.common.EPSLN)) {
+       lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p14), (con * rh)));
+    }
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+
+
+/* ======================================================================
+    projCode/stere.js
+   ====================================================================== */
+
+
+// Initialize the Stereographic projection
+
+Proj4js.Proj.stere = {
+  ssfn_: function(phit, sinphi, eccen) {
+    sinphi *= eccen;
+    return (Math.tan (.5 * (Proj4js.common.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen));
+  },
+  TOL:  1.e-8,
+  NITER:  8,
+  CONV: 1.e-10,
+  S_POLE: 0,
+  N_POLE: 1,
+  OBLIQ:  2,
+  EQUIT:  3,
+
+  init : function() {
+    this.phits = this.lat_ts ? this.lat_ts : Proj4js.common.HALF_PI;
+    var t = Math.abs(this.lat0);
+    if ((Math.abs(t) - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
+      this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE;
+    } else {
+      this.mode = t > Proj4js.common.EPSLN ? this.OBLIQ : this.EQUIT;
+    }
+    this.phits = Math.abs(this.phits);
+    if (this.es) {
+      var X;
+
+      switch (this.mode) {
+      case this.N_POLE:
+      case this.S_POLE:
+        if (Math.abs(this.phits - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
+          this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e));
+        } else {
+          t = Math.sin(this.phits);
+          this.akm1 = Math.cos(this.phits) / Proj4js.common.tsfnz(this.e, this.phits, t);
+          t *= this.e;
+          this.akm1 /= Math.sqrt(1. - t * t);
+        }
+        break;
+      case this.EQUIT:
+        this.akm1 = 2. * this.k0;
+        break;
+      case this.OBLIQ:
+        t = Math.sin(this.lat0);
+        X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - Proj4js.common.HALF_PI;
+        t *= this.e;
+        this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t);
+        this.sinX1 = Math.sin(X);
+        this.cosX1 = Math.cos(X);
+        break;
+      }
+    } else {
+      switch (this.mode) {
+      case this.OBLIQ:
+        this.sinph0 = Math.sin(this.lat0);
+        this.cosph0 = Math.cos(this.lat0);
+      case this.EQUIT:
+        this.akm1 = 2. * this.k0;
+        break;
+      case this.S_POLE:
+      case this.N_POLE:
+        this.akm1 = Math.abs(this.phits - Proj4js.common.HALF_PI) >= Proj4js.common.EPSLN ?
+           Math.cos(this.phits) / Math.tan(Proj4js.common.FORTPI - .5 * this.phits) :
+           2. * this.k0 ;
+        break;
+      }
+    }
+  }, 
+
+// Stereographic forward equations--mapping lat,long to x,y
+  forward: function(p) {
+    var lon = p.x;
+    var lat = p.y;
+    var x, y
+    
+    if (this.sphere) {
+      var  sinphi, cosphi, coslam, sinlam;
+
+      sinphi = Math.sin(lat);
+      cosphi = Math.cos(lat);
+      coslam = Math.cos(lon);
+      sinlam = Math.sin(lon);
+      switch (this.mode) {
+      case this.EQUIT:
+        y = 1. + cosphi * coslam;
+        if (y <= Proj4js.common.EPSLN) {
+          F_ERROR;
+        }
+        y = this.akm1 / y;
+        x = y * cosphi * sinlam;
+        y *= sinphi;
+        break;
+      case this.OBLIQ:
+        y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
+        if (y <= Proj4js.common.EPSLN) {
+          F_ERROR;
+        }
+        y = this.akm1 / y;
+        x = y * cosphi * sinlam;
+        y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
+        break;
+      case this.N_POLE:
+        coslam = -coslam;
+        lat = -lat;
+        //Note: no break here so it conitnues through S_POLE
+      case this.S_POLE:
+        if (Math.abs(lat - Proj4js.common.HALF_PI) < this.TOL) {
+          F_ERROR;
+        }
+        y = this.akm1 * Math.tan(Proj4js.common.FORTPI + .5 * lat)
+        x = sinlam * y;
+        y *= coslam;
+        break;
+      }
+    } else {
+      coslam = Math.cos(lon);
+      sinlam = Math.sin(lon);
+      sinphi = Math.sin(lat);
+      if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
+        X = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e));
+        sinX = Math.sin(X - Proj4js.common.HALF_PI);
+        cosX = Math.cos(X);
+      }
+      switch (this.mode) {
+      case this.OBLIQ:
+        A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam));
+        y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam);
+        x = A * cosX;
+        break;
+      case this.EQUIT:
+        A = 2. * this.akm1 / (1. + cosX * coslam);
+        y = A * sinX;
+        x = A * cosX;
+        break;
+      case this.S_POLE:
+        lat = -lat;
+        coslam = - coslam;
+        sinphi = -sinphi;
+      case this.N_POLE:
+        x = this.akm1 * Proj4js.common.tsfnz(this.e, lat, sinphi);
+        y = - x * coslam;
+        break;
+      }
+      x = x * sinlam;
+    }
+    p.x = x*this.a + this.x0;
+    p.y = y*this.a + this.y0;
+    return p;
+  },
+
+
+//* Stereographic inverse equations--mapping x,y to lat/long
+  inverse: function(p) {
+    var x = (p.x - this.x0)/this.a;   /* descale and de-offset */
+    var y = (p.y - this.y0)/this.a;
+    var lon, lat
+
+    var cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, pi2=0.0;
+    var i;
+
+    if (this.sphere) {
+      var  c, rh, sinc, cosc;
+
+      rh = Math.sqrt(x*x + y*y);
+      c = 2. * Math.atan(rh / this.akm1);
+      sinc = Math.sin(c);
+      cosc = Math.cos(c);
+      lon = 0.;
+      switch (this.mode) {
+      case this.EQUIT:
+        if (Math.abs(rh) <= Proj4js.common.EPSLN) {
+          lat = 0.;
+        } else {
+          lat = Math.asin(y * sinc / rh);
+        }
+        if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh);
+        break;
+      case this.OBLIQ:
+        if (Math.abs(rh) <= Proj4js.common.EPSLN) {
+          lat = this.phi0;
+        } else {
+          lat = Math.asin(cosc * sinph0 + y * sinc * cosph0 / rh);
+        }
+        c = cosc - sinph0 * Math.sin(lat);
+        if (c != 0. || x != 0.) {
+          lon = Math.atan2(x * sinc * cosph0, c * rh);
+        }
+        break;
+      case this.N_POLE:
+        y = -y;
+      case this.S_POLE:
+        if (Math.abs(rh) <= Proj4js.common.EPSLN) {
+          lat = this.phi0;
+        } else {
+          lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc);
+        }
+        lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
+        break;
+      }
+    } else {
+      rho = Math.sqrt(x*x + y*y);
+      switch (this.mode) {
+      case this.OBLIQ:
+      case this.EQUIT:
+        tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1);
+        cosphi = Math.cos(tp);
+        sinphi = Math.sin(tp);
+        if( rho == 0.0 ) {
+          phi_l = Math.asin(cosphi * this.sinX1);
+        } else {
+          phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho));
+        }
+
+        tp = Math.tan(.5 * (Proj4js.common.HALF_PI + phi_l));
+        x *= sinphi;
+        y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi;
+        pi2 = Proj4js.common.HALF_PI;
+        halfe = .5 * this.e;
+        break;
+      case this.N_POLE:
+        y = -y;
+      case this.S_POLE:
+        tp = - rho / this.akm1
+        phi_l = Proj4js.common.HALF_PI - 2. * Math.atan(tp);
+        pi2 = -Proj4js.common.HALF_PI;
+        halfe = -.5 * this.e;
+        break;
+      }
+      for (i = this.NITER; i--; phi_l = lat) { //check this
+        sinphi = this.e * Math.sin(phi_l);
+        lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2;
+        if (Math.abs(phi_l - lat) < this.CONV) {
+          if (this.mode == this.S_POLE) lat = -lat;
+          lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
+          p.x = lon;
+          p.y = lat
+          return p;
+        }
+      }
+    }
+  }
+}; 
+/* ======================================================================
+    projCode/mill.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                    MILLER CYLINDRICAL 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Miller Cylindrical projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE            
+----------              ----           
+T. Mittan   March, 1993
+
+This function was adapted from the Lambert Azimuthal Equal Area projection
+code (FORTRAN) in the General Cartographic Transformation Package software
+which is available from the U.S. Geological Survey National Mapping Division.
+ 
+ALGORITHM REFERENCES
+
+1.  "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
+    The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
+
+2.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+3.  "Software Documentation for GCTP General Cartographic Transformation
+    Package", U.S. Geological Survey National Mapping Division, May 1982.
+*******************************************************************************/
+
+Proj4js.Proj.mill = {
+
+/* Initialize the Miller Cylindrical projection
+  -------------------------------------------*/
+  init: function() {
+    //no-op
+  },
+
+
+  /* Miller Cylindrical forward equations--mapping lat,long to x,y
+    ------------------------------------------------------------*/
+  forward: function(p) {
+    var lon=p.x;
+    var lat=p.y;
+    /* Forward equations
+      -----------------*/
+    dlon = Proj4js.common.adjust_lon(lon -this.long0);
+    var x = this.x0 +this.R * dlon;
+    var y = this.y0 + this.R *Math.log(Math.tan((Proj4js.common.PI / 4.0) + (lat / 2.5))) * 1.25;
+
+    p.x=x;
+    p.y=y;
+    return p;
+  },//millFwd()
+
+  /* Miller Cylindrical inverse equations--mapping x,y to lat/long
+    ------------------------------------------------------------*/
+  inverse: function(p) {
+    p. x -= this.x0;
+    p. y -= this.y0;
+
+    var lon = Proj4js.common.adjust_lon(this.long0 + p.x /this.R);
+    var lat = 2.5 * (Math.atan(Math.exp(p.y/ this.R / 1.25)) - Proj4js.common.PI / 4.0);
+
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }//millInv()
+};
+/* ======================================================================
+    projCode/sinu.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                      SINUSOIDAL
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Sinusoidal projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE            
+----------              ----           
+D. Steinwand, EROS      May, 1991     
+
+This function was adapted from the Sinusoidal projection code (FORTRAN) in the 
+General Cartographic Transformation Package software which is available from 
+the U.S. Geological Survey National Mapping Division.
+ 
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  "Software Documentation for GCTP General Cartographic Transformation
+    Package", U.S. Geological Survey National Mapping Division, May 1982.
+*******************************************************************************/
+
+Proj4js.Proj.sinu = {
+
+  /* Initialize the Sinusoidal projection
+    ------------------------------------*/
+  init: function() {
+    /* Place parameters in static storage for common use
+      -------------------------------------------------*/
+    this.R = 6370997.0; //Radius of earth
+  },
+
+  /* Sinusoidal forward equations--mapping lat,long to x,y
+  -----------------------------------------------------*/
+  forward: function(p) {
+    var x,y,delta_lon;  
+    var lon=p.x;
+    var lat=p.y;  
+    /* Forward equations
+    -----------------*/
+    delta_lon = Proj4js.common.adjust_lon(lon - this.long0);
+    x = this.R * delta_lon * Math.cos(lat) + this.x0;
+    y = this.R * lat + this.y0;
+
+    p.x=x;
+    p.y=y;  
+    return p;
+  },
+
+  inverse: function(p) {
+    var lat,temp,lon; 
+
+    /* Inverse equations
+      -----------------*/
+    p.x -= this.x0;
+    p.y -= this.y0;
+    lat = p.y / this.R;
+    if (Math.abs(lat) > Proj4js.common.HALF_PI) {
+        Proj4js.reportError("sinu:Inv:DataError");
+    }
+    temp = Math.abs(lat) - Proj4js.common.HALF_PI;
+    if (Math.abs(temp) > Proj4js.common.EPSLN) {
+      temp = this.long0+ p.x / (this.R *Math.cos(lat));
+      lon = Proj4js.common.adjust_lon(temp);
+    } else {
+      lon = this.long0;
+    }
+      
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+
+
+/* ======================================================================
+    projCode/geocent.js
+   ====================================================================== */
+
+/*
+Author:       Richard Greenwood rich@greenwoodmap.com
+License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
+*/
+
+/**
+ * convert between geodetic coordinates (longitude, latitude, height)
+ * and gecentric coordinates (X, Y, Z)
+ * ported from Proj 4.9.9 geocent.c
+*/
+
+
+// following constants #define'd in geocent.h
+// var GEOCENT_NO_ERROR  = 0x0000;
+var GEOCENT_LAT_ERROR = 0x0001;
+// var GEOCENT_LON_ERROR = 0x0002;
+// var cs.a_ERROR        = 0x0004;
+// var cs.b_ERROR        = 0x0008;
+// var cs.a_LESS_B_ERROR = 0x0010;
+
+// following constants from geocent.c
+var COS_67P5  = 0.38268343236508977;  /* cosine of 67.5 degrees */
+var AD_C      = 1.0026000;            /* Toms region 1 constant */
+
+function cs_geodetic_to_geocentric (cs, p) {
+
+/*
+ * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
+ * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
+ * according to the current ellipsoid parameters.
+ *
+ *    Latitude  : Geodetic latitude in radians                     (input)
+ *    Longitude : Geodetic longitude in radians                    (input)
+ *    Height    : Geodetic height, in meters                       (input)
+ *    X         : Calculated Geocentric X coordinate, in meters    (output)
+ *    Y         : Calculated Geocentric Y coordinate, in meters    (output)
+ *    Z         : Calculated Geocentric Z coordinate, in meters    (output)
+ *
+ */
+
+  var Longitude = p.x;
+  var Latitude = p.y;
+  var Height = p.z;
+  var X;  // output
+  var Y;
+  var Z;
+
+  var Error_Code=0;  //  GEOCENT_NO_ERROR;
+  var Rn;            /*  Earth radius at location  */
+  var Sin_Lat;       /*  Math.sin(Latitude)  */
+  var Sin2_Lat;      /*  Square of Math.sin(Latitude)  */
+  var Cos_Lat;       /*  Math.cos(Latitude)  */
+
+  /*
+  ** Don't blow up if Latitude is just a little out of the value
+  ** range as it may just be a rounding issue.  Also removed longitude
+  ** test, it should be wrapped by Math.cos() and Math.sin().  NFW for PROJ.4, Sep/2001.
+  */
+  if( Latitude < -HALF_PI && Latitude > -1.001 * HALF_PI )
+      Latitude = -HALF_PI;
+  else if( Latitude > HALF_PI && Latitude < 1.001 * HALF_PI )
+      Latitude = HALF_PI;
+  else if ((Latitude < -HALF_PI) || (Latitude > HALF_PI))
+  { /* Latitude out of range */
+    Error_Code |= GEOCENT_LAT_ERROR;
+  }
+
+  if (!Error_Code)
+  { /* no errors */
+    if (Longitude > PI)
+      Longitude -= (2*PI);
+    Sin_Lat = Math.sin(Latitude);
+    Cos_Lat = Math.cos(Latitude);
+    Sin2_Lat = Sin_Lat * Sin_Lat;
+    Rn = cs.a / (Math.sqrt(1.0e0 - cs.es * Sin2_Lat));
+    X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
+    Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
+    Z = ((Rn * (1 - cs.es)) + Height) * Sin_Lat;
+
+  }
+
+  p.x = X;
+  p.y = Y;
+  p.z = Z;
+  return Error_Code;
+} // cs_geodetic_to_geocentric()
+
+
+/** Convert_Geocentric_To_Geodetic
+ * The method used here is derived from 'An Improved Algorithm for
+ * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
+ */
+
+function cs_geocentric_to_geodetic (cs, p) {
+
+  var X =p.x;
+  var Y = p.y;
+  var Z = p.z;
+  var Longitude;
+  var Latitude;
+  var Height;
+
+  var W;        /* distance from Z axis */
+  var W2;       /* square of distance from Z axis */
+  var T0;       /* initial estimate of vertical component */
+  var T1;       /* corrected estimate of vertical component */
+  var S0;       /* initial estimate of horizontal component */
+  var S1;       /* corrected estimate of horizontal component */
+  var Sin_B0;   /* Math.sin(B0), B0 is estimate of Bowring aux variable */
+  var Sin3_B0;  /* cube of Math.sin(B0) */
+  var Cos_B0;   /* Math.cos(B0) */
+  var Sin_p1;   /* Math.sin(phi1), phi1 is estimated latitude */
+  var Cos_p1;   /* Math.cos(phi1) */
+  var Rn;       /* Earth radius at location */
+  var Sum;      /* numerator of Math.cos(phi1) */
+  var At_Pole;  /* indicates location is in polar region */
+
+  X = parseFloat(X);  // cast from string to float
+  Y = parseFloat(Y);
+  Z = parseFloat(Z);
+
+  At_Pole = false;
+  if (X != 0.0)
+  {
+      Longitude = Math.atan2(Y,X);
+  }
+  else
+  {
+      if (Y > 0)
+      {
+          Longitude = HALF_PI;
+      }
+      else if (Y < 0)
+      {
+          Longitude = -HALF_PI;
+      }
+      else
+      {
+          At_Pole = true;
+          Longitude = 0.0;
+          if (Z > 0.0)
+          {  /* north pole */
+              Latitude = HALF_PI;
+          }
+          else if (Z < 0.0)
+          {  /* south pole */
+              Latitude = -HALF_PI;
+          }
+          else
+          {  /* center of earth */
+              Latitude = HALF_PI;
+              Height = -cs.b;
+              return;
+          }
+      }
+  }
+  W2 = X*X + Y*Y;
+  W = Math.sqrt(W2);
+  T0 = Z * AD_C;
+  S0 = Math.sqrt(T0 * T0 + W2);
+  Sin_B0 = T0 / S0;
+  Cos_B0 = W / S0;
+  Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
+  T1 = Z + cs.b * cs.ep2 * Sin3_B0;
+  Sum = W - cs.a * cs.es * Cos_B0 * Cos_B0 * Cos_B0;
+  S1 = Math.sqrt(T1*T1 + Sum * Sum);
+  Sin_p1 = T1 / S1;
+  Cos_p1 = Sum / S1;
+  Rn = cs.a / Math.sqrt(1.0 - cs.es * Sin_p1 * Sin_p1);
+  if (Cos_p1 >= COS_67P5)
+  {
+      Height = W / Cos_p1 - Rn;
+  }
+  else if (Cos_p1 <= -COS_67P5)
+  {
+      Height = W / -Cos_p1 - Rn;
+  }
+  else
+  {
+      Height = Z / Sin_p1 + Rn * (cs.es - 1.0);
+  }
+  if (At_Pole == false)
+  {
+      Latitude = Math.atan(Sin_p1 / Cos_p1);
+  }
+
+  p.x = Longitude;
+  p.y =Latitude;
+  p.z = Height;
+  return 0;
+} // cs_geocentric_to_geodetic()
+
+
+
+/****************************************************************/
+// pj_geocentic_to_wgs84(defn, p )
+//    defn = coordinate system definition,
+//  p = point to transform in geocentric coordinates (x,y,z)
+function cs_geocentric_to_wgs84( defn, p ) {
+
+  if( defn.datum_type == PJD_3PARAM )
+  {
+    // if( x[io] == HUGE_VAL )
+    //    continue;
+    p.x += defn.datum_params[0];
+    p.y += defn.datum_params[1];
+    p.z += defn.datum_params[2];
+
+  }
+  else  // if( defn.datum_type == PJD_7PARAM )
+  {
+    var Dx_BF =defn.datum_params[0];
+    var Dy_BF =defn.datum_params[1];
+    var Dz_BF =defn.datum_params[2];
+    var Rx_BF =defn.datum_params[3];
+    var Ry_BF =defn.datum_params[4];
+    var Rz_BF =defn.datum_params[5];
+    var M_BF  =defn.datum_params[6];
+    // if( x[io] == HUGE_VAL )
+    //    continue;
+    var x_out = M_BF*(       p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
+    var y_out = M_BF*( Rz_BF*p.x +       p.y - Rx_BF*p.z) + Dy_BF;
+    var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y +       p.z) + Dz_BF;
+    p.x = x_out;
+    p.y = y_out;
+    p.z = z_out;
+  }
+} // cs_geocentric_to_wgs84
+
+/****************************************************************/
+// pj_geocentic_from_wgs84()
+//  coordinate system definition,
+//  point to transform in geocentric coordinates (x,y,z)
+function cs_geocentric_from_wgs84( defn, p ) {
+
+  if( defn.datum_type == PJD_3PARAM )
+  {
+    //if( x[io] == HUGE_VAL )
+    //    continue;
+    p.x -= defn.datum_params[0];
+    p.y -= defn.datum_params[1];
+    p.z -= defn.datum_params[2];
+
+  }
+  else // if( defn.datum_type == PJD_7PARAM )
+  {
+    var Dx_BF =defn.datum_params[0];
+    var Dy_BF =defn.datum_params[1];
+    var Dz_BF =defn.datum_params[2];
+    var Rx_BF =defn.datum_params[3];
+    var Ry_BF =defn.datum_params[4];
+    var Rz_BF =defn.datum_params[5];
+    var M_BF  =defn.datum_params[6];
+    var x_tmp = (p.x - Dx_BF) / M_BF;
+    var y_tmp = (p.y - Dy_BF) / M_BF;
+    var z_tmp = (p.z - Dz_BF) / M_BF;
+    //if( x[io] == HUGE_VAL )
+    //    continue;
+
+    p.x =        x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
+    p.y = -Rz_BF*x_tmp +       y_tmp + Rx_BF*z_tmp;
+    p.z =  Ry_BF*x_tmp - Rx_BF*y_tmp +       z_tmp;
+  }
+} //cs_geocentric_from_wgs84()
+/* ======================================================================
+    projCode/vandg.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                    VAN DER GRINTEN 
+
+PURPOSE:  Transforms input Easting and Northing to longitude and
+    latitude for the Van der Grinten projection.  The
+    Easting and Northing must be in meters.  The longitude
+    and latitude values will be returned in radians.
+
+PROGRAMMER              DATE            
+----------              ----           
+T. Mittan   March, 1993
+
+This function was adapted from the Van Der Grinten projection code
+(FORTRAN) in the General Cartographic Transformation Package software
+which is available from the U.S. Geological Survey National Mapping Division.
+ 
+ALGORITHM REFERENCES
+
+1.  "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
+    The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
+
+2.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+3.  "Software Documentation for GCTP General Cartographic Transformation
+    Package", U.S. Geological Survey National Mapping Division, May 1982.
+*******************************************************************************/
+
+Proj4js.Proj.vandg = {
+
+/* Initialize the Van Der Grinten projection
+  ----------------------------------------*/
+  init: function() {
+    this.R = 6370997.0; //Radius of earth
+  },
+
+  forward: function(p) {
+
+    var lon=p.x;
+    var lat=p.y;  
+
+    /* Forward equations
+    -----------------*/
+    var dlon = Proj4js.common.adjust_lon(lon - this.long0);
+    var x,y;
+
+    if (Math.abs(lat) <= Proj4js.common.EPSLN) {
+      x = this.x0  + this.R * dlon;
+      y = this.y0;
+    }
+    var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI));
+    if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) {
+      x = this.x0;
+      if (lat >= 0) {
+        y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta);
+      } else {
+        y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta);
+      }
+      //  return(OK);
+    }
+    var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI));
+    var asq = al * al;
+    var sinth = Math.sin(theta);
+    var costh = Math.cos(theta);
+
+    var g = costh / (sinth + costh - 1.0);
+    var gsq = g * g;
+    var m = g * (2.0 / sinth - 1.0);
+    var msq = m * m;
+    var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq);
+    if (dlon < 0) {
+     con = -con;
+    }
+    x = this.x0 + con;
+    con = Math.abs(con / (Proj4js.common.PI * this.R));
+    if (lat >= 0) {
+     y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
+    } else {
+     y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
+    }
+    p.x = x;
+    p.y = y;
+    return p;
+  },
+
+/* Van Der Grinten inverse equations--mapping x,y to lat/long
+  ---------------------------------------------------------*/
+  inverse: function(p) {
+    var dlon;
+    var xx,yy,xys,c1,c2,c3;
+    var al,asq;
+    var a1;
+    var m1;
+    var con;
+    var th1;
+    var d;
+
+    /* inverse equations
+    -----------------*/
+    p.x -= this.x0;
+    p.y -= this.y0;
+    con = Proj4js.common.PI * this.R;
+    xx = p.x / con;
+    yy =p.y / con;
+    xys = xx * xx + yy * yy;
+    c1 = -Math.abs(yy) * (1.0 + xys);
+    c2 = c1 - 2.0 * yy * yy + xx * xx;
+    c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys;
+    d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0;
+    a1 = (c1 - c2 * c2 / 3.0 / c3) / c3;
+    m1 = 2.0 * Math.sqrt( -a1 / 3.0);
+    con = ((3.0 * d) / a1) / m1;
+    if (Math.abs(con) > 1.0) {
+      if (con >= 0.0) {
+        con = 1.0;
+      } else {
+        con = -1.0;
+      }
+    }
+    th1 = Math.acos(con) / 3.0;
+    if (p.y >= 0) {
+      lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
+    } else {
+      lat = -(-m1 * Math.cos(th1 + PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
+    }
+
+    if (Math.abs(xx) < Proj4js.common.EPSLN) {
+      lon = this.long0;
+    }
+    lon = Proj4js.common.adjust_lon(this.long0 + Proj4js.common.PI * (xys - 1.0 + Math.sqrt(1.0 + 2.0 * (xx * xx - yy * yy) + xys * xys)) / 2.0 / xx);
+
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+/* ======================================================================
+    projCode/gauss.js
+   ====================================================================== */
+
+
+Proj4js.Proj.gauss = {
+
+  init : function() {
+    sphi = Math.sin(this.lat0);
+    cphi = Math.cos(this.lat0);  
+    cphi *= cphi;
+    this.rc = Math.sqrt(1.0 - this.es) / (1.0 - this.es * sphi * sphi);
+    this.C = Math.sqrt(1.0 + this.es * cphi * cphi / (1.0 - this.es));
+    this.phic0 = Math.asin(sphi / this.C);
+    this.ratexp = 0.5 * this.C * this.e;
+    this.K = Math.tan(0.5 * this.phic0 + Proj4js.common.FORTPI) / (Math.pow(Math.tan(0.5*this.lat0 + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e*sphi, this.ratexp));
+  },
+
+  forward : function(p) {
+    var lon = p.x;
+    var lat = p.y;
+
+    p.y = 2.0 * Math.atan( this.K * Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e * Math.sin(lat), this.ratexp) ) - Proj4js.common.HALF_PI;
+    p.x = this.C * lon;
+    return p;
+  },
+
+  inverse : function(p) {
+    var DEL_TOL = 1e-14;
+    var lon = p.x / this.C;
+    var lat = p.y;
+    num = Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI)/this.K, 1./this.C);
+    for (var i = Proj4js.common.MAX_ITER; i>0; --i) {
+      lat = 2.0 * Math.atan(num * Proj4js.common.srat(this.e * Math.sin(p.y), -0.5 * this.e)) - Proj4js.common.HALF_PI;
+      if (Math.abs(lat - p.y) < DEL_TOL) break;
+      p.y = lat;
+    } 
+    /* convergence failed */
+    if (!i) {
+      Proj4js.reportError("gauss:inverse:convergence failed");
+      return null;
+    }
+    p.x = lon;
+    p.y = lat;
+    return p;
+  }
+};
+
+/* ======================================================================
+    projCode/omerc.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                       OBLIQUE MERCATOR (HOTINE) 
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Oblique Mercator projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+T. Mittan   Mar, 1993
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+*******************************************************************************/
+
+Proj4js.Proj.omerc = {
+
+  /* Initialize the Oblique Mercator  projection
+    ------------------------------------------*/
+  init: function() {
+    if (!this.mode) this.mode=0;
+    if (!this.lon1)   {this.lon1=0;this.mode=1;}
+    if (!this.lon2)   this.lon2=0;
+    if (!this.lat2)    this.lat2=0;
+
+    /* Place parameters in static storage for common use
+      -------------------------------------------------*/
+    var temp = this.b/ this.a;
+    var es = 1.0 - Math.pow(temp,2);
+    var e = Math.sqrt(es);
+
+    this.sin_p20=Math.sin(this.lat0);
+    this.cos_p20=Math.cos(this.lat0);
+
+    this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20;
+    this.com = Math.sqrt(1.0 - es);
+    this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es));
+    this.al = this.a * this.bl * this.k0 * this.com / this.con;
+    if (Math.abs(this.lat0) < Proj4js.common.EPSLN) {
+       this.ts = 1.0;
+       this.d = 1.0;
+       this.el = 1.0;
+    } else {
+       this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20);
+       this.con = Math.sqrt(this.con);
+       this.d = this.bl * this.com / (this.cos_p20 * this.con);
+       if ((this.d * this.d - 1.0) > 0.0) {
+          if (this.lat0 >= 0.0) {
+             this.f = this.d + Math.sqrt(this.d * this.d - 1.0);
+          } else {
+             this.f = this.d - Math.sqrt(this.d * this.d - 1.0);
+          }
+       } else {
+         this.f = this.d;
+       }
+       this.el = this.f * Math.pow(this.ts,this.bl);
+    }
+
+    //this.longc=52.60353916666667;
+
+    if (this.mode != 0) {
+       this.g = .5 * (this.f - 1.0/this.f);
+       this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d);
+       this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl;
+
+       /* Report parameters common to format B
+       -------------------------------------*/
+       //genrpt(azimuth * R2D,"Azimuth of Central Line:    ");
+       //cenlon(lon_origin);
+      // cenlat(lat_origin);
+
+       this.con = Math.abs(this.lat0);
+       if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) {
+            this.singam=Math.sin(this.gama);
+            this.cosgam=Math.cos(this.gama);
+
+            this.sinaz=Math.sin(this.alpha);
+            this.cosaz=Math.cos(this.alpha);
+
+            if (this.lat0>= 0) {
+               this.u =  (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
+            } else {
+               this.u =  -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
+            }
+          } else {
+            Proj4js.reportError("omerc:Init:DataError");
+          }
+       } else {
+       this.sinphi =Math. sin(this.at1);
+       this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);
+       this.sinphi = Math.sin(this.lat2);
+       this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);
+       this.h = Math.pow(this.ts1,this.bl);
+       this.l = Math.pow(this.ts2,this.bl);
+       this.f = this.el/this.h;
+       this.g = .5 * (this.f - 1.0/this.f);
+       this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h);
+       this.p = (this.l - this.h) / (this.l + this.h);
+       this.dlon = this.lon1 - this.lon2;
+       if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI;
+       if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI;
+       this.dlon = this.lon1 - this.lon2;
+       this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl;
+       this.dlon  = Proj4js.common.adjust_lon(this.lon1 - this.longc);
+       this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g);
+       this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama));
+
+       /* Report parameters common to format A
+       -------------------------------------*/
+
+       if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) {
+          Proj4js.reportError("omercInitDataError");
+          //return(202);
+       } else {
+          this.con = Math.abs(this.lat1);
+       }
+       if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - HALF_PI) <= Proj4js.common.EPSLN)) {
+           Proj4js.reportError("omercInitDataError");
+                //return(202);
+       } else {
+         if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
+            Proj4js.reportError("omercInitDataError");
+            //return(202);
+         }
+       }
+
+       this.singam=Math.sin(this.gam);
+       this.cosgam=Math.cos(this.gam);
+
+       this.sinaz=Math.sin(this.alpha);
+       this.cosaz=Math.cos(this.alpha);  
+
+
+       if (this.lat0 >= 0) {
+          this.u =  (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
+       } else {
+          this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
+       }
+     }
+  },
+
+
+  /* Oblique Mercator forward equations--mapping lat,long to x,y
+    ----------------------------------------------------------*/
+  forward: function(p) {
+    var theta;    /* angle          */
+    var sin_phi, cos_phi;/* sin and cos value       */
+    var b;    /* temporary values       */
+    var c, t, tq; /* temporary values       */
+    var con, n, ml; /* cone constant, small m     */
+    var q,us,vl;
+    var ul,vs;
+    var s;
+    var dlon;
+    var ts1;
+
+    var lon=p.x;
+    var lat=p.y;
+    /* Forward equations
+      -----------------*/
+    sin_phi = Math.sin(lat);
+    dlon = Proj4js.common.adjust_lon(lon - this.longc);
+    vl = Math.sin(this.bl * dlon);
+    if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) {
+       ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi);
+       q = this.el / (Math.pow(ts1,this.bl));
+       s = .5 * (q - 1.0 / q);
+       t = .5 * (q + 1.0/ q);
+       ul = (s * this.singam - vl * this.cosgam) / t;
+       con = Math.cos(this.bl * dlon);
+       if (Math.abs(con) < .0000001) {
+          us = this.al * this.bl * dlon;
+       } else {
+          us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl;
+          if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl;
+       }
+    } else {
+       if (lat >= 0) {
+          ul = this.singam;
+       } else {
+          ul = -this.singam;
+       }
+       us = this.al * lat / this.bl;
+    }
+    if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) {
+       //alert("Point projects into infinity","omer-for");
+       Proj4js.reportError("omercFwdInfinity");
+       //return(205);
+    }
+    vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl;
+    us = us - this.u;
+    var x = this.x0 + vs * this.cosaz + us * this.sinaz;
+    var y = this.y0 + us * this.cosaz - vs * this.sinaz;
+
+    p.x=x;
+    p.y=y;
+    return p;
+  },
+
+  inverse: function(p) {
+    var delta_lon;  /* Delta longitude (Given longitude - center  */
+    var theta;    /* angle          */
+    var delta_theta;  /* adjusted longitude       */
+    var sin_phi, cos_phi;/* sin and cos value       */
+    var b;    /* temporary values       */
+    var c, t, tq; /* temporary values       */
+    var con, n, ml; /* cone constant, small m     */
+    var vs,us,q,s,ts1;
+    var vl,ul,bs;
+    var dlon;
+    var  flag;
+
+    /* Inverse equations
+      -----------------*/
+    p.x -= this.x0;
+    p.y -= this.y0;
+    flag = 0;
+    vs = p.x * this.cosaz - p.y * this.sinaz;
+    us = p.y * this.cosaz + p.x * this.sinaz;
+    us = us + this.u;
+    q = Math.exp(-this.bl * vs / this.al);
+    s = .5 * (q - 1.0/q);
+    t = .5 * (q + 1.0/q);
+    vl = Math.sin(this.bl * us / this.al);
+    ul = (vl * this.cosgam + s * this.singam)/t;
+    if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN)
+       {
+       lon = this.longc;
+       if (ul >= 0.0) {
+          lat = Proj4js.common.HALF_PI;
+       } else {
+         lat = -Proj4js.common.HALF_PI;
+       }
+    } else {
+       con = 1.0 / this.bl;
+       ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con);
+       lat = Proj4js.common.phi2z(this.e,ts1);
+       //if (flag != 0)
+          //return(flag);
+       //~ con = Math.cos(this.bl * us /al);
+       theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl;
+       lon = Proj4js.common.adjust_lon(theta);
+    }
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+/* ======================================================================
+    projCode/lcc.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            LAMBERT CONFORMAL CONIC
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Lambert Conformal Conic projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+2.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+*******************************************************************************/
+
+
+//<2104> +proj=lcc +lat_1=10.16666666666667 +lat_0=10.16666666666667 +lon_0=-71.60561777777777 +k_0=1 +x0=-17044 +x0=-23139.97 +ellps=intl +units=m +no_defs  no_defs
+
+// Initialize the Lambert Conformal conic projection
+// -----------------------------------------------------------------
+
+//Proj4js.Proj.lcc = Class.create();
+Proj4js.Proj.lcc = {
+  init : function() {
+
+    // array of:  r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north
+    //double c_lat;                   /* center latitude                      */
+    //double c_lon;                   /* center longitude                     */
+    //double lat1;                    /* first standard parallel              */
+    //double lat2;                    /* second standard parallel             */
+    //double r_maj;                   /* major axis                           */
+    //double r_min;                   /* minor axis                           */
+    //double false_east;              /* x offset in meters                   */
+    //double false_north;             /* y offset in meters                   */
+
+      if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined
+      if (!this.k0) this.k0 = 1.0;
+
+    // Standard Parallels cannot be equal and on opposite sides of the equator
+      if (Math.abs(this.lat1+this.lat2) < Proj4js.common.EPSLN) {
+        Proj4js.reportError("lcc:init: Equal Latitudes");
+        return;
+      }
+
+      var temp = this.b / this.a;
+      this.e = Math.sqrt(1.0 - temp*temp);
+
+      var sin1 = Math.sin(this.lat1);
+      var cos1 = Math.cos(this.lat1);
+      var ms1 = Proj4js.common.msfnz(this.e, sin1, cos1);
+      var ts1 = Proj4js.common.tsfnz(this.e, this.lat1, sin1);
+
+      var sin2 = Math.sin(this.lat2);
+      var cos2 = Math.cos(this.lat2);
+      var ms2 = Proj4js.common.msfnz(this.e, sin2, cos2);
+      var ts2 = Proj4js.common.tsfnz(this.e, this.lat2, sin2);
+
+      var ts0 = Proj4js.common.tsfnz(this.e, this.lat0, Math.sin(this.lat0));
+
+      if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
+        this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2);
+      } else {
+        this.ns = sin1;
+      }
+      this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns));
+      this.rh = this.a * this.f0 * Math.pow(ts0, this.ns);
+      if (!this.title) this.title = "Lambert Conformal Conic";
+    },
+
+
+    // Lambert Conformal conic forward equations--mapping lat,long to x,y
+    // -----------------------------------------------------------------
+    forward : function(p) {
+
+      var lon = p.x;
+      var lat = p.y;
+
+    // convert to radians
+      if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) {
+        //lon = lon * Proj4js.common.D2R;
+        //lat = lat * Proj4js.common.D2R;
+      } else {
+        Proj4js.reportError("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat);
+        return null;
+      }
+
+      var con  = Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI);
+      var ts;
+      if (con > Proj4js.common.EPSLN) {
+        ts = Proj4js.common.tsfnz(this.e, lat, Math.sin(lat) );
+        rh1 = this.a * this.f0 * Math.pow(ts, this.ns);
+      } else {
+        con = lat * this.ns;
+        if (con <= 0) {
+          Proj4js.reportError("lcc:forward: No Projection");
+          return null;
+        }
+        rh1 = 0;
+      }
+      var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
+      p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0;
+      p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0;
+
+      return p;
+    },
+
+  // Lambert Conformal Conic inverse equations--mapping x,y to lat/long
+  // -----------------------------------------------------------------
+  inverse : function(p) {
+
+    var rh1, con, ts;
+    var lat, lon;
+    x = (p.x - this.x0)/this.k0;
+    y = (this.rh - (p.y - this.y0)/this.k0);
+    if (this.ns > 0) {
+      rh1 = Math.sqrt (x * x + y * y);
+      con = 1.0;
+    } else {
+      rh1 = -Math.sqrt (x * x + y * y);
+      con = -1.0;
+    }
+    var theta = 0.0;
+    if (rh1 != 0) {
+      theta = Math.atan2((con * x),(con * y));
+    }
+    if ((rh1 != 0) || (this.ns > 0.0)) {
+      con = 1.0/this.ns;
+      ts = Math.pow((rh1/(this.a * this.f0)), con);
+      lat = Proj4js.common.phi2z(this.e, ts);
+      if (lat == -9999) return null;
+    } else {
+      lat = -Proj4js.common.HALF_PI;
+    }
+    lon = Proj4js.common.adjust_lon(theta/this.ns + this.long0);
+
+    p.x = lon;
+    p.y = lat;
+    return p;
+  }
+};
+
+
+
+
+/* ======================================================================
+    projCode/laea.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                  LAMBERT AZIMUTHAL EQUAL-AREA
+ 
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the Lambert Azimuthal Equal-Area projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE            
+----------              ----           
+D. Steinwand, EROS      March, 1991   
+
+This function was adapted from the Lambert Azimuthal Equal Area projection
+code (FORTRAN) in the General Cartographic Transformation Package software
+which is available from the U.S. Geological Survey National Mapping Division.
+ 
+ALGORITHM REFERENCES
+
+1.  "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
+    The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
+
+2.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+
+3.  "Software Documentation for GCTP General Cartographic Transformation
+    Package", U.S. Geological Survey National Mapping Division, May 1982.
+*******************************************************************************/
+
+Proj4js.Proj.laea = {
+
+
+/* Initialize the Lambert Azimuthal Equal Area projection
+  ------------------------------------------------------*/
+  init: function() {
+    this.sin_lat_o=Math.sin(this.lat0);
+    this.cos_lat_o=Math.cos(this.lat0);
+  },
+
+/* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y
+  -----------------------------------------------------------------------*/
+  forward: function(p) {
+
+    /* Forward equations
+      -----------------*/
+    var lon=p.x;
+    var lat=p.y;
+    var delta_lon = Proj4js.common.adjust_lon(lon - this.long0);
+
+    //v 1.0
+    var sin_lat=Math.sin(lat);
+    var cos_lat=Math.cos(lat);
+
+    var sin_delta_lon=Math.sin(delta_lon);
+    var cos_delta_lon=Math.cos(delta_lon);
+
+    var g =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon;
+    if (g == -1.0) {
+      Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+ 2.0 * R);
+      return null;
+    }
+    var ksp = this.a * Math.sqrt(2.0 / (1.0 + g));
+    var x = ksp * cos_lat * sin_delta_lon + this.x0;
+    var y = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.x0;
+    p.x = x;
+    p.y = y
+    return p;
+  },//lamazFwd()
+
+/* Inverse equations
+  -----------------*/
+  inverse: function(p) {
+    p.x -= this.x0;
+    p.y -= this.y0;
+
+    var Rh = Math.sqrt(p.x *p.x +p.y * p.y);
+    var temp = Rh / (2.0 * this.a);
+
+    if (temp > 1) {
+      Proj4js.reportError("laea:Inv:DataError");
+      return null;
+    }
+
+    var z = 2.0 * Proj4js.common.asinz(temp);
+    var sin_z=Math.sin(z);
+    var cos_z=Math.cos(z);
+
+    var lon =this.long0;
+    if (Math.abs(Rh) > Proj4js.common.EPSLN) {
+       var lat = Proj4js.common.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh);
+       var temp =Math.abs(this.lat0) - Proj4js.common.HALF_PI;
+       if (Math.abs(temp) > Proj4js.common.EPSLN) {
+          temp = cos_z -this.sin_lat_o * Math.sin(lat);
+          if(temp!=0.0) lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh));
+       } else if (this.lat0 < 0.0) {
+          lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x,p.y));
+       } else {
+          lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
+       }
+    } else {
+      lat = this.lat0;
+    }
+    //return(OK);
+    p.x = lon;
+    p.y = lat;
+    return p;
+  }//lamazInv()
+};
+
+
+
+/* ======================================================================
+    projCode/aeqd.js
+   ====================================================================== */
+
+Proj4js.Proj.aeqd = {
+
+  init : function() {
+    this.sin_p12=Math.sin(this.lat0)
+    this.cos_p12=Math.cos(this.lat0)
+  },
+
+  forward: function(p) {
+    var lon=p.x;
+    var lat=p.y;
+    var ksp;
+
+    var sinphi=Math.sin(p.y);
+    var cosphi=Math.cos(p.y); 
+    var dlon = Proj4js.common.adjust_lon(lon - this.long0);
+    var coslon = Math.cos(dlon);
+    var g = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon;
+    if (Math.abs(Math.abs(g) - 1.0) < Proj4js.common.EPSLN) {
+       ksp = 1.0;
+       if (g < 0.0) {
+         Proj4js.reportError("aeqd:Fwd:PointError");
+         return;
+       }
+    } else {
+       var z = Math.acos(g);
+       ksp = z/Math.sin(z);
+    }
+    p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon);
+    p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon);
+    return p;
+  },
+
+  inverse: function(p){
+    p.x -= this.x0;
+    p.y -= this.y0;
+
+    var rh = Math.sqrt(p.x * p.x + p.y *p.y);
+    if (rh > (2.0 * Proj4js.common.HALF_PI * this.a)) {
+       Proj4js.reportError("aeqdInvDataError");
+       return;
+    }
+    var z = rh / this.a;
+
+    var sinz=Math.sin(z)
+    var cosz=Math.cos(z)
+
+    var lon = this.long0;
+    var lat;
+    if (Math.abs(rh) <= Proj4js.common.EPSLN) {
+      lat = this.lat0;
+    } else {
+      lat = Proj4js.common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh);
+      var con = Math.abs(this.lat0) - Proj4js.common.HALF_PI;
+      if (Math.abs(con) <= Proj4js.common.EPSLN) {
+        if (lat0 >= 0.0) {
+          lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x , -p.y));
+        } else {
+          lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x , p.y));
+        }
+      } else {
+        con = cosz - this.sin_p12 * Math.sin(lat);
+        if ((Math.abs(con) < Proj4js.common.EPSLN) && (Math.abs(p.x) < Proj4js.common.EPSLN)) {
+           //no-op, just keep the lon value as is
+        } else {
+          var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh));
+          lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh)));
+        }
+      }
+    }
+
+    p.x = lon;
+    p.y = lat;
+    return p;
+  } 
+};
+/* ======================================================================
+    projCode/moll.js
+   ====================================================================== */
+
+/*******************************************************************************
+NAME                            MOLLWEIDE
+
+PURPOSE:  Transforms input longitude and latitude to Easting and
+    Northing for the MOllweide projection.  The
+    longitude and latitude must be in radians.  The Easting
+    and Northing values will be returned in meters.
+
+PROGRAMMER              DATE
+----------              ----
+D. Steinwand, EROS      May, 1991;  Updated Sept, 1992; Updated Feb, 1993
+S. Nelson, EDC    Jun, 2993;  Made corrections in precision and
+          number of iterations.
+
+ALGORITHM REFERENCES
+
+1.  Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
+    U.S. Geological Survey Professional Paper 1453 , United State Government
+    Printing Office, Washington D.C., 1989.
+
+2.  Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
+    Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
+    State Government Printing Office, Washington D.C., 1987.
+*******************************************************************************/
+
+Proj4js.Proj.moll = {
+
+  /* Initialize the Mollweide projection
+    ------------------------------------*/
+  init: function(){
+    //no-op
+  },
+
+  /* Mollweide forward equations--mapping lat,long to x,y
+    ----------------------------------------------------*/
+  forward: function(p) {
+
+    /* Forward equations
+      -----------------*/
+    var lon=p.x;
+    var lat=p.y;
+
+    var delta_lon = Proj4js.common.adjust_lon(lon - this.long0);
+    var theta = lat;
+    var con = Proj4js.common.PI * Math.sin(lat);
+
+    /* Iterate using the Newton-Raphson method to find theta
+      -----------------------------------------------------*/
+    for (var i=0;;i++) {
+       var delta_theta = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta));
+       theta += delta_theta;
+       if (Math.abs(delta_theta) < Proj4js.common.EPSLN) break;
+       if (i >= 50) {
+          Proj4js.reportError("moll:Fwd:IterationError");
+         //return(241);
+       }
+    }
+    theta /= 2.0;
+
+    /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting"
+       this is done here because of precision problems with "cos(theta)"
+       --------------------------------------------------------------------------*/
+    if (Proj4js.common.PI/2 - Math.abs(lat) < Proj4js.common.EPSLN) delta_lon =0;
+    var x = 0.900316316158 * this.R * delta_lon * Math.cos(theta) + this.x0;
+    var y = 1.4142135623731 * this.R * Math.sin(theta) + this.y0;
+
+    p.x=x;
+    p.y=y;
+    return p;
+  },
+
+  inverse: function(p){
+    var theta;
+    var arg;
+
+    /* Inverse equations
+      -----------------*/
+    p.x-= this.x0;
+    //~ p.y -= this.y0;
+    var arg = p.y /  (1.4142135623731 * this.R);
+
+    /* Because of division by zero problems, 'arg' can not be 1.0.  Therefore
+       a number very close to one is used instead.
+       -------------------------------------------------------------------*/
+    if(Math.abs(arg) > 0.999999999999) arg=0.999999999999;
+    var theta =Math.asin(arg);
+    var lon = Proj4js.common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.R * Math.cos(theta))));
+    if(lon < (-Proj4js.common.PI)) lon= -Proj4js.common.PI;
+    if(lon > Proj4js.common.PI) lon= Proj4js.common.PI;
+    arg = (2.0 * theta + Math.sin(2.0 * theta)) / Proj4js.common.PI;
+    if(Math.abs(arg) > 1.0)arg=1.0;
+    var lat = Math.asin(arg);
+    //return(OK);
+
+    p.x=lon;
+    p.y=lat;
+    return p;
+  }
+};
+
diff --git a/src/main/webapp/lib/proj4js/proj4js-compressed.js b/src/main/webapp/lib/proj4js/proj4js-compressed.js
new file mode 100755
index 0000000000000000000000000000000000000000..d19bfad560bfdf46f5c435cc12be15c85aeaa99e
--- /dev/null
+++ b/src/main/webapp/lib/proj4js/proj4js-compressed.js
@@ -0,0 +1,206 @@
+/*
+  proj4js.js -- Javascript reprojection library. 
+  
+  Author:       Mike Adair madairATdmsolutions.ca
+                Richard Greenwood rich@greenwoodmap.com
+  License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html 
+                Note: This program is an almost direct port of the C library
+                Proj4.
+*/
+Proj4js={defaultDatum:'WGS84',proxyScript:null,defsLookupService:'http://spatialreference.org/ref',libPath:'../lib/',transform:function(source,dest,point){if(!source.readyToUse||!dest.readyToUse){this.reportError("Proj4js initialization for "+source.srsCode+" not yet complete");return;}
+if(point.transformed){this.log("point already transformed");return;}
+if((source.srsProjNumber=="900913"&&dest.datumCode!="WGS84")||(dest.srsProjNumber=="900913"&&source.datumCode!="WGS84")){var wgs84=Proj4js.WGS84;this.transform(source,wgs84,point);point.transformed=false;source=wgs84;}
+if(source.projName=="longlat"){point.x*=Proj4js.common.D2R;point.y*=Proj4js.common.D2R;}else{if(source.to_meter){point.x*=source.to_meter;point.y*=source.to_meter;}
+source.inverse(point);}
+if(source.from_greenwich){point.x+=source.from_greenwich;}
+point=this.datum_transform(source.datum,dest.datum,point);if(dest.from_greenwich){point.x-=dest.from_greenwich;}
+if(dest.projName=="longlat"){point.x*=Proj4js.common.R2D;point.y*=Proj4js.common.R2D;}else{dest.forward(point);if(dest.to_meter){point.x/=dest.to_meter;point.y/=dest.to_meter;}}
+point.transformed=true;return point;},datum_transform:function(source,dest,point){if(source.compare_datums(dest)){return point;}
+if(source.datum_type==Proj4js.common.PJD_NODATUM||dest.datum_type==Proj4js.common.PJD_NODATUM){return point;}
+if(source.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+if(dest.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+if(source.es!=dest.es||source.a!=dest.a||source.datum_type==Proj4js.common.PJD_3PARAM||source.datum_type==Proj4js.common.PJD_7PARAM||dest.datum_type==Proj4js.common.PJD_3PARAM||dest.datum_type==Proj4js.common.PJD_7PARAM)
+{source.geodetic_to_geocentric(point);if(source.datum_type==Proj4js.common.PJD_3PARAM||source.datum_type==Proj4js.common.PJD_7PARAM){source.geocentric_to_wgs84(point);}
+if(dest.datum_type==Proj4js.common.PJD_3PARAM||dest.datum_type==Proj4js.common.PJD_7PARAM){dest.geocentric_from_wgs84(point);}
+dest.geocentric_to_geodetic(point);}
+if(dest.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+return point;},reportError:function(msg){},log:function(msg){},loadProjDefinition:function(proj){if(this.defs[proj.srsCode])return this.defs[proj.srsCode];var options={method:'get',asynchronous:false,onSuccess:this.defsLoadedFromDisk.bind(this,proj.srsCode)}
+var url=this.libPath+'defs/'+proj.srsAuth.toUpperCase()+proj.srsProjNumber+'.js';new OpenLayers.Ajax.Request(url,options);if(this.defs[proj.srsCode])return this.defs[proj.srsCode];if(this.proxyScript){var url=this.proxyScript+this.defsLookupService+'/'+proj.srsAuth+'/'+proj.srsProjNumber+'/proj4';options.onSuccess=this.defsLoadedFromService.bind(this,proj.srsCode)
+options.onFailure=this.defsFailed.bind(this,proj.srsCode);new OpenLayers.Ajax.Request(url,options);}
+return this.defs[proj.srsCode];},defsLoadedFromDisk:function(srsCode,transport){eval(transport.responseText);},defsLoadedFromService:function(srsCode,transport){this.defs[srsCode]=transport.responseText;Proj4js.defs[srsCode]=transport.responseText},defsFailed:function(srsCode){this.reportError('failed to load projection definition for: '+srsCode);OpenLayers.Util.extend(this.defs[srsCode],this.defs['WGS84']);},loadProjCode:function(projName){if(this.Proj[projName])return;var options={method:'get',asynchronous:false,onSuccess:this.loadProjCodeSuccess.bind(this,projName),onFailure:this.loadProjCodeFailure.bind(this,projName)};var url=this.libPath+'projCode/'+projName+'.js';new OpenLayers.Ajax.Request(url,options);},loadProjCodeSuccess:function(projName,transport){eval(transport.responseText);if(this.Proj[projName].dependsOn){this.loadProjCode(this.Proj[projName].dependsOn);}},loadProjCodeFailure:function(projName){Proj4js.reportError("failed to find projection file for: "+projName);}};Proj4js.Proj=OpenLayers.Class({readyToUse:false,title:null,projName:null,units:null,datum:null,initialize:function(srsCode){this.srsCode=srsCode.toUpperCase();if(this.srsCode.indexOf("EPSG")==0){this.srsCode=this.srsCode;this.srsAuth='epsg';this.srsProjNumber=this.srsCode.substring(5);}else{this.srsAuth='';this.srsProjNumber=this.srsCode;}
+var defs=Proj4js.loadProjDefinition(this);if(defs){this.parseDefs(defs);Proj4js.loadProjCode(this.projName);this.callInit();}},callInit:function(){Proj4js.log('projection script loaded for:'+this.projName);OpenLayers.Util.extend(this,Proj4js.Proj[this.projName]);this.init();this.mapXYToLonLat=this.inverse;this.lonLatToMapXY=this.forward;this.readyToUse=true;},parseDefs:function(proj4opts){this.defData=proj4opts;var paramName,paramVal;var paramArray=this.defData.split("+");for(var prop=0;prop<paramArray.length;prop++){var property=paramArray[prop].split("=");paramName=property[0].toLowerCase();paramVal=property[1];switch(paramName.replace(/\s/gi,"")){case"":break;case"title":this.title=paramVal;break;case"proj":this.projName=paramVal.replace(/\s/gi,"");break;case"units":this.units=paramVal.replace(/\s/gi,"");break;case"datum":this.datumCode=paramVal.replace(/\s/gi,"");break;case"nadgrids":this.nagrids=paramVal.replace(/\s/gi,"");break;case"ellps":this.ellps=paramVal.replace(/\s/gi,"");break;case"a":this.a=parseFloat(paramVal);break;case"b":this.b=parseFloat(paramVal);break;case"lat_0":this.lat0=paramVal*Proj4js.common.D2R;break;case"lat_1":this.lat1=paramVal*Proj4js.common.D2R;break;case"lat_2":this.lat2=paramVal*Proj4js.common.D2R;break;case"lat_ts":this.lat_ts=paramVal*Proj4js.common.D2R;break;case"lon_0":this.long0=paramVal*Proj4js.common.D2R;break;case"x_0":this.x0=parseFloat(paramVal);break;case"y_0":this.y0=parseFloat(paramVal);break;case"k_0":this.k0=parseFloat(paramVal);break;case"k":this.k0=parseFloat(paramVal);break;case"R_A":this.R=parseFloat(paramVal);break;case"zone":this.zone=parseInt(paramVal);break;case"south":this.utmSouth=true;break;case"towgs84":this.datum_params=paramVal.split(",");break;case"to_meter":this.to_meter=parseFloat(paramVal);break;case"from_greenwich":this.from_greenwich=paramVal*Proj4js.common.D2R;break;case"pm":paramVal=paramVal.replace(/\s/gi,"");this.from_greenwich=Proj4js.PrimeMeridian[paramVal]?Proj4js.PrimeMeridian[paramVal]*Proj4js.common.D2R:0.0;break;case"no_defs":break;default:Proj4js.log("Unrecognized parameter: "+paramName);}}
+this.deriveConstants();},deriveConstants:function(){if(this.nagrids=='@null')this.datumCode='none';if(this.datumCode&&this.datumCode!='none'){var datumDef=Proj4js.Datum[this.datumCode];if(datumDef){this.datum_params=datumDef.towgs84.split(',');this.ellps=datumDef.ellipse;this.datumName=datumDef.datumName;}}
+if(!this.a){var ellipse=Proj4js.Ellipsoid[this.ellps]?Proj4js.Ellipsoid[this.ellps]:Proj4js.Ellipsoid['WGS84'];OpenLayers.Util.extend(this,ellipse);}
+if(this.rf&&!this.b)this.b=(1.0-1.0/this.rf)*this.a;if(Math.abs(this.a-this.b)<Proj4js.common.EPSLN)this.sphere=true;this.a2=this.a*this.a;this.b2=this.b*this.b;this.es=(this.a2-this.b2)/this.a2;this.e=Math.sqrt(this.es);this.ep2=(this.a2-this.b2)/this.b2;if(!this.k0)this.k0=1.0;this.datum=new Proj4js.datum(this);}});Proj4js.Proj.longlat={init:function(){},forward:function(pt){return pt;},inverse:function(pt){return pt;}};Proj4js.defs={'WGS84':"+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84",'EPSG:4326':"+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84",'EPSG:4269':"+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83"};Proj4js.common={PI:Math.PI,HALF_PI:Math.PI*0.5,TWO_PI:Math.PI*2,FORTPI:0.78539816339744833,R2D:57.2957795131,D2R:0.0174532925199,SEC_TO_RAD:4.84813681109535993589914102357e-6,EPSLN:1.0e-10,MAX_ITER:20,COS_67P5:0.38268343236508977,AD_C:1.0026000,PJD_UNKNOWN:0,PJD_3PARAM:1,PJD_7PARAM:2,PJD_GRIDSHIFT:3,PJD_WGS84:4,PJD_NODATUM:5,SRS_WGS84_SEMIMAJOR:6378137.0,msfnz:function(eccent,sinphi,cosphi){var con=eccent*sinphi;return cosphi/(Math.sqrt(1.0-con*con));},tsfnz:function(eccent,phi,sinphi){var con=eccent*sinphi;var com=.5*eccent;con=Math.pow(((1.0-con)/(1.0+con)),com);return(Math.tan(.5*(this.HALF_PI-phi))/con);},phi2z:function(eccent,ts){var eccnth=.5*eccent;var con,dphi;var phi=this.HALF_PI-2*Math.atan(ts);for(i=0;i<=15;i++){con=eccent*Math.sin(phi);dphi=this.HALF_PI-2*Math.atan(ts*(Math.pow(((1.0-con)/(1.0+con)),eccnth)))-phi;phi+=dphi;if(Math.abs(dphi)<=.0000000001)return phi;}
+alert("phi2z has NoConvergence");return(-9999);},qsfnz:function(eccent,sinphi,cosphi){var con;if(eccent>1.0e-7){con=eccent*sinphi;return((1.0-eccent*eccent)*(sinphi/(1.0-con*con)-(.5/eccent)*Math.log((1.0-con)/(1.0+con))));}else{return(2.0*sinphi);}},asinz:function(x){if(Math.abs(x)>1.0){x=(x>1.0)?1.0:-1.0;}
+return Math.asin(x);},e0fn:function(x){return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},e1fn:function(x){return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},e2fn:function(x){return(0.05859375*x*x*(1.0+0.75*x));},e3fn:function(x){return(x*x*x*(35.0/3072.0));},mlfn:function(e0,e1,e2,e3,phi){return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},srat:function(esinp,exp){return(Math.pow((1.0-esinp)/(1.0+esinp),exp));},sign:function(x){if(x<0.0)return(-1);else return(1);},adjust_lon:function(x){x=(Math.abs(x)<this.PI)?x:(x-(this.sign(x)*this.TWO_PI));return x;}};Proj4js.datum=OpenLayers.Class({initialize:function(proj){this.datum_type=Proj4js.common.PJD_WGS84;if(proj.datumCode&&proj.datumCode=='none'){this.datum_type=Proj4js.common.PJD_NODATUM;}
+if(proj&&proj.datum_params){for(var i=0;i<proj.datum_params.length;i++){proj.datum_params[i]=parseFloat(proj.datum_params[i]);}
+if(proj.datum_params[0]!=0||proj.datum_params[1]!=0||proj.datum_params[2]!=0){this.datum_type=Proj4js.common.PJD_3PARAM;}
+if(proj.datum_params.length>3){if(proj.datum_params[3]!=0||proj.datum_params[4]!=0||proj.datum_params[5]!=0||proj.datum_params[6]!=0){this.datum_type=Proj4js.common.PJD_7PARAM;proj.datum_params[3]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[4]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[5]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[6]=(proj.datum_params[6]/1000000.0)+1.0;}}}
+if(proj){this.a=proj.a;this.b=proj.b;this.es=proj.es;this.ep2=proj.ep2;this.datum_params=proj.datum_params;}},compare_datums:function(dest){if(this.datum_type!=dest.datum_type){return false;}else if(this.a!=dest.a||Math.abs(this.es-dest.es)>0.000000000050){return false;}else if(this.datum_type==Proj4js.common.PJD_3PARAM){return(this.datum_params[0]==dest.datum_params[0]&&this.datum_params[1]==dest.datum_params[1]&&this.datum_params[2]==dest.datum_params[2]);}else if(this.datum_type==Proj4js.common.PJD_7PARAM){return(this.datum_params[0]==dest.datum_params[0]&&this.datum_params[1]==dest.datum_params[1]&&this.datum_params[2]==dest.datum_params[2]&&this.datum_params[3]==dest.datum_params[3]&&this.datum_params[4]==dest.datum_params[4]&&this.datum_params[5]==dest.datum_params[5]&&this.datum_params[6]==dest.datum_params[6]);}else if(this.datum_type==Proj4js.common.PJD_GRIDSHIFT){return strcmp(pj_param(this.params,"snadgrids").s,pj_param(dest.params,"snadgrids").s)==0;}else{return true;}},geodetic_to_geocentric:function(p){var Longitude=p.x;var Latitude=p.y;var Height=p.z?p.z:0;var X;var Y;var Z;var Error_Code=0;var Rn;var Sin_Lat;var Sin2_Lat;var Cos_Lat;if(Latitude<-Proj4js.common.HALF_PI&&Latitude>-1.001*Proj4js.common.HALF_PI){Latitude=-Proj4js.common.HALF_PI;}else if(Latitude>Proj4js.common.HALF_PI&&Latitude<1.001*Proj4js.common.HALF_PI){Latitude=Proj4js.common.HALF_PI;}else if((Latitude<-Proj4js.common.HALF_PI)||(Latitude>Proj4js.common.HALF_PI)){Proj4js.reportError('geocent:lat out of range:'+Latitude);return null;}
+if(Longitude>Proj4js.common.PI)Longitude-=(2*Proj4js.common.PI);Sin_Lat=Math.sin(Latitude);Cos_Lat=Math.cos(Latitude);Sin2_Lat=Sin_Lat*Sin_Lat;Rn=this.a/(Math.sqrt(1.0e0-this.es*Sin2_Lat));X=(Rn+Height)*Cos_Lat*Math.cos(Longitude);Y=(Rn+Height)*Cos_Lat*Math.sin(Longitude);Z=((Rn*(1-this.es))+Height)*Sin_Lat;p.x=X;p.y=Y;p.z=Z;return Error_Code;},geocentric_to_geodetic:function(p){var genau=1.E-12;var genau2=(genau*genau);var maxiter=30;var P;var RR;var CT;var ST;var RX;var RK;var RN;var CPHI0;var SPHI0;var CPHI;var SPHI;var SDPHI;var At_Pole;var iter;var X=p.x;var Y=p.y;var Z=p.z?p.z:0.0;var Longitude;var Latitude;var Height;At_Pole=false;P=Math.sqrt(X*X+Y*Y);RR=Math.sqrt(X*X+Y*Y+Z*Z);if(P/this.a<genau){At_Pole=true;Longitude=0.0;if(RR/this.a<genau){Latitude=Proj4js.common.HALF_PI;Height=-this.b;return;}}else{Longitude=Math.atan2(Y,X);}
+CT=Z/RR;ST=P/RR;RX=1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);CPHI0=ST*(1.0-this.es)*RX;SPHI0=CT*RX;iter=0;do
+{iter++;RN=this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);Height=P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);RK=this.es*RN/(RN+Height);RX=1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);CPHI=ST*(1.0-RK)*RX;SPHI=CT*RX;SDPHI=SPHI*CPHI0-CPHI*SPHI0;CPHI0=CPHI;SPHI0=SPHI;}
+while(SDPHI*SDPHI>genau2&&iter<maxiter);Latitude=Math.atan(SPHI/Math.abs(CPHI));p.x=Longitude;p.y=Latitude;p.z=Height;return p;},geocentric_to_geodetic_noniter:function(p){var X=p.x;var Y=p.y;var Z=p.z?p.z:0;var Longitude;var Latitude;var Height;var W;var W2;var T0;var T1;var S0;var S1;var Sin_B0;var Sin3_B0;var Cos_B0;var Sin_p1;var Cos_p1;var Rn;var Sum;var At_Pole;X=parseFloat(X);Y=parseFloat(Y);Z=parseFloat(Z);At_Pole=false;if(X!=0.0)
+{Longitude=Math.atan2(Y,X);}
+else
+{if(Y>0)
+{Longitude=Proj4js.common.HALF_PI;}
+else if(Y<0)
+{Longitude=-Proj4js.common.HALF_PI;}
+else
+{At_Pole=true;Longitude=0.0;if(Z>0.0)
+{Latitude=Proj4js.common.HALF_PI;}
+else if(Z<0.0)
+{Latitude=-Proj4js.common.HALF_PI;}
+else
+{Latitude=Proj4js.common.HALF_PI;Height=-this.b;return;}}}
+W2=X*X+Y*Y;W=Math.sqrt(W2);T0=Z*Proj4js.common.AD_C;S0=Math.sqrt(T0*T0+W2);Sin_B0=T0/S0;Cos_B0=W/S0;Sin3_B0=Sin_B0*Sin_B0*Sin_B0;T1=Z+this.b*this.ep2*Sin3_B0;Sum=W-this.a*this.es*Cos_B0*Cos_B0*Cos_B0;S1=Math.sqrt(T1*T1+Sum*Sum);Sin_p1=T1/S1;Cos_p1=Sum/S1;Rn=this.a/Math.sqrt(1.0-this.es*Sin_p1*Sin_p1);if(Cos_p1>=Proj4js.common.COS_67P5)
+{Height=W/Cos_p1-Rn;}
+else if(Cos_p1<=-Proj4js.common.COS_67P5)
+{Height=W/-Cos_p1-Rn;}
+else
+{Height=Z/Sin_p1+Rn*(this.es-1.0);}
+if(At_Pole==false)
+{Latitude=Math.atan(Sin_p1/Cos_p1);}
+p.x=Longitude;p.y=Latitude;p.z=Height;return p;},geocentric_to_wgs84:function(p){if(this.datum_type==Proj4js.common.PJD_3PARAM)
+{p.x+=this.datum_params[0];p.y+=this.datum_params[1];p.z+=this.datum_params[2];}
+else
+{var Dx_BF=this.datum_params[0];var Dy_BF=this.datum_params[1];var Dz_BF=this.datum_params[2];var Rx_BF=this.datum_params[3];var Ry_BF=this.datum_params[4];var Rz_BF=this.datum_params[5];var M_BF=this.datum_params[6];var x_out=M_BF*(p.x-Rz_BF*p.y+Ry_BF*p.z)+Dx_BF;var y_out=M_BF*(Rz_BF*p.x+p.y-Rx_BF*p.z)+Dy_BF;var z_out=M_BF*(-Ry_BF*p.x+Rx_BF*p.y+p.z)+Dz_BF;p.x=x_out;p.y=y_out;p.z=z_out;}},geocentric_from_wgs84:function(p){if(this.datum_type==Proj4js.common.PJD_3PARAM)
+{p.x-=this.datum_params[0];p.y-=this.datum_params[1];p.z-=this.datum_params[2];}
+else
+{var Dx_BF=this.datum_params[0];var Dy_BF=this.datum_params[1];var Dz_BF=this.datum_params[2];var Rx_BF=this.datum_params[3];var Ry_BF=this.datum_params[4];var Rz_BF=this.datum_params[5];var M_BF=this.datum_params[6];var x_tmp=(p.x-Dx_BF)/M_BF;var y_tmp=(p.y-Dy_BF)/M_BF;var z_tmp=(p.z-Dz_BF)/M_BF;p.x=x_tmp+Rz_BF*y_tmp-Ry_BF*z_tmp;p.y=-Rz_BF*x_tmp+y_tmp+Rx_BF*z_tmp;p.z=Ry_BF*x_tmp-Rx_BF*y_tmp+z_tmp;}}});Proj4js.Point=OpenLayers.Class({initialize:function(x,y,z){if(typeof x=='object'){this.x=x[0];this.y=x[1];this.z=x[2]||0.0;}else{this.x=x;this.y=y;this.z=z||0.0;}},clone:function(){return new Proj4js.Point(this.x,this.y,this.z);},toString:function(){return("x="+this.x+",y="+this.y);},toShortString:function(){return(this.x+", "+this.y);}});Proj4js.PrimeMeridian={"greenwich":0.0,"lisbon":-9.131906111111,"paris":2.337229166667,"bogota":-74.080916666667,"madrid":-3.687938888889,"rome":12.452333333333,"bern":7.439583333333,"jakarta":106.807719444444,"ferro":-17.666666666667,"brussels":4.367975,"stockholm":18.058277777778,"athens":23.7163375,"oslo":10.722916666667};Proj4js.Ellipsoid={"MERIT":{a:6378137.0,rf:298.257,ellipseName:"MERIT 1983"},"SGS85":{a:6378136.0,rf:298.257,ellipseName:"Soviet Geodetic System 85"},"GRS80":{a:6378137.0,rf:298.257222101,ellipseName:"GRS 1980(IUGG, 1980)"},"IAU76":{a:6378140.0,rf:298.257,ellipseName:"IAU 1976"},"airy":{a:6377563.396,b:6356256.910,ellipseName:"Airy 1830"},"APL4.":{a:6378137,rf:298.25,ellipseName:"Appl. Physics. 1965"},"NWL9D":{a:6378145.0,rf:298.25,ellipseName:"Naval Weapons Lab., 1965"},"mod_airy":{a:6377340.189,b:6356034.446,ellipseName:"Modified Airy"},"andrae":{a:6377104.43,rf:300.0,ellipseName:"Andrae 1876 (Den., Iclnd.)"},"aust_SA":{a:6378160.0,rf:298.25,ellipseName:"Australian Natl & S. Amer. 1969"},"GRS67":{a:6378160.0,rf:298.2471674270,ellipseName:"GRS 67(IUGG 1967)"},"bessel":{a:6377397.155,rf:299.1528128,ellipseName:"Bessel 1841"},"bess_nam":{a:6377483.865,rf:299.1528128,ellipseName:"Bessel 1841 (Namibia)"},"clrk66":{a:6378206.4,b:6356583.8,ellipseName:"Clarke 1866"},"clrk80":{a:6378249.145,rf:293.4663,ellipseName:"Clarke 1880 mod."},"CPM":{a:6375738.7,rf:334.29,ellipseName:"Comm. des Poids et Mesures 1799"},"delmbr":{a:6376428.0,rf:311.5,ellipseName:"Delambre 1810 (Belgium)"},"engelis":{a:6378136.05,rf:298.2566,ellipseName:"Engelis 1985"},"evrst30":{a:6377276.345,rf:300.8017,ellipseName:"Everest 1830"},"evrst48":{a:6377304.063,rf:300.8017,ellipseName:"Everest 1948"},"evrst56":{a:6377301.243,rf:300.8017,ellipseName:"Everest 1956"},"evrst69":{a:6377295.664,rf:300.8017,ellipseName:"Everest 1969"},"evrstSS":{a:6377298.556,rf:300.8017,ellipseName:"Everest (Sabah & Sarawak)"},"fschr60":{a:6378166.0,rf:298.3,ellipseName:"Fischer (Mercury Datum) 1960"},"fschr60m":{a:6378155.0,rf:298.3,ellipseName:"Fischer 1960"},"fschr68":{a:6378150.0,rf:298.3,ellipseName:"Fischer 1968"},"helmert":{a:6378200.0,rf:298.3,ellipseName:"Helmert 1906"},"hough":{a:6378270.0,rf:297.0,ellipseName:"Hough"},"intl":{a:6378388.0,rf:297.0,ellipseName:"International 1909 (Hayford)"},"kaula":{a:6378163.0,rf:298.24,ellipseName:"Kaula 1961"},"lerch":{a:6378139.0,rf:298.257,ellipseName:"Lerch 1979"},"mprts":{a:6397300.0,rf:191.0,ellipseName:"Maupertius 1738"},"new_intl":{a:6378157.5,b:6356772.2,ellipseName:"New International 1967"},"plessis":{a:6376523.0,rf:6355863.0,ellipseName:"Plessis 1817 (France)"},"krass":{a:6378245.0,rf:298.3,ellipseName:"Krassovsky, 1942"},"SEasia":{a:6378155.0,b:6356773.3205,ellipseName:"Southeast Asia"},"walbeck":{a:6376896.0,b:6355834.8467,ellipseName:"Walbeck"},"WGS60":{a:6378165.0,rf:298.3,ellipseName:"WGS 60"},"WGS66":{a:6378145.0,rf:298.25,ellipseName:"WGS 66"},"WGS72":{a:6378135.0,rf:298.26,ellipseName:"WGS 72"},"WGS84":{a:6378137.0,rf:298.257223563,ellipseName:"WGS 84"},"sphere":{a:6370997.0,b:6370997.0,ellipseName:"Normal Sphere (r=6370997)"}};Proj4js.Datum={"WGS84":{towgs84:"0,0,0",ellipse:"WGS84",datumName:""},"GGRS87":{towgs84:"-199.87,74.79,246.62",ellipse:"GRS80",datumName:"Greek_Geodetic_Reference_System_1987"},"NAD83":{towgs84:"0,0,0",ellipse:"GRS80",datumName:"North_American_Datum_1983"},"NAD27":{nadgrids:"@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",ellipse:"clrk66",datumName:"North_American_Datum_1927"},"potsdam":{towgs84:"606.0,23.0,413.0",ellipse:"bessel",datumName:"Potsdam Rauenberg 1950 DHDN"},"carthage":{towgs84:"-263.0,6.0,431.0",ellipse:"clark80",datumName:"Carthage 1934 Tunisia"},"hermannskogel":{towgs84:"653.0,-212.0,449.0",ellipse:"bessel",datumName:"Hermannskogel"},"ire65":{towgs84:"482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",ellipse:"mod_airy",datumName:"Ireland 1965"},"nzgd49":{towgs84:"59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",ellipse:"intl",datumName:"New Zealand Geodetic Datum 1949"},"OSGB36":{towgs84:"446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",ellipse:"airy",datumName:"Airy 1830"}};Proj4js.WGS84=new Proj4js.Proj('WGS84');Proj4js.Datum['OSB36']=Proj4js.Datum['OSGB36'];Proj4js.Proj.sterea={dependsOn:'gauss',init:function(){Proj4js.Proj['gauss'].init.apply(this);if(!this.rc){Proj4js.reportError("sterea:init:E_ERROR_0");return;}
+this.sinc0=Math.sin(this.phic0);this.cosc0=Math.cos(this.phic0);this.R2=2.0*this.rc;if(!this.title)this.title="Oblique Stereographic Alternative";},forward:function(p){p.x=Proj4js.common.adjust_lon(p.x-this.long0);Proj4js.Proj['gauss'].forward.apply(this,[p]);sinc=Math.sin(p.y);cosc=Math.cos(p.y);cosl=Math.cos(p.x);k=this.k0*this.R2/(1.0+this.sinc0*sinc+this.cosc0*cosc*cosl);p.x=k*cosc*Math.sin(p.x);p.y=k*(this.cosc0*sinc-this.sinc0*cosc*cosl);p.x=this.a*p.x+this.x0;p.y=this.a*p.y+this.y0;return p;},inverse:function(p){var lon,lat;p.x=(p.x-this.x0)/this.a;p.y=(p.y-this.y0)/this.a;p.x/=this.k0;p.y/=this.k0;if((rho=Math.sqrt(p.x*p.x+p.y*p.y))){c=2.0*Math.atan2(rho,this.R2);sinc=Math.sin(c);cosc=Math.cos(c);lat=Math.asin(cosc*this.sinc0+p.y*sinc*this.cosc0/rho);lon=Math.atan2(p.x*sinc,rho*this.cosc0*cosc-p.y*this.sinc0*sinc);}else{lat=this.phic0;lon=0.;}
+p.x=lon;p.y=lat;Proj4js.Proj['gauss'].inverse.apply(this,[p]);p.x=Proj4js.common.adjust_lon(p.x+this.long0);return p;}};Proj4js.Proj.aea={init:function(){if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("aeaInitEqualLatitudes");return;}
+this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e3=Math.sqrt(this.es);this.sin_po=Math.sin(this.lat1);this.cos_po=Math.cos(this.lat1);this.t1=this.sin_po
+this.con=this.sin_po;this.ms1=Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);this.qs1=Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);this.sin_po=Math.sin(this.lat2);this.cos_po=Math.cos(this.lat2);this.t2=this.sin_po;this.ms2=Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);this.qs2=Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);this.sin_po=Math.sin(this.lat0);this.cos_po=Math.cos(this.lat0);this.t3=this.sin_po;this.qs0=Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);if(Math.abs(this.lat1-this.lat2)>Proj4js.common.EPSLN){this.ns0=(this.ms1*this.ms1-this.ms2*this.ms2)/(this.qs2-this.qs1);}else{this.ns0=this.con;}
+this.c=this.ms1*this.ms1+this.ns0*this.qs1;this.rh=this.a*Math.sqrt(this.c-this.ns0*this.qs0)/this.ns0;},forward:function(p){var lon=p.x;var lat=p.y;this.sin_phi=Math.sin(lat);this.cos_phi=Math.cos(lat);var qs=Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi);var rh1=this.a*Math.sqrt(this.c-this.ns0*qs)/this.ns0;var theta=this.ns0*Proj4js.common.adjust_lon(lon-this.long0);var x=rh1*Math.sin(theta)+this.x0;var y=this.rh-rh1*Math.cos(theta)+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var rh1,qs,con,theta,lon,lat;p.x-=this.x0;p.y=this.rh-p.y+this.y0;if(this.ns0>=0){rh1=Math.sqrt(p.x*p.x+p.y*p.y);con=1.0;}else{rh1=-Math.sqrt(p.x*p.x+p.y*p.y);con=-1.0;}
+theta=0.0;if(rh1!=0.0){theta=Math.atan2(con*p.x,con*p.y);}
+con=rh1*this.ns0/this.a;qs=(this.c-con*con)/this.ns0;if(this.e3>=1e-10){con=1-.5*(1.0-this.es)*Math.log((1.0-this.e3)/(1.0+this.e3))/this.e3;if(Math.abs(Math.abs(con)-Math.abs(qs))>.0000000001){lat=this.phi1z(this.e3,qs);}else{if(qs>=0){lat=.5*PI;}else{lat=-.5*PI;}}}else{lat=this.phi1z(e3,qs);}
+lon=Proj4js.common.adjust_lon(theta/this.ns0+this.long0);p.x=lon;p.y=lat;return p;},phi1z:function(eccent,qs){var con,com,dphi;var phi=Proj4js.common.asinz(.5*qs);if(eccent<Proj4js.common.EPSLN)return phi;var eccnts=eccent*eccent;for(var i=1;i<=25;i++){sinphi=Math.sin(phi);cosphi=Math.cos(phi);con=eccent*sinphi;com=1.0-con*con;dphi=.5*com*com/cosphi*(qs/(1.0-eccnts)-sinphi/com+.5/eccent*Math.log((1.0-con)/(1.0+con)));phi=phi+dphi;if(Math.abs(dphi)<=1e-7)return phi;}
+Proj4js.reportError("aea:phi1z:Convergence error");return null;}};function phi4z(eccent,e0,e1,e2,e3,a,b,c,phi){var sinphi,sin2ph,tanph,ml,mlp,con1,con2,con3,dphi,i;phi=a;for(i=1;i<=15;i++){sinphi=Math.sin(phi);tanphi=Math.tan(phi);c=tanphi*Math.sqrt(1.0-eccent*sinphi*sinphi);sin2ph=Math.sin(2.0*phi);ml=e0*phi-e1*sin2ph+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi);mlp=e0-2.0*e1*Math.cos(2.0*phi)+4.0*e2*Math.cos(4.0*phi)-6.0*e3*Math.cos(6.0*phi);con1=2.0*ml+c*(ml*ml+b)-2.0*a*(c*ml+1.0);con2=eccent*sin2ph*(ml*ml+b-2.0*a*ml)/(2.0*c);con3=2.0*(a-ml)*(c*mlp-2.0/sin2ph)-2.0*mlp;dphi=con1/(con2+con3);phi+=dphi;if(Math.abs(dphi)<=.0000000001)return(phi);}
+Proj4js.reportError("phi4z: No convergence");return null;}
+function e4fn(x){var con,com;con=1.0+x;com=1.0-x;return(Math.sqrt((Math.pow(con,con))*(Math.pow(com,com))));}
+Proj4js.Proj.poly={init:function(){var temp;if(this.lat0=0)this.lat0=90;this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);},forward:function(p){var sinphi,cosphi;var al;var c;var con,ml;var ms;var x,y;var lon=p.x;var lat=p.y;con=Proj4js.common.adjust_lon(lon-this.long0);if(Math.abs(lat)<=.0000001){x=this.x0+this.a*con;y=this.y0-this.a*this.ml0;}else{sinphi=Math.sin(lat);cosphi=Math.cos(lat);ml=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);ms=Proj4js.common.msfnz(this.e,sinphi,cosphi);con=sinphi;x=this.x0+this.a*ms*Math.sin(con)/sinphi;y=this.y0+this.a*(ml-this.ml0+ms*(1.0-Math.cos(con))/sinphi);}
+p.x=x;p.y=y;return p;},inverse:function(p){var sin_phi,cos_phi;var al;var b;var c;var con,ml;var iflg;var lon,lat;p.x-=this.x0;p.y-=this.y0;al=this.ml0+p.y/this.a;iflg=0;if(Math.abs(al)<=.0000001){lon=p.x/this.a+this.long0;lat=0.0;}else{b=al*al+(p.x/this.a)*(p.x/this.a);iflg=phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat);if(iflg!=1)return(iflg);lon=Proj4js.common.adjust_lon((asinz(p.x*c/this.a)/Math.sin(lat))+this.long0);}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.equi={init:function(){if(!this.x0)this.x0=0;if(!this.y0)this.y0=0;if(!this.lat0)this.lat0=0;if(!this.long0)this.long0=0;},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+this.a*dlon*Math.cos(this.lat0);var y=this.y0+this.a*lat;this.t1=x;this.t2=Math.cos(this.lat0);p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var lat=p.y/this.a;if(Math.abs(lat)>Proj4js.common.HALF_PI){Proj4js.reportError("equi:Inv:DataError");}
+var lon=Proj4js.common.adjust_lon(this.long0+p.x/(this.a*Math.cos(this.lat0)));p.x=lon;p.y=lat;}};Proj4js.Proj.merc={init:function(){if(this.lat_ts){if(this.sphere){this.k0=Math.cos(this.lat_ts);}else{this.k0=Proj4js.common.msfnz(this.es,Math.sin(this.lat_ts),Math.cos(this.lat_ts));}}},forward:function(p){var lon=p.x;var lat=p.y;if(lat*Proj4js.common.R2D>90.0&&lat*Proj4js.common.R2D<-90.0&&lon*Proj4js.common.R2D>180.0&&lon*Proj4js.common.R2D<-180.0){Proj4js.reportError("merc:forward: llInputOutOfRange: "+lon+" : "+lat);return null;}
+var x,y;if(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN){Proj4js.reportError("merc:forward: ll2mAtPoles");return null;}else{if(this.sphere){x=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(lon-this.long0);y=this.y0+this.a*this.k0*Math.log(Math.tan(Proj4js.common.FORTPI+0.5*lat));}else{var sinphi=Math.sin(lat);var ts=Proj4js.common.tsfnz(this.e,lat,sinphi);x=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(lon-this.long0);y=this.y0-this.a*this.k0*Math.log(ts);}
+p.x=x;p.y=y;return p;}},inverse:function(p){var x=p.x-this.x0;var y=p.y-this.y0;var lon,lat;if(this.sphere){lat=Proj4js.common.HALF_PI-2.0*Math.atan(Math.exp(-y/this.a*this.k0));}else{var ts=Math.exp(-y/(this.a*this.k0));lat=Proj4js.common.phi2z(this.e,ts);if(lat==-9999){Proj4js.reportError("merc:inverse: lat = -9999");return null;}}
+lon=Proj4js.common.adjust_lon(this.long0+x/(this.a*this.k0));p.x=lon;p.y=lat;return p;}};Proj4js.Proj.utm={dependsOn:'tmerc',init:function(){if(!this.zone){Proj4js.reportError("utm:init: zone must be specified for UTM");return;}
+this.lat0=0.0;this.long0=((6*Math.abs(this.zone))-183)*Proj4js.common.D2R;this.x0=500000.0;this.y0=this.utmSouth?10000000.0:0.0;this.k0=0.9996;Proj4js.Proj['tmerc'].init.apply(this);this.forward=Proj4js.Proj['tmerc'].forward;this.inverse=Proj4js.Proj['tmerc'].inverse;}};Proj4js.Proj.eqdc={init:function(){if(!this.mode)this.mode=0;this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.sinphi=Math.sin(this.lat1);this.cosphi=Math.cos(this.lat1);this.ms1=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml1=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat1);if(this.mode!=0){if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("eqdc:Init:EqualLatitudes");}
+this.sinphi=Math.sin(this.lat2);this.cosphi=Math.cos(this.lat2);this.ms2=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml2=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat2);if(Math.abs(this.lat1-this.lat2)>=Proj4js.common.EPSLN){this.ns=(this.ms1-this.ms2)/(this.ml2-this.ml1);}else{this.ns=this.sinphi;}}else{this.ns=this.sinphi;}
+this.g=this.ml1+this.ms1/this.ns;this.ml0=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);this.rh=this.a*(this.g-this.ml0);},forward:function(p){var lon=p.x;var lat=p.y;var ml=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);var rh1=this.a*(this.g-ml);var theta=this.ns*Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+rh1*Math.sin(theta);var y=this.y0+this.rh-rh1*Math.cos(theta);p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y=this.rh-p.y+this.y0;var con,rh1;if(this.ns>=0){var rh1=Math.sqrt(p.x*p.x+p.y*p.y);var con=1.0;}else{rh1=-Math.sqrt(p.x*p.x+p.y*p.y);con=-1.0;}
+var theta=0.0;if(rh1!=0.0)theta=Math.atan2(con*p.x,con*p.y);var ml=this.g-rh1/this.a;var lat=this.phi3z(this.ml,this.e0,this.e1,this.e2,this.e3);var lon=Proj4js.common.adjust_lon(this.long0+theta/this.ns);p.x=lon;p.y=lat;return p;},phi3z:function(ml,e0,e1,e2,e3){var phi;var dphi;phi=ml;for(var i=0;i<15;i++){dphi=(ml+e1*Math.sin(2.0*phi)-e2*Math.sin(4.0*phi)+e3*Math.sin(6.0*phi))/e0-phi;phi+=dphi;if(Math.abs(dphi)<=.0000000001){return phi;}}
+Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");return null;}};Proj4js.Proj.tmerc={init:function(){this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);},forward:function(p){var lon=p.x;var lat=p.y;var delta_lon=Proj4js.common.adjust_lon(lon-this.long0);var con;var x,y;var sin_phi=Math.sin(lat);var cos_phi=Math.cos(lat);if(this.sphere){var b=cos_phi*Math.sin(delta_lon);if((Math.abs(Math.abs(b)-1.0))<.0000000001){Proj4js.reportError("tmerc:forward: Point projects into infinity");return(93);}else{x=.5*this.a*this.k0*Math.log((1.0+b)/(1.0-b));con=Math.acos(cos_phi*Math.cos(delta_lon)/Math.sqrt(1.0-b*b));if(lat<0)con=-con;y=this.a*this.k0*(con-this.lat0);}}else{var al=cos_phi*delta_lon;var als=Math.pow(al,2);var c=this.ep2*Math.pow(cos_phi,2);var tq=Math.tan(lat);var t=Math.pow(tq,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var ml=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);x=this.k0*n*al*(1.0+als/6.0*(1.0-t+c+als/20.0*(5.0-18.0*t+Math.pow(t,2)+72.0*c-58.0*this.ep2)))+this.x0;y=this.k0*(ml-this.ml0+n*tq*(als*(0.5+als/24.0*(5.0-t+9.0*c+4.0*Math.pow(c,2)+als/30.0*(61.0-58.0*t+Math.pow(t,2)+600.0*c-330.0*this.ep2)))))+this.y0;}
+p.x=x;p.y=y;return p;},inverse:function(p){var con,phi;var delta_phi;var i;var max_iter=6;var lat,lon;if(this.sphere){var f=Math.exp(p.x/(this.a*this.k0));var g=.5*(f-1/f);var temp=this.lat0+p.y/(this.a*this.k0);var h=Math.cos(temp);con=Math.sqrt((1.0-h*h)/(1.0+g*g));lat=Math.asinz(con);if(temp<0)
+lat=-lat;if((g==0)&&(h==0)){lon=this.long0;}else{lon=Proj4js.common.adjust_lon(Math.atan2(g,h)+this.long0);}}else{var x=p.x-this.x0;var y=p.y-this.y0;con=(this.ml0+y/this.k0)/this.a;phi=con;for(i=0;;i++){delta_phi=((con+this.e1*Math.sin(2.0*phi)-this.e2*Math.sin(4.0*phi)+this.e3*Math.sin(6.0*phi))/this.e0)-phi;phi+=delta_phi;if(Math.abs(delta_phi)<=Proj4js.common.EPSLN)break;if(i>=max_iter){Proj4js.reportError("tmerc:inverse: Latitude failed to converge");return(95);}}
+if(Math.abs(phi)<Proj4js.common.HALF_PI){var sin_phi=Math.sin(phi);var cos_phi=Math.cos(phi);var tan_phi=Math.tan(phi);var c=this.ep2*Math.pow(cos_phi,2);var cs=Math.pow(c,2);var t=Math.pow(tan_phi,2);var ts=Math.pow(t,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var r=n*(1.0-this.es)/con;var d=x/(n*this.k0);var ds=Math.pow(d,2);lat=phi-(n*tan_phi*ds/r)*(0.5-ds/24.0*(5.0+3.0*t+10.0*c-4.0*cs-9.0*this.ep2-ds/30.0*(61.0+90.0*t+298.0*c+45.0*ts-252.0*this.ep2-3.0*cs)));lon=Proj4js.common.adjust_lon(this.long0+(d*(1.0-ds/6.0*(1.0+2.0*t+c-ds/20.0*(5.0-2.0*c+28.0*t-3.0*cs+8.0*this.ep2+24.0*ts)))/cos_phi));}else{lat=Proj4js.common.HALF_PI*Proj4js.common.sign(y);lon=this.long0;}}
+p.x=lon;p.y=lat;return p;}};Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs";Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];Proj4js.Proj.ortho={init:function(def){;this.sin_p14=Math.sin(this.lat0);this.cos_p14=Math.cos(this.lat0);},forward:function(p){var sinphi,cosphi;var dlon;var coslon;var ksp;var g;var lon=p.x;var lat=p.y;dlon=Proj4js.common.adjust_lon(lon-this.long0);sinphi=Math.sin(lat);cosphi=Math.cos(lat);coslon=Math.cos(dlon);g=this.sin_p14*sinphi+this.cos_p14*cosphi*coslon;ksp=1.0;if((g>0)||(Math.abs(g)<=Proj4js.common.EPSLN)){var x=this.a*ksp*cosphi*Math.sin(dlon);var y=this.y0+this.a*ksp*(this.cos_p14*sinphi-this.sin_p14*cosphi*coslon);}else{Proj4js.reportError("orthoFwdPointError");}
+p.x=x;p.y=y;return p;},inverse:function(p){var rh;var z;var sinz,cosz;var temp;var con;var lon,lat;p.x-=this.x0;p.y-=this.y0;rh=Math.sqrt(p.x*p.x+p.y*p.y);if(rh>this.a+.0000001){Proj4js.reportError("orthoInvDataError");}
+z=Proj4js.common.asinz(rh/this.a);sinz=Math.sin(z);cosi=Math.cos(z);lon=this.long0;if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.lat0;}
+lat=Proj4js.common.asinz(cosz*this.sin_p14+(y*sinz*this.cos_p14)/rh);con=Math.abs(lat0)-Proj4js.common.HALF_PI;if(Math.abs(con)<=Proj4js.common.EPSLN){if(this.lat0>=0){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x,-p.y));}else{lon=Proj4js.common.adjust_lon(this.long0-Math.atan2(-p.x,p.y));}}
+con=cosz-this.sin_p14*Math.sin(lat);if((Math.abs(con)>=Proj4js.common.EPSLN)||(Math.abs(x)>=Proj4js.common.EPSLN)){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2((p.x*sinz*this.cos_p14),(con*rh)));}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.stere={ssfn_:function(phit,sinphi,eccen){sinphi*=eccen;return(Math.tan(.5*(Proj4js.common.HALF_PI+phit))*Math.pow((1.-sinphi)/(1.+sinphi),.5*eccen));},TOL:1.e-8,NITER:8,CONV:1.e-10,S_POLE:0,N_POLE:1,OBLIQ:2,EQUIT:3,init:function(){this.phits=this.lat_ts?this.lat_ts:Proj4js.common.HALF_PI;var t=Math.abs(this.lat0);if((Math.abs(t)-Proj4js.common.HALF_PI)<Proj4js.common.EPSLN){this.mode=this.lat0<0.?this.S_POLE:this.N_POLE;}else{this.mode=t>Proj4js.common.EPSLN?this.OBLIQ:this.EQUIT;}
+this.phits=Math.abs(this.phits);if(this.es){var X;switch(this.mode){case this.N_POLE:case this.S_POLE:if(Math.abs(this.phits-Proj4js.common.HALF_PI)<Proj4js.common.EPSLN){this.akm1=2.*this.k0/Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e));}else{t=Math.sin(this.phits);this.akm1=Math.cos(this.phits)/Proj4js.common.tsfnz(this.e,this.phits,t);t*=this.e;this.akm1/=Math.sqrt(1.-t*t);}
+break;case this.EQUIT:this.akm1=2.*this.k0;break;case this.OBLIQ:t=Math.sin(this.lat0);X=2.*Math.atan(this.ssfn_(this.lat0,t,this.e))-Proj4js.common.HALF_PI;t*=this.e;this.akm1=2.*this.k0*Math.cos(this.lat0)/Math.sqrt(1.-t*t);this.sinX1=Math.sin(X);this.cosX1=Math.cos(X);break;}}else{switch(this.mode){case this.OBLIQ:this.sinph0=Math.sin(this.lat0);this.cosph0=Math.cos(this.lat0);case this.EQUIT:this.akm1=2.*this.k0;break;case this.S_POLE:case this.N_POLE:this.akm1=Math.abs(this.phits-Proj4js.common.HALF_PI)>=Proj4js.common.EPSLN?Math.cos(this.phits)/Math.tan(Proj4js.common.FORTPI-.5*this.phits):2.*this.k0;break;}}},forward:function(p){var lon=p.x;var lat=p.y;var x,y
+if(this.sphere){var sinphi,cosphi,coslam,sinlam;sinphi=Math.sin(lat);cosphi=Math.cos(lat);coslam=Math.cos(lon);sinlam=Math.sin(lon);switch(this.mode){case this.EQUIT:y=1.+cosphi*coslam;if(y<=Proj4js.common.EPSLN){F_ERROR;}
+y=this.akm1/y;x=y*cosphi*sinlam;y*=sinphi;break;case this.OBLIQ:y=1.+this.sinph0*sinphi+this.cosph0*cosphi*coslam;if(y<=Proj4js.common.EPSLN){F_ERROR;}
+y=this.akm1/y;x=y*cosphi*sinlam;y*=this.cosph0*sinphi-this.sinph0*cosphi*coslam;break;case this.N_POLE:coslam=-coslam;lat=-lat;case this.S_POLE:if(Math.abs(lat-Proj4js.common.HALF_PI)<this.TOL){F_ERROR;}
+y=this.akm1*Math.tan(Proj4js.common.FORTPI+.5*lat)
+x=sinlam*y;y*=coslam;break;}}else{coslam=Math.cos(lon);sinlam=Math.sin(lon);sinphi=Math.sin(lat);if(this.mode==this.OBLIQ||this.mode==this.EQUIT){X=2.*Math.atan(this.ssfn_(lat,sinphi,this.e));sinX=Math.sin(X-Proj4js.common.HALF_PI);cosX=Math.cos(X);}
+switch(this.mode){case this.OBLIQ:A=this.akm1/(this.cosX1*(1.+this.sinX1*sinX+this.cosX1*cosX*coslam));y=A*(this.cosX1*sinX-this.sinX1*cosX*coslam);x=A*cosX;break;case this.EQUIT:A=2.*this.akm1/(1.+cosX*coslam);y=A*sinX;x=A*cosX;break;case this.S_POLE:lat=-lat;coslam=-coslam;sinphi=-sinphi;case this.N_POLE:x=this.akm1*Proj4js.common.tsfnz(this.e,lat,sinphi);y=-x*coslam;break;}
+x=x*sinlam;}
+p.x=x*this.a+this.x0;p.y=y*this.a+this.y0;return p;},inverse:function(p){var x=(p.x-this.x0)/this.a;var y=(p.y-this.y0)/this.a;var lon,lat
+var cosphi,sinphi,tp=0.0,phi_l=0.0,rho,halfe=0.0,pi2=0.0;var i;if(this.sphere){var c,rh,sinc,cosc;rh=Math.sqrt(x*x+y*y);c=2.*Math.atan(rh/this.akm1);sinc=Math.sin(c);cosc=Math.cos(c);lon=0.;switch(this.mode){case this.EQUIT:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=0.;}else{lat=Math.asin(y*sinc/rh);}
+if(cosc!=0.||x!=0.)lon=Math.atan2(x*sinc,cosc*rh);break;case this.OBLIQ:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.phi0;}else{lat=Math.asin(cosc*sinph0+y*sinc*cosph0/rh);}
+c=cosc-sinph0*Math.sin(lat);if(c!=0.||x!=0.){lon=Math.atan2(x*sinc*cosph0,c*rh);}
+break;case this.N_POLE:y=-y;case this.S_POLE:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.phi0;}else{lat=Math.asin(this.mode==this.S_POLE?-cosc:cosc);}
+lon=(x==0.&&y==0.)?0.:Math.atan2(x,y);break;}}else{rho=Math.sqrt(x*x+y*y);switch(this.mode){case this.OBLIQ:case this.EQUIT:tp=2.*Math.atan2(rho*this.cosX1,this.akm1);cosphi=Math.cos(tp);sinphi=Math.sin(tp);if(rho==0.0){phi_l=Math.asin(cosphi*this.sinX1);}else{phi_l=Math.asin(cosphi*this.sinX1+(y*sinphi*this.cosX1/rho));}
+tp=Math.tan(.5*(Proj4js.common.HALF_PI+phi_l));x*=sinphi;y=rho*this.cosX1*cosphi-y*this.sinX1*sinphi;pi2=Proj4js.common.HALF_PI;halfe=.5*this.e;break;case this.N_POLE:y=-y;case this.S_POLE:tp=-rho/this.akm1
+phi_l=Proj4js.common.HALF_PI-2.*Math.atan(tp);pi2=-Proj4js.common.HALF_PI;halfe=-.5*this.e;break;}
+for(i=this.NITER;i--;phi_l=lat){sinphi=this.e*Math.sin(phi_l);lat=2.*Math.atan(tp*Math.pow((1.+sinphi)/(1.-sinphi),halfe))-pi2;if(Math.abs(phi_l-lat)<this.CONV){if(this.mode==this.S_POLE)lat=-lat;lon=(x==0.&&y==0.)?0.:Math.atan2(x,y);p.x=lon;p.y=lat
+return p;}}}}};Proj4js.Proj.mill={init:function(){},forward:function(p){var lon=p.x;var lat=p.y;dlon=Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+this.R*dlon;var y=this.y0+this.R*Math.log(Math.tan((Proj4js.common.PI/4.0)+(lat/2.5)))*1.25;p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var lon=Proj4js.common.adjust_lon(this.long0+p.x/this.R);var lat=2.5*(Math.atan(Math.exp(p.y/this.R/1.25))-Proj4js.common.PI/4.0);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.sinu={init:function(){this.R=6370997.0;},forward:function(p){var x,y,delta_lon;var lon=p.x;var lat=p.y;delta_lon=Proj4js.common.adjust_lon(lon-this.long0);x=this.R*delta_lon*Math.cos(lat)+this.x0;y=this.R*lat+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var lat,temp,lon;p.x-=this.x0;p.y-=this.y0;lat=p.y/this.R;if(Math.abs(lat)>Proj4js.common.HALF_PI){Proj4js.reportError("sinu:Inv:DataError");}
+temp=Math.abs(lat)-Proj4js.common.HALF_PI;if(Math.abs(temp)>Proj4js.common.EPSLN){temp=this.long0+p.x/(this.R*Math.cos(lat));lon=Proj4js.common.adjust_lon(temp);}else{lon=this.long0;}
+p.x=lon;p.y=lat;return p;}};var GEOCENT_LAT_ERROR=0x0001;var COS_67P5=0.38268343236508977;var AD_C=1.0026000;function cs_geodetic_to_geocentric(cs,p){var Longitude=p.x;var Latitude=p.y;var Height=p.z;var X;var Y;var Z;var Error_Code=0;var Rn;var Sin_Lat;var Sin2_Lat;var Cos_Lat;if(Latitude<-HALF_PI&&Latitude>-1.001*HALF_PI)
+Latitude=-HALF_PI;else if(Latitude>HALF_PI&&Latitude<1.001*HALF_PI)
+Latitude=HALF_PI;else if((Latitude<-HALF_PI)||(Latitude>HALF_PI))
+{Error_Code|=GEOCENT_LAT_ERROR;}
+if(!Error_Code)
+{if(Longitude>PI)
+Longitude-=(2*PI);Sin_Lat=Math.sin(Latitude);Cos_Lat=Math.cos(Latitude);Sin2_Lat=Sin_Lat*Sin_Lat;Rn=cs.a/(Math.sqrt(1.0e0-cs.es*Sin2_Lat));X=(Rn+Height)*Cos_Lat*Math.cos(Longitude);Y=(Rn+Height)*Cos_Lat*Math.sin(Longitude);Z=((Rn*(1-cs.es))+Height)*Sin_Lat;}
+p.x=X;p.y=Y;p.z=Z;return Error_Code;}
+function cs_geocentric_to_geodetic(cs,p){var X=p.x;var Y=p.y;var Z=p.z;var Longitude;var Latitude;var Height;var W;var W2;var T0;var T1;var S0;var S1;var Sin_B0;var Sin3_B0;var Cos_B0;var Sin_p1;var Cos_p1;var Rn;var Sum;var At_Pole;X=parseFloat(X);Y=parseFloat(Y);Z=parseFloat(Z);At_Pole=false;if(X!=0.0)
+{Longitude=Math.atan2(Y,X);}
+else
+{if(Y>0)
+{Longitude=HALF_PI;}
+else if(Y<0)
+{Longitude=-HALF_PI;}
+else
+{At_Pole=true;Longitude=0.0;if(Z>0.0)
+{Latitude=HALF_PI;}
+else if(Z<0.0)
+{Latitude=-HALF_PI;}
+else
+{Latitude=HALF_PI;Height=-cs.b;return;}}}
+W2=X*X+Y*Y;W=Math.sqrt(W2);T0=Z*AD_C;S0=Math.sqrt(T0*T0+W2);Sin_B0=T0/S0;Cos_B0=W/S0;Sin3_B0=Sin_B0*Sin_B0*Sin_B0;T1=Z+cs.b*cs.ep2*Sin3_B0;Sum=W-cs.a*cs.es*Cos_B0*Cos_B0*Cos_B0;S1=Math.sqrt(T1*T1+Sum*Sum);Sin_p1=T1/S1;Cos_p1=Sum/S1;Rn=cs.a/Math.sqrt(1.0-cs.es*Sin_p1*Sin_p1);if(Cos_p1>=COS_67P5)
+{Height=W/Cos_p1-Rn;}
+else if(Cos_p1<=-COS_67P5)
+{Height=W/-Cos_p1-Rn;}
+else
+{Height=Z/Sin_p1+Rn*(cs.es-1.0);}
+if(At_Pole==false)
+{Latitude=Math.atan(Sin_p1/Cos_p1);}
+p.x=Longitude;p.y=Latitude;p.z=Height;return 0;}
+function cs_geocentric_to_wgs84(defn,p){if(defn.datum_type==PJD_3PARAM)
+{p.x+=defn.datum_params[0];p.y+=defn.datum_params[1];p.z+=defn.datum_params[2];}
+else
+{var Dx_BF=defn.datum_params[0];var Dy_BF=defn.datum_params[1];var Dz_BF=defn.datum_params[2];var Rx_BF=defn.datum_params[3];var Ry_BF=defn.datum_params[4];var Rz_BF=defn.datum_params[5];var M_BF=defn.datum_params[6];var x_out=M_BF*(p.x-Rz_BF*p.y+Ry_BF*p.z)+Dx_BF;var y_out=M_BF*(Rz_BF*p.x+p.y-Rx_BF*p.z)+Dy_BF;var z_out=M_BF*(-Ry_BF*p.x+Rx_BF*p.y+p.z)+Dz_BF;p.x=x_out;p.y=y_out;p.z=z_out;}}
+function cs_geocentric_from_wgs84(defn,p){if(defn.datum_type==PJD_3PARAM)
+{p.x-=defn.datum_params[0];p.y-=defn.datum_params[1];p.z-=defn.datum_params[2];}
+else
+{var Dx_BF=defn.datum_params[0];var Dy_BF=defn.datum_params[1];var Dz_BF=defn.datum_params[2];var Rx_BF=defn.datum_params[3];var Ry_BF=defn.datum_params[4];var Rz_BF=defn.datum_params[5];var M_BF=defn.datum_params[6];var x_tmp=(p.x-Dx_BF)/M_BF;var y_tmp=(p.y-Dy_BF)/M_BF;var z_tmp=(p.z-Dz_BF)/M_BF;p.x=x_tmp+Rz_BF*y_tmp-Ry_BF*z_tmp;p.y=-Rz_BF*x_tmp+y_tmp+Rx_BF*z_tmp;p.z=Ry_BF*x_tmp-Rx_BF*y_tmp+z_tmp;}}
+Proj4js.Proj.vandg={init:function(){this.R=6370997.0;},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var x,y;if(Math.abs(lat)<=Proj4js.common.EPSLN){x=this.x0+this.R*dlon;y=this.y0;}
+var theta=Proj4js.common.asinz(2.0*Math.abs(lat/Proj4js.common.PI));if((Math.abs(dlon)<=Proj4js.common.EPSLN)||(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN)){x=this.x0;if(lat>=0){y=this.y0+Proj4js.common.PI*this.R*Math.tan(.5*theta);}else{y=this.y0+Proj4js.common.PI*this.R*-Math.tan(.5*theta);}}
+var al=.5*Math.abs((Proj4js.common.PI/dlon)-(dlon/Proj4js.common.PI));var asq=al*al;var sinth=Math.sin(theta);var costh=Math.cos(theta);var g=costh/(sinth+costh-1.0);var gsq=g*g;var m=g*(2.0/sinth-1.0);var msq=m*m;var con=Proj4js.common.PI*this.R*(al*(g-msq)+Math.sqrt(asq*(g-msq)*(g-msq)-(msq+asq)*(gsq-msq)))/(msq+asq);if(dlon<0){con=-con;}
+x=this.x0+con;con=Math.abs(con/(Proj4js.common.PI*this.R));if(lat>=0){y=this.y0+Proj4js.common.PI*this.R*Math.sqrt(1.0-con*con-2.0*al*con);}else{y=this.y0-Proj4js.common.PI*this.R*Math.sqrt(1.0-con*con-2.0*al*con);}
+p.x=x;p.y=y;return p;},inverse:function(p){var dlon;var xx,yy,xys,c1,c2,c3;var al,asq;var a1;var m1;var con;var th1;var d;p.x-=this.x0;p.y-=this.y0;con=Proj4js.common.PI*this.R;xx=p.x/con;yy=p.y/con;xys=xx*xx+yy*yy;c1=-Math.abs(yy)*(1.0+xys);c2=c1-2.0*yy*yy+xx*xx;c3=-2.0*c1+1.0+2.0*yy*yy+xys*xys;d=yy*yy/c3+(2.0*c2*c2*c2/c3/c3/c3-9.0*c1*c2/c3/c3)/27.0;a1=(c1-c2*c2/3.0/c3)/c3;m1=2.0*Math.sqrt(-a1/3.0);con=((3.0*d)/a1)/m1;if(Math.abs(con)>1.0){if(con>=0.0){con=1.0;}else{con=-1.0;}}
+th1=Math.acos(con)/3.0;if(p.y>=0){lat=(-m1*Math.cos(th1+Proj4js.common.PI/3.0)-c2/3.0/c3)*Proj4js.common.PI;}else{lat=-(-m1*Math.cos(th1+PI/3.0)-c2/3.0/c3)*Proj4js.common.PI;}
+if(Math.abs(xx)<Proj4js.common.EPSLN){lon=this.long0;}
+lon=Proj4js.common.adjust_lon(this.long0+Proj4js.common.PI*(xys-1.0+Math.sqrt(1.0+2.0*(xx*xx-yy*yy)+xys*xys))/2.0/xx);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.gauss={init:function(){sphi=Math.sin(this.lat0);cphi=Math.cos(this.lat0);cphi*=cphi;this.rc=Math.sqrt(1.0-this.es)/(1.0-this.es*sphi*sphi);this.C=Math.sqrt(1.0+this.es*cphi*cphi/(1.0-this.es));this.phic0=Math.asin(sphi/this.C);this.ratexp=0.5*this.C*this.e;this.K=Math.tan(0.5*this.phic0+Proj4js.common.FORTPI)/(Math.pow(Math.tan(0.5*this.lat0+Proj4js.common.FORTPI),this.C)*Proj4js.common.srat(this.e*sphi,this.ratexp));},forward:function(p){var lon=p.x;var lat=p.y;p.y=2.0*Math.atan(this.K*Math.pow(Math.tan(0.5*lat+Proj4js.common.FORTPI),this.C)*Proj4js.common.srat(this.e*Math.sin(lat),this.ratexp))-Proj4js.common.HALF_PI;p.x=this.C*lon;return p;},inverse:function(p){var DEL_TOL=1e-14;var lon=p.x/this.C;var lat=p.y;num=Math.pow(Math.tan(0.5*lat+Proj4js.common.FORTPI)/this.K,1./this.C);for(var i=Proj4js.common.MAX_ITER;i>0;--i){lat=2.0*Math.atan(num*Proj4js.common.srat(this.e*Math.sin(p.y),-0.5*this.e))-Proj4js.common.HALF_PI;if(Math.abs(lat-p.y)<DEL_TOL)break;p.y=lat;}
+if(!i){Proj4js.reportError("gauss:inverse:convergence failed");return null;}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.omerc={init:function(){if(!this.mode)this.mode=0;if(!this.lon1){this.lon1=0;this.mode=1;}
+if(!this.lon2)this.lon2=0;if(!this.lat2)this.lat2=0;var temp=this.b/this.a;var es=1.0-Math.pow(temp,2);var e=Math.sqrt(es);this.sin_p20=Math.sin(this.lat0);this.cos_p20=Math.cos(this.lat0);this.con=1.0-this.es*this.sin_p20*this.sin_p20;this.com=Math.sqrt(1.0-es);this.bl=Math.sqrt(1.0+this.es*Math.pow(this.cos_p20,4.0)/(1.0-es));this.al=this.a*this.bl*this.k0*this.com/this.con;if(Math.abs(this.lat0)<Proj4js.common.EPSLN){this.ts=1.0;this.d=1.0;this.el=1.0;}else{this.ts=Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20);this.con=Math.sqrt(this.con);this.d=this.bl*this.com/(this.cos_p20*this.con);if((this.d*this.d-1.0)>0.0){if(this.lat0>=0.0){this.f=this.d+Math.sqrt(this.d*this.d-1.0);}else{this.f=this.d-Math.sqrt(this.d*this.d-1.0);}}else{this.f=this.d;}
+this.el=this.f*Math.pow(this.ts,this.bl);}
+if(this.mode!=0){this.g=.5*(this.f-1.0/this.f);this.gama=Proj4js.common.asinz(Math.sin(this.alpha)/this.d);this.longc=this.longc-Proj4js.common.asinz(this.g*Math.tan(this.gama))/this.bl;this.con=Math.abs(this.lat0);if((this.con>Proj4js.common.EPSLN)&&(Math.abs(this.con-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN)){this.singam=Math.sin(this.gama);this.cosgam=Math.cos(this.gama);this.sinaz=Math.sin(this.alpha);this.cosaz=Math.cos(this.alpha);if(this.lat0>=0){this.u=(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}else{this.u=-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}}else{Proj4js.reportError("omerc:Init:DataError");}}else{this.sinphi=Math.sin(this.at1);this.ts1=Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);this.sinphi=Math.sin(this.lat2);this.ts2=Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);this.h=Math.pow(this.ts1,this.bl);this.l=Math.pow(this.ts2,this.bl);this.f=this.el/this.h;this.g=.5*(this.f-1.0/this.f);this.j=(this.el*this.el-this.l*this.h)/(this.el*this.el+this.l*this.h);this.p=(this.l-this.h)/(this.l+this.h);this.dlon=this.lon1-this.lon2;if(this.dlon<-Proj4js.common.PI)this.lon2=this.lon2-2.0*Proj4js.common.PI;if(this.dlon>Proj4js.common.PI)this.lon2=this.lon2+2.0*Proj4js.common.PI;this.dlon=this.lon1-this.lon2;this.longc=.5*(this.lon1+this.lon2)-Math.atan(this.j*Math.tan(.5*this.bl*this.dlon)/this.p)/this.bl;this.dlon=Proj4js.common.adjust_lon(this.lon1-this.longc);this.gama=Math.atan(Math.sin(this.bl*this.dlon)/this.g);this.alpha=Proj4js.common.asinz(this.d*Math.sin(this.gama));if(Math.abs(this.lat1-this.lat2)<=Proj4js.common.EPSLN){Proj4js.reportError("omercInitDataError");}else{this.con=Math.abs(this.lat1);}
+if((this.con<=Proj4js.common.EPSLN)||(Math.abs(this.con-HALF_PI)<=Proj4js.common.EPSLN)){Proj4js.reportError("omercInitDataError");}else{if(Math.abs(Math.abs(this.lat0)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN){Proj4js.reportError("omercInitDataError");}}
+this.singam=Math.sin(this.gam);this.cosgam=Math.cos(this.gam);this.sinaz=Math.sin(this.alpha);this.cosaz=Math.cos(this.alpha);if(this.lat0>=0){this.u=(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}else{this.u=-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}}},forward:function(p){var theta;var sin_phi,cos_phi;var b;var c,t,tq;var con,n,ml;var q,us,vl;var ul,vs;var s;var dlon;var ts1;var lon=p.x;var lat=p.y;sin_phi=Math.sin(lat);dlon=Proj4js.common.adjust_lon(lon-this.longc);vl=Math.sin(this.bl*dlon);if(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN){ts1=Proj4js.common.tsfnz(this.e,lat,sin_phi);q=this.el/(Math.pow(ts1,this.bl));s=.5*(q-1.0/q);t=.5*(q+1.0/q);ul=(s*this.singam-vl*this.cosgam)/t;con=Math.cos(this.bl*dlon);if(Math.abs(con)<.0000001){us=this.al*this.bl*dlon;}else{us=this.al*Math.atan((s*this.cosgam+vl*this.singam)/con)/this.bl;if(con<0)us=us+Proj4js.common.PI*this.al/this.bl;}}else{if(lat>=0){ul=this.singam;}else{ul=-this.singam;}
+us=this.al*lat/this.bl;}
+if(Math.abs(Math.abs(ul)-1.0)<=Proj4js.common.EPSLN){Proj4js.reportError("omercFwdInfinity");}
+vs=.5*this.al*Math.log((1.0-ul)/(1.0+ul))/this.bl;us=us-this.u;var x=this.x0+vs*this.cosaz+us*this.sinaz;var y=this.y0+us*this.cosaz-vs*this.sinaz;p.x=x;p.y=y;return p;},inverse:function(p){var delta_lon;var theta;var delta_theta;var sin_phi,cos_phi;var b;var c,t,tq;var con,n,ml;var vs,us,q,s,ts1;var vl,ul,bs;var dlon;var flag;p.x-=this.x0;p.y-=this.y0;flag=0;vs=p.x*this.cosaz-p.y*this.sinaz;us=p.y*this.cosaz+p.x*this.sinaz;us=us+this.u;q=Math.exp(-this.bl*vs/this.al);s=.5*(q-1.0/q);t=.5*(q+1.0/q);vl=Math.sin(this.bl*us/this.al);ul=(vl*this.cosgam+s*this.singam)/t;if(Math.abs(Math.abs(ul)-1.0)<=Proj4js.common.EPSLN)
+{lon=this.longc;if(ul>=0.0){lat=Proj4js.common.HALF_PI;}else{lat=-Proj4js.common.HALF_PI;}}else{con=1.0/this.bl;ts1=Math.pow((this.el/Math.sqrt((1.0+ul)/(1.0-ul))),con);lat=Proj4js.common.phi2z(this.e,ts1);theta=this.longc-Math.atan2((s*this.cosgam-vl*this.singam),con)/this.bl;lon=Proj4js.common.adjust_lon(theta);}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.lcc={init:function(){if(!this.lat2){this.lat2=this.lat0;}
+if(!this.k0)this.k0=1.0;if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("lcc:init: Equal Latitudes");return;}
+var temp=this.b/this.a;this.e=Math.sqrt(1.0-temp*temp);var sin1=Math.sin(this.lat1);var cos1=Math.cos(this.lat1);var ms1=Proj4js.common.msfnz(this.e,sin1,cos1);var ts1=Proj4js.common.tsfnz(this.e,this.lat1,sin1);var sin2=Math.sin(this.lat2);var cos2=Math.cos(this.lat2);var ms2=Proj4js.common.msfnz(this.e,sin2,cos2);var ts2=Proj4js.common.tsfnz(this.e,this.lat2,sin2);var ts0=Proj4js.common.tsfnz(this.e,this.lat0,Math.sin(this.lat0));if(Math.abs(this.lat1-this.lat2)>Proj4js.common.EPSLN){this.ns=Math.log(ms1/ms2)/Math.log(ts1/ts2);}else{this.ns=sin1;}
+this.f0=ms1/(this.ns*Math.pow(ts1,this.ns));this.rh=this.a*this.f0*Math.pow(ts0,this.ns);if(!this.title)this.title="Lambert Conformal Conic";},forward:function(p){var lon=p.x;var lat=p.y;if(lat<=90.0&&lat>=-90.0&&lon<=180.0&&lon>=-180.0){}else{Proj4js.reportError("lcc:forward: llInputOutOfRange: "+lon+" : "+lat);return null;}
+var con=Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI);var ts;if(con>Proj4js.common.EPSLN){ts=Proj4js.common.tsfnz(this.e,lat,Math.sin(lat));rh1=this.a*this.f0*Math.pow(ts,this.ns);}else{con=lat*this.ns;if(con<=0){Proj4js.reportError("lcc:forward: No Projection");return null;}
+rh1=0;}
+var theta=this.ns*Proj4js.common.adjust_lon(lon-this.long0);p.x=this.k0*(rh1*Math.sin(theta))+this.x0;p.y=this.k0*(this.rh-rh1*Math.cos(theta))+this.y0;return p;},inverse:function(p){var rh1,con,ts;var lat,lon;x=(p.x-this.x0)/this.k0;y=(this.rh-(p.y-this.y0)/this.k0);if(this.ns>0){rh1=Math.sqrt(x*x+y*y);con=1.0;}else{rh1=-Math.sqrt(x*x+y*y);con=-1.0;}
+var theta=0.0;if(rh1!=0){theta=Math.atan2((con*x),(con*y));}
+if((rh1!=0)||(this.ns>0.0)){con=1.0/this.ns;ts=Math.pow((rh1/(this.a*this.f0)),con);lat=Proj4js.common.phi2z(this.e,ts);if(lat==-9999)return null;}else{lat=-Proj4js.common.HALF_PI;}
+lon=Proj4js.common.adjust_lon(theta/this.ns+this.long0);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.laea={init:function(){this.sin_lat_o=Math.sin(this.lat0);this.cos_lat_o=Math.cos(this.lat0);},forward:function(p){var lon=p.x;var lat=p.y;var delta_lon=Proj4js.common.adjust_lon(lon-this.long0);var sin_lat=Math.sin(lat);var cos_lat=Math.cos(lat);var sin_delta_lon=Math.sin(delta_lon);var cos_delta_lon=Math.cos(delta_lon);var g=this.sin_lat_o*sin_lat+this.cos_lat_o*cos_lat*cos_delta_lon;if(g==-1.0){Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+2.0*R);return null;}
+var ksp=this.a*Math.sqrt(2.0/(1.0+g));var x=ksp*cos_lat*sin_delta_lon+this.x0;var y=ksp*(this.cos_lat_o*sin_lat-this.sin_lat_o*cos_lat*cos_delta_lon)+this.x0;p.x=x;p.y=y
+return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var Rh=Math.sqrt(p.x*p.x+p.y*p.y);var temp=Rh/(2.0*this.a);if(temp>1){Proj4js.reportError("laea:Inv:DataError");return null;}
+var z=2.0*Proj4js.common.asinz(temp);var sin_z=Math.sin(z);var cos_z=Math.cos(z);var lon=this.long0;if(Math.abs(Rh)>Proj4js.common.EPSLN){var lat=Proj4js.common.asinz(this.sin_lat_o*cos_z+this.cos_lat_o*sin_z*p.y/Rh);var temp=Math.abs(this.lat0)-Proj4js.common.HALF_PI;if(Math.abs(temp)>Proj4js.common.EPSLN){temp=cos_z-this.sin_lat_o*Math.sin(lat);if(temp!=0.0)lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh));}else if(this.lat0<0.0){lon=Proj4js.common.adjust_lon(this.long0-Math.atan2(-p.x,p.y));}else{lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x,-p.y));}}else{lat=this.lat0;}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.aeqd={init:function(){this.sin_p12=Math.sin(this.lat0)
+this.cos_p12=Math.cos(this.lat0)},forward:function(p){var lon=p.x;var lat=p.y;var ksp;var sinphi=Math.sin(p.y);var cosphi=Math.cos(p.y);var dlon=Proj4js.common.adjust_lon(lon-this.long0);var coslon=Math.cos(dlon);var g=this.sin_p12*sinphi+this.cos_p12*cosphi*coslon;if(Math.abs(Math.abs(g)-1.0)<Proj4js.common.EPSLN){ksp=1.0;if(g<0.0){Proj4js.reportError("aeqd:Fwd:PointError");return;}}else{var z=Math.acos(g);ksp=z/Math.sin(z);}
+p.x=this.x0+this.a*ksp*cosphi*Math.sin(dlon);p.y=this.y0+this.a*ksp*(this.cos_p12*sinphi-this.sin_p12*cosphi*coslon);return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var rh=Math.sqrt(p.x*p.x+p.y*p.y);if(rh>(2.0*Proj4js.common.HALF_PI*this.a)){Proj4js.reportError("aeqdInvDataError");return;}
+var z=rh/this.a;var sinz=Math.sin(z)
+var cosz=Math.cos(z)
+var lon=this.long0;var lat;if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.lat0;}else{lat=Proj4js.common.asinz(cosz*this.sin_p12+(p.y*sinz*this.cos_p12)/rh);var con=Math.abs(this.lat0)-Proj4js.common.HALF_PI;if(Math.abs(con)<=Proj4js.common.EPSLN){if(lat0>=0.0){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x,-p.y));}else{lon=Proj4js.common.adjust_lon(this.long0-Math.atan2(-p.x,p.y));}}else{con=cosz-this.sin_p12*Math.sin(lat);if((Math.abs(con)<Proj4js.common.EPSLN)&&(Math.abs(p.x)<Proj4js.common.EPSLN)){}else{var temp=Math.atan2((p.x*sinz*this.cos_p12),(con*rh));lon=Proj4js.common.adjust_lon(this.long0+Math.atan2((p.x*sinz*this.cos_p12),(con*rh)));}}}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.moll={init:function(){},forward:function(p){var lon=p.x;var lat=p.y;var delta_lon=Proj4js.common.adjust_lon(lon-this.long0);var theta=lat;var con=Proj4js.common.PI*Math.sin(lat);for(var i=0;;i++){var delta_theta=-(theta+Math.sin(theta)-con)/(1.0+Math.cos(theta));theta+=delta_theta;if(Math.abs(delta_theta)<Proj4js.common.EPSLN)break;if(i>=50){Proj4js.reportError("moll:Fwd:IterationError");}}
+theta/=2.0;if(Proj4js.common.PI/2-Math.abs(lat)<Proj4js.common.EPSLN)delta_lon=0;var x=0.900316316158*this.R*delta_lon*Math.cos(theta)+this.x0;var y=1.4142135623731*this.R*Math.sin(theta)+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var theta;var arg;p.x-=this.x0;var arg=p.y/(1.4142135623731*this.R);if(Math.abs(arg)>0.999999999999)arg=0.999999999999;var theta=Math.asin(arg);var lon=Proj4js.common.adjust_lon(this.long0+(p.x/(0.900316316158*this.R*Math.cos(theta))));if(lon<(-Proj4js.common.PI))lon=-Proj4js.common.PI;if(lon>Proj4js.common.PI)lon=Proj4js.common.PI;arg=(2.0*theta+Math.sin(2.0*theta))/Proj4js.common.PI;if(Math.abs(arg)>1.0)arg=1.0;var lat=Math.asin(arg);p.x=lon;p.y=lat;return p;}};
\ No newline at end of file
diff --git a/src/main/webapp/require.js b/src/main/webapp/require.js
deleted file mode 100644
index 068e34c8de8517eb9b5836029cae0cf8de1d1971..0000000000000000000000000000000000000000
--- a/src/main/webapp/require.js
+++ /dev/null
@@ -1,2063 +0,0 @@
-/** vim: et:ts=4:sw=4:sts=4
- * @license RequireJS 1.0.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
- * Available via the MIT or new BSD license.
- * see: http://github.com/jrburke/requirejs for details
- */
-/*jslint strict: false, plusplus: false, sub: true */
-/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
-
-var requirejs, require, define;
-(function (undefined) {
-    //Change this version number for each release.
-    var version = "1.0.8",
-        commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
-        cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g,
-        currDirRegExp = /^\.\//,
-        jsSuffixRegExp = /\.js$/,
-        ostring = Object.prototype.toString,
-        ap = Array.prototype,
-        aps = ap.slice,
-        apsp = ap.splice,
-        isBrowser = !!(typeof window !== "undefined" && navigator && document),
-        isWebWorker = !isBrowser && typeof importScripts !== "undefined",
-        //PS3 indicates loaded and complete, but need to wait for complete
-        //specifically. Sequence is "loading", "loaded", execution,
-        // then "complete". The UA check is unfortunate, but not sure how
-        //to feature test w/o causing perf issues.
-        readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
-                      /^complete$/ : /^(complete|loaded)$/,
-        defContextName = "_",
-        //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
-        isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]",
-        empty = {},
-        contexts = {},
-        globalDefQueue = [],
-        interactiveScript = null,
-        checkLoadedDepth = 0,
-        useInteractive = false,
-        reservedDependencies = {
-            require: true,
-            module: true,
-            exports: true
-        },
-        req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script,
-        src, subPath, mainScript, dataMain, globalI, ctx, jQueryCheck, checkLoadedTimeoutId;
-
-    function isFunction(it) {
-        return ostring.call(it) === "[object Function]";
-    }
-
-    function isArray(it) {
-        return ostring.call(it) === "[object Array]";
-    }
-
-    /**
-     * Simple function to mix in properties from source into target,
-     * but only if target does not already have a property of the same name.
-     * This is not robust in IE for transferring methods that match
-     * Object.prototype names, but the uses of mixin here seem unlikely to
-     * trigger a problem related to that.
-     */
-    function mixin(target, source, force) {
-        for (var prop in source) {
-            if (!(prop in empty) && (!(prop in target) || force)) {
-                target[prop] = source[prop];
-            }
-        }
-        return req;
-    }
-
-    /**
-     * Constructs an error with a pointer to an URL with more information.
-     * @param {String} id the error ID that maps to an ID on a web page.
-     * @param {String} message human readable error.
-     * @param {Error} [err] the original error, if there is one.
-     *
-     * @returns {Error}
-     */
-    function makeError(id, msg, err) {
-        var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
-        if (err) {
-            e.originalError = err;
-        }
-        return e;
-    }
-
-    /**
-     * Used to set up package paths from a packagePaths or packages config object.
-     * @param {Object} pkgs the object to store the new package config
-     * @param {Array} currentPackages an array of packages to configure
-     * @param {String} [dir] a prefix dir to use.
-     */
-    function configurePackageDir(pkgs, currentPackages, dir) {
-        var i, location, pkgObj;
-
-        for (i = 0; (pkgObj = currentPackages[i]); i++) {
-            pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj;
-            location = pkgObj.location;
-
-            //Add dir to the path, but avoid paths that start with a slash
-            //or have a colon (indicates a protocol)
-            if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) {
-                location = dir + "/" + (location || pkgObj.name);
-            }
-
-            //Create a brand new object on pkgs, since currentPackages can
-            //be passed in again, and config.pkgs is the internal transformed
-            //state for all package configs.
-            pkgs[pkgObj.name] = {
-                name: pkgObj.name,
-                location: location || pkgObj.name,
-                //Remove leading dot in main, so main paths are normalized,
-                //and remove any trailing .js, since different package
-                //envs have different conventions: some use a module name,
-                //some use a file name.
-                main: (pkgObj.main || "main")
-                      .replace(currDirRegExp, '')
-                      .replace(jsSuffixRegExp, '')
-            };
-        }
-    }
-
-    /**
-     * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM
-     * ready callbacks, but jQuery 1.6 supports a holdReady() API instead.
-     * At some point remove the readyWait/ready() support and just stick
-     * with using holdReady.
-     */
-    function jQueryHoldReady($, shouldHold) {
-        if ($.holdReady) {
-            $.holdReady(shouldHold);
-        } else if (shouldHold) {
-            $.readyWait += 1;
-        } else {
-            $.ready(true);
-        }
-    }
-
-    if (typeof define !== "undefined") {
-        //If a define is already in play via another AMD loader,
-        //do not overwrite.
-        return;
-    }
-
-    if (typeof requirejs !== "undefined") {
-        if (isFunction(requirejs)) {
-            //Do not overwrite and existing requirejs instance.
-            return;
-        } else {
-            cfg = requirejs;
-            requirejs = undefined;
-        }
-    }
-
-    //Allow for a require config object
-    if (typeof require !== "undefined" && !isFunction(require)) {
-        //assume it is a config object.
-        cfg = require;
-        require = undefined;
-    }
-
-    /**
-     * Creates a new context for use in require and define calls.
-     * Handle most of the heavy lifting. Do not want to use an object
-     * with prototype here to avoid using "this" in require, in case it
-     * needs to be used in more super secure envs that do not want this.
-     * Also there should not be that many contexts in the page. Usually just
-     * one for the default context, but could be extra for multiversion cases
-     * or if a package needs a special context for a dependency that conflicts
-     * with the standard context.
-     */
-    function newContext(contextName) {
-        var context, resume,
-            config = {
-                waitSeconds: 7,
-                baseUrl: "./",
-                paths: {},
-                pkgs: {},
-                catchError: {}
-            },
-            defQueue = [],
-            specified = {
-                "require": true,
-                "exports": true,
-                "module": true
-            },
-            urlMap = {},
-            defined = {},
-            loaded = {},
-            waiting = {},
-            waitAry = [],
-            urlFetched = {},
-            managerCounter = 0,
-            managerCallbacks = {},
-            plugins = {},
-            //Used to indicate which modules in a build scenario
-            //need to be full executed.
-            needFullExec = {},
-            fullExec = {},
-            resumeDepth = 0;
-
-        /**
-         * Trims the . and .. from an array of path segments.
-         * It will keep a leading path segment if a .. will become
-         * the first path segment, to help with module name lookups,
-         * which act like paths, but can be remapped. But the end result,
-         * all paths that use this function should look normalized.
-         * NOTE: this method MODIFIES the input array.
-         * @param {Array} ary the array of path segments.
-         */
-        function trimDots(ary) {
-            var i, part;
-            for (i = 0; (part = ary[i]); i++) {
-                if (part === ".") {
-                    ary.splice(i, 1);
-                    i -= 1;
-                } else if (part === "..") {
-                    if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
-                        //End of the line. Keep at least one non-dot
-                        //path segment at the front so it can be mapped
-                        //correctly to disk. Otherwise, there is likely
-                        //no path mapping for a path starting with '..'.
-                        //This can still fail, but catches the most reasonable
-                        //uses of ..
-                        break;
-                    } else if (i > 0) {
-                        ary.splice(i - 1, 2);
-                        i -= 2;
-                    }
-                }
-            }
-        }
-
-        /**
-         * Given a relative module name, like ./something, normalize it to
-         * a real name that can be mapped to a path.
-         * @param {String} name the relative name
-         * @param {String} baseName a real name that the name arg is relative
-         * to.
-         * @returns {String} normalized name
-         */
-        function normalize(name, baseName) {
-            var pkgName, pkgConfig;
-
-            //Adjust any relative paths.
-            if (name && name.charAt(0) === ".") {
-                //If have a base name, try to normalize against it,
-                //otherwise, assume it is a top-level require that will
-                //be relative to baseUrl in the end.
-                if (baseName) {
-                    if (config.pkgs[baseName]) {
-                        //If the baseName is a package name, then just treat it as one
-                        //name to concat the name with.
-                        baseName = [baseName];
-                    } else {
-                        //Convert baseName to array, and lop off the last part,
-                        //so that . matches that "directory" and not name of the baseName's
-                        //module. For instance, baseName of "one/two/three", maps to
-                        //"one/two/three.js", but we want the directory, "one/two" for
-                        //this normalization.
-                        baseName = baseName.split("/");
-                        baseName = baseName.slice(0, baseName.length - 1);
-                    }
-
-                    name = baseName.concat(name.split("/"));
-                    trimDots(name);
-
-                    //Some use of packages may use a . path to reference the
-                    //"main" module name, so normalize for that.
-                    pkgConfig = config.pkgs[(pkgName = name[0])];
-                    name = name.join("/");
-                    if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
-                        name = pkgName;
-                    }
-                } else if (name.indexOf("./") === 0) {
-                    // No baseName, so this is ID is resolved relative
-                    // to baseUrl, pull off the leading dot.
-                    name = name.substring(2);
-                }
-            }
-            return name;
-        }
-
-        /**
-         * Creates a module mapping that includes plugin prefix, module
-         * name, and path. If parentModuleMap is provided it will
-         * also normalize the name via require.normalize()
-         *
-         * @param {String} name the module name
-         * @param {String} [parentModuleMap] parent module map
-         * for the module name, used to resolve relative names.
-         *
-         * @returns {Object}
-         */
-        function makeModuleMap(name, parentModuleMap) {
-            var index = name ? name.indexOf("!") : -1,
-                prefix = null,
-                parentName = parentModuleMap ? parentModuleMap.name : null,
-                originalName = name,
-                normalizedName, url, pluginModule;
-
-            if (index !== -1) {
-                prefix = name.substring(0, index);
-                name = name.substring(index + 1, name.length);
-            }
-
-            if (prefix) {
-                prefix = normalize(prefix, parentName);
-            }
-
-            //Account for relative paths if there is a base name.
-            if (name) {
-                if (prefix) {
-                    pluginModule = defined[prefix];
-                    if (pluginModule && pluginModule.normalize) {
-                        //Plugin is loaded, use its normalize method.
-                        normalizedName = pluginModule.normalize(name, function (name) {
-                            return normalize(name, parentName);
-                        });
-                    } else {
-                        normalizedName = normalize(name, parentName);
-                    }
-                } else {
-                    //A regular module.
-                    normalizedName = normalize(name, parentName);
-
-                    url = urlMap[normalizedName];
-                    if (!url) {
-                        //Calculate url for the module, if it has a name.
-                        //Use name here since nameToUrl also calls normalize,
-                        //and for relative names that are outside the baseUrl
-                        //this causes havoc. Was thinking of just removing
-                        //parentModuleMap to avoid extra normalization, but
-                        //normalize() still does a dot removal because of
-                        //issue #142, so just pass in name here and redo
-                        //the normalization. Paths outside baseUrl are just
-                        //messy to support.
-                        url = context.nameToUrl(name, null, parentModuleMap);
-
-                        //Store the URL mapping for later.
-                        urlMap[normalizedName] = url;
-                    }
-                }
-            }
-
-            return {
-                prefix: prefix,
-                name: normalizedName,
-                parentMap: parentModuleMap,
-                url: url,
-                originalName: originalName,
-                fullName: prefix ? prefix + "!" + (normalizedName || '') : normalizedName
-            };
-        }
-
-        /**
-         * Determine if priority loading is done. If so clear the priorityWait
-         */
-        function isPriorityDone() {
-            var priorityDone = true,
-                priorityWait = config.priorityWait,
-                priorityName, i;
-            if (priorityWait) {
-                for (i = 0; (priorityName = priorityWait[i]); i++) {
-                    if (!loaded[priorityName]) {
-                        priorityDone = false;
-                        break;
-                    }
-                }
-                if (priorityDone) {
-                    delete config.priorityWait;
-                }
-            }
-            return priorityDone;
-        }
-
-        function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) {
-            return function () {
-                //A version of a require function that passes a moduleName
-                //value for items that may need to
-                //look up paths relative to the moduleName
-                var args = aps.call(arguments, 0), lastArg;
-                if (enableBuildCallback &&
-                    isFunction((lastArg = args[args.length - 1]))) {
-                    lastArg.__requireJsBuild = true;
-                }
-                args.push(relModuleMap);
-                return func.apply(null, args);
-            };
-        }
-
-        /**
-         * Helper function that creates a require function object to give to
-         * modules that ask for it as a dependency. It needs to be specific
-         * per module because of the implication of path mappings that may
-         * need to be relative to the module name.
-         */
-        function makeRequire(relModuleMap, enableBuildCallback, altRequire) {
-            var modRequire = makeContextModuleFunc(altRequire || context.require, relModuleMap, enableBuildCallback);
-
-            mixin(modRequire, {
-                nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),
-                toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),
-                defined: makeContextModuleFunc(context.requireDefined, relModuleMap),
-                specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),
-                isBrowser: req.isBrowser
-            });
-            return modRequire;
-        }
-
-        /*
-         * Queues a dependency for checking after the loader is out of a
-         * "paused" state, for example while a script file is being loaded
-         * in the browser, where it may have many modules defined in it.
-         */
-        function queueDependency(manager) {
-            context.paused.push(manager);
-        }
-
-        function execManager(manager) {
-            var i, ret, err, errFile, errModuleTree,
-                cb = manager.callback,
-                map = manager.map,
-                fullName = map.fullName,
-                args = manager.deps,
-                listeners = manager.listeners,
-                execCb = config.requireExecCb || req.execCb,
-                cjsModule;
-
-            //Call the callback to define the module, if necessary.
-            if (cb && isFunction(cb)) {
-                if (config.catchError.define) {
-                    try {
-                        ret = execCb(fullName, manager.callback, args, defined[fullName]);
-                    } catch (e) {
-                        err = e;
-                    }
-                } else {
-                    ret = execCb(fullName, manager.callback, args, defined[fullName]);
-                }
-
-                if (fullName) {
-                    //If setting exports via "module" is in play,
-                    //favor that over return value and exports. After that,
-                    //favor a non-undefined return value over exports use.
-                    cjsModule = manager.cjsModule;
-                    if (cjsModule &&
-                        cjsModule.exports !== undefined &&
-                        //Make sure it is not already the exports value
-                        cjsModule.exports !== defined[fullName]) {
-                        ret = defined[fullName] = manager.cjsModule.exports;
-                    } else if (ret === undefined && manager.usingExports) {
-                        //exports already set the defined value.
-                        ret = defined[fullName];
-                    } else {
-                        //Use the return value from the function.
-                        defined[fullName] = ret;
-                        //If this module needed full execution in a build
-                        //environment, mark that now.
-                        if (needFullExec[fullName]) {
-                            fullExec[fullName] = true;
-                        }
-                    }
-                }
-            } else if (fullName) {
-                //May just be an object definition for the module. Only
-                //worry about defining if have a module name.
-                ret = defined[fullName] = cb;
-
-                //If this module needed full execution in a build
-                //environment, mark that now.
-                if (needFullExec[fullName]) {
-                    fullExec[fullName] = true;
-                }
-            }
-
-            //Clean up waiting. Do this before error calls, and before
-            //calling back listeners, so that bookkeeping is correct
-            //in the event of an error and error is reported in correct order,
-            //since the listeners will likely have errors if the
-            //onError function does not throw.
-            if (waiting[manager.id]) {
-                delete waiting[manager.id];
-                manager.isDone = true;
-                context.waitCount -= 1;
-                if (context.waitCount === 0) {
-                    //Clear the wait array used for cycles.
-                    waitAry = [];
-                }
-            }
-
-            //Do not need to track manager callback now that it is defined.
-            delete managerCallbacks[fullName];
-
-            //Allow instrumentation like the optimizer to know the order
-            //of modules executed and their dependencies.
-            if (req.onResourceLoad && !manager.placeholder) {
-                req.onResourceLoad(context, map, manager.depArray);
-            }
-
-            if (err) {
-                errFile = (fullName ? makeModuleMap(fullName).url : '') ||
-                           err.fileName || err.sourceURL;
-                errModuleTree = err.moduleTree;
-                err = makeError('defineerror', 'Error evaluating ' +
-                                'module "' + fullName + '" at location "' +
-                                errFile + '":\n' +
-                                err + '\nfileName:' + errFile +
-                                '\nlineNumber: ' + (err.lineNumber || err.line), err);
-                err.moduleName = fullName;
-                err.moduleTree = errModuleTree;
-                return req.onError(err);
-            }
-
-            //Let listeners know of this manager's value.
-            for (i = 0; (cb = listeners[i]); i++) {
-                cb(ret);
-            }
-
-            return undefined;
-        }
-
-        /**
-         * Helper that creates a callack function that is called when a dependency
-         * is ready, and sets the i-th dependency for the manager as the
-         * value passed to the callback generated by this function.
-         */
-        function makeArgCallback(manager, i) {
-            return function (value) {
-                //Only do the work if it has not been done
-                //already for a dependency. Cycle breaking
-                //logic in forceExec could mean this function
-                //is called more than once for a given dependency.
-                if (!manager.depDone[i]) {
-                    manager.depDone[i] = true;
-                    manager.deps[i] = value;
-                    manager.depCount -= 1;
-                    if (!manager.depCount) {
-                        //All done, execute!
-                        execManager(manager);
-                    }
-                }
-            };
-        }
-
-        function callPlugin(pluginName, depManager) {
-            var map = depManager.map,
-                fullName = map.fullName,
-                name = map.name,
-                plugin = plugins[pluginName] ||
-                        (plugins[pluginName] = defined[pluginName]),
-                load;
-
-            //No need to continue if the manager is already
-            //in the process of loading.
-            if (depManager.loading) {
-                return;
-            }
-            depManager.loading = true;
-
-            load = function (ret) {
-                depManager.callback = function () {
-                    return ret;
-                };
-                execManager(depManager);
-
-                loaded[depManager.id] = true;
-
-                //The loading of this plugin
-                //might have placed other things
-                //in the paused queue. In particular,
-                //a loader plugin that depends on
-                //a different plugin loaded resource.
-                resume();
-            };
-
-            //Allow plugins to load other code without having to know the
-            //context or how to "complete" the load.
-            load.fromText = function (moduleName, text) {
-                /*jslint evil: true */
-                var hasInteractive = useInteractive;
-
-                //Indicate a the module is in process of loading.
-                loaded[moduleName] = false;
-                context.scriptCount += 1;
-
-                //Indicate this is not a "real" module, so do not track it
-                //for builds, it does not map to a real file.
-                context.fake[moduleName] = true;
-
-                //Turn off interactive script matching for IE for any define
-                //calls in the text, then turn it back on at the end.
-                if (hasInteractive) {
-                    useInteractive = false;
-                }
-
-                req.exec(text);
-
-                if (hasInteractive) {
-                    useInteractive = true;
-                }
-
-                //Support anonymous modules.
-                context.completeLoad(moduleName);
-            };
-
-            //No need to continue if the plugin value has already been
-            //defined by a build.
-            if (fullName in defined) {
-                load(defined[fullName]);
-            } else {
-                //Use parentName here since the plugin's name is not reliable,
-                //could be some weird string with no path that actually wants to
-                //reference the parentName's path.
-                plugin.load(name, makeRequire(map.parentMap, true, function (deps, cb) {
-                    var moduleDeps = [],
-                        i, dep, depMap;
-                    //Convert deps to full names and hold on to them
-                    //for reference later, when figuring out if they
-                    //are blocked by a circular dependency.
-                    for (i = 0; (dep = deps[i]); i++) {
-                        depMap = makeModuleMap(dep, map.parentMap);
-                        deps[i] = depMap.fullName;
-                        if (!depMap.prefix) {
-                            moduleDeps.push(deps[i]);
-                        }
-                    }
-                    depManager.moduleDeps = (depManager.moduleDeps || []).concat(moduleDeps);
-                    return context.require(deps, cb);
-                }), load, config);
-            }
-        }
-
-        /**
-         * Adds the manager to the waiting queue. Only fully
-         * resolved items should be in the waiting queue.
-         */
-        function addWait(manager) {
-            if (!waiting[manager.id]) {
-                waiting[manager.id] = manager;
-                waitAry.push(manager);
-                context.waitCount += 1;
-            }
-        }
-
-        /**
-         * Function added to every manager object. Created out here
-         * to avoid new function creation for each manager instance.
-         */
-        function managerAdd(cb) {
-            this.listeners.push(cb);
-        }
-
-        function getManager(map, shouldQueue) {
-            var fullName = map.fullName,
-                prefix = map.prefix,
-                plugin = prefix ? plugins[prefix] ||
-                                (plugins[prefix] = defined[prefix]) : null,
-                manager, created, pluginManager, prefixMap;
-
-            if (fullName) {
-                manager = managerCallbacks[fullName];
-            }
-
-            if (!manager) {
-                created = true;
-                manager = {
-                    //ID is just the full name, but if it is a plugin resource
-                    //for a plugin that has not been loaded,
-                    //then add an ID counter to it.
-                    id: (prefix && !plugin ?
-                        (managerCounter++) + '__p@:' : '') +
-                        (fullName || '__r@' + (managerCounter++)),
-                    map: map,
-                    depCount: 0,
-                    depDone: [],
-                    depCallbacks: [],
-                    deps: [],
-                    listeners: [],
-                    add: managerAdd
-                };
-
-                specified[manager.id] = true;
-
-                //Only track the manager/reuse it if this is a non-plugin
-                //resource. Also only track plugin resources once
-                //the plugin has been loaded, and so the fullName is the
-                //true normalized value.
-                if (fullName && (!prefix || plugins[prefix])) {
-                    managerCallbacks[fullName] = manager;
-                }
-            }
-
-            //If there is a plugin needed, but it is not loaded,
-            //first load the plugin, then continue on.
-            if (prefix && !plugin) {
-                prefixMap = makeModuleMap(prefix);
-
-                //Clear out defined and urlFetched if the plugin was previously
-                //loaded/defined, but not as full module (as in a build
-                //situation). However, only do this work if the plugin is in
-                //defined but does not have a module export value.
-                if (prefix in defined && !defined[prefix]) {
-                    delete defined[prefix];
-                    delete urlFetched[prefixMap.url];
-                }
-
-                pluginManager = getManager(prefixMap, true);
-                pluginManager.add(function (plugin) {
-                    //Create a new manager for the normalized
-                    //resource ID and have it call this manager when
-                    //done.
-                    var newMap = makeModuleMap(map.originalName, map.parentMap),
-                        normalizedManager = getManager(newMap, true);
-
-                    //Indicate this manager is a placeholder for the real,
-                    //normalized thing. Important for when trying to map
-                    //modules and dependencies, for instance, in a build.
-                    manager.placeholder = true;
-
-                    normalizedManager.add(function (resource) {
-                        manager.callback = function () {
-                            return resource;
-                        };
-                        execManager(manager);
-                    });
-                });
-            } else if (created && shouldQueue) {
-                //Indicate the resource is not loaded yet if it is to be
-                //queued.
-                loaded[manager.id] = false;
-                queueDependency(manager);
-                addWait(manager);
-            }
-
-            return manager;
-        }
-
-        function main(inName, depArray, callback, relModuleMap) {
-            var moduleMap = makeModuleMap(inName, relModuleMap),
-                name = moduleMap.name,
-                fullName = moduleMap.fullName,
-                manager = getManager(moduleMap),
-                id = manager.id,
-                deps = manager.deps,
-                i, depArg, depName, depPrefix, cjsMod;
-
-            if (fullName) {
-                //If module already defined for context, or already loaded,
-                //then leave. Also leave if jQuery is registering but it does
-                //not match the desired version number in the config.
-                if (fullName in defined || loaded[id] === true ||
-                    (fullName === "jquery" && config.jQuery &&
-                     config.jQuery !== callback().fn.jquery)) {
-                    return;
-                }
-
-                //Set specified/loaded here for modules that are also loaded
-                //as part of a layer, where onScriptLoad is not fired
-                //for those cases. Do this after the inline define and
-                //dependency tracing is done.
-                specified[id] = true;
-                loaded[id] = true;
-
-                //If module is jQuery set up delaying its dom ready listeners.
-                if (fullName === "jquery" && callback) {
-                    jQueryCheck(callback());
-                }
-            }
-
-            //Attach real depArray and callback to the manager. Do this
-            //only if the module has not been defined already, so do this after
-            //the fullName checks above. IE can call main() more than once
-            //for a module.
-            manager.depArray = depArray;
-            manager.callback = callback;
-
-            //Add the dependencies to the deps field, and register for callbacks
-            //on the dependencies.
-            for (i = 0; i < depArray.length; i++) {
-                depArg = depArray[i];
-                //There could be cases like in IE, where a trailing comma will
-                //introduce a null dependency, so only treat a real dependency
-                //value as a dependency.
-                if (depArg) {
-                    //Split the dependency name into plugin and name parts
-                    depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap));
-                    depName = depArg.fullName;
-                    depPrefix = depArg.prefix;
-
-                    //Fix the name in depArray to be just the name, since
-                    //that is how it will be called back later.
-                    depArray[i] = depName;
-
-                    //Fast path CommonJS standard dependencies.
-                    if (depName === "require") {
-                        deps[i] = makeRequire(moduleMap);
-                    } else if (depName === "exports") {
-                        //CommonJS module spec 1.1
-                        deps[i] = defined[fullName] = {};
-                        manager.usingExports = true;
-                    } else if (depName === "module") {
-                        //CommonJS module spec 1.1
-                        manager.cjsModule = cjsMod = deps[i] = {
-                            id: name,
-                            uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined,
-                            exports: defined[fullName]
-                        };
-                    } else if (depName in defined && !(depName in waiting) &&
-                               (!(fullName in needFullExec) ||
-                                (fullName in needFullExec && fullExec[depName]))) {
-                        //Module already defined, and not in a build situation
-                        //where the module is a something that needs full
-                        //execution and this dependency has not been fully
-                        //executed. See r.js's requirePatch.js for more info
-                        //on fullExec.
-                        deps[i] = defined[depName];
-                    } else {
-                        //Mark this dependency as needing full exec if
-                        //the current module needs full exec.
-                        if (fullName in needFullExec) {
-                            needFullExec[depName] = true;
-                            //Reset state so fully executed code will get
-                            //picked up correctly.
-                            delete defined[depName];
-                            urlFetched[depArg.url] = false;
-                        }
-
-                        //Either a resource that is not loaded yet, or a plugin
-                        //resource for either a plugin that has not
-                        //loaded yet.
-                        manager.depCount += 1;
-                        manager.depCallbacks[i] = makeArgCallback(manager, i);
-                        getManager(depArg, true).add(manager.depCallbacks[i]);
-                    }
-                }
-            }
-
-            //Do not bother tracking the manager if it is all done.
-            if (!manager.depCount) {
-                //All done, execute!
-                execManager(manager);
-            } else {
-                addWait(manager);
-            }
-        }
-
-        /**
-         * Convenience method to call main for a define call that was put on
-         * hold in the defQueue.
-         */
-        function callDefMain(args) {
-            main.apply(null, args);
-        }
-
-        /**
-         * jQuery 1.4.3+ supports ways to hold off calling
-         * calling jQuery ready callbacks until all scripts are loaded. Be sure
-         * to track it if the capability exists.. Also, since jQuery 1.4.3 does
-         * not register as a module, need to do some global inference checking.
-         * Even if it does register as a module, not guaranteed to be the precise
-         * name of the global. If a jQuery is tracked for this context, then go
-         * ahead and register it as a module too, if not already in process.
-         */
-        jQueryCheck = function (jqCandidate) {
-            if (!context.jQuery) {
-                var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null);
-
-                if ($) {
-                    //If a specific version of jQuery is wanted, make sure to only
-                    //use this jQuery if it matches.
-                    if (config.jQuery && $.fn.jquery !== config.jQuery) {
-                        return;
-                    }
-
-                    if ("holdReady" in $ || "readyWait" in $) {
-                        context.jQuery = $;
-
-                        //Manually create a "jquery" module entry if not one already
-                        //or in process. Note this could trigger an attempt at
-                        //a second jQuery registration, but does no harm since
-                        //the first one wins, and it is the same value anyway.
-                        callDefMain(["jquery", [], function () {
-                            return jQuery;
-                        }]);
-
-                        //Ask jQuery to hold DOM ready callbacks.
-                        if (context.scriptCount) {
-                            jQueryHoldReady($, true);
-                            context.jQueryIncremented = true;
-                        }
-                    }
-                }
-            }
-        };
-
-        function findCycle(manager, traced) {
-            var fullName = manager.map.fullName,
-                depArray = manager.depArray,
-                fullyLoaded = true,
-                i, depName, depManager, result;
-
-            if (manager.isDone || !fullName || !loaded[fullName]) {
-                return result;
-            }
-
-            //Found the cycle.
-            if (traced[fullName]) {
-                return manager;
-            }
-
-            traced[fullName] = true;
-
-            //Trace through the dependencies.
-            if (depArray) {
-                for (i = 0; i < depArray.length; i++) {
-                    //Some array members may be null, like if a trailing comma
-                    //IE, so do the explicit [i] access and check if it has a value.
-                    depName = depArray[i];
-                    if (!loaded[depName] && !reservedDependencies[depName]) {
-                        fullyLoaded = false;
-                        break;
-                    }
-                    depManager = waiting[depName];
-                    if (depManager && !depManager.isDone && loaded[depName]) {
-                        result = findCycle(depManager, traced);
-                        if (result) {
-                            break;
-                        }
-                    }
-                }
-                if (!fullyLoaded) {
-                    //Discard the cycle that was found, since it cannot
-                    //be forced yet. Also clear this module from traced.
-                    result = undefined;
-                    delete traced[fullName];
-                }
-            }
-
-            return result;
-        }
-
-        function forceExec(manager, traced) {
-            var fullName = manager.map.fullName,
-                depArray = manager.depArray,
-                i, depName, depManager, prefix, prefixManager, value;
-
-
-            if (manager.isDone || !fullName || !loaded[fullName]) {
-                return undefined;
-            }
-
-            if (fullName) {
-                if (traced[fullName]) {
-                    return defined[fullName];
-                }
-
-                traced[fullName] = true;
-            }
-
-            //Trace through the dependencies.
-            if (depArray) {
-                for (i = 0; i < depArray.length; i++) {
-                    //Some array members may be null, like if a trailing comma
-                    //IE, so do the explicit [i] access and check if it has a value.
-                    depName = depArray[i];
-                    if (depName) {
-                        //First, make sure if it is a plugin resource that the
-                        //plugin is not blocked.
-                        prefix = makeModuleMap(depName).prefix;
-                        if (prefix && (prefixManager = waiting[prefix])) {
-                            forceExec(prefixManager, traced);
-                        }
-                        depManager = waiting[depName];
-                        if (depManager && !depManager.isDone && loaded[depName]) {
-                            value = forceExec(depManager, traced);
-                            manager.depCallbacks[i](value);
-                        }
-                    }
-                }
-            }
-
-            return defined[fullName];
-        }
-
-        /**
-         * Checks if all modules for a context are loaded, and if so, evaluates the
-         * new ones in right dependency order.
-         *
-         * @private
-         */
-        function checkLoaded() {
-            var waitInterval = config.waitSeconds * 1000,
-                //It is possible to disable the wait interval by using waitSeconds of 0.
-                expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
-                noLoads = "", hasLoadedProp = false, stillLoading = false,
-                cycleDeps = [],
-                i, prop, err, manager, cycleManager, moduleDeps;
-
-            //If there are items still in the paused queue processing wait.
-            //This is particularly important in the sync case where each paused
-            //item is processed right away but there may be more waiting.
-            if (context.pausedCount > 0) {
-                return undefined;
-            }
-
-            //Determine if priority loading is done. If so clear the priority. If
-            //not, then do not check
-            if (config.priorityWait) {
-                if (isPriorityDone()) {
-                    //Call resume, since it could have
-                    //some waiting dependencies to trace.
-                    resume();
-                } else {
-                    return undefined;
-                }
-            }
-
-            //See if anything is still in flight.
-            for (prop in loaded) {
-                if (!(prop in empty)) {
-                    hasLoadedProp = true;
-                    if (!loaded[prop]) {
-                        if (expired) {
-                            noLoads += prop + " ";
-                        } else {
-                            stillLoading = true;
-                            if (prop.indexOf('!') === -1) {
-                                //No reason to keep looking for unfinished
-                                //loading. If the only stillLoading is a
-                                //plugin resource though, keep going,
-                                //because it may be that a plugin resource
-                                //is waiting on a non-plugin cycle.
-                                cycleDeps = [];
-                                break;
-                            } else {
-                                moduleDeps = managerCallbacks[prop] && managerCallbacks[prop].moduleDeps;
-                                if (moduleDeps) {
-                                    cycleDeps.push.apply(cycleDeps, moduleDeps);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            //Check for exit conditions.
-            if (!hasLoadedProp && !context.waitCount) {
-                //If the loaded object had no items, then the rest of
-                //the work below does not need to be done.
-                return undefined;
-            }
-            if (expired && noLoads) {
-                //If wait time expired, throw error of unloaded modules.
-                err = makeError("timeout", "Load timeout for modules: " + noLoads);
-                err.requireType = "timeout";
-                err.requireModules = noLoads;
-                err.contextName = context.contextName;
-                return req.onError(err);
-            }
-
-            //If still loading but a plugin is waiting on a regular module cycle
-            //break the cycle.
-            if (stillLoading && cycleDeps.length) {
-                for (i = 0; (manager = waiting[cycleDeps[i]]); i++) {
-                    if ((cycleManager = findCycle(manager, {}))) {
-                        forceExec(cycleManager, {});
-                        break;
-                    }
-                }
-
-            }
-
-            //If still waiting on loads, and the waiting load is something
-            //other than a plugin resource, or there are still outstanding
-            //scripts, then just try back later.
-            if (!expired && (stillLoading || context.scriptCount)) {
-                //Something is still waiting to load. Wait for it, but only
-                //if a timeout is not already in effect.
-                if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
-                    checkLoadedTimeoutId = setTimeout(function () {
-                        checkLoadedTimeoutId = 0;
-                        checkLoaded();
-                    }, 50);
-                }
-                return undefined;
-            }
-
-            //If still have items in the waiting cue, but all modules have
-            //been loaded, then it means there are some circular dependencies
-            //that need to be broken.
-            //However, as a waiting thing is fired, then it can add items to
-            //the waiting cue, and those items should not be fired yet, so
-            //make sure to redo the checkLoaded call after breaking a single
-            //cycle, if nothing else loaded then this logic will pick it up
-            //again.
-            if (context.waitCount) {
-                //Cycle through the waitAry, and call items in sequence.
-                for (i = 0; (manager = waitAry[i]); i++) {
-                    forceExec(manager, {});
-                }
-
-                //If anything got placed in the paused queue, run it down.
-                if (context.paused.length) {
-                    resume();
-                }
-
-                //Only allow this recursion to a certain depth. Only
-                //triggered by errors in calling a module in which its
-                //modules waiting on it cannot finish loading, or some circular
-                //dependencies that then may add more dependencies.
-                //The value of 5 is a bit arbitrary. Hopefully just one extra
-                //pass, or two for the case of circular dependencies generating
-                //more work that gets resolved in the sync node case.
-                if (checkLoadedDepth < 5) {
-                    checkLoadedDepth += 1;
-                    checkLoaded();
-                }
-            }
-
-            checkLoadedDepth = 0;
-
-            //Check for DOM ready, and nothing is waiting across contexts.
-            req.checkReadyState();
-
-            return undefined;
-        }
-
-        /**
-         * Resumes tracing of dependencies and then checks if everything is loaded.
-         */
-        resume = function () {
-            var manager, map, url, i, p, args, fullName;
-
-            //Any defined modules in the global queue, intake them now.
-            context.takeGlobalQueue();
-
-            resumeDepth += 1;
-
-            if (context.scriptCount <= 0) {
-                //Synchronous envs will push the number below zero with the
-                //decrement above, be sure to set it back to zero for good measure.
-                //require() calls that also do not end up loading scripts could
-                //push the number negative too.
-                context.scriptCount = 0;
-            }
-
-            //Make sure any remaining defQueue items get properly processed.
-            while (defQueue.length) {
-                args = defQueue.shift();
-                if (args[0] === null) {
-                    return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
-                } else {
-                    callDefMain(args);
-                }
-            }
-
-            //Skip the resume of paused dependencies
-            //if current context is in priority wait.
-            if (!config.priorityWait || isPriorityDone()) {
-                while (context.paused.length) {
-                    p = context.paused;
-                    context.pausedCount += p.length;
-                    //Reset paused list
-                    context.paused = [];
-
-                    for (i = 0; (manager = p[i]); i++) {
-                        map = manager.map;
-                        url = map.url;
-                        fullName = map.fullName;
-
-                        //If the manager is for a plugin managed resource,
-                        //ask the plugin to load it now.
-                        if (map.prefix) {
-                            callPlugin(map.prefix, manager);
-                        } else {
-                            //Regular dependency.
-                            if (!urlFetched[url] && !loaded[fullName]) {
-                                (config.requireLoad || req.load)(context, fullName, url);
-
-                                //Mark the URL as fetched, but only if it is
-                                //not an empty: URL, used by the optimizer.
-                                //In that case we need to be sure to call
-                                //load() for each module that is mapped to
-                                //empty: so that dependencies are satisfied
-                                //correctly.
-                                if (url.indexOf('empty:') !== 0) {
-                                    urlFetched[url] = true;
-                                }
-                            }
-                        }
-                    }
-
-                    //Move the start time for timeout forward.
-                    context.startTime = (new Date()).getTime();
-                    context.pausedCount -= p.length;
-                }
-            }
-
-            //Only check if loaded when resume depth is 1. It is likely that
-            //it is only greater than 1 in sync environments where a factory
-            //function also then calls the callback-style require. In those
-            //cases, the checkLoaded should not occur until the resume
-            //depth is back at the top level.
-            if (resumeDepth === 1) {
-                checkLoaded();
-            }
-
-            resumeDepth -= 1;
-
-            return undefined;
-        };
-
-        //Define the context object. Many of these fields are on here
-        //just to make debugging easier.
-        context = {
-            contextName: contextName,
-            config: config,
-            defQueue: defQueue,
-            waiting: waiting,
-            waitCount: 0,
-            specified: specified,
-            loaded: loaded,
-            urlMap: urlMap,
-            urlFetched: urlFetched,
-            scriptCount: 0,
-            defined: defined,
-            paused: [],
-            pausedCount: 0,
-            plugins: plugins,
-            needFullExec: needFullExec,
-            fake: {},
-            fullExec: fullExec,
-            managerCallbacks: managerCallbacks,
-            makeModuleMap: makeModuleMap,
-            normalize: normalize,
-            /**
-             * Set a configuration for the context.
-             * @param {Object} cfg config object to integrate.
-             */
-            configure: function (cfg) {
-                var paths, prop, packages, pkgs, packagePaths, requireWait;
-
-                //Make sure the baseUrl ends in a slash.
-                if (cfg.baseUrl) {
-                    if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") {
-                        cfg.baseUrl += "/";
-                    }
-                }
-
-                //Save off the paths and packages since they require special processing,
-                //they are additive.
-                paths = config.paths;
-                packages = config.packages;
-                pkgs = config.pkgs;
-
-                //Mix in the config values, favoring the new values over
-                //existing ones in context.config.
-                mixin(config, cfg, true);
-
-                //Adjust paths if necessary.
-                if (cfg.paths) {
-                    for (prop in cfg.paths) {
-                        if (!(prop in empty)) {
-                            paths[prop] = cfg.paths[prop];
-                        }
-                    }
-                    config.paths = paths;
-                }
-
-                packagePaths = cfg.packagePaths;
-                if (packagePaths || cfg.packages) {
-                    //Convert packagePaths into a packages config.
-                    if (packagePaths) {
-                        for (prop in packagePaths) {
-                            if (!(prop in empty)) {
-                                configurePackageDir(pkgs, packagePaths[prop], prop);
-                            }
-                        }
-                    }
-
-                    //Adjust packages if necessary.
-                    if (cfg.packages) {
-                        configurePackageDir(pkgs, cfg.packages);
-                    }
-
-                    //Done with modifications, assing packages back to context config
-                    config.pkgs = pkgs;
-                }
-
-                //If priority loading is in effect, trigger the loads now
-                if (cfg.priority) {
-                    //Hold on to requireWait value, and reset it after done
-                    requireWait = context.requireWait;
-
-                    //Allow tracing some require calls to allow the fetching
-                    //of the priority config.
-                    context.requireWait = false;
-                    //But first, call resume to register any defined modules that may
-                    //be in a data-main built file before the priority config
-                    //call.
-                    resume();
-
-                    context.require(cfg.priority);
-
-                    //Trigger a resume right away, for the case when
-                    //the script with the priority load is done as part
-                    //of a data-main call. In that case the normal resume
-                    //call will not happen because the scriptCount will be
-                    //at 1, since the script for data-main is being processed.
-                    resume();
-
-                    //Restore previous state.
-                    context.requireWait = requireWait;
-                    config.priorityWait = cfg.priority;
-                }
-
-                //If a deps array or a config callback is specified, then call
-                //require with those args. This is useful when require is defined as a
-                //config object before require.js is loaded.
-                if (cfg.deps || cfg.callback) {
-                    context.require(cfg.deps || [], cfg.callback);
-                }
-            },
-
-            requireDefined: function (moduleName, relModuleMap) {
-                return makeModuleMap(moduleName, relModuleMap).fullName in defined;
-            },
-
-            requireSpecified: function (moduleName, relModuleMap) {
-                return makeModuleMap(moduleName, relModuleMap).fullName in specified;
-            },
-
-            require: function (deps, callback, relModuleMap) {
-                var moduleName, fullName, moduleMap;
-                if (typeof deps === "string") {
-                    if (isFunction(callback)) {
-                        //Invalid call
-                        return req.onError(makeError("requireargs", "Invalid require call"));
-                    }
-
-                    //Synchronous access to one module. If require.get is
-                    //available (as in the Node adapter), prefer that.
-                    //In this case deps is the moduleName and callback is
-                    //the relModuleMap
-                    if (req.get) {
-                        return req.get(context, deps, callback);
-                    }
-
-                    //Just return the module wanted. In this scenario, the
-                    //second arg (if passed) is just the relModuleMap.
-                    moduleName = deps;
-                    relModuleMap = callback;
-
-                    //Normalize module name, if it contains . or ..
-                    moduleMap = makeModuleMap(moduleName, relModuleMap);
-                    fullName = moduleMap.fullName;
-
-                    if (!(fullName in defined)) {
-                        return req.onError(makeError("notloaded", "Module name '" +
-                                    moduleMap.fullName +
-                                    "' has not been loaded yet for context: " +
-                                    contextName));
-                    }
-                    return defined[fullName];
-                }
-
-                //Call main but only if there are dependencies or
-                //a callback to call.
-                if (deps && deps.length || callback) {
-                    main(null, deps, callback, relModuleMap);
-                }
-
-                //If the require call does not trigger anything new to load,
-                //then resume the dependency processing.
-                if (!context.requireWait) {
-                    while (!context.scriptCount && context.paused.length) {
-                        resume();
-                    }
-                }
-                return context.require;
-            },
-
-            /**
-             * Internal method to transfer globalQueue items to this context's
-             * defQueue.
-             */
-            takeGlobalQueue: function () {
-                //Push all the globalDefQueue items into the context's defQueue
-                if (globalDefQueue.length) {
-                    //Array splice in the values since the context code has a
-                    //local var ref to defQueue, so cannot just reassign the one
-                    //on context.
-                    apsp.apply(context.defQueue,
-                               [context.defQueue.length - 1, 0].concat(globalDefQueue));
-                    globalDefQueue = [];
-                }
-            },
-
-            /**
-             * Internal method used by environment adapters to complete a load event.
-             * A load event could be a script load or just a load pass from a synchronous
-             * load call.
-             * @param {String} moduleName the name of the module to potentially complete.
-             */
-            completeLoad: function (moduleName) {
-                var args;
-
-                context.takeGlobalQueue();
-
-                while (defQueue.length) {
-                    args = defQueue.shift();
-
-                    if (args[0] === null) {
-                        args[0] = moduleName;
-                        break;
-                    } else if (args[0] === moduleName) {
-                        //Found matching define call for this script!
-                        break;
-                    } else {
-                        //Some other named define call, most likely the result
-                        //of a build layer that included many define calls.
-                        callDefMain(args);
-                        args = null;
-                    }
-                }
-                if (args) {
-                    callDefMain(args);
-                } else {
-                    //A script that does not call define(), so just simulate
-                    //the call for it. Special exception for jQuery dynamic load.
-                    callDefMain([moduleName, [],
-                                moduleName === "jquery" && typeof jQuery !== "undefined" ?
-                                function () {
-                                    return jQuery;
-                                } : null]);
-                }
-
-                //Doing this scriptCount decrement branching because sync envs
-                //need to decrement after resume, otherwise it looks like
-                //loading is complete after the first dependency is fetched.
-                //For browsers, it works fine to decrement after, but it means
-                //the checkLoaded setTimeout 50 ms cost is taken. To avoid
-                //that cost, decrement beforehand.
-                if (req.isAsync) {
-                    context.scriptCount -= 1;
-                }
-                resume();
-                if (!req.isAsync) {
-                    context.scriptCount -= 1;
-                }
-            },
-
-            /**
-             * Converts a module name + .extension into an URL path.
-             * *Requires* the use of a module name. It does not support using
-             * plain URLs like nameToUrl.
-             */
-            toUrl: function (moduleNamePlusExt, relModuleMap) {
-                var index = moduleNamePlusExt.lastIndexOf("."),
-                    ext = null;
-
-                if (index !== -1) {
-                    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
-                    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
-                }
-
-                return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);
-            },
-
-            /**
-             * Converts a module name to a file path. Supports cases where
-             * moduleName may actually be just an URL.
-             */
-            nameToUrl: function (moduleName, ext, relModuleMap) {
-                var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
-                    config = context.config;
-
-                //Normalize module name if have a base relative module name to work from.
-                moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);
-
-                //If a colon is in the URL, it indicates a protocol is used and it is just
-                //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
-                //or ends with .js, then assume the user meant to use an url and not a module id.
-                //The slash is important for protocol-less URLs as well as full paths.
-                if (req.jsExtRegExp.test(moduleName)) {
-                    //Just a plain path, not module name lookup, so just return it.
-                    //Add extension if it is included. This is a bit wonky, only non-.js things pass
-                    //an extension, this method probably needs to be reworked.
-                    url = moduleName + (ext ? ext : "");
-                } else {
-                    //A module that needs to be converted to a path.
-                    paths = config.paths;
-                    pkgs = config.pkgs;
-
-                    syms = moduleName.split("/");
-                    //For each module name segment, see if there is a path
-                    //registered for it. Start with most specific name
-                    //and work up from it.
-                    for (i = syms.length; i > 0; i--) {
-                        parentModule = syms.slice(0, i).join("/");
-                        if (paths[parentModule]) {
-                            syms.splice(0, i, paths[parentModule]);
-                            break;
-                        } else if ((pkg = pkgs[parentModule])) {
-                            //If module name is just the package name, then looking
-                            //for the main module.
-                            if (moduleName === pkg.name) {
-                                pkgPath = pkg.location + '/' + pkg.main;
-                            } else {
-                                pkgPath = pkg.location;
-                            }
-                            syms.splice(0, i, pkgPath);
-                            break;
-                        }
-                    }
-
-                    //Join the path parts together, then figure out if baseUrl is needed.
-                    url = syms.join("/") + (ext || ".js");
-                    url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url;
-                }
-
-                return config.urlArgs ? url +
-                                        ((url.indexOf('?') === -1 ? '?' : '&') +
-                                         config.urlArgs) : url;
-            }
-        };
-
-        //Make these visible on the context so can be called at the very
-        //end of the file to bootstrap
-        context.jQueryCheck = jQueryCheck;
-        context.resume = resume;
-
-        return context;
-    }
-
-    /**
-     * Main entry point.
-     *
-     * If the only argument to require is a string, then the module that
-     * is represented by that string is fetched for the appropriate context.
-     *
-     * If the first argument is an array, then it will be treated as an array
-     * of dependency string names to fetch. An optional function callback can
-     * be specified to execute when all of those dependencies are available.
-     *
-     * Make a local req variable to help Caja compliance (it assumes things
-     * on a require that are not standardized), and to give a short
-     * name for minification/local scope use.
-     */
-    req = requirejs = function (deps, callback) {
-
-        //Find the right context, use default
-        var contextName = defContextName,
-            context, config;
-
-        // Determine if have config object in the call.
-        if (!isArray(deps) && typeof deps !== "string") {
-            // deps is a config object
-            config = deps;
-            if (isArray(callback)) {
-                // Adjust args if there are dependencies
-                deps = callback;
-                callback = arguments[2];
-            } else {
-                deps = [];
-            }
-        }
-
-        if (config && config.context) {
-            contextName = config.context;
-        }
-
-        context = contexts[contextName] ||
-                  (contexts[contextName] = newContext(contextName));
-
-        if (config) {
-            context.configure(config);
-        }
-
-        return context.require(deps, callback);
-    };
-
-    /**
-     * Support require.config() to make it easier to cooperate with other
-     * AMD loaders on globally agreed names.
-     */
-    req.config = function (config) {
-        return req(config);
-    };
-
-    /**
-     * Export require as a global, but only if it does not already exist.
-     */
-    if (!require) {
-        require = req;
-    }
-
-    /**
-     * Global require.toUrl(), to match global require, mostly useful
-     * for debugging/work in the global space.
-     */
-    req.toUrl = function (moduleNamePlusExt) {
-        return contexts[defContextName].toUrl(moduleNamePlusExt);
-    };
-
-    req.version = version;
-
-    //Used to filter out dependencies that are already paths.
-    req.jsExtRegExp = /^\/|:|\?|\.js$/;
-    s = req.s = {
-        contexts: contexts,
-        //Stores a list of URLs that should not get async script tag treatment.
-        skipAsync: {}
-    };
-
-    req.isAsync = req.isBrowser = isBrowser;
-    if (isBrowser) {
-        head = s.head = document.getElementsByTagName("head")[0];
-        //If BASE tag is in play, using appendChild is a problem for IE6.
-        //When that browser dies, this can be removed. Details in this jQuery bug:
-        //http://dev.jquery.com/ticket/2709
-        baseElement = document.getElementsByTagName("base")[0];
-        if (baseElement) {
-            head = s.head = baseElement.parentNode;
-        }
-    }
-
-    /**
-     * Any errors that require explicitly generates will be passed to this
-     * function. Intercept/override it if you want custom error handling.
-     * @param {Error} err the error object.
-     */
-    req.onError = function (err) {
-        throw err;
-    };
-
-    /**
-     * Does the request to load a module for the browser case.
-     * Make this a separate function to allow other environments
-     * to override it.
-     *
-     * @param {Object} context the require context to find state.
-     * @param {String} moduleName the name of the module.
-     * @param {Object} url the URL to the module.
-     */
-    req.load = function (context, moduleName, url) {
-        req.resourcesReady(false);
-
-        context.scriptCount += 1;
-        req.attach(url, context, moduleName);
-
-        //If tracking a jQuery, then make sure its ready callbacks
-        //are put on hold to prevent its ready callbacks from
-        //triggering too soon.
-        if (context.jQuery && !context.jQueryIncremented) {
-            jQueryHoldReady(context.jQuery, true);
-            context.jQueryIncremented = true;
-        }
-    };
-
-    function getInteractiveScript() {
-        var scripts, i, script;
-        if (interactiveScript && interactiveScript.readyState === 'interactive') {
-            return interactiveScript;
-        }
-
-        scripts = document.getElementsByTagName('script');
-        for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {
-            if (script.readyState === 'interactive') {
-                return (interactiveScript = script);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * The function that handles definitions of modules. Differs from
-     * require() in that a string for the module should be the first argument,
-     * and the function to execute after dependencies are loaded should
-     * return a value to define the module corresponding to the first argument's
-     * name.
-     */
-    define = function (name, deps, callback) {
-        var node, context;
-
-        //Allow for anonymous functions
-        if (typeof name !== 'string') {
-            //Adjust args appropriately
-            callback = deps;
-            deps = name;
-            name = null;
-        }
-
-        //This module may not have dependencies
-        if (!isArray(deps)) {
-            callback = deps;
-            deps = [];
-        }
-
-        //If no name, and callback is a function, then figure out if it a
-        //CommonJS thing with dependencies.
-        if (!deps.length && isFunction(callback)) {
-            //Remove comments from the callback string,
-            //look for require calls, and pull them into the dependencies,
-            //but only if there are function args.
-            if (callback.length) {
-                callback
-                    .toString()
-                    .replace(commentRegExp, "")
-                    .replace(cjsRequireRegExp, function (match, dep) {
-                        deps.push(dep);
-                    });
-
-                //May be a CommonJS thing even without require calls, but still
-                //could use exports, and module. Avoid doing exports and module
-                //work though if it just needs require.
-                //REQUIRES the function to expect the CommonJS variables in the
-                //order listed below.
-                deps = (callback.length === 1 ? ["require"] : ["require", "exports", "module"]).concat(deps);
-            }
-        }
-
-        //If in IE 6-8 and hit an anonymous define() call, do the interactive
-        //work.
-        if (useInteractive) {
-            node = currentlyAddingScript || getInteractiveScript();
-            if (node) {
-                if (!name) {
-                    name = node.getAttribute("data-requiremodule");
-                }
-                context = contexts[node.getAttribute("data-requirecontext")];
-            }
-        }
-
-        //Always save off evaluating the def call until the script onload handler.
-        //This allows multiple modules to be in a file without prematurely
-        //tracing dependencies, and allows for anonymous module support,
-        //where the module name is not known until the script onload event
-        //occurs. If no context, use the global queue, and get it processed
-        //in the onscript load callback.
-        (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
-
-        return undefined;
-    };
-
-    define.amd = {
-        multiversion: true,
-        plugins: true,
-        jQuery: true
-    };
-
-    /**
-     * Executes the text. Normally just uses eval, but can be modified
-     * to use a more environment specific call.
-     * @param {String} text the text to execute/evaluate.
-     */
-    req.exec = function (text) {
-        return eval(text);
-    };
-
-    /**
-     * Executes a module callack function. Broken out as a separate function
-     * solely to allow the build system to sequence the files in the built
-     * layer in the right sequence.
-     *
-     * @private
-     */
-    req.execCb = function (name, callback, args, exports) {
-        return callback.apply(exports, args);
-    };
-
-
-    /**
-     * Adds a node to the DOM. Public function since used by the order plugin.
-     * This method should not normally be called by outside code.
-     */
-    req.addScriptToDom = function (node) {
-        //For some cache cases in IE 6-8, the script executes before the end
-        //of the appendChild execution, so to tie an anonymous define
-        //call to the module name (which is stored on the node), hold on
-        //to a reference to this node, but clear after the DOM insertion.
-        currentlyAddingScript = node;
-        if (baseElement) {
-            head.insertBefore(node, baseElement);
-        } else {
-            head.appendChild(node);
-        }
-        currentlyAddingScript = null;
-    };
-
-    /**
-     * callback for script loads, used to check status of loading.
-     *
-     * @param {Event} evt the event from the browser for the script
-     * that was loaded.
-     *
-     * @private
-     */
-    req.onScriptLoad = function (evt) {
-        //Using currentTarget instead of target for Firefox 2.0's sake. Not
-        //all old browsers will be supported, but this one was easy enough
-        //to support and still makes sense.
-        var node = evt.currentTarget || evt.srcElement, contextName, moduleName,
-            context;
-
-        if (evt.type === "load" || (node && readyRegExp.test(node.readyState))) {
-            //Reset interactive script so a script node is not held onto for
-            //to long.
-            interactiveScript = null;
-
-            //Pull out the name of the module and the context.
-            contextName = node.getAttribute("data-requirecontext");
-            moduleName = node.getAttribute("data-requiremodule");
-            context = contexts[contextName];
-
-            contexts[contextName].completeLoad(moduleName);
-
-            //Clean up script binding. Favor detachEvent because of IE9
-            //issue, see attachEvent/addEventListener comment elsewhere
-            //in this file.
-            if (node.detachEvent && !isOpera) {
-                //Probably IE. If not it will throw an error, which will be
-                //useful to know.
-                node.detachEvent("onreadystatechange", req.onScriptLoad);
-            } else {
-                node.removeEventListener("load", req.onScriptLoad, false);
-            }
-        }
-    };
-
-    /**
-     * Attaches the script represented by the URL to the current
-     * environment. Right now only supports browser loading,
-     * but can be redefined in other environments to do the right thing.
-     * @param {String} url the url of the script to attach.
-     * @param {Object} context the context that wants the script.
-     * @param {moduleName} the name of the module that is associated with the script.
-     * @param {Function} [callback] optional callback, defaults to require.onScriptLoad
-     * @param {String} [type] optional type, defaults to text/javascript
-     * @param {Function} [fetchOnlyFunction] optional function to indicate the script node
-     * should be set up to fetch the script but do not attach it to the DOM
-     * so that it can later be attached to execute it. This is a way for the
-     * order plugin to support ordered loading in IE. Once the script is fetched,
-     * but not executed, the fetchOnlyFunction will be called.
-     */
-    req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) {
-        var node;
-        if (isBrowser) {
-            //In the browser so use a script tag
-            callback = callback || req.onScriptLoad;
-            node = context && context.config && context.config.xhtml ?
-                    document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") :
-                    document.createElement("script");
-            node.type = type || (context && context.config.scriptType) ||
-                        "text/javascript";
-            node.charset = "utf-8";
-            //Use async so Gecko does not block on executing the script if something
-            //like a long-polling comet tag is being run first. Gecko likes
-            //to evaluate scripts in DOM order, even for dynamic scripts.
-            //It will fetch them async, but only evaluate the contents in DOM
-            //order, so a long-polling script tag can delay execution of scripts
-            //after it. But telling Gecko we expect async gets us the behavior
-            //we want -- execute it whenever it is finished downloading. Only
-            //Helps Firefox 3.6+
-            //Allow some URLs to not be fetched async. Mostly helps the order!
-            //plugin
-            node.async = !s.skipAsync[url];
-
-            if (context) {
-                node.setAttribute("data-requirecontext", context.contextName);
-            }
-            node.setAttribute("data-requiremodule", moduleName);
-
-            //Set up load listener. Test attachEvent first because IE9 has
-            //a subtle issue in its addEventListener and script onload firings
-            //that do not match the behavior of all other browsers with
-            //addEventListener support, which fire the onload event for a
-            //script right after the script execution. See:
-            //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
-            //UNFORTUNATELY Opera implements attachEvent but does not follow the script
-            //script execution mode.
-            if (node.attachEvent &&
-                // check if node.attachEvent is artificially added by custom script or
-                // natively supported by browser
-                // read https://github.com/jrburke/requirejs/issues/187
-                // if we can NOT find [native code] then it must NOT natively supported.
-                // in IE8, node.attachEvent does not have toString()
-                // TODO: a better way to check interactive mode
-                !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code]') < 0) &&
-                !isOpera) {
-                //Probably IE. IE (at least 6-8) do not fire
-                //script onload right after executing the script, so
-                //we cannot tie the anonymous define call to a name.
-                //However, IE reports the script as being in "interactive"
-                //readyState at the time of the define call.
-                useInteractive = true;
-
-
-                if (fetchOnlyFunction) {
-                    //Need to use old school onreadystate here since
-                    //when the event fires and the node is not attached
-                    //to the DOM, the evt.srcElement is null, so use
-                    //a closure to remember the node.
-                    node.onreadystatechange = function (evt) {
-                        //Script loaded but not executed.
-                        //Clear loaded handler, set the real one that
-                        //waits for script execution.
-                        if (node.readyState === 'loaded') {
-                            node.onreadystatechange = null;
-                            node.attachEvent("onreadystatechange", callback);
-                            fetchOnlyFunction(node);
-                        }
-                    };
-                } else {
-                    node.attachEvent("onreadystatechange", callback);
-                }
-            } else {
-                node.addEventListener("load", callback, false);
-            }
-            node.src = url;
-
-            //Fetch only means waiting to attach to DOM after loaded.
-            if (!fetchOnlyFunction) {
-                req.addScriptToDom(node);
-            }
-
-            return node;
-        } else if (isWebWorker) {
-            //In a web worker, use importScripts. This is not a very
-            //efficient use of importScripts, importScripts will block until
-            //its script is downloaded and evaluated. However, if web workers
-            //are in play, the expectation that a build has been done so that
-            //only one script needs to be loaded anyway. This may need to be
-            //reevaluated if other use cases become common.
-            importScripts(url);
-
-            //Account for anonymous modules
-            context.completeLoad(moduleName);
-        }
-        return null;
-    };
-
-    //Look for a data-main script attribute, which could also adjust the baseUrl.
-    if (isBrowser) {
-        //Figure out baseUrl. Get it from the script tag with require.js in it.
-        scripts = document.getElementsByTagName("script");
-
-        for (globalI = scripts.length - 1; globalI > -1 && (script = scripts[globalI]); globalI--) {
-            //Set the "head" where we can append children by
-            //using the script's parent.
-            if (!head) {
-                head = script.parentNode;
-            }
-
-            //Look for a data-main attribute to set main script for the page
-            //to load. If it is there, the path to data main becomes the
-            //baseUrl, if it is not already set.
-            if ((dataMain = script.getAttribute('data-main'))) {
-                if (!cfg.baseUrl) {
-                    //Pull off the directory of data-main for use as the
-                    //baseUrl.
-                    src = dataMain.split('/');
-                    mainScript = src.pop();
-                    subPath = src.length ? src.join('/')  + '/' : './';
-
-                    //Set final config.
-                    cfg.baseUrl = subPath;
-                    //Strip off any trailing .js since dataMain is now
-                    //like a module name.
-                    dataMain = mainScript.replace(jsSuffixRegExp, '');
-                }
-
-                //Put the data-main script in the files to load.
-                cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
-
-                break;
-            }
-        }
-    }
-
-    //See if there is nothing waiting across contexts, and if not, trigger
-    //resourcesReady.
-    req.checkReadyState = function () {
-        var contexts = s.contexts, prop;
-        for (prop in contexts) {
-            if (!(prop in empty)) {
-                if (contexts[prop].waitCount) {
-                    return;
-                }
-            }
-        }
-        req.resourcesReady(true);
-    };
-
-    /**
-     * Internal function that is triggered whenever all scripts/resources
-     * have been loaded by the loader. Can be overridden by other, for
-     * instance the domReady plugin, which wants to know when all resources
-     * are loaded.
-     */
-    req.resourcesReady = function (isReady) {
-        var contexts, context, prop;
-
-        //First, set the public variable indicating that resources are loading.
-        req.resourcesDone = isReady;
-
-        if (req.resourcesDone) {
-            //If jQuery with DOM ready delayed, release it now.
-            contexts = s.contexts;
-            for (prop in contexts) {
-                if (!(prop in empty)) {
-                    context = contexts[prop];
-                    if (context.jQueryIncremented) {
-                        jQueryHoldReady(context.jQuery, false);
-                        context.jQueryIncremented = false;
-                    }
-                }
-            }
-        }
-    };
-
-    //FF < 3.6 readyState fix. Needed so that domReady plugin
-    //works well in that environment, since require.js is normally
-    //loaded via an HTML script tag so it will be there before window load,
-    //where the domReady plugin is more likely to be loaded after window load.
-    req.pageLoaded = function () {
-        if (document.readyState !== "complete") {
-            document.readyState = "complete";
-        }
-    };
-    if (isBrowser) {
-        if (document.addEventListener) {
-            if (!document.readyState) {
-                document.readyState = "loading";
-                window.addEventListener("load", req.pageLoaded, false);
-            }
-        }
-    }
-
-    //Set up default context. If require was a configuration object, use that as base config.
-    req(cfg);
-
-    //If modules are built into require.js, then need to make sure dependencies are
-    //traced. Use a setTimeout in the browser world, to allow all the modules to register
-    //themselves. In a non-browser env, assume that modules are not built into require.js,
-    //which seems odd to do on the server.
-    if (req.isAsync && typeof setTimeout !== "undefined") {
-        ctx = s.contexts[(cfg.context || defContextName)];
-        //Indicate that the script that includes require() is still loading,
-        //so that require()'d dependencies are not traced until the end of the
-        //file is parsed (approximated via the setTimeout call).
-        ctx.requireWait = true;
-        setTimeout(function () {
-            ctx.requireWait = false;
-
-            if (!ctx.scriptCount) {
-                ctx.resume();
-            }
-            req.checkReadyState();
-        }, 0);
-    }
-}());