<!DOCTYPE html>




 <html class="no-js not-oldie" lang="en" dir="ltr"> 
<head>
	  <meta charset="utf-8" />
	  <meta name="HandheldFriendly" content="true" />
	  <link rel="shortcut icon" href="https://www2.epa.gov/sites/all/themes/epa/favicon.ico" type="image/vnd.microsoft.icon" />
	  <meta name="MobileOptimized" content="width" />
	  <meta http-equiv="cleartype" content="on" />
	  <meta http-equiv="ImageToolbar" content="false" />
	  <meta name="viewport" content="width=device-width" />
	
	  
                 
                 <title>Greenhouse Gas Equivalencies Calculator | US EPA</title>
               
                 
                 
                 <meta name="keywords" content="GHG, Calculator, GHG Equivalencies Calculator" />
                 
                 
                 
                 

	
    

    
	  <style>
          
          
          @media print {
            body * { visibility: hidden; }
            #output * { visibility: visible; }
            #output { position: absolute; top: 0px; left: 0px; }
        }

          
          body {
              
              font-family: Tahoma, Geneva, Verdana, sans-serif;
          }
	  
          
          .roundbox {
	position:relative;
    height: 180px;
    width: 220px;
	float:left;
	margin-left:10px;
    margin-right: 15px;
	margin-top:10px;
	margin-bottom:15px;
    border: 1px solid #D1D1D1;
    border-radius: 20px;
}

.rounboxIcon {
    position: absolute;
    left: 0px;
    top: 0;
    bottom: 0;
    margin: auto;
    max-width: 40%;
}

.roundboxDescr{
    position: absolute;
    left: 50%;
    right: 5px;
    top: 45px;
    color: #797979;
    font-size: 14px !important;
    font-family: Verdana, Geneva, sans-serif;
	
}

.roundboxOutfield {
	font-family:Arial, Helvetica, sans-serif;
	color:#47aa42;
	font-size:22px;
	font-weight:600;
	text-align:right;
	border:none;
	box-shadow:none;
	position:absolute;
    background:transparent;
    right: 10px;
    top: 5px;
}

.emissType {
	clear:both;
	font-size:18px !important;
	font-weight:bold;
	margin-bottom:0px !important;
	margin-left:0;
	margin-top:10px;
}

.i-icon {
	position:absolute;
    left: 8px;
    top: 8px;
    z-index:1;
}

.calculate {
	box-shadow: 1px 1px 0px 0px #FFFFFF inset;
	width:179px;
	height:42px;
	font-family:Verdana, Geneva, sans-serif;
	font-weight:bold;
	color:white;
	text-shadow:1px 1px #3a7937;
	font-size:18px;
	border: 1px solid #24891e;
	border-radius:10px;
	
	background-image: url('calculator_resources/calcGrad.gif');
	background-repeat:repeat-x;
	/* IE10 Consumer Preview */ 
	background-image: -ms-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Mozilla Firefox */ 
	background-image: -moz-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Opera */ 
	background-image: -o-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Webkit (Safari/Chrome 10) */ 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #81DA7D), color-stop(1, #47AB41));
	/* Webkit (Chrome 11+) */ 
	background-image: -webkit-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* W3C Markup, IE10 Release Preview */ 
	background-image: linear-gradient(to bottom, #81DA7D 0%, #47AB41 100%);
}

.calculate:hover {
	box-shadow: 1px 1px 0px 0px #FFFFFF inset;
	width:179px;
	height:42px;
	font-family:Verdana, Geneva, sans-serif;
	font-weight:bold;
	color:white;
	font-size:18px;
	border: 2px solid #24891e;
	border-radius:10px;
	/* IE10 Consumer Preview */ 
	background-image: -ms-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Mozilla Firefox */ 
	background-image: -moz-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Opera */ 
	background-image: -o-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* Webkit (Safari/Chrome 10) */ 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #81DA7D), color-stop(1, #47AB41));
	/* Webkit (Chrome 11+) */ 
	background-image: -webkit-linear-gradient(top, #81DA7D 0%, #47AB41 100%);
	/* W3C Markup, IE10 Release Preview */ 
	background-image: linear-gradient(to bottom, #81DA7D 0%, #47AB41 100%);
}

.calculate:active {
	box-shadow: 1px 1px 0px 0px #FFFFFF inset;
	width:179px;
	height:42px;
	font-family:Verdana, Geneva, sans-serif;
	font-weight:bold;
	color:white;
	font-size:18px;
	border: 1px solid #FFFFFF;
	border-radius:10px;
	/* IE10 Consumer Preview */ 
	background-image: -ms-linear-gradient(top, #47AB41 0%, #81DA7D 100%);
	/* Mozilla Firefox */ 
	background-image: -moz-linear-gradient(top, #47AB41 0%, #81DA7D 100%);
	/* Opera */ 
	background-image: -o-linear-gradient(top, #47AB41 0%, #81DA7D 100%);
	/* Webkit (Safari/Chrome 10) */ 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #47AB41), color-stop(1, #47AB4181DA7D));
	/* Webkit (Chrome 11+) */ 
	background-image: -webkit-linear-gradient(top, #47AB41 0%, #81DA7D 100%);
	/* W3C Markup, IE10 Release Preview */ 
	background-image: linear-gradient(to bottom, #47AB41 0%, #81DA7D 100%);
}

/* this is supposed to contain the select in a div.  the div is supposed to cut the
ugly arrow off of the select so it can be replaced.  haven't gotten this to work.*/
.styled-select2 {
	float:left;
	position:relative;
	margin-left:10px;
	bottom:2px;
	width: 230px;
	height: 25px;
	overflow: hidden;
	border-radius:5px;
	border:1px #b4b4b4 solid;	
}

/*this should be .styled-select select { ... } if the above rule worked.  the width
would be larger than the div above, 250px */
.styled-select {
	width:150px;
	height:25px;
	font-size:13px;
	font-family:Verdana, Geneva, sans-serif;
	border:1px #b4b4b4 solid;
	border-radius:5px;
	
	background-image: url('calculator_resources/selectGrad.gif');
	background-repeat:repeat-x;
	/* IE10 Consumer Preview */ 
	background-image: -ms-linear-gradient(top, #FBFBFB 0%, #D7D5D9 100%);
	/* Mozilla Firefox */ 
	background-image: -moz-linear-gradient(top, #FBFBFB 0%, #D7D5D9 100%);
	/* Opera */ 
	background-image: -o-linear-gradient(top, #FBFBFB 0%, #D7D5D9 100%);
	/* Webkit (Safari/Chrome 10) */ 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #FBFBFB), color-stop(1, #D7D5D9));
	/* Webkit (Chrome 11+) */ 
	background-image: -webkit-linear-gradient(top, #FBFBFB 0%, #D7D5D9 100%);
	/* W3C Markup, IE10 Release Preview */ 
	background-image: linear-gradient(to bottom, #FBFBFB 0%, #D7D5D9 100%);
	
}

.styled-or {    font-family: Verdana, Geneva, sans-serif;
    color: #777;
    font-size: 10px;
    font-style: italic;
    font-weight: bold;
    position: absolute;
    left: 100%;
    top: 0;
    bottom: 0;
    margin: auto;
    display: block;
    width: 85px;
    height: 0px;
    margin-left: 3px;
}








	  </style>

    
    <style>
        /* Tab Content - menucool.com */

ul.tabs
{
    padding: 7px 0;
    font-size: 0;
    margin:0;
    list-style-type: none;
    text-align: left; /*set to left, center, or right to align the tabs as desired*/
}
        
ul.tabs li
{
    display: inline;
    margin: 0;
    margin-right:3px; /*distance between tabs*/
}
        
ul.tabs li a
{
    font: Bold 14px Verdana;
    text-decoration: none;
    position: relative;
    padding: 7px 16px;
    border: 1px solid #0f6cb9;
    border-bottom-color:#0f6cb9;
    color: #FFF;
    background:url('calculator_resources/tabbg2.gif');
	background-repeat:repeat-x;
    border-radius: 3px 3px 0 0;
    outline:none;
}
        
ul.tabs li a:visited
{
    color: #000;
}
        
ul.tabs li a:hover
{
    border: 1px solid #0f6cb9;
	height:70px;
    background:#0f6cb9 
}
        
ul.tabs li.selected a, ul.tabs li.selected a:hover
{
    position: relative;
    top: 0px;
    font-weight:bold;
	color:#194878;
    background: white;
    border: 1px solid #0f6cb9;
    border-bottom-color: white;
}
        
        
ul.tabs li.selected a:hover
{
    text-decoration: none;
}
     

div.tabcontents
{
    border: 1px solid #0f6cb9; 
	padding: 20px;
	/*margin-right:248px;*/
    background-color:#FFF;
    border-radius: 0 3px 3px 3px;
}
    </style>

    
    <style>
        .superscript {
	font-size: 10px;
	vertical-align: top;
	line-height: 8px;
}

.subscript {
	font-size: 10px;
	vertical-align: bottom;
	line-height: 8px;
}

.imgleft {
	float: left;
	margin: 0 10px 10px 0;
}

.imgright {
	float: right;
	margin: 0 0 10px 10px;
}

#content ul.new {
	margin: 0 0 0 5px;
	padding: 0;
	font-size:11px;
}

#content .sections ul {
	margin: 0;
	padding: 0 5px;
}

#content .sections h5 {
	margin: 0;
}

#content .sections h5 a {
	display: block;
	height: 39px;
}

#content .sections p {
	margin: 0 !important;
	padding: 0;
}

#content ul.spaced {
	padding-bottom: 5px;
}

#content ul.spaced li {
	margin-bottom: 5px;
}

/* Energy and You */
.energyandyou {
	width: 275px;
	background: url(../images/homepage/bkgd_energyandyou.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.energyandyou h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_energyandyou.gif) transparent top left no-repeat;
	height: 39px;
}

.energyandyou div {
	background: url(../images/homepage/footer_energyandyou.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

/* State and Local Programs */
.statelocal {
	width: 275px;
	background: url(../images/homepage/bkgd_statelocal.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.statelocal h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_statelocal.gif) transparent top left no-repeat;
	height: 39px;
}

.statelocal div {
	background: url(../images/homepage/footer_statelocal.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

/* Programs */
.programs {
	width: 275px;
	background: url(../images/homepage/bkgd_programs.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.programs h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_programs.gif) transparent top left no-repeat;
	height: 39px;
}

.programs div {
	background: url(../images/homepage/footer_programs.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

/* Clean Energy resources */
.resources {
	width: 275px;
	background: url(../images/homepage/bkgd_resources.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.resources h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_resources.gif) transparent top left no-repeat;
	height: 39px;
}

.resources div {
	background: url(../images/homepage/footer_resources.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

/* NAPEE */
.napee {
	width: 275px;
	background: url(../images/homepage/bkgd_napee.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.napee h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_napee.gif) transparent top left no-repeat;
	height: 56px;
}

.napee div {
	background: url(../images/homepage/footer_napee.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

#content dl.napee-list {
	width: 60%;
}

.napee-list dt {
	font-weight: bold;
	padding: 5px;
	border: 1px dashed #369;
	margin-bottom: 10px;
	background-color: #a1bdd1;
}

#content .napee-list dd {
	margin: 0 0 20px 0 !important;
}

#content .napee-list ul {
	padding-left: 5px;
	padding-bottom: 0;
	margin-bottom: 0;
}


/* Climate Leaders Tech Initiative*/
.tech {
	width: 275px;
	background: url(../images/homepage/bkgd_tech.gif) transparent top left repeat-y;
	float: left;
	margin: 0 20px 20px 0;
}

.tech h5 {
	text-indent: -222em;
	background: url(../images/homepage/header_tech.gif) transparent top left no-repeat;
	height: 39px;
}

.tech div {
	background: url(../images/homepage/footer_tech.gif) transparent bottom left no-repeat;
	padding: 0 20px 20px 20px;
}

#content ul.technologies {
	list-style: none;
	padding: 0;
	margin: 0 auto;
}

#content ul.technologies li {
	margin: 0;
	padding: 0;
	float: left;
}

#content ul.technologies li a, #content ul.technologies li a:visited {
	display: block;
	padding: 8px 10px 5px 10px;
	text-decoration: none;
	color: #fff;
	background-color: #036;
	width: 90px;
	height: 15px;
	text-align: center;
	vertical-align: middle;
}

#content table.results th {
	vertical-align: bottom;
}

#content table.results td {
	vertical-align: top;
}

#content table.details {
	width: 80%;
}

#content h2.show {
	font-size: 1.3em;
	padding: 7px 25px 5px 25px;
	margin: 0;
	background: url(../images/bkgd_expand.gif) #f26722 top left no-repeat;
}

#content h2.show a, #content h2.show a:visited {
	color: #fff;
	text-decoration: none;
	font-weight: normal;
}


#content h2.open {
	background-image: none !important;
}

.hide {
	border-left: 1px solid #f26722;
	border-right: 1px solid #f26722;
	padding: 10px;
}

#content div.hide p {
	margin: 0 0 15px 0;
}

#content ol.commitments {
	list-style: lower-latin;
}

/* Lightbox styles */

#jquery-overlay {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 90;
	width: 100%;
	height: 500px;
}
#jquery-lightbox {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	z-index: 100;
	text-align: center;
	line-height: 0;
}
#jquery-lightbox a img { border: none; }
#lightbox-container-image-box {
	position: relative;
	background-color: #fff;
	width: 250px;
	height: 250px;
	margin: 0 auto;
}
#lightbox-container-image { padding: 10px; }
#lightbox-loading {
	position: absolute;
	top: 40%;
	left: 0%;
	height: 25%;
	width: 100%;
	text-align: center;
	line-height: 0;
}
#lightbox-nav {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	width: 100%;
	z-index: 10;
}
#lightbox-container-image-box > #lightbox-nav { left: 0; }
#lightbox-nav a { outline: none;}
#lightbox-nav-btnPrev, #lightbox-nav-btnNext {
	width: 49%;
	height: 100%;
	display: block;
}
#lightbox-nav-btnPrev { 
	left: 0; 
	float: left;
}
#lightbox-nav-btnNext { 
	right: 0; 
	float: right;
}
#lightbox-container-image-data-box {
	font: 10px Verdana, Helvetica, sans-serif;
	background-color: #fff;
	margin: 0 auto;
	line-height: 1.4em;
	overflow: auto;
	width: 100%;
	padding: 0 10px 0;
}
#lightbox-container-image-data {
	padding: 0 10px; 
	color: #666; 
}
#lightbox-container-image-data #lightbox-image-details { 
	width: 70%; 
	float: left; 
	text-align: left; 
}	
#lightbox-image-details-caption { font-weight: bold; }
#lightbox-image-details-currentNumber {
	display: block; 
	clear: left; 
	padding-bottom: 1.0em;	
}			
#lightbox-secNav-btnClose {
	width: 66px; 
	float: right;
	padding-bottom: 0.7em;	
}

/* Impacts Box Styles */

#content #explore {
	width: 508px;
	background: url(../images/bkgd_impacts_body.gif) transparent top left repeat-y;
	font-size: 0.9em;
}

#content #explore h5 {
	padding: 0;
	margin: 0 0 3px 15px;
	color: #0a6549;
	font-size: 1.1em
}

#explore .header {
	background: url(../images/bkgd_impacts_header.gif) transparent top left no-repeat;
	height: 59px;
	text-indent: -222em;
}

#explore .footer {
	background: url(../images/bkgd_impacts_footer.gif) transparent top left no-repeat;
	height: 21px;
	clear: both;
}

#content #explore ul {
	list-style: none !important;
	padding: 0;
	margin: 0 0 0 15px;
	list-style-image: none;
}

#content #explore li {
	margin: 0 0 2px 0;
}

#content #explore .left, #content #explore .right {
	width: 245px;
}

#explore .left {
	background: url(../images/bkgd_impacts_bar.gif) transparent top right no-repeat;
	padding-right: 18px;
}

#content #explore a, #content #explore a:visited {
	text-decoration: none;
}

/* Form stuff */

#content form.mailer label {
	display: block;
	float: left;
	width: 125px;
}

#content ol#tips {
	list-style: none;
	margin: 0;
	padding: 0;
}

#content ol#tips li {
	margin: 0 0 20px 0;
	padding: 0 0 0 45px;
}

#content ol#tips li.n1 {
	background: url(../images/numbers/1.gif) transparent top left no-repeat;
}

#content ol#tips li.n2 {
	background: url(../images/numbers/2.gif) transparent top left no-repeat;
}

#content ol#tips li.n3 {
	background: url(../images/numbers/3.gif) transparent top left no-repeat;
}

#content ol#tips li.n4 {
	background: url(../images/numbers/4.gif) transparent top left no-repeat;
}

#content ol#tips li.n5 {
	background: url(../images/numbers/5.gif) transparent top left no-repeat;
}

#content ol#tips li.n6 {
	background: url(../images/numbers/6.gif) transparent top left no-repeat;
}

#content ol#tips li.n7 {
	background: url(../images/numbers/7.gif) transparent top left no-repeat;
}

#content ol#tips li.n8 {
	background: url(../images/numbers/8.gif) transparent top left no-repeat;
}

#content ol#tips li.n9 {
	background: url(../images/numbers/9.gif) transparent top left no-repeat;
}

#content ol#tips li.n10 {
	background: url(../images/numbers/10.gif) transparent top left no-repeat;
}

#content ol#tips li.n11 {
	background: url(../images/numbers/11.gif) transparent top left no-repeat;
}

#content ol#tips li.n12 {
	background: url(../images/numbers/12.gif) transparent top left no-repeat;
}

#content ol#footnotes {
	margin: 0 0 0 22px;
	padding: 0;
	font-size: 0.8em;
}

/* Styles from ICF for the Calculator */

#content .note {
	font-size: 0.8em;
	font-style: italic;
}

#content .calculation {
	text-align: center;
	margin: 1.0em 10%;
	padding: 0.3em;
	font-size: 0.9em;
	line-height: 20px;
	background-color: #f1f1f1;
	border: 2px solid #ccc;
}

#content .calculation p {
	margin-top: 0;
}

/* Added to handle ICF's IE 6 bug */

.calculator-warning {
	display: block;
	font-weight: bold;
	color: #C00;
	margin: 0 0 5px 0;
}

/* For hide and reveal depending on whether javascript is enabled.  */



.revealed {display:none;}
.revealed2 {display:inline;}

/*   policy maps related styels  */

#content #maps {
	padding: 2px;
	width: 500px;
}

#content #maps h3 { 
	margin:20px 0 0 0;
	line-height:20px;
}

.current {
	font-family:Verdana, Arial, Helvetica, sans-serif; 
	font-size:12px; 
	font-weight:normal;
}


.rightarea {
	float:right;
	width:200px;
	margin-left:5px;
}


#content #listings p { margin:6px 0 0 0;}
#content #listings ul { margin-bottom:0px;}
#content #listings h3 { margin:16px 0 6px 0;}
#content #listings h4 { margin:6px 0 12px 0;}

#content .clear {
	clear:both;
}

#content .clearleft {
	clear:left;
}

/* Added 04.21.09 by JJoven for Social Media related pages */

#content ul.social {
	list-style: none;
	margin: 0 0 20px 0;
	width: 205px;
	padding: 0;
	font-weight: bold;
}

#content ul.social li {
	padding: 0;
	margin: 0;
	display: inline;
}

#content ul.social a, #content ul.social a:visited {
	text-decoration: none;
	display: block;
	border-bottom: 1px solid #e8e8e8;
	padding: 15px 0 15px 60px;
	color: #33c;
}

#content ul.social a:hover {
	text-decoration: underline;
}

a.rss {
	background: url(../images/icons/rss.gif) transparent 15px 8px no-repeat;
}

a.twitter {
	background: url(../images/icons/twitter.gif) transparent 15px 6px no-repeat;
}

a.fbook {
	background: url(../images/icons/facebook.gif) transparent 15px 8px no-repeat;
}

a.podcasts {
	background: url(../images/icons/podcast.gif) transparent 15px 4px no-repeat;
}

a.widgets {
	background: url(../images/icons/widget.gif) transparent 15px 4px no-repeat;
}

a.rss {
	background: url(../images/icons/rss.gif) transparent 15px 8px no-repeat;
}

#content ul.social a.email {
	background: url(../images/icons/email.gif) transparent 15px 8px no-repeat;
	border: 0;
}

#content a.get-widget, #content a.get-widget:visited {
	display: block;
	font-weight: bold;
	text-decoration: none;
	color: #33c;
	background: url(../images/bkgd-add-arrow.gif) transparent top left no-repeat;
	padding: 6px 0 8px 25px;
	margin: -2px 0 10px 0;
}

#content a.get-widget:hover {
	text-decoration: underline;
}

.more-videos {
	display: block;
	float: left;
	margin: 0 0 0 50px;
}

.news {
	float: left;
}

.instructions {
	width: 438px;
	background-color: #f0eeee;
	float: left;
}

#content .instructions p {
	margin: 0 10px;
	padding: 0;
}

.instructions .top {
	background: url(../images/bkgd-instructions-top.gif) transparent top left no-repeat;
	height: 10px;
}

.instructions .bottom {
	background: url(../images/bkgd-instructions-bottom.gif) transparent top left no-repeat;
	height: 10px;
}

.podcast-title {
	display: block;
	font-weight: bold;
	font-size: 16px;
	margin: 15px 0 10px 0;
}

#podcast-info {
	width: 207px;
	background: url(../images/icons/bkgd-podcasts.gif) #f5f4f4 top left repeat-x;
	padding: 0 0 10px 0;
	margin: 25px 0 0 0;
}

#podcast-info .top {
	height: 36px;
	background: url(../images/icons/bkgd-podcasts-column.gif) transparent top left no-repeat;
}

#content #podcast-info h3 {
	text-align: center;
	margin: 0;
	padding: 0;
	color: #976bb2;
}

#content #podcast-info p {
	margin: 10px 15px;
}

.category {
	background: url(../images/icons/rss.gif) transparent top left no-repeat;
	padding: 8px 0 10px 40px;
}
.smallbold {
	font-size:9px;
	font-weight:bold;
}

#fluctuation { height: 600px; width: 800px; }

a.tooltip {
outline:none;
}

a.tooltip strong {
line-height:30px;
}

a.tooltip:hover {
text-decoration:none;
}

a.tooltip span {
z-index:10;
display:none;
margin-top:-30px;
margin-left:28px;
width:240px;
line-height:16px;
border-radius:4px;
-moz-border-radius:4px;
-webkit-border-radius:4px;
-moz-box-shadow:5px 5px 8px #CCC;
-webkit-box-shadow:5px 5px 8px #CCC;
box-shadow:5px 5px 8px #CCC;
padding:14px 20px;
}

a.tooltip:hover span {
display:inline;
position:absolute;
color:#111;
border:1px solid #DCA;
background:#fffAF0;
}

.callout {
z-index:20;
position:absolute;
top:30px;
border:0;
left:-12px;
}
.output_field{
	font-family:"Verdana";	
}
    </style>




	</head>
	<body class="blank" style="background:none;" >
    
    <noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-L8ZB" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-L8ZB');</script>
    
	  


        <div id="content" style="margin:0;">


           


            <noscript>
                <p class="warning">This calculator requires JavaScript, which is currently disabled in your browser. To calculate the equivalencies manually, you can refer to <a target="_top" href="http://www2.epa.gov/energy/ghg-equivalencies-calculator-calculations-and-references"> the calculations and assumptions page</a>.</p>
            </noscript>

            
            <div> <img src="calculator_resources/logo.jpg"/></div>
            
            <div style="margin-left: 1em;margin-bottom: 2em; float: right; background: #efefef; width: 300px;  padding-bottom: 10px;">
                <h5 style="background: #d4d4d4; padding: 10px; margin-top: 0">About This Calculator</h5>
                <ul style="padding-right:15px;">
                    <li style="padding-bottom:6px;">Last Updated: May 2016</li>
                    <li style="padding-bottom:6px;"><a href="https://www.epa.gov/energy/ghg-equivalencies-calculator-calculations-and-references" target="_top">How are the equivalencies calculated?</a></li>
                    <li style="padding-bottom:6px;"><a target="_top" href="https://www.epa.gov/energy/ghg-equivalencies-calculator-revision-history">Latest updates and revision history</a></li>
                    <li style="padding-bottom:6px;"><a target="_top"  href="https://www.epa.gov/node/166957/">Frequent questions</a></li>
                    <li style="padding-bottom:6px;">To subscribe to the Greenhouse Gas Equivalencies Calculator Update Newsletter send a blank email to <a  target="_top" href="mailto:ghgeqcalc-subscribe@lists.epa.gov">ghgeqcalc-subscribe@lists.epa.gov</a></li>
                </ul>
            </div>
            
            <p style="text-align:justify;">Did you ever wonder what reducing carbon dioxide (CO<sub>2</sub>) emissions by 1 million metric tons means in everyday terms? The greenhouse gas equivalencies calculator can help you understand just that, translating abstract measurements into concrete terms you can understand, such as the annual emissions from cars, households, or power plants.</p>
            <p style="text-align:justify;">This calculator may be useful in communicating your  greenhouse gas reduction strategy, reduction targets, or other initiatives  aimed at reducing greenhouse gas emissions.</p>
            
            
            
            
            <h2 style="">Enter Your Data</h2>

            
            <p>
                There are two options for entering reduction data into this calculator.<br />
            </p>
             <p>Please note that these estimates are approximate and should not be used for emission inventory or formal carbon footprinting exercises. See the equations and sources used for this calculator on the <a target="_top" href="http://www2.epa.gov/energy/ghg-equivalencies-calculator-calculations-and-references">Calculations and References page</a>.</p>
            
            <a href="javascript:window.print()" id="printButton" style="float:right; cursor:pointer; color:blue; text-decoration:underline; clear:both;">Print Your Results</a>

            <ul class="tabs" style="clear:both;" data-persist="true">
                <li><a href="#energy">If You Have Energy Data</a></li>
                <li><a href="#emissions">If You Have Emissions Data</a></li>
            </ul>
            <div class="tabcontents">
                <div id="energy">
                   

                    

                    

                </div>
                
            </div>


            <p style="display:none;">
                <span id="startError"></span>**This calculator uses an eGRID non-baseload
                national average emissions rate when calculating &ldquo;kilowatt-hours of electricity&rdquo;
                to &ldquo;carbon dioxide equivalent.&rdquo;
            </p>

        </div>

 <h5>Other Calculators</h5>
                    <p>There are other EPA calculators that can estimate greenhouse gas emission reductions for</p>

                    <ul>
                        <li> <a  target="_top" href="http://www3.epa.gov/climatechange/ghgemissions/individual.html">Individuals and households</a>, and</li>
                        <li><a  target="_top" href="https://www.epa.gov/warm">Waste</a>.</li>
                    </ul>
                    <p>For basic information and details on greenhouse gas emissions, visit the  Emissions section of <a  target="_top" href="http://www3.epa.gov/climatechange/ghgemissions/index.html">EPA&#8217;s climate change site</a>.</p>






	   


        
	  <script>

          /* http://www.menucool.com/tabbed-content Free to use. Version 2013.7.6 */
          (function () { var g = function (a) { if (a && a.stopPropagation) a.stopPropagation(); else window.event.cancelBubble = true; var b = a ? a : window.event; b.preventDefault && b.preventDefault() }, d = function (a, c, b) { if (a.addEventListener) a.addEventListener(c, b, false); else a.attachEvent && a.attachEvent("on" + c, b) }, a = function (c, a) { var b = new RegExp("(^| )" + a + "( |$)"); return b.test(c.className) ? true : false }, j = function (b, c, d) { if (!a(b, c)) if (b.className == "") b.className = c; else if (d) b.className = c + " " + b.className; else b.className += " " + c }, h = function (a, b) { var c = new RegExp("(^| )" + b + "( |$)"); a.className = a.className.replace(c, "$1"); a.className = a.className.replace(/ $/, "") }, e = function () { var b = window.location.pathname; if (b.indexOf("/") != -1) b = b.split("/"); var a = b[b.length - 1] || "root"; if (a.indexOf(".") != -1) a = a.substring(0, a.indexOf(".")); if (a > 20) a = a.substring(a.length - 19); return a }, c = "mi" + e(), b = function (b, a) { this.g(b, a) }; b.prototype = { h: function () { var b = new RegExp(c + this.a + "=(\\d+)"), a = document.cookie.match(b); return a ? a[1] : this.i() }, i: function () { for (var b = 0, c = this.b.length; b < c; b++) if (a(this.b[b].parentNode, "selected")) return b; return 0 }, j: function (b, d) { var c = document.getElementById(b.TargetId); if (!c) return; this.l(c); for (var a = 0; a < this.b.length; a++) if (this.b[a] == b) { j(b.parentNode, "selected"); d && this.d && this.k(this.a, a) } else h(this.b[a].parentNode, "selected") }, k: function (a, b) { document.cookie = c + a + "=" + b + "; path=/" }, l: function (b) { for (var a = 0; a < this.c.length; a++) this.c[a].style.display = this.c[a].id == b.id ? "block" : "none" }, m: function () { this.c = []; for (var c = this, a = 0; a < this.b.length; a++) { var b = document.getElementById(this.b[a].TargetId); if (b) { this.c.push(b); d(this.b[a], "click", function (b) { var a = this; if (a === window) a = window.event.srcElement; c.j(a, 1); g(b); return false }) } } }, g: function (f, h) { this.a = h; this.b = []; for (var e = f.getElementsByTagName("a"), i = /#([^?]+)/, a, b, c = 0; c < e.length; c++) { b = e[c]; a = b.getAttribute("href"); if (a.indexOf("#") == -1) continue; else { var d = a.match(i); if (d) { a = d[1]; b.TargetId = a; this.b.push(b) } else continue } } var g = f.getAttribute("data-persist") || ""; this.d = g.toLowerCase() == "true" ? 1 : 0; this.m(); this.n() }, n: function () { var a = this.d ? parseInt(this.h()) : this.i(); if (a >= this.b.length) a = 0; this.j(this.b[a], 0) } }; var k = [], i = function (e) { var b = false; function a() { if (b) return; b = true; setTimeout(e, 4) } if (document.addEventListener) document.addEventListener("DOMContentLoaded", a, false); else if (document.attachEvent) { try { var f = window.frameElement != null } catch (g) { } if (document.documentElement.doScroll && !f) { function c() { if (b) return; try { document.documentElement.doScroll("left"); a() } catch (d) { setTimeout(c, 10) } } c() } document.attachEvent("onreadystatechange", function () { document.readyState === "complete" && a() }) } d(window, "load", a) }, f = function () { for (var d = document.getElementsByTagName("ul"), c = 0, e = d.length; c < e; c++) a(d[c], "tabs") && k.push(new b(d[c], c)) }; i(f); return {} })()
	  </script>

        
        <script>
            /*  Prototype JavaScript framework, version 1.7.1
 *  (c) 2005-2010 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
 *--------------------------------------------------------------------------*/

            var Prototype = {

                Version: '1.7.1',

                Browser: (function () {
                    var ua = navigator.userAgent;
                    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
                    return {
                        IE: !!window.attachEvent && !isOpera,
                        Opera: isOpera,
                        WebKit: ua.indexOf('AppleWebKit/') > -1,
                        Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
                        MobileSafari: /Apple.*Mobile/.test(ua)
                    }
                })(),

                BrowserFeatures: {
                    XPath: !!document.evaluate,

                    SelectorsAPI: !!document.querySelector,

                    ElementExtensions: (function () {
                        var constructor = window.Element || window.HTMLElement;
                        return !!(constructor && constructor.prototype);
                    })(),
                    SpecificElementExtensions: (function () {
                        if (typeof window.HTMLDivElement !== 'undefined')
                            return true;

                        var div = document.createElement('div'),
                            form = document.createElement('form'),
                            isSupported = false;

                        if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
                            isSupported = true;
                        }

                        div = form = null;

                        return isSupported;
                    })()
                },

                ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
                JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

                emptyFunction: function () { },

                K: function (x) { return x }
            };

            if (Prototype.Browser.MobileSafari)
                Prototype.BrowserFeatures.SpecificElementExtensions = false;
            /* Based on Alex Arnell's inheritance implementation. */

            var Class = (function () {

                var IS_DONTENUM_BUGGY = (function () {
                    for (var p in { toString: 1 }) {
                        if (p === 'toString') return false;
                    }
                    return true;
                })();

                function subclass() { };
                function create() {
                    var parent = null, properties = $A(arguments);
                    if (Object.isFunction(properties[0]))
                        parent = properties.shift();

                    function klass() {
                        this.initialize.apply(this, arguments);
                    }

                    Object.extend(klass, Class.Methods);
                    klass.superclass = parent;
                    klass.subclasses = [];

                    if (parent) {
                        subclass.prototype = parent.prototype;
                        klass.prototype = new subclass;
                        parent.subclasses.push(klass);
                    }

                    for (var i = 0, length = properties.length; i < length; i++)
                        klass.addMethods(properties[i]);

                    if (!klass.prototype.initialize)
                        klass.prototype.initialize = Prototype.emptyFunction;

                    klass.prototype.constructor = klass;
                    return klass;
                }

                function addMethods(source) {
                    var ancestor = this.superclass && this.superclass.prototype,
                        properties = Object.keys(source);

                    if (IS_DONTENUM_BUGGY) {
                        if (source.toString != Object.prototype.toString)
                            properties.push("toString");
                        if (source.valueOf != Object.prototype.valueOf)
                            properties.push("valueOf");
                    }

                    for (var i = 0, length = properties.length; i < length; i++) {
                        var property = properties[i], value = source[property];
                        if (ancestor && Object.isFunction(value) &&
                            value.argumentNames()[0] == "$super") {
                            var method = value;
                            value = (function (m) {
                                return function () { return ancestor[m].apply(this, arguments); };
                            })(property).wrap(method);

                            value.valueOf = (function (method) {
                                return function () { return method.valueOf.call(method); };
                            })(method);

                            value.toString = (function (method) {
                                return function () { return method.toString.call(method); };
                            })(method);
                        }
                        this.prototype[property] = value;
                    }

                    return this;
                }

                return {
                    create: create,
                    Methods: {
                        addMethods: addMethods
                    }
                };
            })();
            (function () {

                var _toString = Object.prototype.toString,
                    _hasOwnProperty = Object.prototype.hasOwnProperty,
                    NULL_TYPE = 'Null',
                    UNDEFINED_TYPE = 'Undefined',
                    BOOLEAN_TYPE = 'Boolean',
                    NUMBER_TYPE = 'Number',
                    STRING_TYPE = 'String',
                    OBJECT_TYPE = 'Object',
                    FUNCTION_CLASS = '[object Function]',
                    BOOLEAN_CLASS = '[object Boolean]',
                    NUMBER_CLASS = '[object Number]',
                    STRING_CLASS = '[object String]',
                    ARRAY_CLASS = '[object Array]',
                    DATE_CLASS = '[object Date]',
                    NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
                      typeof JSON.stringify === 'function' &&
                      JSON.stringify(0) === '0' &&
                      typeof JSON.stringify(Prototype.K) === 'undefined';



                var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',
                 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];

                var IS_DONTENUM_BUGGY = (function () {
                    for (var p in { toString: 1 }) {
                        if (p === 'toString') return false;
                    }
                    return true;
                })();

                function Type(o) {
                    switch (o) {
                        case null: return NULL_TYPE;
                        case (void 0): return UNDEFINED_TYPE;
                    }
                    var type = typeof o;
                    switch (type) {
                        case 'boolean': return BOOLEAN_TYPE;
                        case 'number': return NUMBER_TYPE;
                        case 'string': return STRING_TYPE;
                    }
                    return OBJECT_TYPE;
                }

                function extend(destination, source) {
                    for (var property in source)
                        destination[property] = source[property];
                    return destination;
                }

                function inspect(object) {
                    try {
                        if (isUndefined(object)) return 'undefined';
                        if (object === null) return 'null';
                        return object.inspect ? object.inspect() : String(object);
                    } catch (e) {
                        if (e instanceof RangeError) return '...';
                        throw e;
                    }
                }

                function toJSON(value) {
                    return Str('', { '': value }, []);
                }

                function Str(key, holder, stack) {
                    var value = holder[key];
                    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
                        value = value.toJSON(key);
                    }

                    var _class = _toString.call(value);

                    switch (_class) {
                        case NUMBER_CLASS:
                        case BOOLEAN_CLASS:
                        case STRING_CLASS:
                            value = value.valueOf();
                    }

                    switch (value) {
                        case null: return 'null';
                        case true: return 'true';
                        case false: return 'false';
                    }

                    var type = typeof value;
                    switch (type) {
                        case 'string':
                            return value.inspect(true);
                        case 'number':
                            return isFinite(value) ? String(value) : 'null';
                        case 'object':

                            for (var i = 0, length = stack.length; i < length; i++) {
                                if (stack[i] === value) {
                                    throw new TypeError("Cyclic reference to '" + value + "' in object");
                                }
                            }
                            stack.push(value);

                            var partial = [];
                            if (_class === ARRAY_CLASS) {
                                for (var i = 0, length = value.length; i < length; i++) {
                                    var str = Str(i, value, stack);
                                    partial.push(typeof str === 'undefined' ? 'null' : str);
                                }
                                partial = '[' + partial.join(',') + ']';
                            } else {
                                var keys = Object.keys(value);
                                for (var i = 0, length = keys.length; i < length; i++) {
                                    var key = keys[i], str = Str(key, value, stack);
                                    if (typeof str !== "undefined") {
                                        partial.push(key.inspect(true) + ':' + str);
                                    }
                                }
                                partial = '{' + partial.join(',') + '}';
                            }
                            stack.pop();
                            return partial;
                    }
                }

                function stringify(object) {
                    return JSON.stringify(object);
                }

                function toQueryString(object) {
                    return $H(object).toQueryString();
                }

                function toHTML(object) {
                    return object && object.toHTML ? object.toHTML() : String.interpret(object);
                }

                function keys(object) {
                    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
                    var results = [];
                    for (var property in object) {
                        if (_hasOwnProperty.call(object, property))
                            results.push(property);
                    }

                    if (IS_DONTENUM_BUGGY) {
                        for (var i = 0; property = DONT_ENUMS[i]; i++) {
                            if (_hasOwnProperty.call(object, property))
                                results.push(property);
                        }
                    }

                    return results;
                }

                function values(object) {
                    var results = [];
                    for (var property in object)
                        results.push(object[property]);
                    return results;
                }

                function clone(object) {
                    return extend({}, object);
                }

                function isElement(object) {
                    return !!(object && object.nodeType == 1);
                }

                function isArray(object) {
                    return _toString.call(object) === ARRAY_CLASS;
                }

                var hasNativeIsArray = (typeof Array.isArray == 'function')
                  && Array.isArray([]) && !Array.isArray({});

                if (hasNativeIsArray) {
                    isArray = Array.isArray;
                }

                function isHash(object) {
                    return object instanceof Hash;
                }

                function isFunction(object) {
                    return _toString.call(object) === FUNCTION_CLASS;
                }

                function isString(object) {
                    return _toString.call(object) === STRING_CLASS;
                }

                function isNumber(object) {
                    return _toString.call(object) === NUMBER_CLASS;
                }

                function isDate(object) {
                    return _toString.call(object) === DATE_CLASS;
                }

                function isUndefined(object) {
                    return typeof object === "undefined";
                }

                extend(Object, {
                    extend: extend,
                    inspect: inspect,
                    toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
                    toQueryString: toQueryString,
                    toHTML: toHTML,
                    keys: Object.keys || keys,
                    values: values,
                    clone: clone,
                    isElement: isElement,
                    isArray: isArray,
                    isHash: isHash,
                    isFunction: isFunction,
                    isString: isString,
                    isNumber: isNumber,
                    isDate: isDate,
                    isUndefined: isUndefined
                });
            })();
            Object.extend(Function.prototype, (function () {
                var slice = Array.prototype.slice;

                function update(array, args) {
                    var arrayLength = array.length, length = args.length;
                    while (length--) array[arrayLength + length] = args[length];
                    return array;
                }

                function merge(array, args) {
                    array = slice.call(array, 0);
                    return update(array, args);
                }

                function argumentNames() {
                    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
                      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
                      .replace(/\s+/g, '').split(',');
                    return names.length == 1 && !names[0] ? [] : names;
                }


                function bind(context) {
                    if (arguments.length < 2 && Object.isUndefined(arguments[0]))
                        return this;

                    if (!Object.isFunction(this))
                        throw new TypeError("The object is not callable.");

                    var nop = function () { };
                    var __method = this, args = slice.call(arguments, 1);

                    var bound = function () {
                        var a = merge(args, arguments), c = context;
                        var c = this instanceof bound ? this : context;
                        return __method.apply(c, a);
                    };

                    nop.prototype = this.prototype;
                    bound.prototype = new nop();

                    return bound;
                }

                function bindAsEventListener(context) {
                    var __method = this, args = slice.call(arguments, 1);
                    return function (event) {
                        var a = update([event || window.event], args);
                        return __method.apply(context, a);
                    }
                }

                function curry() {
                    if (!arguments.length) return this;
                    var __method = this, args = slice.call(arguments, 0);
                    return function () {
                        var a = merge(args, arguments);
                        return __method.apply(this, a);
                    }
                }

                function delay(timeout) {
                    var __method = this, args = slice.call(arguments, 1);
                    timeout = timeout * 1000;
                    return window.setTimeout(function () {
                        return __method.apply(__method, args);
                    }, timeout);
                }

                function defer() {
                    var args = update([0.01], arguments);
                    return this.delay.apply(this, args);
                }

                function wrap(wrapper) {
                    var __method = this;
                    return function () {
                        var a = update([__method.bind(this)], arguments);
                        return wrapper.apply(this, a);
                    }
                }

                function methodize() {
                    if (this._methodized) return this._methodized;
                    var __method = this;
                    return this._methodized = function () {
                        var a = update([this], arguments);
                        return __method.apply(null, a);
                    };
                }

                var extensions = {
                    argumentNames: argumentNames,
                    bindAsEventListener: bindAsEventListener,
                    curry: curry,
                    delay: delay,
                    defer: defer,
                    wrap: wrap,
                    methodize: methodize
                };

                if (!Function.prototype.bind)
                    extensions.bind = bind;

                return extensions;
            })());



            (function (proto) {


                function toISOString() {
                    return this.getUTCFullYear() + '-' +
                      (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
                      this.getUTCDate().toPaddedString(2) + 'T' +
                      this.getUTCHours().toPaddedString(2) + ':' +
                      this.getUTCMinutes().toPaddedString(2) + ':' +
                      this.getUTCSeconds().toPaddedString(2) + 'Z';
                }


                function toJSON() {
                    return this.toISOString();
                }

                if (!proto.toISOString) proto.toISOString = toISOString;
                if (!proto.toJSON) proto.toJSON = toJSON;

            })(Date.prototype);


            RegExp.prototype.match = RegExp.prototype.test;

            RegExp.escape = function (str) {
                return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
            };
            var PeriodicalExecuter = Class.create({
                initialize: function (callback, frequency) {
                    this.callback = callback;
                    this.frequency = frequency;
                    this.currentlyExecuting = false;

                    this.registerCallback();
                },

                registerCallback: function () {
                    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
                },

                execute: function () {
                    this.callback(this);
                },

                stop: function () {
                    if (!this.timer) return;
                    clearInterval(this.timer);
                    this.timer = null;
                },

                onTimerEvent: function () {
                    if (!this.currentlyExecuting) {
                        try {
                            this.currentlyExecuting = true;
                            this.execute();
                            this.currentlyExecuting = false;
                        } catch (e) {
                            this.currentlyExecuting = false;
                            throw e;
                        }
                    }
                }
            });
            Object.extend(String, {
                interpret: function (value) {
                    return value == null ? '' : String(value);
                },
                specialChar: {
                    '\b': '\\b',
                    '\t': '\\t',
                    '\n': '\\n',
                    '\f': '\\f',
                    '\r': '\\r',
                    '\\': '\\\\'
                }
            });

            Object.extend(String.prototype, (function () {
                var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
                  typeof JSON.parse === 'function' &&
                  JSON.parse('{"test": true}').test;

                function prepareReplacement(replacement) {
                    if (Object.isFunction(replacement)) return replacement;
                    var template = new Template(replacement);
                    return function (match) { return template.evaluate(match) };
                }

                function gsub(pattern, replacement) {
                    var result = '', source = this, match;
                    replacement = prepareReplacement(replacement);

                    if (Object.isString(pattern))
                        pattern = RegExp.escape(pattern);

                    if (!(pattern.length || pattern.source)) {
                        replacement = replacement('');
                        return replacement + source.split('').join(replacement) + replacement;
                    }

                    while (source.length > 0) {
                        if (match = source.match(pattern)) {
                            result += source.slice(0, match.index);
                            result += String.interpret(replacement(match));
                            source = source.slice(match.index + match[0].length);
                        } else {
                            result += source, source = '';
                        }
                    }
                    return result;
                }

                function sub(pattern, replacement, count) {
                    replacement = prepareReplacement(replacement);
                    count = Object.isUndefined(count) ? 1 : count;

                    return this.gsub(pattern, function (match) {
                        if (--count < 0) return match[0];
                        return replacement(match);
                    });
                }

                function scan(pattern, iterator) {
                    this.gsub(pattern, iterator);
                    return String(this);
                }

                function truncate(length, truncation) {
                    length = length || 30;
                    truncation = Object.isUndefined(truncation) ? '...' : truncation;
                    return this.length > length ?
                      this.slice(0, length - truncation.length) + truncation : String(this);
                }

                function strip() {
                    return this.replace(/^\s+/, '').replace(/\s+$/, '');
                }

                function stripTags() {
                    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
                }

                function stripScripts() {
                    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
                }

                function extractScripts() {
                    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
                        matchOne = new RegExp(Prototype.ScriptFragment, 'im');
                    return (this.match(matchAll) || []).map(function (scriptTag) {
                        return (scriptTag.match(matchOne) || ['', ''])[1];
                    });
                }

                function evalScripts() {
                    return this.extractScripts().map(function (script) { return eval(script); });
                }

                function escapeHTML() {
                    return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                }

                function unescapeHTML() {
                    return this.stripTags().replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
                }


                function toQueryParams(separator) {
                    var match = this.strip().match(/([^?#]*)(#.*)?$/);
                    if (!match) return {};

                    return match[1].split(separator || '&').inject({}, function (hash, pair) {
                        if ((pair = pair.split('='))[0]) {
                            var key = decodeURIComponent(pair.shift()),
                                value = pair.length > 1 ? pair.join('=') : pair[0];

                            if (value != undefined) value = decodeURIComponent(value);

                            if (key in hash) {
                                if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
                                hash[key].push(value);
                            }
                            else hash[key] = value;
                        }
                        return hash;
                    });
                }

                function toArray() {
                    return this.split('');
                }

                function succ() {
                    return this.slice(0, this.length - 1) +
                      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
                }

                function times(count) {
                    return count < 1 ? '' : new Array(count + 1).join(this);
                }

                function camelize() {
                    return this.replace(/-+(.)?/g, function (match, chr) {
                        return chr ? chr.toUpperCase() : '';
                    });
                }

                function capitalize() {
                    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
                }

                function underscore() {
                    return this.replace(/::/g, '/')
                               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
                               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
                               .replace(/-/g, '_')
                               .toLowerCase();
                }

                function dasherize() {
                    return this.replace(/_/g, '-');
                }

                function inspect(useDoubleQuotes) {
                    var escapedString = this.replace(/[\x00-\x1f\\]/g, function (character) {
                        if (character in String.specialChar) {
                            return String.specialChar[character];
                        }
                        return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
                    });
                    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
                    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
                }

                function unfilterJSON(filter) {
                    return this.replace(filter || Prototype.JSONFilter, '$1');
                }

                function isJSON() {
                    var str = this;
                    if (str.blank()) return false;
                    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
                    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
                    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
                    return (/^[\],:{}\s]*$/).test(str);
                }

                function evalJSON(sanitize) {
                    var json = this.unfilterJSON(),
                        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
                    if (cx.test(json)) {
                        json = json.replace(cx, function (a) {
                            return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                        });
                    }
                    try {
                        if (!sanitize || json.isJSON()) return eval('(' + json + ')');
                    } catch (e) { }
                    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
                }

                function parseJSON() {
                    var json = this.unfilterJSON();
                    return JSON.parse(json);
                }

                function include(pattern) {
                    return this.indexOf(pattern) > -1;
                }

                function startsWith(pattern) {
                    return this.lastIndexOf(pattern, 0) === 0;
                }

                function endsWith(pattern) {
                    var d = this.length - pattern.length;
                    return d >= 0 && this.indexOf(pattern, d) === d;
                }

                function empty() {
                    return this == '';
                }

                function blank() {
                    return /^\s*$/.test(this);
                }

                function interpolate(object, pattern) {
                    return new Template(this, pattern).evaluate(object);
                }

                return {
                    gsub: gsub,
                    sub: sub,
                    scan: scan,
                    truncate: truncate,
                    strip: String.prototype.trim || strip,
                    stripTags: stripTags,
                    stripScripts: stripScripts,
                    extractScripts: extractScripts,
                    evalScripts: evalScripts,
                    escapeHTML: escapeHTML,
                    unescapeHTML: unescapeHTML,
                    toQueryParams: toQueryParams,
                    parseQuery: toQueryParams,
                    toArray: toArray,
                    succ: succ,
                    times: times,
                    camelize: camelize,
                    capitalize: capitalize,
                    underscore: underscore,
                    dasherize: dasherize,
                    inspect: inspect,
                    unfilterJSON: unfilterJSON,
                    isJSON: isJSON,
                    evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
                    include: include,
                    startsWith: startsWith,
                    endsWith: endsWith,
                    empty: empty,
                    blank: blank,
                    interpolate: interpolate
                };
            })());

            var Template = Class.create({
                initialize: function (template, pattern) {
                    this.template = template.toString();
                    this.pattern = pattern || Template.Pattern;
                },

                evaluate: function (object) {
                    if (object && Object.isFunction(object.toTemplateReplacements))
                        object = object.toTemplateReplacements();

                    return this.template.gsub(this.pattern, function (match) {
                        if (object == null) return (match[1] + '');

                        var before = match[1] || '';
                        if (before == '\\') return match[2];

                        var ctx = object, expr = match[3],
                            pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;

                        match = pattern.exec(expr);
                        if (match == null) return before;

                        while (match != null) {
                            var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
                            ctx = ctx[comp];
                            if (null == ctx || '' == match[3]) break;
                            expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
                            match = pattern.exec(expr);
                        }

                        return before + String.interpret(ctx);
                    });
                }
            });
            Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

            var $break = {};

            var Enumerable = (function () {
                function each(iterator, context) {
                    try {
                        this._each(iterator, context);
                    } catch (e) {
                        if (e != $break) throw e;
                    }
                    return this;
                }

                function eachSlice(number, iterator, context) {
                    var index = -number, slices = [], array = this.toArray();
                    if (number < 1) return array;
                    while ((index += number) < array.length)
                        slices.push(array.slice(index, index + number));
                    return slices.collect(iterator, context);
                }

                function all(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var result = true;
                    this.each(function (value, index) {
                        result = result && !!iterator.call(context, value, index, this);
                        if (!result) throw $break;
                    }, this);
                    return result;
                }

                function any(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var result = false;
                    this.each(function (value, index) {
                        if (result = !!iterator.call(context, value, index, this))
                            throw $break;
                    }, this);
                    return result;
                }

                function collect(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var results = [];
                    this.each(function (value, index) {
                        results.push(iterator.call(context, value, index, this));
                    }, this);
                    return results;
                }

                function detect(iterator, context) {
                    var result;
                    this.each(function (value, index) {
                        if (iterator.call(context, value, index, this)) {
                            result = value;
                            throw $break;
                        }
                    }, this);
                    return result;
                }

                function findAll(iterator, context) {
                    var results = [];
                    this.each(function (value, index) {
                        if (iterator.call(context, value, index, this))
                            results.push(value);
                    }, this);
                    return results;
                }

                function grep(filter, iterator, context) {
                    iterator = iterator || Prototype.K;
                    var results = [];

                    if (Object.isString(filter))
                        filter = new RegExp(RegExp.escape(filter));

                    this.each(function (value, index) {
                        if (filter.match(value))
                            results.push(iterator.call(context, value, index, this));
                    }, this);
                    return results;
                }

                function include(object) {
                    if (Object.isFunction(this.indexOf))
                        if (this.indexOf(object) != -1) return true;

                    var found = false;
                    this.each(function (value) {
                        if (value == object) {
                            found = true;
                            throw $break;
                        }
                    });
                    return found;
                }

                function inGroupsOf(number, fillWith) {
                    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
                    return this.eachSlice(number, function (slice) {
                        while (slice.length < number) slice.push(fillWith);
                        return slice;
                    });
                }

                function inject(memo, iterator, context) {
                    this.each(function (value, index) {
                        memo = iterator.call(context, memo, value, index, this);
                    }, this);
                    return memo;
                }

                function invoke(method) {
                    var args = $A(arguments).slice(1);
                    return this.map(function (value) {
                        return value[method].apply(value, args);
                    });
                }

                function max(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var result;
                    this.each(function (value, index) {
                        value = iterator.call(context, value, index, this);
                        if (result == null || value >= result)
                            result = value;
                    }, this);
                    return result;
                }

                function min(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var result;
                    this.each(function (value, index) {
                        value = iterator.call(context, value, index, this);
                        if (result == null || value < result)
                            result = value;
                    }, this);
                    return result;
                }

                function partition(iterator, context) {
                    iterator = iterator || Prototype.K;
                    var trues = [], falses = [];
                    this.each(function (value, index) {
                        (iterator.call(context, value, index, this) ?
                            trues : falses).push(value);
                    }, this);
                    return [trues, falses];
                }

                function pluck(property) {
                    var results = [];
                    this.each(function (value) {
                        results.push(value[property]);
                    });
                    return results;
                }

                function reject(iterator, context) {
                    var results = [];
                    this.each(function (value, index) {
                        if (!iterator.call(context, value, index, this))
                            results.push(value);
                    }, this);
                    return results;
                }

                function sortBy(iterator, context) {
                    return this.map(function (value, index) {
                        return {
                            value: value,
                            criteria: iterator.call(context, value, index, this)
                        };
                    }, this).sort(function (left, right) {
                        var a = left.criteria, b = right.criteria;
                        return a < b ? -1 : a > b ? 1 : 0;
                    }).pluck('value');
                }

                function toArray() {
                    return this.map();
                }

                function zip() {
                    var iterator = Prototype.K, args = $A(arguments);
                    if (Object.isFunction(args.last()))
                        iterator = args.pop();

                    var collections = [this].concat(args).map($A);
                    return this.map(function (value, index) {
                        return iterator(collections.pluck(index));
                    });
                }

                function size() {
                    return this.toArray().length;
                }

                function inspect() {
                    return '#<Enumerable:' + this.toArray().inspect() + '>';
                }









                return {
                    each: each,
                    eachSlice: eachSlice,
                    all: all,
                    every: all,
                    any: any,
                    some: any,
                    collect: collect,
                    map: collect,
                    detect: detect,
                    findAll: findAll,
                    select: findAll,
                    filter: findAll,
                    grep: grep,
                    include: include,
                    member: include,
                    inGroupsOf: inGroupsOf,
                    inject: inject,
                    invoke: invoke,
                    max: max,
                    min: min,
                    partition: partition,
                    pluck: pluck,
                    reject: reject,
                    sortBy: sortBy,
                    toArray: toArray,
                    entries: toArray,
                    zip: zip,
                    size: size,
                    inspect: inspect,
                    find: detect
                };
            })();

            function $A(iterable) {
                if (!iterable) return [];
                if ('toArray' in Object(iterable)) return iterable.toArray();
                var length = iterable.length || 0, results = new Array(length);
                while (length--) results[length] = iterable[length];
                return results;
            }


            function $w(string) {
                if (!Object.isString(string)) return [];
                string = string.strip();
                return string ? string.split(/\s+/) : [];
            }

            Array.from = $A;


            (function () {
                var arrayProto = Array.prototype,
                    slice = arrayProto.slice,
                    _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

                function each(iterator, context) {
                    for (var i = 0, length = this.length >>> 0; i < length; i++) {
                        if (i in this) iterator.call(context, this[i], i, this);
                    }
                }
                if (!_each) _each = each;

                function clear() {
                    this.length = 0;
                    return this;
                }

                function first() {
                    return this[0];
                }

                function last() {
                    return this[this.length - 1];
                }

                function compact() {
                    return this.select(function (value) {
                        return value != null;
                    });
                }

                function flatten() {
                    return this.inject([], function (array, value) {
                        if (Object.isArray(value))
                            return array.concat(value.flatten());
                        array.push(value);
                        return array;
                    });
                }

                function without() {
                    var values = slice.call(arguments, 0);
                    return this.select(function (value) {
                        return !values.include(value);
                    });
                }

                function reverse(inline) {
                    return (inline === false ? this.toArray() : this)._reverse();
                }

                function uniq(sorted) {
                    return this.inject([], function (array, value, index) {
                        if (0 == index || (sorted ? array.last() != value : !array.include(value)))
                            array.push(value);
                        return array;
                    });
                }

                function intersect(array) {
                    return this.uniq().findAll(function (item) {
                        return array.indexOf(item) !== -1;
                    });
                }


                function clone() {
                    return slice.call(this, 0);
                }

                function size() {
                    return this.length;
                }

                function inspect() {
                    return '[' + this.map(Object.inspect).join(', ') + ']';
                }

                function indexOf(item, i) {
                    if (this == null) throw new TypeError();

                    var array = Object(this), length = array.length >>> 0;
                    if (length === 0) return -1;

                    i = Number(i);
                    if (isNaN(i)) {
                        i = 0;
                    } else if (i !== 0 && isFinite(i)) {
                        i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
                    }

                    if (i > length) return -1;

                    var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);
                    for (; k < length; k++)
                        if (k in array && array[k] === item) return k;
                    return -1;
                }


                function lastIndexOf(item, i) {
                    if (this == null) throw new TypeError();

                    var array = Object(this), length = array.length >>> 0;
                    if (length === 0) return -1;

                    if (!Object.isUndefined(i)) {
                        i = Number(i);
                        if (isNaN(i)) {
                            i = 0;
                        } else if (i !== 0 && isFinite(i)) {
                            i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
                        }
                    } else {
                        i = length;
                    }

                    var k = i >= 0 ? Math.min(i, length - 1) :
                     length - Math.abs(i);

                    for (; k >= 0; k--)
                        if (k in array && array[k] === item) return k;
                    return -1;
                }

                function concat(_) {
                    var array = [], items = slice.call(arguments, 0), item, n = 0;
                    items.unshift(this);
                    for (var i = 0, length = items.length; i < length; i++) {
                        item = items[i];
                        if (Object.isArray(item) && !('callee' in item)) {
                            for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
                                if (j in item) array[n] = item[j];
                                n++;
                            }
                        } else {
                            array[n++] = item;
                        }
                    }
                    array.length = n;
                    return array;
                }


                function wrapNative(method) {
                    return function () {
                        if (arguments.length === 0) {
                            return method.call(this, Prototype.K);
                        } else if (arguments[0] === undefined) {
                            var args = slice.call(arguments, 1);
                            args.unshift(Prototype.K);
                            return method.apply(this, args);
                        } else {
                            return method.apply(this, arguments);
                        }
                    };
                }


                function map(iterator) {
                    if (this == null) throw new TypeError();
                    iterator = iterator || Prototype.K;

                    var object = Object(this);
                    var results = [], context = arguments[1], n = 0;

                    for (var i = 0, length = object.length >>> 0; i < length; i++) {
                        if (i in object) {
                            results[n] = iterator.call(context, object[i], i, object);
                        }
                        n++;
                    }
                    results.length = n;
                    return results;
                }

                if (arrayProto.map) {
                    map = wrapNative(Array.prototype.map);
                }

                function filter(iterator) {
                    if (this == null || !Object.isFunction(iterator))
                        throw new TypeError();

                    var object = Object(this);
                    var results = [], context = arguments[1], value;

                    for (var i = 0, length = object.length >>> 0; i < length; i++) {
                        if (i in object) {
                            value = object[i];
                            if (iterator.call(context, value, i, object)) {
                                results.push(value);
                            }
                        }
                    }
                    return results;
                }

                if (arrayProto.filter) {
                    filter = Array.prototype.filter;
                }

                function some(iterator) {
                    if (this == null) throw new TypeError();
                    iterator = iterator || Prototype.K;
                    var context = arguments[1];

                    var object = Object(this);
                    for (var i = 0, length = object.length >>> 0; i < length; i++) {
                        if (i in object && iterator.call(context, object[i], i, object)) {
                            return true;
                        }
                    }

                    return false;
                }

                if (arrayProto.some) {
                    var some = wrapNative(Array.prototype.some);
                }


                function every(iterator) {
                    if (this == null) throw new TypeError();
                    iterator = iterator || Prototype.K;
                    var context = arguments[1];

                    var object = Object(this);
                    for (var i = 0, length = object.length >>> 0; i < length; i++) {
                        if (i in object && !iterator.call(context, object[i], i, object)) {
                            return false;
                        }
                    }

                    return true;
                }

                if (arrayProto.every) {
                    var every = wrapNative(Array.prototype.every);
                }

                var _reduce = arrayProto.reduce;
                function inject(memo, iterator) {
                    iterator = iterator || Prototype.K;
                    var context = arguments[2];
                    return _reduce.call(this, iterator.bind(context), memo);
                }

                if (!arrayProto.reduce) {
                    var inject = Enumerable.inject;
                }

                Object.extend(arrayProto, Enumerable);

                if (!arrayProto._reverse)
                    arrayProto._reverse = arrayProto.reverse;

                Object.extend(arrayProto, {
                    _each: _each,

                    map: map,
                    collect: map,
                    select: filter,
                    filter: filter,
                    findAll: filter,
                    some: some,
                    any: some,
                    every: every,
                    all: every,
                    inject: inject,

                    clear: clear,
                    first: first,
                    last: last,
                    compact: compact,
                    flatten: flatten,
                    without: without,
                    reverse: reverse,
                    uniq: uniq,
                    intersect: intersect,
                    clone: clone,
                    toArray: clone,
                    size: size,
                    inspect: inspect
                });

                var CONCAT_ARGUMENTS_BUGGY = (function () {
                    return [].concat(arguments)[0][0] !== 1;
                })(1, 2);

                if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

                if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
                if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
            })();
            function $H(object) {
                return new Hash(object);
            };

            var Hash = Class.create(Enumerable, (function () {
                function initialize(object) {
                    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
                }


                function _each(iterator, context) {
                    for (var key in this._object) {
                        var value = this._object[key], pair = [key, value];
                        pair.key = key;
                        pair.value = value;
                        iterator.call(context, pair);
                    }
                }

                function set(key, value) {
                    return this._object[key] = value;
                }

                function get(key) {
                    if (this._object[key] !== Object.prototype[key])
                        return this._object[key];
                }

                function unset(key) {
                    var value = this._object[key];
                    delete this._object[key];
                    return value;
                }

                function toObject() {
                    return Object.clone(this._object);
                }



                function keys() {
                    return this.pluck('key');
                }

                function values() {
                    return this.pluck('value');
                }

                function index(value) {
                    var match = this.detect(function (pair) {
                        return pair.value === value;
                    });
                    return match && match.key;
                }

                function merge(object) {
                    return this.clone().update(object);
                }

                function update(object) {
                    return new Hash(object).inject(this, function (result, pair) {
                        result.set(pair.key, pair.value);
                        return result;
                    });
                }

                function toQueryPair(key, value) {
                    if (Object.isUndefined(value)) return key;

                    var value = String.interpret(value);

                    value = value.gsub(/(\r)?\n/, '\r\n');
                    value = encodeURIComponent(value);
                    value = value.gsub(/%20/, '+');
                    return key + '=' + value;
                }

                function toQueryString() {
                    return this.inject([], function (results, pair) {
                        var key = encodeURIComponent(pair.key), values = pair.value;

                        if (values && typeof values == 'object') {
                            if (Object.isArray(values)) {
                                var queryValues = [];
                                for (var i = 0, len = values.length, value; i < len; i++) {
                                    value = values[i];
                                    queryValues.push(toQueryPair(key, value));
                                }
                                return results.concat(queryValues);
                            }
                        } else results.push(toQueryPair(key, values));
                        return results;
                    }).join('&');
                }

                function inspect() {
                    return '#<Hash:{' + this.map(function (pair) {
                        return pair.map(Object.inspect).join(': ');
                    }).join(', ') + '}>';
                }

                function clone() {
                    return new Hash(this);
                }

                return {
                    initialize: initialize,
                    _each: _each,
                    set: set,
                    get: get,
                    unset: unset,
                    toObject: toObject,
                    toTemplateReplacements: toObject,
                    keys: keys,
                    values: values,
                    index: index,
                    merge: merge,
                    update: update,
                    toQueryString: toQueryString,
                    inspect: inspect,
                    toJSON: toObject,
                    clone: clone
                };
            })());

            Hash.from = $H;
            Object.extend(Number.prototype, (function () {
                function toColorPart() {
                    return this.toPaddedString(2, 16);
                }

                function succ() {
                    return this + 1;
                }

                function times(iterator, context) {
                    $R(0, this, true).each(iterator, context);
                    return this;
                }

                function toPaddedString(length, radix) {
                    var string = this.toString(radix || 10);
                    return '0'.times(length - string.length) + string;
                }

                function abs() {
                    return Math.abs(this);
                }

                function round() {
                    return Math.round(this);
                }

                function ceil() {
                    return Math.ceil(this);
                }

                function floor() {
                    return Math.floor(this);
                }

                return {
                    toColorPart: toColorPart,
                    succ: succ,
                    times: times,
                    toPaddedString: toPaddedString,
                    abs: abs,
                    round: round,
                    ceil: ceil,
                    floor: floor
                };
            })());

            function $R(start, end, exclusive) {
                return new ObjectRange(start, end, exclusive);
            }

            var ObjectRange = Class.create(Enumerable, (function () {
                function initialize(start, end, exclusive) {
                    this.start = start;
                    this.end = end;
                    this.exclusive = exclusive;
                }

                function _each(iterator, context) {
                    var value = this.start;
                    while (this.include(value)) {
                        iterator.call(context, value);
                        value = value.succ();
                    }
                }

                function include(value) {
                    if (value < this.start)
                        return false;
                    if (this.exclusive)
                        return value < this.end;
                    return value <= this.end;
                }

                return {
                    initialize: initialize,
                    _each: _each,
                    include: include
                };
            })());



            var Abstract = {};


            var Try = {
                these: function () {
                    var returnValue;

                    for (var i = 0, length = arguments.length; i < length; i++) {
                        var lambda = arguments[i];
                        try {
                            returnValue = lambda();
                            break;
                        } catch (e) { }
                    }

                    return returnValue;
                }
            };

            var Ajax = {
                getTransport: function () {
                    return Try.these(
                      function () { return new XMLHttpRequest() },
                      function () { return new ActiveXObject('Msxml2.XMLHTTP') },
                      function () { return new ActiveXObject('Microsoft.XMLHTTP') }
                    ) || false;
                },

                activeRequestCount: 0
            };

            Ajax.Responders = {
                responders: [],

                _each: function (iterator, context) {
                    this.responders._each(iterator, context);
                },

                register: function (responder) {
                    if (!this.include(responder))
                        this.responders.push(responder);
                },

                unregister: function (responder) {
                    this.responders = this.responders.without(responder);
                },

                dispatch: function (callback, request, transport, json) {
                    this.each(function (responder) {
                        if (Object.isFunction(responder[callback])) {
                            try {
                                responder[callback].apply(responder, [request, transport, json]);
                            } catch (e) { }
                        }
                    });
                }
            };

            Object.extend(Ajax.Responders, Enumerable);

            Ajax.Responders.register({
                onCreate: function () { Ajax.activeRequestCount++ },
                onComplete: function () { Ajax.activeRequestCount-- }
            });
            Ajax.Base = Class.create({
                initialize: function (options) {
                    this.options = {
                        method: 'post',
                        asynchronous: true,
                        contentType: 'application/x-www-form-urlencoded',
                        encoding: 'UTF-8',
                        parameters: '',
                        evalJSON: true,
                        evalJS: true
                    };
                    Object.extend(this.options, options || {});

                    this.options.method = this.options.method.toLowerCase();

                    if (Object.isHash(this.options.parameters))
                        this.options.parameters = this.options.parameters.toObject();
                }
            });
            Ajax.Request = Class.create(Ajax.Base, {
                _complete: false,

                initialize: function ($super, url, options) {
                    $super(options);
                    this.transport = Ajax.getTransport();
                    this.request(url);
                },

                request: function (url) {
                    this.url = url;
                    this.method = this.options.method;
                    var params = Object.isString(this.options.parameters) ?
                          this.options.parameters :
                          Object.toQueryString(this.options.parameters);

                    if (!['get', 'post'].include(this.method)) {
                        params += (params ? '&' : '') + "_method=" + this.method;
                        this.method = 'post';
                    }

                    if (params && this.method === 'get') {
                        this.url += (this.url.include('?') ? '&' : '?') + params;
                    }

                    this.parameters = params.toQueryParams();

                    try {
                        var response = new Ajax.Response(this);
                        if (this.options.onCreate) this.options.onCreate(response);
                        Ajax.Responders.dispatch('onCreate', this, response);

                        this.transport.open(this.method.toUpperCase(), this.url,
                          this.options.asynchronous);

                        if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

                        this.transport.onreadystatechange = this.onStateChange.bind(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);
                    }
                },

                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',
                        'X-Prototype-Version': Prototype.Version,
                        'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
                    };

                    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';
                    }

                    if (typeof this.options.requestHeaders == 'object') {
                        var extras = this.options.requestHeaders;

                        if (Object.isFunction(extras.push))
                            for (var i = 0, length = extras.length; i < length; i += 2)
                                headers[extras[i]] = extras[i + 1];
                        else
                            $H(extras).each(function (pair) { headers[pair.key] = pair.value });
                    }

                    for (var name in headers)
                        this.transport.setRequestHeader(name, headers[name]);
                },

                success: function () {
                    var status = this.getStatus();
                    return !status || (status >= 200 && status < 300) || status == 304;
                },

                getStatus: function () {
                    try {
                        if (this.transport.status === 1223) return 204;
                        return this.transport.status || 0;
                    } catch (e) { return 0 }
                },

                respondToReadyState: function (readyState) {
                    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);

                    if (state == 'Complete') {
                        try {
                            this._complete = true;
                            (this.options['on' + response.status]
                             || this.options['on' + (this.success() ? 'Success' : 'Failure')]
                             || Prototype.emptyFunction)(response, response.headerJSON);
                        } catch (e) {
                            this.dispatchException(e);
                        }

                        var contentType = response.getHeader('Content-type');
                        if (this.options.evalJS == 'force'
                            || (this.options.evalJS && this.isSameOrigin() && contentType
                            && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
                            this.evalResponse();
                    }

                    try {
                        (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
                        Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
                    } catch (e) {
                        this.dispatchException(e);
                    }

                    if (state == 'Complete') {
                        this.transport.onreadystatechange = Prototype.emptyFunction;
                    }
                },

                isSameOrigin: function () {
                    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
                    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
                        protocol: location.protocol,
                        domain: document.domain,
                        port: location.port ? ':' + location.port : ''
                    }));
                },

                getHeader: function (name) {
                    try {
                        return this.transport.getResponseHeader(name) || null;
                    } catch (e) { return null; }
                },

                evalResponse: function () {
                    try {
                        return eval((this.transport.responseText || '').unfilterJSON());
                    } catch (e) {
                        this.dispatchException(e);
                    }
                },

                dispatchException: function (exception) {
                    (this.options.onException || Prototype.emptyFunction)(this, exception);
                    Ajax.Responders.dispatch('onException', this, exception);
                }
            });

            Ajax.Request.Events =
              ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];








            Ajax.Response = Class.create({
                initialize: function (request) {
                    this.request = request;
                    var transport = this.transport = request.transport,
                        readyState = this.readyState = transport.readyState;

                    if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
                        this.status = this.getStatus();
                        this.statusText = this.getStatusText();
                        this.responseText = String.interpret(transport.responseText);
                        this.headerJSON = this._getHeaderJSON();
                    }

                    if (readyState == 4) {
                        var xml = transport.responseXML;
                        this.responseXML = Object.isUndefined(xml) ? null : xml;
                        this.responseJSON = this._getResponseJSON();
                    }
                },

                status: 0,

                statusText: '',

                getStatus: Ajax.Request.prototype.getStatus,

                getStatusText: function () {
                    try {
                        return this.transport.statusText || '';
                    } catch (e) { return '' }
                },

                getHeader: Ajax.Request.prototype.getHeader,

                getAllHeaders: function () {
                    try {
                        return this.getAllResponseHeaders();
                    } catch (e) { return null }
                },

                getResponseHeader: function (name) {
                    return this.transport.getResponseHeader(name);
                },

                getAllResponseHeaders: function () {
                    return this.transport.getAllResponseHeaders();
                },

                _getHeaderJSON: function () {
                    var json = this.getHeader('X-JSON');
                    if (!json) return null;

                    try {
                        json = decodeURIComponent(escape(json));
                    } catch (e) {
                    }

                    try {
                        return json.evalJSON(this.request.options.sanitizeJSON ||
                          !this.request.isSameOrigin());
                    } catch (e) {
                        this.request.dispatchException(e);
                    }
                },

                _getResponseJSON: function () {
                    var options = this.request.options;
                    if (!options.evalJSON || (options.evalJSON != 'force' &&
                      !(this.getHeader('Content-type') || '').include('application/json')) ||
                        this.responseText.blank())
                        return null;
                    try {
                        return this.responseText.evalJSON(options.sanitizeJSON ||
                          !this.request.isSameOrigin());
                    } catch (e) {
                        this.request.dispatchException(e);
                    }
                }
            });

            Ajax.Updater = Class.create(Ajax.Request, {
                initialize: function ($super, container, url, options) {
                    this.container = {
                        success: (container.success || container),
                        failure: (container.failure || (container.success ? null : container))
                    };

                    options = Object.clone(options);
                    var onComplete = options.onComplete;
                    options.onComplete = (function (response, json) {
                        this.updateContent(response.responseText);
                        if (Object.isFunction(onComplete)) onComplete(response, json);
                    }).bind(this);

                    $super(url, options);
                },

                updateContent: function (responseText) {
                    var receiver = this.container[this.success() ? 'success' : 'failure'],
                        options = this.options;

                    if (!options.evalScripts) responseText = responseText.stripScripts();

                    if (receiver = $(receiver)) {
                        if (options.insertion) {
                            if (Object.isString(options.insertion)) {
                                var insertion = {}; insertion[options.insertion] = responseText;
                                receiver.insert(insertion);
                            }
                            else options.insertion(receiver, responseText);
                        }
                        else receiver.update(responseText);
                    }
                }
            });

            Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
                initialize: function ($super, container, url, options) {
                    $super(options);
                    this.onComplete = this.options.onComplete;

                    this.frequency = (this.options.frequency || 2);
                    this.decay = (this.options.decay || 1);

                    this.updater = {};
                    this.container = container;
                    this.url = url;

                    this.start();
                },

                start: function () {
                    this.options.onComplete = this.updateComplete.bind(this);
                    this.onTimerEvent();
                },

                stop: function () {
                    this.updater.options.onComplete = undefined;
                    clearTimeout(this.timer);
                    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
                },

                updateComplete: function (response) {
                    if (this.options.decay) {
                        this.decay = (response.responseText == this.lastText ?
                          this.decay * this.options.decay : 1);

                        this.lastText = response.responseText;
                    }
                    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
                },

                onTimerEvent: function () {
                    this.updater = new Ajax.Updater(this.container, this.url, this.options);
                }
            });

            (function (GLOBAL) {

                var UNDEFINED;
                var SLICE = Array.prototype.slice;

                var DIV = document.createElement('div');


                function $(element) {
                    if (arguments.length > 1) {
                        for (var i = 0, elements = [], length = arguments.length; i < length; i++)
                            elements.push($(arguments[i]));
                        return elements;
                    }

                    if (Object.isString(element))
                        element = document.getElementById(element);
                    return Element.extend(element);
                }

                GLOBAL.$ = $;


                if (!GLOBAL.Node) GLOBAL.Node = {};

                if (!GLOBAL.Node.ELEMENT_NODE) {
                    Object.extend(GLOBAL.Node, {
                        ELEMENT_NODE: 1,
                        ATTRIBUTE_NODE: 2,
                        TEXT_NODE: 3,
                        CDATA_SECTION_NODE: 4,
                        ENTITY_REFERENCE_NODE: 5,
                        ENTITY_NODE: 6,
                        PROCESSING_INSTRUCTION_NODE: 7,
                        COMMENT_NODE: 8,
                        DOCUMENT_NODE: 9,
                        DOCUMENT_TYPE_NODE: 10,
                        DOCUMENT_FRAGMENT_NODE: 11,
                        NOTATION_NODE: 12
                    });
                }

                var ELEMENT_CACHE = {};

                function shouldUseCreationCache(tagName, attributes) {
                    if (tagName === 'select') return false;
                    if ('type' in attributes) return false;
                    return true;
                }

                var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function () {
                    try {
                        var el = document.createElement('<input name="x">');
                        return el.tagName.toLowerCase() === 'input' && el.name === 'x';
                    }
                    catch (err) {
                        return false;
                    }
                })();


                var oldElement = GLOBAL.Element;
                function Element(tagName, attributes) {
                    attributes = attributes || {};
                    tagName = tagName.toLowerCase();

                    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
                        tagName = '<' + tagName + ' name="' + attributes.name + '">';
                        delete attributes.name;
                        return Element.writeAttribute(document.createElement(tagName), attributes);
                    }

                    if (!ELEMENT_CACHE[tagName])
                        ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));

                    var node = shouldUseCreationCache(tagName, attributes) ?
                     ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);

                    return Element.writeAttribute(node, attributes);
                }

                GLOBAL.Element = Element;

                Object.extend(GLOBAL.Element, oldElement || {});
                if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;

                Element.Methods = { ByTag: {}, Simulated: {} };

                var methods = {};

                var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };
                function inspect(element) {
                    element = $(element);
                    var result = '<' + element.tagName.toLowerCase();

                    var attribute, value;
                    for (var property in INSPECT_ATTRIBUTES) {
                        attribute = INSPECT_ATTRIBUTES[property];
                        value = (element[property] || '').toString();
                        if (value) result += ' ' + attribute + '=' + value.inspect(true);
                    }

                    return result + '>';
                }

                methods.inspect = inspect;


                function visible(element) {
                    return $(element).style.display !== 'none';
                }

                function toggle(element, bool) {
                    element = $(element);
                    if (Object.isUndefined(bool))
                        bool = !Element.visible(element);
                    Element[bool ? 'show' : 'hide'](element);

                    return element;
                }

                function hide(element) {
                    element = $(element);
                    element.style.display = 'none';
                    return element;
                }

                function show(element) {
                    element = $(element);
                    element.style.display = '';
                    return element;
                }


                Object.extend(methods, {
                    visible: visible,
                    toggle: toggle,
                    hide: hide,
                    show: show
                });


                function remove(element) {
                    element = $(element);
                    element.parentNode.removeChild(element);
                    return element;
                }

                var SELECT_ELEMENT_INNERHTML_BUGGY = (function () {
                    var el = document.createElement("select"),
                        isBuggy = true;
                    el.innerHTML = "<option value=\"test\">test</option>";
                    if (el.options && el.options[0]) {
                        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
                    }
                    el = null;
                    return isBuggy;
                })();

                var TABLE_ELEMENT_INNERHTML_BUGGY = (function () {
                    try {
                        var el = document.createElement("table");
                        if (el && el.tBodies) {
                            el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
                            var isBuggy = typeof el.tBodies[0] == "undefined";
                            el = null;
                            return isBuggy;
                        }
                    } catch (e) {
                        return true;
                    }
                })();

                var LINK_ELEMENT_INNERHTML_BUGGY = (function () {
                    try {
                        var el = document.createElement('div');
                        el.innerHTML = "<link />";
                        var isBuggy = (el.childNodes.length === 0);
                        el = null;
                        return isBuggy;
                    } catch (e) {
                        return true;
                    }
                })();

                var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
                 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;

                var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
                    var s = document.createElement("script"),
                        isBuggy = false;
                    try {
                        s.appendChild(document.createTextNode(""));
                        isBuggy = !s.firstChild ||
                          s.firstChild && s.firstChild.nodeType !== 3;
                    } catch (e) {
                        isBuggy = true;
                    }
                    s = null;
                    return isBuggy;
                })();

                function update(element, content) {
                    element = $(element);

                    var descendants = element.getElementsByTagName('*'),
                     i = descendants.length;
                    while (i--) purgeElement(descendants[i]);

                    if (content && content.toElement)
                        content = content.toElement();

                    if (Object.isElement(content))
                        return element.update().insert(content);


                    content = Object.toHTML(content);
                    var tagName = element.tagName.toUpperCase();

                    if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
                        element.text = content;
                        return element;
                    }

                    if (ANY_INNERHTML_BUGGY) {
                        if (tagName in INSERTION_TRANSLATIONS.tags) {
                            while (element.firstChild)
                                element.removeChild(element.firstChild);

                            var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());
                            for (var i = 0, node; node = nodes[i]; i++)
                                element.appendChild(node);

                        } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
                            while (element.firstChild)
                                element.removeChild(element.firstChild);

                            var nodes = getContentFromAnonymousElement(tagName,
                             content.stripScripts(), true);

                            for (var i = 0, node; node = nodes[i]; i++)
                                element.appendChild(node);
                        } else {
                            element.innerHTML = content.stripScripts();
                        }
                    } else {
                        element.innerHTML = content.stripScripts();
                    }

                    content.evalScripts.bind(content).defer();
                    return element;
                }

                function replace(element, content) {
                    element = $(element);

                    if (content && content.toElement) {
                        content = content.toElement();
                    } else if (!Object.isElement(content)) {
                        content = Object.toHTML(content);
                        var range = element.ownerDocument.createRange();
                        range.selectNode(element);
                        content.evalScripts.bind(content).defer();
                        content = range.createContextualFragment(content.stripScripts());
                    }

                    element.parentNode.replaceChild(content, element);
                    return element;
                }

                var INSERTION_TRANSLATIONS = {
                    before: function (element, node) {
                        element.parentNode.insertBefore(node, element);
                    },
                    top: function (element, node) {
                        element.insertBefore(node, element.firstChild);
                    },
                    bottom: function (element, node) {
                        element.appendChild(node);
                    },
                    after: function (element, node) {
                        element.parentNode.insertBefore(node, element.nextSibling);
                    },

                    tags: {
                        TABLE: ['<table>', '</table>', 1],
                        TBODY: ['<table><tbody>', '</tbody></table>', 2],
                        TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
                        TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
                        SELECT: ['<select>', '</select>', 1]
                    }
                };

                var tags = INSERTION_TRANSLATIONS.tags;

                Object.extend(tags, {
                    THEAD: tags.TBODY,
                    TFOOT: tags.TBODY,
                    TH: tags.TD
                });

                function replace_IE(element, content) {
                    element = $(element);
                    if (content && content.toElement)
                        content = content.toElement();
                    if (Object.isElement(content)) {
                        element.parentNode.replaceChild(content, element);
                        return element;
                    }

                    content = Object.toHTML(content);
                    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();

                    if (tagName in INSERTION_TRANSLATIONS.tags) {
                        var nextSibling = Element.next(element);
                        var fragments = getContentFromAnonymousElement(
                         tagName, content.stripScripts());

                        parent.removeChild(element);

                        var iterator;
                        if (nextSibling)
                            iterator = function (node) { parent.insertBefore(node, nextSibling) };
                        else
                            iterator = function (node) { parent.appendChild(node); }

                        fragments.each(iterator);
                    } else {
                        element.outerHTML = content.stripScripts();
                    }

                    content.evalScripts.bind(content).defer();
                    return element;
                }

                if ('outerHTML' in document.documentElement)
                    replace = replace_IE;

                function isContent(content) {
                    if (Object.isUndefined(content) || content === null) return false;

                    if (Object.isString(content) || Object.isNumber(content)) return true;
                    if (Object.isElement(content)) return true;
                    if (content.toElement || content.toHTML) return true;

                    return false;
                }

                function insertContentAt(element, content, position) {
                    position = position.toLowerCase();
                    var method = INSERTION_TRANSLATIONS[position];

                    if (content && content.toElement) content = content.toElement();
                    if (Object.isElement(content)) {
                        method(element, content);
                        return element;
                    }

                    content = Object.toHTML(content);
                    var tagName = ((position === 'before' || position === 'after') ?
                     element.parentNode : element).tagName.toUpperCase();

                    var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());

                    if (position === 'top' || position === 'after') childNodes.reverse();

                    for (var i = 0, node; node = childNodes[i]; i++)
                        method(element, node);

                    content.evalScripts.bind(content).defer();
                }

                function insert(element, insertions) {
                    element = $(element);

                    if (isContent(insertions))
                        insertions = { bottom: insertions };

                    for (var position in insertions)
                        insertContentAt(element, insertions[position], position);

                    return element;
                }

                function wrap(element, wrapper, attributes) {
                    element = $(element);

                    if (Object.isElement(wrapper)) {
                        $(wrapper).writeAttribute(attributes || {});
                    } else if (Object.isString(wrapper)) {
                        wrapper = new Element(wrapper, attributes);
                    } else {
                        wrapper = new Element('div', wrapper);
                    }

                    if (element.parentNode)
                        element.parentNode.replaceChild(wrapper, element);

                    wrapper.appendChild(element);

                    return wrapper;
                }

                function cleanWhitespace(element) {
                    element = $(element);
                    var node = element.firstChild;

                    while (node) {
                        var nextNode = node.nextSibling;
                        if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue))
                            element.removeChild(node);
                        node = nextNode;
                    }
                    return element;
                }

                function empty(element) {
                    return $(element).innerHTML.blank();
                }

                function getContentFromAnonymousElement(tagName, html, force) {
                    var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;

                    var workaround = !!t;
                    if (!workaround && force) {
                        workaround = true;
                        t = ['', '', 0];
                    }

                    if (workaround) {
                        div.innerHTML = '&#160;' + t[0] + html + t[1];
                        div.removeChild(div.firstChild);
                        for (var i = t[2]; i--;)
                            div = div.firstChild;
                    } else {
                        div.innerHTML = html;
                    }

                    return $A(div.childNodes);
                }

                function clone(element, deep) {
                    if (!(element = $(element))) return;
                    var clone = element.cloneNode(deep);
                    if (!HAS_UNIQUE_ID_PROPERTY) {
                        clone._prototypeUID = UNDEFINED;
                        if (deep) {
                            var descendants = Element.select(clone, '*'),
                             i = descendants.length;
                            while (i--)
                                descendants[i]._prototypeUID = UNDEFINED;
                        }
                    }
                    return Element.extend(clone);
                }

                function purgeElement(element) {
                    var uid = getUniqueElementID(element);
                    if (uid) {
                        Element.stopObserving(element);
                        if (!HAS_UNIQUE_ID_PROPERTY)
                            element._prototypeUID = UNDEFINED;
                        delete Element.Storage[uid];
                    }
                }

                function purgeCollection(elements) {
                    var i = elements.length;
                    while (i--)
                        purgeElement(elements[i]);
                }

                function purgeCollection_IE(elements) {
                    var i = elements.length, element, uid;
                    while (i--) {
                        element = elements[i];
                        uid = getUniqueElementID(element);
                        delete Element.Storage[uid];
                        delete Event.cache[uid];
                    }
                }

                if (HAS_UNIQUE_ID_PROPERTY) {
                    purgeCollection = purgeCollection_IE;
                }


                function purge(element) {
                    if (!(element = $(element))) return;
                    purgeElement(element);

                    var descendants = element.getElementsByTagName('*'),
                     i = descendants.length;

                    while (i--) purgeElement(descendants[i]);

                    return null;
                }

                Object.extend(methods, {
                    remove: remove,
                    update: update,
                    replace: replace,
                    insert: insert,
                    wrap: wrap,
                    cleanWhitespace: cleanWhitespace,
                    empty: empty,
                    clone: clone,
                    purge: purge
                });



                function recursivelyCollect(element, property, maximumLength) {
                    element = $(element);
                    maximumLength = maximumLength || -1;
                    var elements = [];

                    while (element = element[property]) {
                        if (element.nodeType === Node.ELEMENT_NODE)
                            elements.push(Element.extend(element));

                        if (elements.length === maximumLength) break;
                    }

                    return elements;
                }


                function ancestors(element) {
                    return recursivelyCollect(element, 'parentNode');
                }

                function descendants(element) {
                    return Element.select(element, '*');
                }

                function firstDescendant(element) {
                    element = $(element).firstChild;
                    while (element && element.nodeType !== Node.ELEMENT_NODE)
                        element = element.nextSibling;

                    return $(element);
                }

                function immediateDescendants(element) {
                    var results = [], child = $(element).firstChild;

                    while (child) {
                        if (child.nodeType === Node.ELEMENT_NODE)
                            results.push(Element.extend(child));

                        child = child.nextSibling;
                    }

                    return results;
                }

                function previousSiblings(element) {
                    return recursivelyCollect(element, 'previousSibling');
                }

                function nextSiblings(element) {
                    return recursivelyCollect(element, 'nextSibling');
                }

                function siblings(element) {
                    element = $(element);
                    var previous = previousSiblings(element),
                     next = nextSiblings(element);
                    return previous.reverse().concat(next);
                }

                function match(element, selector) {
                    element = $(element);

                    if (Object.isString(selector))
                        return Prototype.Selector.match(element, selector);

                    return selector.match(element);
                }


                function _recursivelyFind(element, property, expression, index) {
                    element = $(element), expression = expression || 0, index = index || 0;
                    if (Object.isNumber(expression)) {
                        index = expression, expression = null;
                    }

                    while (element = element[property]) {
                        if (element.nodeType !== 1) continue;
                        if (expression && !Prototype.Selector.match(element, expression))
                            continue;
                        if (--index >= 0) continue;

                        return Element.extend(element);
                    }
                }


                function up(element, expression, index) {
                    element = $(element);

                    if (arguments.length === 1) return $(element.parentNode);
                    return _recursivelyFind(element, 'parentNode', expression, index);
                }

                function down(element, expression, index) {
                    element = $(element), expression = expression || 0, index = index || 0;

                    if (Object.isNumber(expression))
                        index = expression, expression = '*';

                    var node = Prototype.Selector.select(expression, element)[index];
                    return Element.extend(node);
                }

                function previous(element, expression, index) {
                    return _recursivelyFind(element, 'previousSibling', expression, index);
                }

                function next(element, expression, index) {
                    return _recursivelyFind(element, 'nextSibling', expression, index);
                }

                function select(element) {
                    element = $(element);
                    var expressions = SLICE.call(arguments, 1).join(', ');
                    return Prototype.Selector.select(expressions, element);
                }

                function adjacent(element) {
                    element = $(element);
                    var expressions = SLICE.call(arguments, 1).join(', ');
                    var siblings = Element.siblings(element), results = [];
                    for (var i = 0, sibling; sibling = siblings[i]; i++) {
                        if (Prototype.Selector.match(sibling, expressions))
                            results.push(sibling);
                    }

                    return results;
                }

                function descendantOf_DOM(element, ancestor) {
                    element = $(element), ancestor = $(ancestor);
                    while (element = element.parentNode)
                        if (element === ancestor) return true;
                    return false;
                }

                function descendantOf_contains(element, ancestor) {
                    element = $(element), ancestor = $(ancestor);
                    if (!ancestor.contains) return descendantOf_DOM(element, ancestor);
                    return ancestor.contains(element) && ancestor !== element;
                }

                function descendantOf_compareDocumentPosition(element, ancestor) {
                    element = $(element), ancestor = $(ancestor);
                    return (element.compareDocumentPosition(ancestor) & 8) === 8;
                }

                var descendantOf;
                if (DIV.compareDocumentPosition) {
                    descendantOf = descendantOf_compareDocumentPosition;
                } else if (DIV.contains) {
                    descendantOf = descendantOf_contains;
                } else {
                    descendantOf = descendantOf_DOM;
                }


                Object.extend(methods, {
                    recursivelyCollect: recursivelyCollect,
                    ancestors: ancestors,
                    descendants: descendants,
                    firstDescendant: firstDescendant,
                    immediateDescendants: immediateDescendants,
                    previousSiblings: previousSiblings,
                    nextSiblings: nextSiblings,
                    siblings: siblings,
                    match: match,
                    up: up,
                    down: down,
                    previous: previous,
                    next: next,
                    select: select,
                    adjacent: adjacent,
                    descendantOf: descendantOf,

                    getElementsBySelector: select,

                    childElements: immediateDescendants
                });


                var idCounter = 1;
                function identify(element) {
                    element = $(element);
                    var id = Element.readAttribute(element, 'id');
                    if (id) return id;

                    do { id = 'anonymous_element_' + idCounter++ } while ($(id));

                    Element.writeAttribute(element, 'id', id);
                    return id;
                }


                function readAttribute(element, name) {
                    return $(element).getAttribute(name);
                }

                function readAttribute_IE(element, name) {
                    element = $(element);

                    var table = ATTRIBUTE_TRANSLATIONS.read;
                    if (table.values[name])
                        return table.values[name](element, name);

                    if (table.names[name]) name = table.names[name];

                    if (name.include(':')) {
                        if (!element.attributes || !element.attributes[name]) return null;
                        return element.attributes[name].value;
                    }

                    return element.getAttribute(name);
                }

                function readAttribute_Opera(element, name) {
                    if (name === 'title') return element.title;
                    return element.getAttribute(name);
                }

                var PROBLEMATIC_ATTRIBUTE_READING = (function () {
                    DIV.setAttribute('onclick', Prototype.emptyFunction);
                    var value = DIV.getAttribute('onclick');
                    var isFunction = (typeof value === 'function');
                    DIV.removeAttribute('onclick');
                    return isFunction;
                })();

                if (PROBLEMATIC_ATTRIBUTE_READING) {
                    readAttribute = readAttribute_IE;
                } else if (Prototype.Browser.Opera) {
                    readAttribute = readAttribute_Opera;
                }


                function writeAttribute(element, name, value) {
                    element = $(element);
                    var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;

                    if (typeof name === 'object') {
                        attributes = name;
                    } else {
                        attributes[name] = Object.isUndefined(value) ? true : value;
                    }

                    for (var attr in attributes) {
                        name = table.names[attr] || attr;
                        value = attributes[attr];
                        if (table.values[attr])
                            name = table.values[attr](element, value);
                        if (value === false || value === null)
                            element.removeAttribute(name);
                        else if (value === true)
                            element.setAttribute(name, name);
                        else element.setAttribute(name, value);
                    }

                    return element;
                }

                function hasAttribute(element, attribute) {
                    attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;
                    var node = $(element).getAttributeNode(attribute);
                    return !!(node && node.specified);
                }

                GLOBAL.Element.Methods.Simulated.hasAttribute = hasAttribute;

                function classNames(element) {
                    return new Element.ClassNames(element);
                }

                var regExpCache = {};
                function getRegExpForClassName(className) {
                    if (regExpCache[className]) return regExpCache[className];

                    var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
                    regExpCache[className] = re;
                    return re;
                }

                function hasClassName(element, className) {
                    if (!(element = $(element))) return;

                    var elementClassName = element.className;

                    if (elementClassName.length === 0) return false;
                    if (elementClassName === className) return true;

                    return getRegExpForClassName(className).test(elementClassName);
                }

                function addClassName(element, className) {
                    if (!(element = $(element))) return;

                    if (!hasClassName(element, className))
                        element.className += (element.className ? ' ' : '') + className;

                    return element;
                }

                function removeClassName(element, className) {
                    if (!(element = $(element))) return;

                    element.className = element.className.replace(
                     getRegExpForClassName(className), ' ').strip();

                    return element;
                }

                function toggleClassName(element, className, bool) {
                    if (!(element = $(element))) return;

                    if (Object.isUndefined(bool))
                        bool = !hasClassName(element, className);

                    var method = Element[bool ? 'addClassName' : 'removeClassName'];
                    return method(element, className);
                }

                var ATTRIBUTE_TRANSLATIONS = {};

                var classProp = 'className', forProp = 'for';

                DIV.setAttribute(classProp, 'x');
                if (DIV.className !== 'x') {
                    DIV.setAttribute('class', 'x');
                    if (DIV.className === 'x')
                        classProp = 'class';
                }

                var LABEL = document.createElement('label');
                LABEL.setAttribute(forProp, 'x');
                if (LABEL.htmlFor !== 'x') {
                    LABEL.setAttribute('htmlFor', 'x');
                    if (LABEL.htmlFor === 'x')
                        forProp = 'htmlFor';
                }
                LABEL = null;

                function _getAttr(element, attribute) {
                    return element.getAttribute(attribute);
                }

                function _getAttr2(element, attribute) {
                    return element.getAttribute(attribute, 2);
                }

                function _getAttrNode(element, attribute) {
                    var node = element.getAttributeNode(attribute);
                    return node ? node.value : '';
                }

                function _getFlag(element, attribute) {
                    return $(element).hasAttribute(attribute) ? attribute : null;
                }

                DIV.onclick = Prototype.emptyFunction;
                var onclickValue = DIV.getAttribute('onclick');

                var _getEv;

                if (String(onclickValue).indexOf('{') > -1) {
                    _getEv = function (element, attribute) {
                        var value = element.getAttribute(attribute);
                        if (!value) return null;
                        value = value.toString();
                        value = value.split('{')[1];
                        value = value.split('}')[0];
                        return value.strip();
                    };
                }
                else if (onclickValue === '') {
                    _getEv = function (element, attribute) {
                        var value = element.getAttribute(attribute);
                        if (!value) return null;
                        return value.strip();
                    };
                }

                ATTRIBUTE_TRANSLATIONS.read = {
                    names: {
                        'class': classProp,
                        'className': classProp,
                        'for': forProp,
                        'htmlFor': forProp
                    },

                    values: {
                        style: function (element) {
                            return element.style.cssText.toLowerCase();
                        },
                        title: function (element) {
                            return element.title;
                        }
                    }
                };

                ATTRIBUTE_TRANSLATIONS.write = {
                    names: {
                        className: 'class',
                        htmlFor: 'for',
                        cellpadding: 'cellPadding',
                        cellspacing: 'cellSpacing'
                    },

                    values: {
                        checked: function (element, value) {
                            element.checked = !!value;
                        },

                        style: function (element, value) {
                            element.style.cssText = value ? value : '';
                        }
                    }
                };

                ATTRIBUTE_TRANSLATIONS.has = { names: {} };

                Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,
                 ATTRIBUTE_TRANSLATIONS.read.names);

                var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +
                 'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');

                for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {
                    ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;
                    ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()] = attr;
                }

                Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {
                    href: _getAttr2,
                    src: _getAttr2,
                    type: _getAttr,
                    action: _getAttrNode,
                    disabled: _getFlag,
                    checked: _getFlag,
                    readonly: _getFlag,
                    multiple: _getFlag,
                    onload: _getEv,
                    onunload: _getEv,
                    onclick: _getEv,
                    ondblclick: _getEv,
                    onmousedown: _getEv,
                    onmouseup: _getEv,
                    onmouseover: _getEv,
                    onmousemove: _getEv,
                    onmouseout: _getEv,
                    onfocus: _getEv,
                    onblur: _getEv,
                    onkeypress: _getEv,
                    onkeydown: _getEv,
                    onkeyup: _getEv,
                    onsubmit: _getEv,
                    onreset: _getEv,
                    onselect: _getEv,
                    onchange: _getEv
                });


                Object.extend(methods, {
                    identify: identify,
                    readAttribute: readAttribute,
                    writeAttribute: writeAttribute,
                    classNames: classNames,
                    hasClassName: hasClassName,
                    addClassName: addClassName,
                    removeClassName: removeClassName,
                    toggleClassName: toggleClassName
                });


                function normalizeStyleName(style) {
                    if (style === 'float' || style === 'styleFloat')
                        return 'cssFloat';
                    return style.camelize();
                }

                function normalizeStyleName_IE(style) {
                    if (style === 'float' || style === 'cssFloat')
                        return 'styleFloat';
                    return style.camelize();
                }

                function setStyle(element, styles) {
                    element = $(element);
                    var elementStyle = element.style, match;

                    if (Object.isString(styles)) {
                        elementStyle.cssText += ';' + styles;
                        if (styles.include('opacity')) {
                            var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1];
                            Element.setOpacity(element, opacity);
                        }
                        return element;
                    }

                    for (var property in styles) {
                        if (property === 'opacity') {
                            Element.setOpacity(element, styles[property]);
                        } else {
                            var value = styles[property];
                            if (property === 'float' || property === 'cssFloat') {
                                property = Object.isUndefined(elementStyle.styleFloat) ?
                                 'cssFloat' : 'styleFloat';
                            }
                            elementStyle[property] = value;
                        }
                    }

                    return element;
                }


                function getStyle(element, style) {
                    element = $(element);
                    style = normalizeStyleName(style);

                    var value = element.style[style];
                    if (!value || value === 'auto') {
                        var css = document.defaultView.getComputedStyle(element, null);
                        value = css ? css[style] : null;
                    }

                    if (style === 'opacity') return value ? parseFloat(value) : 1.0;
                    return value === 'auto' ? null : value;
                }

                function getStyle_Opera(element, style) {
                    switch (style) {
                        case 'height': case 'width':
                            if (!Element.visible(element)) return null;

                            var dim = parseInt(getStyle(element, style), 10);

                            if (dim !== element['offset' + style.capitalize()])
                                return dim + 'px';

                            return Element.measure(element, style);

                        default: return getStyle(element, style);
                    }
                }

                function getStyle_IE(element, style) {
                    element = $(element);
                    style = normalizeStyleName_IE(style);

                    var value = element.style[style];
                    if (!value && element.currentStyle) {
                        value = element.currentStyle[style];
                    }

                    if (style === 'opacity' && !STANDARD_CSS_OPACITY_SUPPORTED)
                        return getOpacity_IE(element);

                    if (value === 'auto') {
                        if ((style === 'width' || style === 'height') && Element.visible(element))
                            return Element.measure(element, style) + 'px';
                        return null;
                    }

                    return value;
                }

                function stripAlphaFromFilter_IE(filter) {
                    return (filter || '').replace(/alpha\([^\)]*\)/gi, '');
                }

                function hasLayout_IE(element) {
                    if (!element.currentStyle.hasLayout)
                        element.style.zoom = 1;
                    return element;
                }

                var STANDARD_CSS_OPACITY_SUPPORTED = (function () {
                    DIV.style.cssText = "opacity:.55";
                    return /^0.55/.test(DIV.style.opacity);
                })();

                function setOpacity(element, value) {
                    element = $(element);
                    if (value == 1 || value === '') value = '';
                    else if (value < 0.00001) value = 0;
                    element.style.opacity = value;
                    return element;
                }

                function setOpacity_IE(element, value) {
                    if (STANDARD_CSS_OPACITY_SUPPORTED)
                        return setOpacity(element, value);

                    element = hasLayout_IE($(element));
                    var filter = Element.getStyle(element, 'filter'),
                     style = element.style;

                    if (value == 1 || value === '') {
                        filter = stripAlphaFromFilter_IE(filter);
                        if (filter) style.filter = filter;
                        else style.removeAttribute('filter');
                        return element;
                    }

                    if (value < 0.00001) value = 0;

                    style.filter = stripAlphaFromFilter_IE(filter) +
                     'alpha(opacity=' + (value * 100) + ')';

                    return element;
                }


                function getOpacity(element) {
                    return Element.getStyle(element, 'opacity');
                }

                function getOpacity_IE(element) {
                    if (STANDARD_CSS_OPACITY_SUPPORTED)
                        return getOpacity(element);

                    var filter = Element.getStyle(element, 'filter');
                    if (filter.length === 0) return 1.0;
                    var match = (filter || '').match(/alpha\(opacity=(.*)\)/);
                    if (match[1]) return parseFloat(match[1]) / 100;
                    return 1.0;
                }


                Object.extend(methods, {
                    setStyle: setStyle,
                    getStyle: getStyle,
                    setOpacity: setOpacity,
                    getOpacity: getOpacity
                });

                if ('styleFloat' in DIV.style) {
                    methods.getStyle = getStyle_IE;
                    methods.setOpacity = setOpacity_IE;
                    methods.getOpacity = getOpacity_IE;
                }

                var UID = 0;

                GLOBAL.Element.Storage = { UID: 1 };

                function getUniqueElementID(element) {
                    if (element === window) return 0;

                    if (typeof element._prototypeUID === 'undefined')
                        element._prototypeUID = Element.Storage.UID++;
                    return element._prototypeUID;
                }

                function getUniqueElementID_IE(element) {
                    if (element === window) return 0;
                    if (element == document) return 1;
                    return element.uniqueID;
                }

                var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);
                if (HAS_UNIQUE_ID_PROPERTY)
                    getUniqueElementID = getUniqueElementID_IE;

                function getStorage(element) {
                    if (!(element = $(element))) return;

                    var uid = getUniqueElementID(element);

                    if (!Element.Storage[uid])
                        Element.Storage[uid] = $H();

                    return Element.Storage[uid];
                }

                function store(element, key, value) {
                    if (!(element = $(element))) return;
                    var storage = getStorage(element);
                    if (arguments.length === 2) {
                        storage.update(key);
                    } else {
                        storage.set(key, value);
                    }
                    return element;
                }

                function retrieve(element, key, defaultValue) {
                    if (!(element = $(element))) return;
                    var storage = getStorage(element), value = storage.get(key);

                    if (Object.isUndefined(value)) {
                        storage.set(key, defaultValue);
                        value = defaultValue;
                    }

                    return value;
                }


                Object.extend(methods, {
                    getStorage: getStorage,
                    store: store,
                    retrieve: retrieve
                });


                var Methods = {}, ByTag = Element.Methods.ByTag,
                 F = Prototype.BrowserFeatures;

                if (!F.ElementExtensions && ('__proto__' in DIV)) {
                    GLOBAL.HTMLElement = {};
                    GLOBAL.HTMLElement.prototype = DIV['__proto__'];
                    F.ElementExtensions = true;
                }

                function checkElementPrototypeDeficiency(tagName) {
                    if (typeof window.Element === 'undefined') return false;
                    var proto = window.Element.prototype;
                    if (proto) {
                        var id = '_' + (Math.random() + '').slice(2),
                         el = document.createElement(tagName);
                        proto[id] = 'x';
                        var isBuggy = (el[id] !== 'x');
                        delete proto[id];
                        el = null;
                        return isBuggy;
                    }

                    return false;
                }

                var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =
                 checkElementPrototypeDeficiency('object');

                function extendElementWith(element, methods) {
                    for (var property in methods) {
                        var value = methods[property];
                        if (Object.isFunction(value) && !(property in element))
                            element[property] = value.methodize();
                    }
                }

                var EXTENDED = {};
                function elementIsExtended(element) {
                    var uid = getUniqueElementID(element);
                    return (uid in EXTENDED);
                }

                function extend(element) {
                    if (!element || elementIsExtended(element)) return element;
                    if (element.nodeType !== Node.ELEMENT_NODE || element == window)
                        return element;

                    var methods = Object.clone(Methods),
                     tagName = element.tagName.toUpperCase();

                    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

                    extendElementWith(element, methods);
                    EXTENDED[getUniqueElementID(element)] = true;
                    return element;
                }

                function extend_IE8(element) {
                    if (!element || elementIsExtended(element)) return element;

                    var t = element.tagName;
                    if (t && (/^(?:object|applet|embed)$/i.test(t))) {
                        extendElementWith(element, Element.Methods);
                        extendElementWith(element, Element.Methods.Simulated);
                        extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
                    }

                    return element;
                }

                if (F.SpecificElementExtensions) {
                    extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;
                }

                function addMethodsToTagName(tagName, methods) {
                    tagName = tagName.toUpperCase();
                    if (!ByTag[tagName]) ByTag[tagName] = {};
                    Object.extend(ByTag[tagName], methods);
                }

                function mergeMethods(destination, methods, onlyIfAbsent) {
                    if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;
                    for (var property in methods) {
                        var value = methods[property];
                        if (!Object.isFunction(value)) continue;
                        if (!onlyIfAbsent || !(property in destination))
                            destination[property] = value.methodize();
                    }
                }

                function findDOMClass(tagName) {
                    var klass;
                    var trans = {
                        "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
                        "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
                        "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
                        "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
                        "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
                        "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
                        "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
                        "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
                        "FrameSet", "IFRAME": "IFrame"
                    };
                    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
                    if (window[klass]) return window[klass];
                    klass = 'HTML' + tagName + 'Element';
                    if (window[klass]) return window[klass];
                    klass = 'HTML' + tagName.capitalize() + 'Element';
                    if (window[klass]) return window[klass];

                    var element = document.createElement(tagName),
                     proto = element['__proto__'] || element.constructor.prototype;

                    element = null;
                    return proto;
                }

                function addMethods(methods) {
                    if (arguments.length === 0) addFormMethods();

                    if (arguments.length === 2) {
                        var tagName = methods;
                        methods = arguments[1];
                    }

                    if (!tagName) {
                        Object.extend(Element.Methods, methods || {});
                    } else {
                        if (Object.isArray(tagName)) {
                            for (var i = 0, tag; tag = tagName[i]; i++)
                                addMethodsToTagName(tag, methods);
                        } else {
                            addMethodsToTagName(tagName, methods);
                        }
                    }

                    var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
                     Element.prototype;

                    if (F.ElementExtensions) {
                        mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
                        mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
                    }

                    if (F.SpecificElementExtensions) {
                        for (var tag in Element.Methods.ByTag) {
                            var klass = findDOMClass(tag);
                            if (Object.isUndefined(klass)) continue;
                            mergeMethods(klass.prototype, ByTag[tag]);
                        }
                    }

                    Object.extend(Element, Element.Methods);
                    Object.extend(Element, Element.Methods.Simulated);
                    delete Element.ByTag;
                    delete Element.Simulated;

                    Element.extend.refresh();

                    ELEMENT_CACHE = {};
                }

                Object.extend(GLOBAL.Element, {
                    extend: extend,
                    addMethods: addMethods
                });

                if (extend === Prototype.K) {
                    GLOBAL.Element.extend.refresh = Prototype.emptyFunction;
                } else {
                    GLOBAL.Element.extend.refresh = function () {
                        if (Prototype.BrowserFeatures.ElementExtensions) return;
                        Object.extend(Methods, Element.Methods);
                        Object.extend(Methods, Element.Methods.Simulated);

                        EXTENDED = {};
                    };
                }

                function addFormMethods() {
                    Object.extend(Form, Form.Methods);
                    Object.extend(Form.Element, Form.Element.Methods);
                    Object.extend(Element.Methods.ByTag, {
                        "FORM": Object.clone(Form.Methods),
                        "INPUT": Object.clone(Form.Element.Methods),
                        "SELECT": Object.clone(Form.Element.Methods),
                        "TEXTAREA": Object.clone(Form.Element.Methods),
                        "BUTTON": Object.clone(Form.Element.Methods)
                    });
                }

                Element.addMethods(methods);

            })(this);
            (function () {

                function toDecimal(pctString) {
                    var match = pctString.match(/^(\d+)%?$/i);
                    if (!match) return null;
                    return (Number(match[1]) / 100);
                }

                function getRawStyle(element, style) {
                    element = $(element);

                    var value = element.style[style];
                    if (!value || value === 'auto') {
                        var css = document.defaultView.getComputedStyle(element, null);
                        value = css ? css[style] : null;
                    }

                    if (style === 'opacity') return value ? parseFloat(value) : 1.0;
                    return value === 'auto' ? null : value;
                }

                function getRawStyle_IE(element, style) {
                    var value = element.style[style];
                    if (!value && element.currentStyle) {
                        value = element.currentStyle[style];
                    }
                    return value;
                }

                function getContentWidth(element, context) {
                    var boxWidth = element.offsetWidth;

                    var bl = getPixelValue(element, 'borderLeftWidth', context) || 0;
                    var br = getPixelValue(element, 'borderRightWidth', context) || 0;
                    var pl = getPixelValue(element, 'paddingLeft', context) || 0;
                    var pr = getPixelValue(element, 'paddingRight', context) || 0;

                    return boxWidth - bl - br - pl - pr;
                }

                if ('currentStyle' in document.documentElement) {
                    getRawStyle = getRawStyle_IE;
                }


                function getPixelValue(value, property, context) {
                    var element = null;
                    if (Object.isElement(value)) {
                        element = value;
                        value = getRawStyle(element, property);
                    }

                    if (value === null || Object.isUndefined(value)) {
                        return null;
                    }

                    if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
                        return window.parseFloat(value);
                    }

                    var isPercentage = value.include('%'), isViewport = (context === document.viewport);

                    if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
                        var style = element.style.left, rStyle = element.runtimeStyle.left;
                        element.runtimeStyle.left = element.currentStyle.left;
                        element.style.left = value || 0;
                        value = element.style.pixelLeft;
                        element.style.left = style;
                        element.runtimeStyle.left = rStyle;

                        return value;
                    }

                    if (element && isPercentage) {
                        context = context || element.parentNode;
                        var decimal = toDecimal(value), whole = null;

                        var isHorizontal = property.include('left') || property.include('right') ||
                         property.include('width');

                        var isVertical = property.include('top') || property.include('bottom') ||
                          property.include('height');

                        if (context === document.viewport) {
                            if (isHorizontal) {
                                whole = document.viewport.getWidth();
                            } else if (isVertical) {
                                whole = document.viewport.getHeight();
                            }
                        } else {
                            if (isHorizontal) {
                                whole = $(context).measure('width');
                            } else if (isVertical) {
                                whole = $(context).measure('height');
                            }
                        }

                        return (whole === null) ? 0 : whole * decimal;
                    }

                    return 0;
                }

                function toCSSPixels(number) {
                    if (Object.isString(number) && number.endsWith('px'))
                        return number;
                    return number + 'px';
                }

                function isDisplayed(element) {
                    while (element && element.parentNode) {
                        var display = element.getStyle('display');
                        if (display === 'none') {
                            return false;
                        }
                        element = $(element.parentNode);
                    }
                    return true;
                }

                var hasLayout = Prototype.K;
                if ('currentStyle' in document.documentElement) {
                    hasLayout = function (element) {
                        if (!element.currentStyle.hasLayout) {
                            element.style.zoom = 1;
                        }
                        return element;
                    };
                }

                function cssNameFor(key) {
                    if (key.include('border')) key = key + '-width';
                    return key.camelize();
                }

                Element.Layout = Class.create(Hash, {
                    initialize: function ($super, element, preCompute) {
                        $super();
                        this.element = $(element);

                        Element.Layout.PROPERTIES.each(function (property) {
                            this._set(property, null);
                        }, this);

                        if (preCompute) {
                            this._preComputing = true;
                            this._begin();
                            Element.Layout.PROPERTIES.each(this._compute, this);
                            this._end();
                            this._preComputing = false;
                        }
                    },

                    _set: function (property, value) {
                        return Hash.prototype.set.call(this, property, value);
                    },

                    set: function (property, value) {
                        throw "Properties of Element.Layout are read-only.";
                    },

                    get: function ($super, property) {
                        var value = $super(property);
                        return value === null ? this._compute(property) : value;
                    },

                    _begin: function () {
                        if (this._isPrepared()) return;

                        var element = this.element;
                        if (isDisplayed(element)) {
                            this._setPrepared(true);
                            return;
                        }


                        var originalStyles = {
                            position: element.style.position || '',
                            width: element.style.width || '',
                            visibility: element.style.visibility || '',
                            display: element.style.display || ''
                        };

                        element.store('prototype_original_styles', originalStyles);

                        var position = getRawStyle(element, 'position'), width = element.offsetWidth;

                        if (width === 0 || width === null) {
                            element.style.display = 'block';
                            width = element.offsetWidth;
                        }

                        var context = (position === 'fixed') ? document.viewport :
                         element.parentNode;

                        var tempStyles = {
                            visibility: 'hidden',
                            display: 'block'
                        };

                        if (position !== 'fixed') tempStyles.position = 'absolute';

                        element.setStyle(tempStyles);

                        var positionedWidth = element.offsetWidth, newWidth;
                        if (width && (positionedWidth === width)) {
                            newWidth = getContentWidth(element, context);
                        } else if (position === 'absolute' || position === 'fixed') {
                            newWidth = getContentWidth(element, context);
                        } else {
                            var parent = element.parentNode, pLayout = $(parent).getLayout();

                            newWidth = pLayout.get('width') -
                             this.get('margin-left') -
                             this.get('border-left') -
                             this.get('padding-left') -
                             this.get('padding-right') -
                             this.get('border-right') -
                             this.get('margin-right');
                        }

                        element.setStyle({ width: newWidth + 'px' });

                        this._setPrepared(true);
                    },

                    _end: function () {
                        var element = this.element;
                        var originalStyles = element.retrieve('prototype_original_styles');
                        element.store('prototype_original_styles', null);
                        element.setStyle(originalStyles);
                        this._setPrepared(false);
                    },

                    _compute: function (property) {
                        var COMPUTATIONS = Element.Layout.COMPUTATIONS;
                        if (!(property in COMPUTATIONS)) {
                            throw "Property not found.";
                        }

                        return this._set(property, COMPUTATIONS[property].call(this, this.element));
                    },

                    _isPrepared: function () {
                        return this.element.retrieve('prototype_element_layout_prepared', false);
                    },

                    _setPrepared: function (bool) {
                        return this.element.store('prototype_element_layout_prepared', bool);
                    },

                    toObject: function () {
                        var args = $A(arguments);
                        var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
                         args.join(' ').split(' ');
                        var obj = {};
                        keys.each(function (key) {
                            if (!Element.Layout.PROPERTIES.include(key)) return;
                            var value = this.get(key);
                            if (value != null) obj[key] = value;
                        }, this);
                        return obj;
                    },

                    toHash: function () {
                        var obj = this.toObject.apply(this, arguments);
                        return new Hash(obj);
                    },

                    toCSS: function () {
                        var args = $A(arguments);
                        var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
                         args.join(' ').split(' ');
                        var css = {};

                        keys.each(function (key) {
                            if (!Element.Layout.PROPERTIES.include(key)) return;
                            if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;

                            var value = this.get(key);
                            if (value != null) css[cssNameFor(key)] = value + 'px';
                        }, this);
                        return css;
                    },

                    inspect: function () {
                        return "#<Element.Layout>";
                    }
                });

                Object.extend(Element.Layout, {
                    PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),

                    COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),

                    COMPUTATIONS: {
                        'height': function (element) {
                            if (!this._preComputing) this._begin();

                            var bHeight = this.get('border-box-height');
                            if (bHeight <= 0) {
                                if (!this._preComputing) this._end();
                                return 0;
                            }

                            var bTop = this.get('border-top'),
                             bBottom = this.get('border-bottom');

                            var pTop = this.get('padding-top'),
                             pBottom = this.get('padding-bottom');

                            if (!this._preComputing) this._end();

                            return bHeight - bTop - bBottom - pTop - pBottom;
                        },

                        'width': function (element) {
                            if (!this._preComputing) this._begin();

                            var bWidth = this.get('border-box-width');
                            if (bWidth <= 0) {
                                if (!this._preComputing) this._end();
                                return 0;
                            }

                            var bLeft = this.get('border-left'),
                             bRight = this.get('border-right');

                            var pLeft = this.get('padding-left'),
                             pRight = this.get('padding-right');

                            if (!this._preComputing) this._end();
                            return bWidth - bLeft - bRight - pLeft - pRight;
                        },

                        'padding-box-height': function (element) {
                            var height = this.get('height'),
                             pTop = this.get('padding-top'),
                             pBottom = this.get('padding-bottom');

                            return height + pTop + pBottom;
                        },

                        'padding-box-width': function (element) {
                            var width = this.get('width'),
                             pLeft = this.get('padding-left'),
                             pRight = this.get('padding-right');

                            return width + pLeft + pRight;
                        },

                        'border-box-height': function (element) {
                            if (!this._preComputing) this._begin();
                            var height = element.offsetHeight;
                            if (!this._preComputing) this._end();
                            return height;
                        },

                        'border-box-width': function (element) {
                            if (!this._preComputing) this._begin();
                            var width = element.offsetWidth;
                            if (!this._preComputing) this._end();
                            return width;
                        },

                        'margin-box-height': function (element) {
                            var bHeight = this.get('border-box-height'),
                             mTop = this.get('margin-top'),
                             mBottom = this.get('margin-bottom');

                            if (bHeight <= 0) return 0;

                            return bHeight + mTop + mBottom;
                        },

                        'margin-box-width': function (element) {
                            var bWidth = this.get('border-box-width'),
                             mLeft = this.get('margin-left'),
                             mRight = this.get('margin-right');

                            if (bWidth <= 0) return 0;

                            return bWidth + mLeft + mRight;
                        },

                        'top': function (element) {
                            var offset = element.positionedOffset();
                            return offset.top;
                        },

                        'bottom': function (element) {
                            var offset = element.positionedOffset(),
                             parent = element.getOffsetParent(),
                             pHeight = parent.measure('height');

                            var mHeight = this.get('border-box-height');

                            return pHeight - mHeight - offset.top;
                        },

                        'left': function (element) {
                            var offset = element.positionedOffset();
                            return offset.left;
                        },

                        'right': function (element) {
                            var offset = element.positionedOffset(),
                             parent = element.getOffsetParent(),
                             pWidth = parent.measure('width');

                            var mWidth = this.get('border-box-width');

                            return pWidth - mWidth - offset.left;
                        },

                        'padding-top': function (element) {
                            return getPixelValue(element, 'paddingTop');
                        },

                        'padding-bottom': function (element) {
                            return getPixelValue(element, 'paddingBottom');
                        },

                        'padding-left': function (element) {
                            return getPixelValue(element, 'paddingLeft');
                        },

                        'padding-right': function (element) {
                            return getPixelValue(element, 'paddingRight');
                        },

                        'border-top': function (element) {
                            return getPixelValue(element, 'borderTopWidth');
                        },

                        'border-bottom': function (element) {
                            return getPixelValue(element, 'borderBottomWidth');
                        },

                        'border-left': function (element) {
                            return getPixelValue(element, 'borderLeftWidth');
                        },

                        'border-right': function (element) {
                            return getPixelValue(element, 'borderRightWidth');
                        },

                        'margin-top': function (element) {
                            return getPixelValue(element, 'marginTop');
                        },

                        'margin-bottom': function (element) {
                            return getPixelValue(element, 'marginBottom');
                        },

                        'margin-left': function (element) {
                            return getPixelValue(element, 'marginLeft');
                        },

                        'margin-right': function (element) {
                            return getPixelValue(element, 'marginRight');
                        }
                    }
                });

                if ('getBoundingClientRect' in document.documentElement) {
                    Object.extend(Element.Layout.COMPUTATIONS, {
                        'right': function (element) {
                            var parent = hasLayout(element.getOffsetParent());
                            var rect = element.getBoundingClientRect(),
                             pRect = parent.getBoundingClientRect();

                            return (pRect.right - rect.right).round();
                        },

                        'bottom': function (element) {
                            var parent = hasLayout(element.getOffsetParent());
                            var rect = element.getBoundingClientRect(),
                             pRect = parent.getBoundingClientRect();

                            return (pRect.bottom - rect.bottom).round();
                        }
                    });
                }

                Element.Offset = Class.create({
                    initialize: function (left, top) {
                        this.left = left.round();
                        this.top = top.round();

                        this[0] = this.left;
                        this[1] = this.top;
                    },

                    relativeTo: function (offset) {
                        return new Element.Offset(
                          this.left - offset.left,
                          this.top - offset.top
                        );
                    },

                    inspect: function () {
                        return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
                    },

                    toString: function () {
                        return "[#{left}, #{top}]".interpolate(this);
                    },

                    toArray: function () {
                        return [this.left, this.top];
                    }
                });

                function getLayout(element, preCompute) {
                    return new Element.Layout(element, preCompute);
                }

                function measure(element, property) {
                    return $(element).getLayout().get(property);
                }

                function getHeight(element) {
                    return Element.getDimensions(element).height;
                }

                function getWidth(element) {
                    return Element.getDimensions(element).width;
                }

                function getDimensions(element) {
                    element = $(element);
                    var display = Element.getStyle(element, 'display');

                    if (display && display !== 'none') {
                        return { width: element.offsetWidth, height: element.offsetHeight };
                    }

                    var style = element.style;
                    var originalStyles = {
                        visibility: style.visibility,
                        position: style.position,
                        display: style.display
                    };

                    var newStyles = {
                        visibility: 'hidden',
                        display: 'block'
                    };

                    if (originalStyles.position !== 'fixed')
                        newStyles.position = 'absolute';

                    Element.setStyle(element, newStyles);

                    var dimensions = {
                        width: element.offsetWidth,
                        height: element.offsetHeight
                    };

                    Element.setStyle(element, originalStyles);

                    return dimensions;
                }

                function getOffsetParent(element) {
                    element = $(element);

                    if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
                        return $(document.body);

                    var isInline = (Element.getStyle(element, 'display') === 'inline');
                    if (!isInline && element.offsetParent) return $(element.offsetParent);

                    while ((element = element.parentNode) && element !== document.body) {
                        if (Element.getStyle(element, 'position') !== 'static') {
                            return isHtml(element) ? $(document.body) : $(element);
                        }
                    }

                    return $(document.body);
                }


                function cumulativeOffset(element) {
                    element = $(element);
                    var valueT = 0, valueL = 0;
                    if (element.parentNode) {
                        do {
                            valueT += element.offsetTop || 0;
                            valueL += element.offsetLeft || 0;
                            element = element.offsetParent;
                        } while (element);
                    }
                    return new Element.Offset(valueL, valueT);
                }

                function positionedOffset(element) {
                    element = $(element);

                    var layout = element.getLayout();

                    var valueT = 0, valueL = 0;
                    do {
                        valueT += element.offsetTop || 0;
                        valueL += element.offsetLeft || 0;
                        element = element.offsetParent;
                        if (element) {
                            if (isBody(element)) break;
                            var p = Element.getStyle(element, 'position');
                            if (p !== 'static') break;
                        }
                    } while (element);

                    valueL -= layout.get('margin-top');
                    valueT -= layout.get('margin-left');

                    return new Element.Offset(valueL, valueT);
                }

                function cumulativeScrollOffset(element) {
                    var valueT = 0, valueL = 0;
                    do {
                        valueT += element.scrollTop || 0;
                        valueL += element.scrollLeft || 0;
                        element = element.parentNode;
                    } while (element);
                    return new Element.Offset(valueL, valueT);
                }

                function viewportOffset(forElement) {
                    var valueT = 0, valueL = 0, docBody = document.body;

                    var element = $(forElement);
                    do {
                        valueT += element.offsetTop || 0;
                        valueL += element.offsetLeft || 0;
                        if (element.offsetParent == docBody &&
                          Element.getStyle(element, 'position') == 'absolute') break;
                    } while (element = element.offsetParent);

                    element = forElement;
                    do {
                        if (element != docBody) {
                            valueT -= element.scrollTop || 0;
                            valueL -= element.scrollLeft || 0;
                        }
                    } while (element = element.parentNode);
                    return new Element.Offset(valueL, valueT);
                }

                function absolutize(element) {
                    element = $(element);

                    if (Element.getStyle(element, 'position') === 'absolute') {
                        return element;
                    }

                    var offsetParent = getOffsetParent(element);
                    var eOffset = element.viewportOffset(),
                     pOffset = offsetParent.viewportOffset();

                    var offset = eOffset.relativeTo(pOffset);
                    var layout = element.getLayout();

                    element.store('prototype_absolutize_original_styles', {
                        left: element.getStyle('left'),
                        top: element.getStyle('top'),
                        width: element.getStyle('width'),
                        height: element.getStyle('height')
                    });

                    element.setStyle({
                        position: 'absolute',
                        top: offset.top + 'px',
                        left: offset.left + 'px',
                        width: layout.get('width') + 'px',
                        height: layout.get('height') + 'px'
                    });

                    return element;
                }

                function relativize(element) {
                    element = $(element);
                    if (Element.getStyle(element, 'position') === 'relative') {
                        return element;
                    }

                    var originalStyles =
                     element.retrieve('prototype_absolutize_original_styles');

                    if (originalStyles) element.setStyle(originalStyles);
                    return element;
                }


                function scrollTo(element) {
                    element = $(element);
                    var pos = Element.cumulativeOffset(element);
                    window.scrollTo(pos.left, pos.top);
                    return element;
                }


                function makePositioned(element) {
                    element = $(element);
                    var position = Element.getStyle(element, 'position'), styles = {};
                    if (position === 'static' || !position) {
                        styles.position = 'relative';
                        if (Prototype.Browser.Opera) {
                            styles.top = 0;
                            styles.left = 0;
                        }
                        Element.setStyle(element, styles);
                        Element.store(element, 'prototype_made_positioned', true);
                    }
                    return element;
                }

                function undoPositioned(element) {
                    element = $(element);
                    var storage = Element.getStorage(element),
                     madePositioned = storage.get('prototype_made_positioned');

                    if (madePositioned) {
                        storage.unset('prototype_made_positioned');
                        Element.setStyle(element, {
                            position: '',
                            top: '',
                            bottom: '',
                            left: '',
                            right: ''
                        });
                    }
                    return element;
                }

                function makeClipping(element) {
                    element = $(element);

                    var storage = Element.getStorage(element),
                     madeClipping = storage.get('prototype_made_clipping');

                    if (Object.isUndefined(madeClipping)) {
                        var overflow = Element.getStyle(element, 'overflow');
                        storage.set('prototype_made_clipping', overflow);
                        if (overflow !== 'hidden')
                            element.style.overflow = 'hidden';
                    }

                    return element;
                }

                function undoClipping(element) {
                    element = $(element);
                    var storage = Element.getStorage(element),
                     overflow = storage.get('prototype_made_clipping');

                    if (!Object.isUndefined(overflow)) {
                        storage.unset('prototype_made_clipping');
                        element.style.overflow = overflow || '';
                    }

                    return element;
                }

                function clonePosition(element, source, options) {
                    options = Object.extend({
                        setLeft: true,
                        setTop: true,
                        setWidth: true,
                        setHeight: true,
                        offsetTop: 0,
                        offsetLeft: 0
                    }, options || {});

                    source = $(source);
                    element = $(element);
                    var p, delta, layout, styles = {};

                    if (options.setLeft || options.setTop) {
                        p = Element.viewportOffset(source);
                        delta = [0, 0];
                        if (Element.getStyle(element, 'position') === 'absolute') {
                            var parent = Element.getOffsetParent(element);
                            if (parent !== document.body) delta = Element.viewportOffset(parent);
                        }
                    }

                    if (options.setWidth || options.setHeight) {
                        layout = Element.getLayout(source);
                    }

                    if (options.setLeft)
                        styles.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
                    if (options.setTop)
                        styles.top = (p[1] - delta[1] + options.offsetTop) + 'px';

                    if (options.setWidth)
                        styles.width = layout.get('border-box-width') + 'px';
                    if (options.setHeight)
                        styles.height = layout.get('border-box-height') + 'px';

                    return Element.setStyle(element, styles);
                }


                if (Prototype.Browser.IE) {
                    getOffsetParent = getOffsetParent.wrap(
                      function (proceed, element) {
                          element = $(element);

                          if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
                              return $(document.body);

                          var position = element.getStyle('position');
                          if (position !== 'static') return proceed(element);

                          element.setStyle({ position: 'relative' });
                          var value = proceed(element);
                          element.setStyle({ position: position });
                          return value;
                      }
                    );

                    positionedOffset = positionedOffset.wrap(function (proceed, element) {
                        element = $(element);
                        if (!element.parentNode) return new Element.Offset(0, 0);
                        var position = element.getStyle('position');
                        if (position !== 'static') return proceed(element);

                        var offsetParent = element.getOffsetParent();
                        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
                            hasLayout(offsetParent);

                        element.setStyle({ position: 'relative' });
                        var value = proceed(element);
                        element.setStyle({ position: position });
                        return value;
                    });
                } else if (Prototype.Browser.Webkit) {
                    cumulativeOffset = function (element) {
                        element = $(element);
                        var valueT = 0, valueL = 0;
                        do {
                            valueT += element.offsetTop || 0;
                            valueL += element.offsetLeft || 0;
                            if (element.offsetParent == document.body) {
                                if (Element.getStyle(element, 'position') == 'absolute') break;
                            }

                            element = element.offsetParent;
                        } while (element);

                        return new Element.Offset(valueL, valueT);
                    };
                }


                Element.addMethods({
                    getLayout: getLayout,
                    measure: measure,
                    getWidth: getWidth,
                    getHeight: getHeight,
                    getDimensions: getDimensions,
                    getOffsetParent: getOffsetParent,
                    cumulativeOffset: cumulativeOffset,
                    positionedOffset: positionedOffset,
                    cumulativeScrollOffset: cumulativeScrollOffset,
                    viewportOffset: viewportOffset,
                    absolutize: absolutize,
                    relativize: relativize,
                    scrollTo: scrollTo,
                    makePositioned: makePositioned,
                    undoPositioned: undoPositioned,
                    makeClipping: makeClipping,
                    undoClipping: undoClipping,
                    clonePosition: clonePosition
                });

                function isBody(element) {
                    return element.nodeName.toUpperCase() === 'BODY';
                }

                function isHtml(element) {
                    return element.nodeName.toUpperCase() === 'HTML';
                }

                function isDocument(element) {
                    return element.nodeType === Node.DOCUMENT_NODE;
                }

                function isDetached(element) {
                    return element !== document.body &&
                     !Element.descendantOf(element, document.body);
                }

                if ('getBoundingClientRect' in document.documentElement) {
                    Element.addMethods({
                        viewportOffset: function (element) {
                            element = $(element);
                            if (isDetached(element)) return new Element.Offset(0, 0);

                            var rect = element.getBoundingClientRect(),
                             docEl = document.documentElement;
                            return new Element.Offset(rect.left - docEl.clientLeft,
                             rect.top - docEl.clientTop);
                        }
                    });
                }


            })();

            (function () {

                var IS_OLD_OPERA = Prototype.Browser.Opera &&
                 (window.parseFloat(window.opera.version()) < 9.5);
                var ROOT = null;
                function getRootElement() {
                    if (ROOT) return ROOT;
                    ROOT = IS_OLD_OPERA ? document.body : document.documentElement;
                    return ROOT;
                }

                function getDimensions() {
                    return { width: this.getWidth(), height: this.getHeight() };
                }

                function getWidth() {
                    return getRootElement().clientWidth;
                }

                function getHeight() {
                    return getRootElement().clientHeight;
                }

                function getScrollOffsets() {
                    var x = window.pageXOffset || document.documentElement.scrollLeft ||
                     document.body.scrollLeft;
                    var y = window.pageYOffset || document.documentElement.scrollTop ||
                     document.body.scrollTop;

                    return new Element.Offset(x, y);
                }

                document.viewport = {
                    getDimensions: getDimensions,
                    getWidth: getWidth,
                    getHeight: getHeight,
                    getScrollOffsets: getScrollOffsets
                };

            })();
            window.$$ = function () {
                var expression = $A(arguments).join(', ');
                return Prototype.Selector.select(expression, document);
            };

            Prototype.Selector = (function () {

                function select() {
                    throw new Error('Method "Prototype.Selector.select" must be defined.');
                }

                function match() {
                    throw new Error('Method "Prototype.Selector.match" must be defined.');
                }

                function find(elements, expression, index) {
                    index = index || 0;
                    var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;

                    for (i = 0; i < length; i++) {
                        if (match(elements[i], expression) && index == matchIndex++) {
                            return Element.extend(elements[i]);
                        }
                    }
                }

                function extendElements(elements) {
                    for (var i = 0, length = elements.length; i < length; i++) {
                        Element.extend(elements[i]);
                    }
                    return elements;
                }


                var K = Prototype.K;

                return {
                    select: select,
                    match: match,
                    find: find,
                    extendElements: (Element.extend === K) ? K : extendElements,
                    extendElement: Element.extend
                };
            })();
            /*!
             * Sizzle CSS Selector Engine
             *  Copyright 2011, The Dojo Foundation
             *  Released under the MIT, BSD, and GPL Licenses.
             *  More information: http://sizzlejs.com/
             */
            (function () {

                var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
                    done = 0,
                    toString = Object.prototype.toString,
                    hasDuplicate = false,
                    baseHasDuplicate = true,
                    rBackslash = /\\/g,
                    rNonWord = /\W/;

                [0, 0].sort(function () {
                    baseHasDuplicate = false;
                    return 0;
                });

                var Sizzle = function (selector, context, results, seed) {
                    results = results || [];
                    context = context || document;

                    var origContext = context;

                    if (context.nodeType !== 1 && context.nodeType !== 9) {
                        return [];
                    }

                    if (!selector || typeof selector !== "string") {
                        return results;
                    }

                    var m, set, checkSet, extra, ret, cur, pop, i,
                        prune = true,
                        contextXML = Sizzle.isXML(context),
                        parts = [],
                        soFar = selector;

                    do {
                        chunker.exec("");
                        m = chunker.exec(soFar);

                        if (m) {
                            soFar = m[3];

                            parts.push(m[1]);

                            if (m[2]) {
                                extra = m[3];
                                break;
                            }
                        }
                    } while (m);

                    if (parts.length > 1 && origPOS.exec(selector)) {

                        if (parts.length === 2 && Expr.relative[parts[0]]) {
                            set = posProcess(parts[0] + parts[1], context);

                        } else {
                            set = Expr.relative[parts[0]] ?
                                [context] :
                                Sizzle(parts.shift(), context);

                            while (parts.length) {
                                selector = parts.shift();

                                if (Expr.relative[selector]) {
                                    selector += parts.shift();
                                }

                                set = posProcess(selector, set);
                            }
                        }

                    } else {
                        if (!seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
                                Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])) {

                            ret = Sizzle.find(parts.shift(), context, contextXML);
                            context = ret.expr ?
                                Sizzle.filter(ret.expr, ret.set)[0] :
                                ret.set[0];
                        }

                        if (context) {
                            ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
                                Sizzle.find(parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML);

                            set = ret.expr ?
                                Sizzle.filter(ret.expr, ret.set) :
                                ret.set;

                            if (parts.length > 0) {
                                checkSet = makeArray(set);

                            } else {
                                prune = false;
                            }

                            while (parts.length) {
                                cur = parts.pop();
                                pop = cur;

                                if (!Expr.relative[cur]) {
                                    cur = "";
                                } else {
                                    pop = parts.pop();
                                }

                                if (pop == null) {
                                    pop = context;
                                }

                                Expr.relative[cur](checkSet, pop, contextXML);
                            }

                        } else {
                            checkSet = parts = [];
                        }
                    }

                    if (!checkSet) {
                        checkSet = set;
                    }

                    if (!checkSet) {
                        Sizzle.error(cur || selector);
                    }

                    if (toString.call(checkSet) === "[object Array]") {
                        if (!prune) {
                            results.push.apply(results, checkSet);

                        } else if (context && context.nodeType === 1) {
                            for (i = 0; checkSet[i] != null; i++) {
                                if (checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i]))) {
                                    results.push(set[i]);
                                }
                            }

                        } else {
                            for (i = 0; checkSet[i] != null; i++) {
                                if (checkSet[i] && checkSet[i].nodeType === 1) {
                                    results.push(set[i]);
                                }
                            }
                        }

                    } else {
                        makeArray(checkSet, results);
                    }

                    if (extra) {
                        Sizzle(extra, origContext, results, seed);
                        Sizzle.uniqueSort(results);
                    }

                    return results;
                };

                Sizzle.uniqueSort = function (results) {
                    if (sortOrder) {
                        hasDuplicate = baseHasDuplicate;
                        results.sort(sortOrder);

                        if (hasDuplicate) {
                            for (var i = 1; i < results.length; i++) {
                                if (results[i] === results[i - 1]) {
                                    results.splice(i--, 1);
                                }
                            }
                        }
                    }

                    return results;
                };

                Sizzle.matches = function (expr, set) {
                    return Sizzle(expr, null, null, set);
                };

                Sizzle.matchesSelector = function (node, expr) {
                    return Sizzle(expr, null, null, [node]).length > 0;
                };

                Sizzle.find = function (expr, context, isXML) {
                    var set;

                    if (!expr) {
                        return [];
                    }

                    for (var i = 0, l = Expr.order.length; i < l; i++) {
                        var match,
                            type = Expr.order[i];

                        if ((match = Expr.leftMatch[type].exec(expr))) {
                            var left = match[1];
                            match.splice(1, 1);

                            if (left.substr(left.length - 1) !== "\\") {
                                match[1] = (match[1] || "").replace(rBackslash, "");
                                set = Expr.find[type](match, context, isXML);

                                if (set != null) {
                                    expr = expr.replace(Expr.match[type], "");
                                    break;
                                }
                            }
                        }
                    }

                    if (!set) {
                        set = typeof context.getElementsByTagName !== "undefined" ?
                            context.getElementsByTagName("*") :
                            [];
                    }

                    return { set: set, expr: expr };
                };

                Sizzle.filter = function (expr, set, inplace, not) {
                    var match, anyFound,
                        old = expr,
                        result = [],
                        curLoop = set,
                        isXMLFilter = set && set[0] && Sizzle.isXML(set[0]);

                    while (expr && set.length) {
                        for (var type in Expr.filter) {
                            if ((match = Expr.leftMatch[type].exec(expr)) != null && match[2]) {
                                var found, item,
                                    filter = Expr.filter[type],
                                    left = match[1];

                                anyFound = false;

                                match.splice(1, 1);

                                if (left.substr(left.length - 1) === "\\") {
                                    continue;
                                }

                                if (curLoop === result) {
                                    result = [];
                                }

                                if (Expr.preFilter[type]) {
                                    match = Expr.preFilter[type](match, curLoop, inplace, result, not, isXMLFilter);

                                    if (!match) {
                                        anyFound = found = true;

                                    } else if (match === true) {
                                        continue;
                                    }
                                }

                                if (match) {
                                    for (var i = 0; (item = curLoop[i]) != null; i++) {
                                        if (item) {
                                            found = filter(item, match, i, curLoop);
                                            var pass = not ^ !!found;

                                            if (inplace && found != null) {
                                                if (pass) {
                                                    anyFound = true;

                                                } else {
                                                    curLoop[i] = false;
                                                }

                                            } else if (pass) {
                                                result.push(item);
                                                anyFound = true;
                                            }
                                        }
                                    }
                                }

                                if (found !== undefined) {
                                    if (!inplace) {
                                        curLoop = result;
                                    }

                                    expr = expr.replace(Expr.match[type], "");

                                    if (!anyFound) {
                                        return [];
                                    }

                                    break;
                                }
                            }
                        }

                        if (expr === old) {
                            if (anyFound == null) {
                                Sizzle.error(expr);

                            } else {
                                break;
                            }
                        }

                        old = expr;
                    }

                    return curLoop;
                };

                Sizzle.error = function (msg) {
                    throw "Syntax error, unrecognized expression: " + msg;
                };

                var Expr = Sizzle.selectors = {
                    order: ["ID", "NAME", "TAG"],

                    match: {
                        ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
                        CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
                        NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
                        ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
                        TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
                        CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
                        POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
                        PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
                    },

                    leftMatch: {},

                    attrMap: {
                        "class": "className",
                        "for": "htmlFor"
                    },

                    attrHandle: {
                        href: function (elem) {
                            return elem.getAttribute("href");
                        },
                        type: function (elem) {
                            return elem.getAttribute("type");
                        }
                    },

                    relative: {
                        "+": function (checkSet, part) {
                            var isPartStr = typeof part === "string",
                                isTag = isPartStr && !rNonWord.test(part),
                                isPartStrNotTag = isPartStr && !isTag;

                            if (isTag) {
                                part = part.toLowerCase();
                            }

                            for (var i = 0, l = checkSet.length, elem; i < l; i++) {
                                if ((elem = checkSet[i])) {
                                    while ((elem = elem.previousSibling) && elem.nodeType !== 1) { }

                                    checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
                                        elem || false :
                                        elem === part;
                                }
                            }

                            if (isPartStrNotTag) {
                                Sizzle.filter(part, checkSet, true);
                            }
                        },

                        ">": function (checkSet, part) {
                            var elem,
                                isPartStr = typeof part === "string",
                                i = 0,
                                l = checkSet.length;

                            if (isPartStr && !rNonWord.test(part)) {
                                part = part.toLowerCase();

                                for (; i < l; i++) {
                                    elem = checkSet[i];

                                    if (elem) {
                                        var parent = elem.parentNode;
                                        checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
                                    }
                                }

                            } else {
                                for (; i < l; i++) {
                                    elem = checkSet[i];

                                    if (elem) {
                                        checkSet[i] = isPartStr ?
                                            elem.parentNode :
                                            elem.parentNode === part;
                                    }
                                }

                                if (isPartStr) {
                                    Sizzle.filter(part, checkSet, true);
                                }
                            }
                        },

                        "": function (checkSet, part, isXML) {
                            var nodeCheck,
                                doneName = done++,
                                checkFn = dirCheck;

                            if (typeof part === "string" && !rNonWord.test(part)) {
                                part = part.toLowerCase();
                                nodeCheck = part;
                                checkFn = dirNodeCheck;
                            }

                            checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
                        },

                        "~": function (checkSet, part, isXML) {
                            var nodeCheck,
                                doneName = done++,
                                checkFn = dirCheck;

                            if (typeof part === "string" && !rNonWord.test(part)) {
                                part = part.toLowerCase();
                                nodeCheck = part;
                                checkFn = dirNodeCheck;
                            }

                            checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
                        }
                    },

                    find: {
                        ID: function (match, context, isXML) {
                            if (typeof context.getElementById !== "undefined" && !isXML) {
                                var m = context.getElementById(match[1]);
                                return m && m.parentNode ? [m] : [];
                            }
                        },

                        NAME: function (match, context) {
                            if (typeof context.getElementsByName !== "undefined") {
                                var ret = [],
                                    results = context.getElementsByName(match[1]);

                                for (var i = 0, l = results.length; i < l; i++) {
                                    if (results[i].getAttribute("name") === match[1]) {
                                        ret.push(results[i]);
                                    }
                                }

                                return ret.length === 0 ? null : ret;
                            }
                        },

                        TAG: function (match, context) {
                            if (typeof context.getElementsByTagName !== "undefined") {
                                return context.getElementsByTagName(match[1]);
                            }
                        }
                    },
                    preFilter: {
                        CLASS: function (match, curLoop, inplace, result, not, isXML) {
                            match = " " + match[1].replace(rBackslash, "") + " ";

                            if (isXML) {
                                return match;
                            }

                            for (var i = 0, elem; (elem = curLoop[i]) != null; i++) {
                                if (elem) {
                                    if (not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0)) {
                                        if (!inplace) {
                                            result.push(elem);
                                        }

                                    } else if (inplace) {
                                        curLoop[i] = false;
                                    }
                                }
                            }

                            return false;
                        },

                        ID: function (match) {
                            return match[1].replace(rBackslash, "");
                        },

                        TAG: function (match, curLoop) {
                            return match[1].replace(rBackslash, "").toLowerCase();
                        },

                        CHILD: function (match) {
                            if (match[1] === "nth") {
                                if (!match[2]) {
                                    Sizzle.error(match[0]);
                                }

                                match[2] = match[2].replace(/^\+|\s*/g, '');

                                var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
                                    match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
                                    !/\D/.test(match[2]) && "0n+" + match[2] || match[2]);

                                match[2] = (test[1] + (test[2] || 1)) - 0;
                                match[3] = test[3] - 0;
                            }
                            else if (match[2]) {
                                Sizzle.error(match[0]);
                            }

                            match[0] = done++;

                            return match;
                        },

                        ATTR: function (match, curLoop, inplace, result, not, isXML) {
                            var name = match[1] = match[1].replace(rBackslash, "");

                            if (!isXML && Expr.attrMap[name]) {
                                match[1] = Expr.attrMap[name];
                            }

                            match[4] = (match[4] || match[5] || "").replace(rBackslash, "");

                            if (match[2] === "~=") {
                                match[4] = " " + match[4] + " ";
                            }

                            return match;
                        },

                        PSEUDO: function (match, curLoop, inplace, result, not) {
                            if (match[1] === "not") {
                                if ((chunker.exec(match[3]) || "").length > 1 || /^\w/.test(match[3])) {
                                    match[3] = Sizzle(match[3], null, null, curLoop);

                                } else {
                                    var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

                                    if (!inplace) {
                                        result.push.apply(result, ret);
                                    }

                                    return false;
                                }

                            } else if (Expr.match.POS.test(match[0]) || Expr.match.CHILD.test(match[0])) {
                                return true;
                            }

                            return match;
                        },

                        POS: function (match) {
                            match.unshift(true);

                            return match;
                        }
                    },

                    filters: {
                        enabled: function (elem) {
                            return elem.disabled === false && elem.type !== "hidden";
                        },

                        disabled: function (elem) {
                            return elem.disabled === true;
                        },

                        checked: function (elem) {
                            return elem.checked === true;
                        },

                        selected: function (elem) {
                            if (elem.parentNode) {
                                elem.parentNode.selectedIndex;
                            }

                            return elem.selected === true;
                        },

                        parent: function (elem) {
                            return !!elem.firstChild;
                        },

                        empty: function (elem) {
                            return !elem.firstChild;
                        },

                        has: function (elem, i, match) {
                            return !!Sizzle(match[3], elem).length;
                        },

                        header: function (elem) {
                            return (/h\d/i).test(elem.nodeName);
                        },

                        text: function (elem) {
                            var attr = elem.getAttribute("type"), type = elem.type;
                            return elem.nodeName.toLowerCase() === "input" && "text" === type && (attr === type || attr === null);
                        },

                        radio: function (elem) {
                            return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
                        },

                        checkbox: function (elem) {
                            return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
                        },

                        file: function (elem) {
                            return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
                        },

                        password: function (elem) {
                            return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
                        },

                        submit: function (elem) {
                            var name = elem.nodeName.toLowerCase();
                            return (name === "input" || name === "button") && "submit" === elem.type;
                        },

                        image: function (elem) {
                            return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
                        },

                        reset: function (elem) {
                            var name = elem.nodeName.toLowerCase();
                            return (name === "input" || name === "button") && "reset" === elem.type;
                        },

                        button: function (elem) {
                            var name = elem.nodeName.toLowerCase();
                            return name === "input" && "button" === elem.type || name === "button";
                        },

                        input: function (elem) {
                            return (/input|select|textarea|button/i).test(elem.nodeName);
                        },

                        focus: function (elem) {
                            return elem === elem.ownerDocument.activeElement;
                        }
                    },
                    setFilters: {
                        first: function (elem, i) {
                            return i === 0;
                        },

                        last: function (elem, i, match, array) {
                            return i === array.length - 1;
                        },

                        even: function (elem, i) {
                            return i % 2 === 0;
                        },

                        odd: function (elem, i) {
                            return i % 2 === 1;
                        },

                        lt: function (elem, i, match) {
                            return i < match[3] - 0;
                        },

                        gt: function (elem, i, match) {
                            return i > match[3] - 0;
                        },

                        nth: function (elem, i, match) {
                            return match[3] - 0 === i;
                        },

                        eq: function (elem, i, match) {
                            return match[3] - 0 === i;
                        }
                    },
                    filter: {
                        PSEUDO: function (elem, match, i, array) {
                            var name = match[1],
                                filter = Expr.filters[name];

                            if (filter) {
                                return filter(elem, i, match, array);

                            } else if (name === "contains") {
                                return (elem.textContent || elem.innerText || Sizzle.getText([elem]) || "").indexOf(match[3]) >= 0;

                            } else if (name === "not") {
                                var not = match[3];

                                for (var j = 0, l = not.length; j < l; j++) {
                                    if (not[j] === elem) {
                                        return false;
                                    }
                                }

                                return true;

                            } else {
                                Sizzle.error(name);
                            }
                        },

                        CHILD: function (elem, match) {
                            var type = match[1],
                                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;

                                case "last":
                                    while ((node = node.nextSibling)) {
                                        if (node.nodeType === 1) {
                                            return false;
                                        }
                                    }

                                    return true;

                                case "nth":
                                    var first = match[2],
                                        last = match[3];

                                    if (first === 1 && last === 0) {
                                        return true;
                                    }

                                    var doneName = match[0],
                                        parent = elem.parentNode;

                                    if (parent && (parent.sizcache !== doneName || !elem.nodeIndex)) {
                                        var count = 0;

                                        for (node = parent.firstChild; node; node = node.nextSibling) {
                                            if (node.nodeType === 1) {
                                                node.nodeIndex = ++count;
                                            }
                                        }

                                        parent.sizcache = doneName;
                                    }

                                    var diff = elem.nodeIndex - last;

                                    if (first === 0) {
                                        return diff === 0;

                                    } else {
                                        return (diff % first === 0 && diff / first >= 0);
                                    }
                            }
                        },

                        ID: function (elem, match) {
                            return elem.nodeType === 1 && elem.getAttribute("id") === match;
                        },

                        TAG: function (elem, match) {
                            return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
                        },

                        CLASS: function (elem, match) {
                            return (" " + (elem.className || elem.getAttribute("class")) + " ")
                                .indexOf(match) > -1;
                        },

                        ATTR: function (elem, match) {
                            var name = match[1],
                                result = Expr.attrHandle[name] ?
                                    Expr.attrHandle[name](elem) :
                                    elem[name] != null ?
                                        elem[name] :
                                        elem.getAttribute(name),
                                value = result + "",
                                type = match[2],
                                check = match[4];

                            return result == null ?
                                type === "!=" :
                                type === "=" ?
                                value === check :
                                type === "*=" ?
                                value.indexOf(check) >= 0 :
                                type === "~=" ?
                                (" " + value + " ").indexOf(check) >= 0 :
                                !check ?
                                value && result !== false :
                                type === "!=" ?
                                value !== check :
                                type === "^=" ?
                                value.indexOf(check) === 0 :
                                type === "$=" ?
                                value.substr(value.length - check.length) === check :
                                type === "|=" ?
                                value === check || value.substr(0, check.length + 1) === check + "-" :
                                false;
                        },

                        POS: function (elem, match, i, array) {
                            var name = match[2],
                                filter = Expr.setFilters[name];

                            if (filter) {
                                return filter(elem, i, match, array);
                            }
                        }
                    }
                };

                var origPOS = Expr.match.POS,
                    fescape = function (all, num) {
                        return "\\" + (num - 0 + 1);
                    };

                for (var type in Expr.match) {
                    Expr.match[type] = new RegExp(Expr.match[type].source + (/(?![^\[]*\])(?![^\(]*\))/.source));
                    Expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + Expr.match[type].source.replace(/\\(\d+)/g, fescape));
                }

                var makeArray = function (array, results) {
                    array = Array.prototype.slice.call(array, 0);

                    if (results) {
                        results.push.apply(results, array);
                        return results;
                    }

                    return array;
                };

                try {
                    Array.prototype.slice.call(document.documentElement.childNodes, 0)[0].nodeType;

                } catch (e) {
                    makeArray = function (array, results) {
                        var i = 0,
                            ret = results || [];

                        if (toString.call(array) === "[object Array]") {
                            Array.prototype.push.apply(ret, array);

                        } else {
                            if (typeof array.length === "number") {
                                for (var l = array.length; i < l; i++) {
                                    ret.push(array[i]);
                                }

                            } else {
                                for (; array[i]; i++) {
                                    ret.push(array[i]);
                                }
                            }
                        }

                        return ret;
                    };
                }

                var sortOrder, siblingCheck;

                if (document.documentElement.compareDocumentPosition) {
                    sortOrder = function (a, b) {
                        if (a === b) {
                            hasDuplicate = true;
                            return 0;
                        }

                        if (!a.compareDocumentPosition || !b.compareDocumentPosition) {
                            return a.compareDocumentPosition ? -1 : 1;
                        }

                        return a.compareDocumentPosition(b) & 4 ? -1 : 1;
                    };

                } else {
                    sortOrder = function (a, b) {
                        if (a === b) {
                            hasDuplicate = true;
                            return 0;

                        } 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 (aup === bup) {
                            return siblingCheck(a, b);

                        } else if (!aup) {
                            return -1;

                        } else if (!bup) {
                            return 1;
                        }

                        while (cur) {
                            ap.unshift(cur);
                            cur = cur.parentNode;
                        }

                        cur = bup;

                        while (cur) {
                            bp.unshift(cur);
                            cur = cur.parentNode;
                        }

                        al = ap.length;
                        bl = bp.length;

                        for (var i = 0; i < al && i < bl; i++) {
                            if (ap[i] !== bp[i]) {
                                return siblingCheck(ap[i], bp[i]);
                            }
                        }

                        return i === al ?
                            siblingCheck(a, bp[i], -1) :
                            siblingCheck(ap[i], b, 1);
                    };

                    siblingCheck = function (a, b, ret) {
                        if (a === b) {
                            return ret;
                        }

                        var cur = a.nextSibling;

                        while (cur) {
                            if (cur === b) {
                                return -1;
                            }

                            cur = cur.nextSibling;
                        }

                        return 1;
                    };
                }

                Sizzle.getText = function (elems) {
                    var ret = "", elem;

                    for (var i = 0; elems[i]; i++) {
                        elem = elems[i];

                        if (elem.nodeType === 3 || elem.nodeType === 4) {
                            ret += elem.nodeValue;

                        } else if (elem.nodeType !== 8) {
                            ret += Sizzle.getText(elem.childNodes);
                        }
                    }

                    return ret;
                };

                (function () {
                    var form = document.createElement("div"),
                        id = "script" + (new Date()).getTime(),
                        root = document.documentElement;

                    form.innerHTML = "<a name='" + id + "'/>";

                    root.insertBefore(form, root.firstChild);

                    if (document.getElementById(id)) {
                        Expr.find.ID = function (match, context, isXML) {
                            if (typeof context.getElementById !== "undefined" && !isXML) {
                                var m = context.getElementById(match[1]);

                                return m ?
                                    m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
                                        [m] :
                                    undefined :
                                    [];
                            }
                        };

                        Expr.filter.ID = function (elem, match) {
                            var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

                            return elem.nodeType === 1 && node && node.nodeValue === match;
                        };
                    }

                    root.removeChild(form);

                    root = form = null;
                })();

                (function () {

                    var div = document.createElement("div");
                    div.appendChild(document.createComment(""));

                    if (div.getElementsByTagName("*").length > 0) {
                        Expr.find.TAG = function (match, context) {
                            var results = context.getElementsByTagName(match[1]);

                            if (match[1] === "*") {
                                var tmp = [];

                                for (var i = 0; results[i]; i++) {
                                    if (results[i].nodeType === 1) {
                                        tmp.push(results[i]);
                                    }
                                }

                                results = tmp;
                            }

                            return results;
                        };
                    }

                    div.innerHTML = "<a href='#'></a>";

                    if (div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
                            div.firstChild.getAttribute("href") !== "#") {

                        Expr.attrHandle.href = function (elem) {
                            return elem.getAttribute("href", 2);
                        };
                    }

                    div = null;
                })();

                if (document.querySelectorAll) {
                    (function () {
                        var oldSizzle = Sizzle,
                            div = document.createElement("div"),
                            id = "__sizzle__";

                        div.innerHTML = "<p class='TEST'></p>";

                        if (div.querySelectorAll && div.querySelectorAll(".TEST").length === 0) {
                            return;
                        }

                        Sizzle = function (query, context, extra, seed) {
                            context = context || document;

                            if (!seed && !Sizzle.isXML(context)) {
                                var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(query);

                                if (match && (context.nodeType === 1 || context.nodeType === 9)) {
                                    if (match[1]) {
                                        return makeArray(context.getElementsByTagName(query), extra);

                                    } else if (match[2] && Expr.find.CLASS && context.getElementsByClassName) {
                                        return makeArray(context.getElementsByClassName(match[2]), extra);
                                    }
                                }

                                if (context.nodeType === 9) {
                                    if (query === "body" && context.body) {
                                        return makeArray([context.body], extra);

                                    } else if (match && match[3]) {
                                        var elem = context.getElementById(match[3]);

                                        if (elem && elem.parentNode) {
                                            if (elem.id === match[3]) {
                                                return makeArray([elem], extra);
                                            }

                                        } else {
                                            return makeArray([], extra);
                                        }
                                    }

                                    try {
                                        return makeArray(context.querySelectorAll(query), extra);
                                    } catch (qsaError) { }

                                } else if (context.nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
                                    var oldContext = context,
                                        old = context.getAttribute("id"),
                                        nid = old || id,
                                        hasParent = context.parentNode,
                                        relativeHierarchySelector = /^\s*[+~]/.test(query);

                                    if (!old) {
                                        context.setAttribute("id", nid);
                                    } else {
                                        nid = nid.replace(/'/g, "\\$&");
                                    }
                                    if (relativeHierarchySelector && hasParent) {
                                        context = context.parentNode;
                                    }

                                    try {
                                        if (!relativeHierarchySelector || hasParent) {
                                            return makeArray(context.querySelectorAll("[id='" + nid + "'] " + query), extra);
                                        }

                                    } catch (pseudoError) {
                                    } finally {
                                        if (!old) {
                                            oldContext.removeAttribute("id");
                                        }
                                    }
                                }
                            }

                            return oldSizzle(query, context, extra, seed);
                        };

                        for (var prop in oldSizzle) {
                            Sizzle[prop] = oldSizzle[prop];
                        }

                        div = null;
                    })();
                }

                (function () {
                    var html = document.documentElement,
                        matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;

                    if (matches) {
                        var disconnectedMatch = !matches.call(document.createElement("div"), "div"),
                            pseudoWorks = false;

                        try {
                            matches.call(document.documentElement, "[test!='']:sizzle");

                        } catch (pseudoError) {
                            pseudoWorks = true;
                        }

                        Sizzle.matchesSelector = function (node, expr) {
                            expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");

                            if (!Sizzle.isXML(node)) {
                                try {
                                    if (pseudoWorks || !Expr.match.PSEUDO.test(expr) && !/!=/.test(expr)) {
                                        var ret = matches.call(node, expr);

                                        if (ret || !disconnectedMatch ||
                                                node.document && node.document.nodeType !== 11) {
                                            return ret;
                                        }
                                    }
                                } catch (e) { }
                            }

                            return Sizzle(expr, null, null, [node]).length > 0;
                        };
                    }
                })();

                (function () {
                    var div = document.createElement("div");

                    div.innerHTML = "<div class='test e'></div><div class='test'></div>";

                    if (!div.getElementsByClassName || div.getElementsByClassName("e").length === 0) {
                        return;
                    }

                    div.lastChild.className = "e";

                    if (div.getElementsByClassName("e").length === 1) {
                        return;
                    }

                    Expr.order.splice(1, 0, "CLASS");
                    Expr.find.CLASS = function (match, context, isXML) {
                        if (typeof context.getElementsByClassName !== "undefined" && !isXML) {
                            return context.getElementsByClassName(match[1]);
                        }
                    };

                    div = null;
                })();

                function dirNodeCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
                    for (var i = 0, l = checkSet.length; i < l; i++) {
                        var elem = checkSet[i];

                        if (elem) {
                            var match = false;

                            elem = elem[dir];

                            while (elem) {
                                if (elem.sizcache === doneName) {
                                    match = checkSet[elem.sizset];
                                    break;
                                }

                                if (elem.nodeType === 1 && !isXML) {
                                    elem.sizcache = doneName;
                                    elem.sizset = i;
                                }

                                if (elem.nodeName.toLowerCase() === cur) {
                                    match = elem;
                                    break;
                                }

                                elem = elem[dir];
                            }

                            checkSet[i] = match;
                        }
                    }
                }

                function dirCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
                    for (var i = 0, l = checkSet.length; i < l; i++) {
                        var elem = checkSet[i];

                        if (elem) {
                            var match = false;

                            elem = elem[dir];

                            while (elem) {
                                if (elem.sizcache === doneName) {
                                    match = checkSet[elem.sizset];
                                    break;
                                }

                                if (elem.nodeType === 1) {
                                    if (!isXML) {
                                        elem.sizcache = doneName;
                                        elem.sizset = i;
                                    }

                                    if (typeof cur !== "string") {
                                        if (elem === cur) {
                                            match = true;
                                            break;
                                        }

                                    } else if (Sizzle.filter(cur, [elem]).length > 0) {
                                        match = elem;
                                        break;
                                    }
                                }

                                elem = elem[dir];
                            }

                            checkSet[i] = match;
                        }
                    }
                }

                if (document.documentElement.contains) {
                    Sizzle.contains = function (a, b) {
                        return a !== b && (a.contains ? a.contains(b) : true);
                    };

                } else if (document.documentElement.compareDocumentPosition) {
                    Sizzle.contains = function (a, b) {
                        return !!(a.compareDocumentPosition(b) & 16);
                    };

                } else {
                    Sizzle.contains = function () {
                        return false;
                    };
                }

                Sizzle.isXML = function (elem) {
                    var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;

                    return documentElement ? documentElement.nodeName !== "HTML" : false;
                };

                var posProcess = function (selector, context) {
                    var match,
                        tmpSet = [],
                        later = "",
                        root = context.nodeType ? [context] : context;

                    while ((match = Expr.match.PSEUDO.exec(selector))) {
                        later += match[0];
                        selector = selector.replace(Expr.match.PSEUDO, "");
                    }

                    selector = Expr.relative[selector] ? selector + "*" : selector;

                    for (var i = 0, l = root.length; i < l; i++) {
                        Sizzle(selector, root[i], tmpSet);
                    }

                    return Sizzle.filter(later, tmpSet);
                };


                window.Sizzle = Sizzle;

            })();

            Prototype._original_property = window.Sizzle;

            ; (function (engine) {
                var extendElements = Prototype.Selector.extendElements;

                function select(selector, scope) {
                    return extendElements(engine(selector, scope || document));
                }

                function match(element, selector) {
                    return engine.matches(selector, [element]).length == 1;
                }

                Prototype.Selector.engine = engine;
                Prototype.Selector.select = select;
                Prototype.Selector.match = match;
            })(Sizzle);

            window.Sizzle = Prototype._original_property;
            delete Prototype._original_property;

            var Form = {
                reset: function (form) {
                    form = $(form);
                    form.reset();
                    return form;
                },

                serializeElements: function (elements, options) {
                    if (typeof options != 'object') options = { hash: !!options };
                    else if (Object.isUndefined(options.hash)) options.hash = true;
                    var key, value, submitted = false, submit = options.submit, accumulator, initial;

                    if (options.hash) {
                        initial = {};
                        accumulator = function (result, key, value) {
                            if (key in result) {
                                if (!Object.isArray(result[key])) result[key] = [result[key]];
                                result[key].push(value);
                            } else result[key] = value;
                            return result;
                        };
                    } else {
                        initial = '';
                        accumulator = function (result, key, value) {
                            value = value.gsub(/(\r)?\n/, '\r\n');
                            value = encodeURIComponent(value);
                            value = value.gsub(/%20/, '+');
                            return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
                        }
                    }

                    return elements.inject(initial, function (result, element) {
                        if (!element.disabled && element.name) {
                            key = element.name; value = $(element).getValue();
                            if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
                                submit !== false && (!submit || key == submit) && (submitted = true)))) {
                                result = accumulator(result, key, value);
                            }
                        }
                        return result;
                    });
                }
            };

            Form.Methods = {
                serialize: function (form, options) {
                    return Form.serializeElements(Form.getElements(form), options);
                },


                getElements: function (form) {
                    var elements = $(form).getElementsByTagName('*');
                    var element, results = [], serializers = Form.Element.Serializers;

                    for (var i = 0; element = elements[i]; i++) {
                        if (serializers[element.tagName.toLowerCase()])
                            results.push(Element.extend(element));
                    }
                    return results;
                },

                getInputs: function (form, typeName, name) {
                    form = $(form);
                    var inputs = form.getElementsByTagName('input');

                    if (!typeName && !name) return $A(inputs).map(Element.extend);

                    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
                        var input = inputs[i];
                        if ((typeName && input.type != typeName) || (name && input.name != name))
                            continue;
                        matchingInputs.push(Element.extend(input));
                    }

                    return matchingInputs;
                },

                disable: function (form) {
                    form = $(form);
                    Form.getElements(form).invoke('disable');
                    return form;
                },

                enable: function (form) {
                    form = $(form);
                    Form.getElements(form).invoke('enable');
                    return form;
                },

                findFirstElement: function (form) {
                    var elements = $(form).getElements().findAll(function (element) {
                        return 'hidden' != element.type && !element.disabled;
                    });
                    var firstByIndex = elements.findAll(function (element) {
                        return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
                    }).sortBy(function (element) { return element.tabIndex }).first();

                    return firstByIndex ? firstByIndex : elements.find(function (element) {
                        return /^(?:input|select|textarea)$/i.test(element.tagName);
                    });
                },

                focusFirstElement: function (form) {
                    form = $(form);
                    var element = form.findFirstElement();
                    if (element) element.activate();
                    return form;
                },

                request: function (form, options) {
                    form = $(form), options = Object.clone(options || {});

                    var params = options.parameters, action = form.readAttribute('action') || '';
                    if (action.blank()) action = window.location.href;
                    options.parameters = form.serialize(true);

                    if (params) {
                        if (Object.isString(params)) params = params.toQueryParams();
                        Object.extend(options.parameters, params);
                    }

                    if (form.hasAttribute('method') && !options.method)
                        options.method = form.method;

                    return new Ajax.Request(action, options);
                }
            };

            /*--------------------------------------------------------------------------*/


            Form.Element = {
                focus: function (element) {
                    $(element).focus();
                    return element;
                },

                select: function (element) {
                    $(element).select();
                    return element;
                }
            };

            Form.Element.Methods = {

                serialize: function (element) {
                    element = $(element);
                    if (!element.disabled && element.name) {
                        var value = element.getValue();
                        if (value != undefined) {
                            var pair = {};
                            pair[element.name] = value;
                            return Object.toQueryString(pair);
                        }
                    }
                    return '';
                },

                getValue: function (element) {
                    element = $(element);
                    var method = element.tagName.toLowerCase();
                    return Form.Element.Serializers[method](element);
                },

                setValue: function (element, value) {
                    element = $(element);
                    var method = element.tagName.toLowerCase();
                    Form.Element.Serializers[method](element, value);
                    return element;
                },

                clear: function (element) {
                    $(element).value = '';
                    return element;
                },

                present: function (element) {
                    return $(element).value != '';
                },

                activate: function (element) {
                    element = $(element);
                    try {
                        element.focus();
                        if (element.select && (element.tagName.toLowerCase() != 'input' ||
                            !(/^(?:button|reset|submit)$/i.test(element.type))))
                            element.select();
                    } catch (e) { }
                    return element;
                },

                disable: function (element) {
                    element = $(element);
                    element.disabled = true;
                    return element;
                },

                enable: function (element) {
                    element = $(element);
                    element.disabled = false;
                    return element;
                }
            };

            /*--------------------------------------------------------------------------*/

            var Field = Form.Element;

            var $F = Form.Element.Methods.getValue;

            /*--------------------------------------------------------------------------*/

            Form.Element.Serializers = (function () {
                function input(element, value) {
                    switch (element.type.toLowerCase()) {
                        case 'checkbox':
                        case 'radio':
                            return inputSelector(element, value);
                        default:
                            return valueSelector(element, value);
                    }
                }

                function inputSelector(element, value) {
                    if (Object.isUndefined(value))
                        return element.checked ? element.value : null;
                    else element.checked = !!value;
                }

                function valueSelector(element, value) {
                    if (Object.isUndefined(value)) return element.value;
                    else element.value = value;
                }

                function select(element, value) {
                    if (Object.isUndefined(value))
                        return (element.type === 'select-one' ? selectOne : selectMany)(element);

                    var opt, currentValue, single = !Object.isArray(value);
                    for (var i = 0, length = element.length; i < length; i++) {
                        opt = element.options[i];
                        currentValue = this.optionValue(opt);
                        if (single) {
                            if (currentValue == value) {
                                opt.selected = true;
                                return;
                            }
                        }
                        else opt.selected = value.include(currentValue);
                    }
                }

                function selectOne(element) {
                    var index = element.selectedIndex;
                    return index >= 0 ? optionValue(element.options[index]) : null;
                }

                function selectMany(element) {
                    var values, length = element.length;
                    if (!length) return null;

                    for (var i = 0, values = []; i < length; i++) {
                        var opt = element.options[i];
                        if (opt.selected) values.push(optionValue(opt));
                    }
                    return values;
                }

                function optionValue(opt) {
                    return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
                }

                return {
                    input: input,
                    inputSelector: inputSelector,
                    textarea: valueSelector,
                    select: select,
                    selectOne: selectOne,
                    selectMany: selectMany,
                    optionValue: optionValue,
                    button: valueSelector
                };
            })();

            /*--------------------------------------------------------------------------*/


            Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
                initialize: function ($super, element, frequency, callback) {
                    $super(callback, frequency);
                    this.element = $(element);
                    this.lastValue = this.getValue();
                },

                execute: function () {
                    var value = this.getValue();
                    if (Object.isString(this.lastValue) && Object.isString(value) ?
                        this.lastValue != value : String(this.lastValue) != String(value)) {
                        this.callback(this.element, value);
                        this.lastValue = value;
                    }
                }
            });

            Form.Element.Observer = Class.create(Abstract.TimedObserver, {
                getValue: function () {
                    return Form.Element.getValue(this.element);
                }
            });

            Form.Observer = Class.create(Abstract.TimedObserver, {
                getValue: function () {
                    return Form.serialize(this.element);
                }
            });

            /*--------------------------------------------------------------------------*/

            Abstract.EventObserver = Class.create({
                initialize: function (element, callback) {
                    this.element = $(element);
                    this.callback = callback;

                    this.lastValue = this.getValue();
                    if (this.element.tagName.toLowerCase() == 'form')
                        this.registerFormCallbacks();
                    else
                        this.registerCallback(this.element);
                },

                onElementEvent: function () {
                    var value = this.getValue();
                    if (this.lastValue != value) {
                        this.callback(this.element, value);
                        this.lastValue = value;
                    }
                },

                registerFormCallbacks: function () {
                    Form.getElements(this.element).each(this.registerCallback, this);
                },

                registerCallback: function (element) {
                    if (element.type) {
                        switch (element.type.toLowerCase()) {
                            case 'checkbox':
                            case 'radio':
                                Event.observe(element, 'click', this.onElementEvent.bind(this));
                                break;
                            default:
                                Event.observe(element, 'change', this.onElementEvent.bind(this));
                                break;
                        }
                    }
                }
            });

            Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
                getValue: function () {
                    return Form.Element.getValue(this.element);
                }
            });

            Form.EventObserver = Class.create(Abstract.EventObserver, {
                getValue: function () {
                    return Form.serialize(this.element);
                }
            });
            (function (GLOBAL) {
                var DIV = document.createElement('div');
                var docEl = document.documentElement;
                var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
                 && 'onmouseleave' in docEl;

                var Event = {
                    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,
                    KEY_HOME: 36,
                    KEY_END: 35,
                    KEY_PAGEUP: 33,
                    KEY_PAGEDOWN: 34,
                    KEY_INSERT: 45
                };


                var isIELegacyEvent = function (event) { return false; };

                if (window.attachEvent) {
                    if (window.addEventListener) {
                        isIELegacyEvent = function (event) {
                            return !(event instanceof window.Event);
                        };
                    } else {
                        isIELegacyEvent = function (event) { return true; };
                    }
                }

                var _isButton;

                function _isButtonForDOMEvents(event, code) {
                    return event.which ? (event.which === code + 1) : (event.button === code);
                }

                var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
                function _isButtonForLegacyEvents(event, code) {
                    return event.button === legacyButtonMap[code];
                }

                function _isButtonForWebKit(event, code) {
                    switch (code) {
                        case 0: return event.which == 1 && !event.metaKey;
                        case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
                        case 2: return event.which == 3;
                        default: return false;
                    }
                }

                if (window.attachEvent) {
                    if (!window.addEventListener) {
                        _isButton = _isButtonForLegacyEvents;
                    } else {
                        _isButton = function (event, code) {
                            return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
                             _isButtonForDOMEvents(event, code);
                        }
                    }
                } else if (Prototype.Browser.WebKit) {
                    _isButton = _isButtonForWebKit;
                } else {
                    _isButton = _isButtonForDOMEvents;
                }

                function isLeftClick(event) { return _isButton(event, 0) }

                function isMiddleClick(event) { return _isButton(event, 1) }

                function isRightClick(event) { return _isButton(event, 2) }

                function element(event) {
                    return Element.extend(_element(event));
                }

                function _element(event) {
                    event = Event.extend(event);

                    var node = event.target, type = event.type,
                     currentTarget = event.currentTarget;

                    if (currentTarget && currentTarget.tagName) {
                        if (type === 'load' || type === 'error' ||
                          (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
                            && currentTarget.type === 'radio'))
                            node = currentTarget;
                    }

                    if (node.nodeType == Node.TEXT_NODE)
                        node = node.parentNode;

                    return Element.extend(node);
                }

                function findElement(event, expression) {
                    var element = _element(event), match = Prototype.Selector.match;
                    if (!expression) return Element.extend(element);
                    while (element) {
                        if (Object.isElement(element) && match(element, expression))
                            return Element.extend(element);
                        element = element.parentNode;
                    }
                }

                function pointer(event) {
                    return { x: pointerX(event), y: pointerY(event) };
                }

                function pointerX(event) {
                    var docElement = document.documentElement,
                     body = document.body || { scrollLeft: 0 };

                    return event.pageX || (event.clientX +
                      (docElement.scrollLeft || body.scrollLeft) -
                      (docElement.clientLeft || 0));
                }

                function pointerY(event) {
                    var docElement = document.documentElement,
                     body = document.body || { scrollTop: 0 };

                    return event.pageY || (event.clientY +
                       (docElement.scrollTop || body.scrollTop) -
                       (docElement.clientTop || 0));
                }


                function stop(event) {
                    Event.extend(event);
                    event.preventDefault();
                    event.stopPropagation();

                    event.stopped = true;
                }


                Event.Methods = {
                    isLeftClick: isLeftClick,
                    isMiddleClick: isMiddleClick,
                    isRightClick: isRightClick,

                    element: element,
                    findElement: findElement,

                    pointer: pointer,
                    pointerX: pointerX,
                    pointerY: pointerY,

                    stop: stop
                };

                var methods = Object.keys(Event.Methods).inject({}, function (m, name) {
                    m[name] = Event.Methods[name].methodize();
                    return m;
                });

                if (window.attachEvent) {
                    function _relatedTarget(event) {
                        var element;
                        switch (event.type) {
                            case 'mouseover':
                            case 'mouseenter':
                                element = event.fromElement;
                                break;
                            case 'mouseout':
                            case 'mouseleave':
                                element = event.toElement;
                                break;
                            default:
                                return null;
                        }
                        return Element.extend(element);
                    }

                    var additionalMethods = {
                        stopPropagation: function () { this.cancelBubble = true },
                        preventDefault: function () { this.returnValue = false },
                        inspect: function () { return '[object Event]' }
                    };

                    Event.extend = function (event, element) {
                        if (!event) return false;

                        if (!isIELegacyEvent(event)) return event;

                        if (event._extendedByPrototype) return event;
                        event._extendedByPrototype = Prototype.emptyFunction;

                        var pointer = Event.pointer(event);

                        Object.extend(event, {
                            target: event.srcElement || element,
                            relatedTarget: _relatedTarget(event),
                            pageX: pointer.x,
                            pageY: pointer.y
                        });

                        Object.extend(event, methods);
                        Object.extend(event, additionalMethods);

                        return event;
                    };
                } else {
                    Event.extend = Prototype.K;
                }

                if (window.addEventListener) {
                    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
                    Object.extend(Event.prototype, methods);
                }

                var EVENT_TRANSLATIONS = {
                    mouseenter: 'mouseover',
                    mouseleave: 'mouseout'
                };

                function getDOMEventName(eventName) {
                    return EVENT_TRANSLATIONS[eventName] || eventName;
                }

                if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)
                    getDOMEventName = Prototype.K;

                function getUniqueElementID(element) {
                    if (element === window) return 0;

                    if (typeof element._prototypeUID === 'undefined')
                        element._prototypeUID = Element.Storage.UID++;
                    return element._prototypeUID;
                }

                function getUniqueElementID_IE(element) {
                    if (element === window) return 0;
                    if (element == document) return 1;
                    return element.uniqueID;
                }

                if ('uniqueID' in DIV)
                    getUniqueElementID = getUniqueElementID_IE;

                function isCustomEvent(eventName) {
                    return eventName.include(':');
                }

                Event._isCustomEvent = isCustomEvent;

                function getRegistryForElement(element, uid) {
                    var CACHE = GLOBAL.Event.cache;
                    if (Object.isUndefined(uid))
                        uid = getUniqueElementID(element);
                    if (!CACHE[uid]) CACHE[uid] = { element: element };
                    return CACHE[uid];
                }

                function destroyRegistryForElement(element, uid) {
                    if (Object.isUndefined(uid))
                        uid = getUniqueElementID(element);
                    delete GLOBAL.Event.cache[uid];
                }


                function register(element, eventName, handler) {
                    var registry = getRegistryForElement(element);
                    if (!registry[eventName]) registry[eventName] = [];
                    var entries = registry[eventName];

                    var i = entries.length;
                    while (i--)
                        if (entries[i].handler === handler) return null;

                    var uid = getUniqueElementID(element);
                    var responder = GLOBAL.Event._createResponder(uid, eventName, handler);
                    var entry = {
                        responder: responder,
                        handler: handler
                    };

                    entries.push(entry);
                    return entry;
                }

                function unregister(element, eventName, handler) {
                    var registry = getRegistryForElement(element);
                    var entries = registry[eventName];
                    if (!entries) return;

                    var i = entries.length, entry;
                    while (i--) {
                        if (entries[i].handler === handler) {
                            entry = entries[i];
                            break;
                        }
                    }

                    if (!entry) return;

                    var index = entries.indexOf(entry);
                    entries.splice(index, 1);

                    return entry;
                }


                function observe(element, eventName, handler) {
                    element = $(element);
                    var entry = register(element, eventName, handler);

                    if (entry === null) return element;

                    var responder = entry.responder;
                    if (isCustomEvent(eventName))
                        observeCustomEvent(element, eventName, responder);
                    else
                        observeStandardEvent(element, eventName, responder);

                    return element;
                }

                function observeStandardEvent(element, eventName, responder) {
                    var actualEventName = getDOMEventName(eventName);
                    if (element.addEventListener) {
                        element.addEventListener(actualEventName, responder, false);
                    } else {
                        element.attachEvent('on' + actualEventName, responder);
                    }
                }

                function observeCustomEvent(element, eventName, responder) {
                    if (element.addEventListener) {
                        element.addEventListener('dataavailable', responder, false);
                    } else {
                        element.attachEvent('ondataavailable', responder);
                        element.attachEvent('onlosecapture', responder);
                    }
                }

                function stopObserving(element, eventName, handler) {
                    element = $(element);
                    var handlerGiven = !Object.isUndefined(handler),
                     eventNameGiven = !Object.isUndefined(eventName);

                    if (!eventNameGiven && !handlerGiven) {
                        stopObservingElement(element);
                        return element;
                    }

                    if (!handlerGiven) {
                        stopObservingEventName(element, eventName);
                        return element;
                    }

                    var entry = unregister(element, eventName, handler);

                    if (!entry) return element;
                    removeEvent(element, eventName, entry.responder);
                    return element;
                }

                function stopObservingStandardEvent(element, eventName, responder) {
                    var actualEventName = getDOMEventName(eventName);
                    if (element.removeEventListener) {
                        element.removeEventListener(actualEventName, responder, false);
                    } else {
                        element.detachEvent('on' + actualEventName, responder);
                    }
                }

                function stopObservingCustomEvent(element, eventName, responder) {
                    if (element.removeEventListener) {
                        element.removeEventListener('dataavailable', responder, false);
                    } else {
                        element.detachEvent('ondataavailable', responder);
                        element.detachEvent('onlosecapture', responder);
                    }
                }



                function stopObservingElement(element) {
                    var uid = getUniqueElementID(element),
                     registry = getRegistryForElement(element, uid);

                    destroyRegistryForElement(element, uid);

                    var entries, i;
                    for (var eventName in registry) {
                        if (eventName === 'element') continue;

                        entries = registry[eventName];
                        i = entries.length;
                        while (i--)
                            removeEvent(element, eventName, entries[i].responder);
                    }
                }

                function stopObservingEventName(element, eventName) {
                    var registry = getRegistryForElement(element);
                    var entries = registry[eventName];
                    if (!entries) return;
                    delete registry[eventName];

                    var i = entries.length;
                    while (i--)
                        removeEvent(element, eventName, entries[i].responder);
                }


                function removeEvent(element, eventName, handler) {
                    if (isCustomEvent(eventName))
                        stopObservingCustomEvent(element, eventName, handler);
                    else
                        stopObservingStandardEvent(element, eventName, handler);
                }



                function getFireTarget(element) {
                    if (element !== document) return element;
                    if (document.createEvent && !element.dispatchEvent)
                        return document.documentElement;
                    return element;
                }

                function fire(element, eventName, memo, bubble) {
                    element = getFireTarget($(element));
                    if (Object.isUndefined(bubble)) bubble = true;
                    memo = memo || {};

                    var event = fireEvent(element, eventName, memo, bubble);
                    return Event.extend(event);
                }

                function fireEvent_DOM(element, eventName, memo, bubble) {
                    var event = document.createEvent('HTMLEvents');
                    event.initEvent('dataavailable', bubble, true);

                    event.eventName = eventName;
                    event.memo = memo;

                    element.dispatchEvent(event);
                    return event;
                }

                function fireEvent_IE(element, eventName, memo, bubble) {
                    var event = document.createEventObject();
                    event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';

                    event.eventName = eventName;
                    event.memo = memo;

                    element.fireEvent(event.eventType, event);
                    return event;
                }

                var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;



                Event.Handler = Class.create({
                    initialize: function (element, eventName, selector, callback) {
                        this.element = $(element);
                        this.eventName = eventName;
                        this.selector = selector;
                        this.callback = callback;
                        this.handler = this.handleEvent.bind(this);
                    },


                    start: function () {
                        Event.observe(this.element, this.eventName, this.handler);
                        return this;
                    },

                    stop: function () {
                        Event.stopObserving(this.element, this.eventName, this.handler);
                        return this;
                    },

                    handleEvent: function (event) {
                        var element = Event.findElement(event, this.selector);
                        if (element) this.callback.call(this.element, event, element);
                    }
                });

                function on(element, eventName, selector, callback) {
                    element = $(element);
                    if (Object.isFunction(selector) && Object.isUndefined(callback)) {
                        callback = selector, selector = null;
                    }

                    return new Event.Handler(element, eventName, selector, callback).start();
                }

                Object.extend(Event, Event.Methods);

                Object.extend(Event, {
                    fire: fire,
                    observe: observe,
                    stopObserving: stopObserving,
                    on: on
                });

                Element.addMethods({
                    fire: fire,

                    observe: observe,

                    stopObserving: stopObserving,

                    on: on
                });

                Object.extend(document, {
                    fire: fire.methodize(),

                    observe: observe.methodize(),

                    stopObserving: stopObserving.methodize(),

                    on: on.methodize(),

                    loaded: false
                });

                if (GLOBAL.Event) Object.extend(window.Event, Event);
                else GLOBAL.Event = Event;

                GLOBAL.Event.cache = {};

                function destroyCache_IE() {
                    GLOBAL.Event.cache = null;
                }

                if (window.attachEvent)
                    window.attachEvent('onunload', destroyCache_IE);

                DIV = null;
                docEl = null;
            })(this);

            (function (GLOBAL) {
                /* Code for creating leak-free event responders is based on work by
                 John-David Dalton. */

                var docEl = document.documentElement;
                var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
                  && 'onmouseleave' in docEl;

                function isSimulatedMouseEnterLeaveEvent(eventName) {
                    return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
                     (eventName === 'mouseenter' || eventName === 'mouseleave');
                }

                function createResponder(uid, eventName, handler) {
                    if (Event._isCustomEvent(eventName))
                        return createResponderForCustomEvent(uid, eventName, handler);
                    if (isSimulatedMouseEnterLeaveEvent(eventName))
                        return createMouseEnterLeaveResponder(uid, eventName, handler);

                    return function (event) {
                        var cacheEntry = Event.cache[uid];
                        var element = cacheEntry.element;

                        Event.extend(event, element);
                        handler.call(element, event);
                    };
                }

                function createResponderForCustomEvent(uid, eventName, handler) {
                    return function (event) {
                        var cacheEntry = Event.cache[uid], element = cacheEntry.element;

                        if (Object.isUndefined(event.eventName))
                            return false;

                        if (event.eventName !== eventName)
                            return false;

                        Event.extend(event, element);
                        handler.call(element, event);
                    };
                }

                function createMouseEnterLeaveResponder(uid, eventName, handler) {
                    return function (event) {
                        var cacheEntry = Event.cache[uid], element = cacheEntry.element;

                        Event.extend(event, element);
                        var parent = event.relatedTarget;

                        while (parent && parent !== element) {
                            try { parent = parent.parentNode; }
                            catch (e) { parent = element; }
                        }

                        if (parent === element) return;
                        handler.call(element, event);
                    }
                }

                GLOBAL.Event._createResponder = createResponder;
                docEl = null;
            })(this);

            (function (GLOBAL) {
                /* Support for the DOMContentLoaded event is based on work by Dan Webb,
                   Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */

                var TIMER;

                function fireContentLoadedEvent() {
                    if (document.loaded) return;
                    if (TIMER) window.clearTimeout(TIMER);
                    document.loaded = true;
                    document.fire('dom:loaded');
                }

                function checkReadyState() {
                    if (document.readyState === 'complete') {
                        document.detachEvent('onreadystatechange', checkReadyState);
                        fireContentLoadedEvent();
                    }
                }

                function pollDoScroll() {
                    try {
                        document.documentElement.doScroll('left');
                    } catch (e) {
                        TIMER = pollDoScroll.defer();
                        return;
                    }

                    fireContentLoadedEvent();
                }

                if (document.addEventListener) {
                    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
                } else {
                    document.attachEvent('onreadystatechange', checkReadyState);
                    if (window == top) TIMER = pollDoScroll.defer();
                }

                Event.observe(window, 'load', fireContentLoadedEvent);
            })(this);


            Element.addMethods();
            /*------------------------------- DEPRECATED -------------------------------*/

            Hash.toQueryString = Object.toQueryString;

            var Toggle = { display: Element.toggle };

            Element.Methods.childOf = Element.Methods.descendantOf;

            var Insertion = {
                Before: function (element, content) {
                    return Element.insert(element, { before: content });
                },

                Top: function (element, content) {
                    return Element.insert(element, { top: content });
                },

                Bottom: function (element, content) {
                    return Element.insert(element, { bottom: content });
                },

                After: function (element, content) {
                    return Element.insert(element, { after: content });
                }
            };

            var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

            var Position = {
                includeScrollOffsets: false,

                prepare: function () {
                    this.deltaX = window.pageXOffset
                                || document.documentElement.scrollLeft
                                || document.body.scrollLeft
                                || 0;
                    this.deltaY = window.pageYOffset
                                || document.documentElement.scrollTop
                                || document.body.scrollTop
                                || 0;
                },

                within: function (element, x, y) {
                    if (this.includeScrollOffsets)
                        return this.withinIncludingScrolloffsets(element, x, y);
                    this.xcomp = x;
                    this.ycomp = y;
                    this.offset = Element.cumulativeOffset(element);

                    return (y >= this.offset[1] &&
                            y < this.offset[1] + element.offsetHeight &&
                            x >= this.offset[0] &&
                            x < this.offset[0] + element.offsetWidth);
                },

                withinIncludingScrolloffsets: function (element, x, y) {
                    var offsetcache = Element.cumulativeScrollOffset(element);

                    this.xcomp = x + offsetcache[0] - this.deltaX;
                    this.ycomp = y + offsetcache[1] - this.deltaY;
                    this.offset = Element.cumulativeOffset(element);

                    return (this.ycomp >= this.offset[1] &&
                            this.ycomp < this.offset[1] + element.offsetHeight &&
                            this.xcomp >= this.offset[0] &&
                            this.xcomp < this.offset[0] + element.offsetWidth);
                },

                overlap: function (mode, element) {
                    if (!mode) return 0;
                    if (mode == 'vertical')
                        return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
                          element.offsetHeight;
                    if (mode == 'horizontal')
                        return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
                          element.offsetWidth;
                },


                cumulativeOffset: Element.Methods.cumulativeOffset,

                positionedOffset: Element.Methods.positionedOffset,

                absolutize: function (element) {
                    Position.prepare();
                    return Element.absolutize(element);
                },

                relativize: function (element) {
                    Position.prepare();
                    return Element.relativize(element);
                },

                realOffset: Element.Methods.cumulativeScrollOffset,

                offsetParent: Element.Methods.getOffsetParent,

                page: Element.Methods.viewportOffset,

                clone: function (source, target, options) {
                    options = options || {};
                    return Element.clonePosition(target, source, options);
                }
            };

            /*--------------------------------------------------------------------------*/

            if (!document.getElementsByClassName) document.getElementsByClassName = function (instanceMethods) {
                function iter(name) {
                    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
                }

                instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
                function (element, className) {
                    className = className.toString().strip();
                    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
                    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
                } : function (element, className) {
                    className = className.toString().strip();
                    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
                    if (!classNames && !className) return elements;

                    var nodes = $(element).getElementsByTagName('*');
                    className = ' ' + className + ' ';

                    for (var i = 0, child, cn; child = nodes[i]; i++) {
                        if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
                            (classNames && classNames.all(function (name) {
                              return !name.toString().blank() && cn.include(' ' + name + ' ');
                        }))))
                            elements.push(Element.extend(child));
                    }
                    return elements;
                };

                return function (className, parentElement) {
                    return $(parentElement || document.body).getElementsByClassName(className);
                };
            }(Element.Methods);

            /*--------------------------------------------------------------------------*/

            Element.ClassNames = Class.create();
            Element.ClassNames.prototype = {
                initialize: function (element) {
                    this.element = $(element);
                },

                _each: function (iterator, context) {
                    this.element.className.split(/\s+/).select(function (name) {
                        return name.length > 0;
                    })._each(iterator, context);
                },

                set: function (className) {
                    this.element.className = className;
                },

                add: function (classNameToAdd) {
                    if (this.include(classNameToAdd)) return;
                    this.set($A(this).concat(classNameToAdd).join(' '));
                },

                remove: function (classNameToRemove) {
                    if (!this.include(classNameToRemove)) return;
                    this.set($A(this).without(classNameToRemove).join(' '));
                },

                toString: function () {
                    return $A(this).join(' ');
                }
            };

            Object.extend(Element.ClassNames.prototype, Enumerable);

            /*--------------------------------------------------------------------------*/

            (function () {


                


                window.Selector = Class.create({
                    initialize: function (expression) {
                        this.expression = expression.strip();
                    },

                    findElements: function (rootElement) {
                        return Prototype.Selector.select(this.expression, rootElement);
                    },

                    match: function (element) {
                        return Prototype.Selector.match(element, this.expression);
                    },

                    toString: function () {
                        return this.expression;
                    },

                    inspect: function () {
                        return "#<Selector: " + this.expression + ">";
                    }
                });

                Object.extend(Selector, {
                    matchElements: function (elements, expression) {
                        var match = Prototype.Selector.match,
                            results = [];

                        for (var i = 0, length = elements.length; i < length; i++) {
                            var element = elements[i];
                            if (match(element, expression)) {
                                results.push(Element.extend(element));
                            }
                        }
                        return results;
                    },

                    findElement: function (elements, expression, index) {
                        index = index || 0;
                        var matchIndex = 0, element;
                        for (var i = 0, length = elements.length; i < length; i++) {
                            element = elements[i];
                            if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
                                return Element.extend(element);
                            }
                        }
                    },

                    findChildElements: function (element, expressions) {
                        var selector = expressions.toArray().join(', ');
                        return Prototype.Selector.select(selector, element || document);
                    }
                });
            })();

        </script>

        
        <script>
            /**
 * File last updated 4/22/2016
 * 
 *
 * Notes: kilowatthours = National non-baseload /1000 * 0.00045359237
 
 * 4/22/2016:
 
--Conversion,	Old Factor,	New Factor--
Electricty use (kilowatt-hours)	0.000689551	0.000702776
Gallons of gasoline consumed	0.008887	0.008887
Passenger vehicles per year	4.75	 4.73 
Therms of natural gas	0.005302	0.005302
MCF of natural gas	NA	0.054717
Barrels of oil consumed	0.43	0.43
Tanker trucks filled with gasoline	75.54	75.540
Home electricity use	7.270	6.852
Home energy use	10.97	9.547
Numer of tree seedlings grown for 10 years	0.039	 0.04 
Acres of U.S. forests storing carbon for one year	1.22	 1.06 
Acres of U.S. forest preserved from conversion to cropland	129.51	 125.46 
Propane cyclinders used for home barbeques	0.024	0.024
Railcars of coal burned	186.5	187.8
Tons of waste recycled instead of landfilled	2.79	3.15
Coal-fired power plant emissions for one year	 3,808,651 	 3,435,618 
Pounds of coal burned	0.000931	0.000937
Miles driven by the average passenger vehicle per year	0.000420	0.000417
Number of garbage trucks of waste recycled instead of landfilled	19.51	 22.06 
Number of wind turbines installed 	 3,633 	 3,960 
Number of incandescent bulbs switched to compact fluorescent bulbs	0.03823	0.03946
Number of incandescent bulbs switched to LEDs	NA	0.02854

 *
 * 4/16/2014: Changed electricity constant from 0.00068927 to 0.000689551, changed wind turbines constant from 3,631 to 3,633.
 *
 * 9/17/2013: Changed conversion factor for home electricity from 6.68 to 7.268 metric tons of CO2. Changed home energy use from 19.43 to 20.02 metric tons of CO2.
 * 
 * 04/24/2013:
 *  Changed the conversion factor for natural gas to be more precise, from 0.005 metric tons of CO2 per therm to 0.005306
 * 
 * 10/4/2012:
 *  Changed electricity use (kilowatt-hours) from 0.0006895556567977 to 0.00070555 metric tons CO2 per kWh
 *  Changed passenger vehicles per year from 5.1 to 4.8 metric tons CO2e per vehicle per year
 *  Changed home electricity use from 8.02 to 6.68 metric tons CO2 per home
 *  Changed home energy use from 11.55 to 19.43 metric tons CO2 per home per year
 *  Changed acres of U.S. forests storing carbon for one year from 4.69 to
 *   1.22 metric ton CO2 sequestered annually by one acre of average U.S. forest
 *  Changed acres of U.S. forests preserved from conversion to cropland from 100.94 to
 *   129.51 metric tons CO2 per acre per year
 *  Changed railcars of coal burned from 183.65 to 232.74 metric tons CO2 per railcar
 *  Changed tons of waste recycled instead of landfilled from 2.87 to
 *   2.67 metric tons CO2e per ton of waste recycled instead of landfilled
 *  Changed coal-fired power plant emissions for one year from 4,220,543 to 3,533,098 metric tons CO2 per power plant
 * 
 * 10/31/2011:
 *  Household energy use from 11.53 to 11.55 
 *
 * 5/25/2011:
 *  Household energy use from 11.77 to 11.53
 *  Household electricity use for one year (# of households) from 8.24 to 8.02
 * 
 * 5/18/2011:
 *  Changed electricity use (kilowatt-hours) from 0.0006895102975607 to 0.0006895556567977 metric tons CO2 per kWh
 *
 * 4/14/2011:
 *  Changed electricity use (kilowatt-hours) from 7.18 x 10-4 to 6.8951 x 10-4 metric tons CO2 per kWh
 *
 * 2/21/2011:
 *  Changed electricity use (kilowatt-hours) from 7.18 x 10-4 to 6.91 x 10-4 metric tons CO2 per kWh
 *  Changed passenger vehicles per year from 5.23 to 5.1 metric tons CO2e per vehicle per year
 *  Changed gallons of gasoline consumed from 8.89 x 10^-3 to 8.92 x 10^-3 metric tons CO2 per gallon of gasoline
 *  Changed tanker trucks filled with gasoline from 74.89 to 75.82 metric tons Co2 per tanker truck
 *  Changed home energy use from 11.75 to 11.77 metric tons CO2 per home
 *  Changed acres of forest carbon preserved from avoided deforestation from 105.38 to 100.94 metric tons CO2 per acre converted
 *  Changed railcars of coal burned from 191.5 to 183.65 metric tons CO2 per railcar
 *  Changed tons of waste recycled instead of landfilled from 2.97 to
 *   2.87 metric tons CO2e per ton of waste recycled instead of landfilled
 *  Changed coal-fired power plant emissions for one year from 3,850,479 to 4,220,543 metric tons CO2 per power plant
 *
 * 3/07/2010:
 *  Changed Propane cylinders used for home barbeques from 0.054 to 0.024 
 *  Changed Household electricity use from 7.7 to 8.24
 *  Changed Household energy use from 11.21 to 11.75
 *  
 * 11/05/2009:
 *  Passenger vehicles per year: 5.23 (was 5.46)
 *  Gallons of gasoline consumed: 8.89 x 10-3 (was 8.81)
 *  Tanker trucks filled with gasoline: 74.89 (was 74.88)
 *  Home electricity use: 7.70 (was 7.21)
 *  Home energy use: 11.21 (was 10.99)
 *  Acres of pine or fir forests storing carbon for one year: 4.69 (was 4.4)
 *  Acres of forest preserved from deforestation: 105.38 (was 143.37)
 *  Propane cylinders used for home barbeques: 0.054 (was 0.024)
 *  Tons of waste recycled instead of landfilled: 2.97 (was 2.90)
 *  Coal-fired power plant emissions for one year: 3,850,479 (was 4,643,734)
 *  
 * 2/12/2009:
 *  Values are from the formulae, please click the question mark besides each item on the html page to find it
 *  Household electricity use for one year (# of households): change from 7.55 to 7.21
 *  Household energy use: change from 11.33 to 10.99
 *  
 */

            var EquivCalc = {};

            // Factors for converting co2,ch4,n2o,hfc,pfc,sf6,and carb to Carbon Dioxide Equivalent
            EquivCalc.conv_factors = new Hash({
                'co2': 1,
                'ch4': 25,
                'n2o': 298,
                'hfc': 14800,
                'pfc': 7390,
                'sf6': 22800,
                'carb': 44 / 12
            });

            EquivCalc.starting_points_factors = {
                "gasoline": 0.008887,
                "kilowatthours": 0.000702776,
                "therms": 0.005302,
                "MCF": 0.05471664,
                "vehicles":  4.734096
            };

            /*
                equivalency factors; 
                i.e. 	4.62 metric ton of Carbon Dioxide Equivalent = 1 car off the road for one year
            */
            EquivCalc.equiv_factors = [
                4.734096,		// Passenger cars not driven for one year
                9.47,		// Household energy use
                0.008887,	// Gallons of gasoline
                0.431926,		// Barrels of oil
                75.5395,		// Tanker trucks filled with gasoline
                6.772,		// Household electricity use for one year (# of households)
                0.0385859869,		// Number of tree seedlings grown for 10 years
                1.0564076752,		// Acres of U.S. forests storing carbon for 1 year
                125.4594641513,		// Acres of U.S. forests preserved from conversion to cropland
                0.024462013,		// Propane cylinders used for home barbeques
                187.7771730923,		// Coal burned/railcars of coal
                3.1510348008,		// Tons of waste recycled instead of landfilled 
                3435617.88125493,	// coal fired power plant for one year
                0.0009371236,	// Pounds of coal burned
                0.0004172481,	// Miles driven by the average passenger vehicle per year
                22.0572436054,		// Number of garbage trucks of waste recycled instead of landfilled
                3959.7436658017,		// Number of wind turbines installed
                0.02821 	// Number of incandescent bulbs switched to LEDs
            ];

            EquivCalc.multiples = [0.9071847, 0.00045359237, 1, 0.001]; //multiples for converting into metric tons
            // The order is: Tons, Pounds, Metric Tons, Kilograms
            // 1 ton [metric] = 1.1023113 ton [short]
            // 1 ton [short] = 907.18474 kilogram
            // 1 ton [metric] = 2,204.6226218 pound
            // 1 ton [short] = 2,000 pound
            EquivCalc.finalResultUnits = 2; // the default units for displaying the result is in Metric Tons

            EquivCalc.setConvFactors = function (e) {
                var targetSelect = Event.element(e);
                var chemName = targetSelect.name.substring(0, 3);
                var chemValue = $F($('conversion_table')[chemName]);
                this.conv_factors.set(chemName, parseFloat($F(targetSelect)));
                if (chemValue != "" && $F($('conversion_table')['y0']) != "") this.calculateTotal();
            }

            EquivCalc.calculateTotal = function (e) {   //alert(this.finalResultUnits)
                if (e) Event.stop(e);
                var total = 0; // variable holding the total greenhouse gas reduction
                var error_flag = "No GHG values have been entered"; // variable holding the appropriate error message
                this.conv_factors.each(function (pair) {
                    var name = pair.key;
                    var value = EquivCalc.stripCommas($F($('conversion_table')[name]));
                    if (value != "" && !isNaN(value)) {
                        value = value * pair.value; // convert to Carbon Dioxide Equivalent
                        value = parseFloat(EquivCalc.convertToTons(name, value)); // convert to Metric Tons
                        total += value;
                        error_flag = "";
                    } else if (value != "" && isNaN(value)) {
                        $('conversion_table')[name].focus();
                        $('conversion_table')[name].select();
                        error_flag = "<span class=\"calculator-warning\">Please enter a valid numerical value.</span>";
                        return;
                    }
                });

                if (error_flag == "") {
                    this.clearErrs();
                    $('output').show();
                    $('conversion_table')['y0'].value = this.commaSplit(this.roundIt(total / this.multiples[this.finalResultUnits]));
                    $('conversion_table').resultUnits[this.finalResultUnits].selected = true;
                    window.location.href = "#results";
                    for (i = 1; i <= this.equiv_factors.length; i++) {
                        var fieldName = "y" + i;
                        $('conversion_table')[fieldName].value = this.commaSplit(this.roundIt(total / this.equiv_factors[i - 1]));
                    }
                }
                else {
                    this.convErr(error_flag);
                }

            }

            EquivCalc.setResultUnits = function () {   //alert("set result units")
                this.finalResultUnits = parseFloat($F($('conversion_table')['resultUnits']));
                //alert($F($('starting_points')['equivalency']))
                if ($F($('conversion_table')['y0']) != "")  //this.calculateTotalV2();
                {
                    if ($F($('starting_points')['equivalency']) != "") {
                        this.calculateTotalV2();
                    }

                    if ($F($('starting_points')['equivalency']) == "") {
                        this.calculateTotal();
                    }
                }
            }

            EquivCalc.convertToTons = function (name, value) {
                var factor = $F($('conversion_table')[name + "units"]);
                return (value * this.multiples[factor]);
            }

            EquivCalc.roundIt = function (number) {
                // this function rounds according to the following rules:
                // - If the figure is above 100 it rounds to a whole number.
                // - If the figure is between 1 and 100, it rounds to one decimal place.
                // - If the figure is between 0.001 and 1, it rounds to three decimal places.
                // - If the figure is less than 0.001, it rounds to four decimal places.

                var absolute = Math.abs(number);
                if (isNaN(number) || number == 0) {
                    return number;
                }
                else {
                    // If the result is above 100 let's just use a whole number. 
                    if (absolute > 100) {
                        number = Math.round(number);
                    }
                        // If it's lower than 100 but greater than 1, let's show it out to one decimal place (e.g., 10.1).
                    else if ((absolute < 100) && (absolute > 1)) {
                        number = Math.round(number * 10) / 10;
                    }
                        // If it's below zero, let's show it out to two decimal places for numbers up to 1/100 (e.g., 0.95, or 0.09)
                        // (Note: at the request of the client, changed this part of the rounding rule to round to 3 decimal places)
                    else if ((absolute < 1) && (absolute > 0.001)) {
                        //number = Math.round(number * 100) / 100;
                        number = Math.round(number * 1000) / 1000;
                    }
                        //  and out to four decimal places for numbers smaller than that (e.g., 0.0097, 0.0030).
                    else {
                        number = Math.round(number * 10000) / 10000;
                    }
                    return number;
                }
            }

            EquivCalc.stripCommas = function (str) {
                var commaFilter = /,/g;
                return str.replace(commaFilter, "");
            }

            EquivCalc.commaSplit = function (srcNumber) {
                var txtNumber = new String(srcNumber);

                if (isNaN(srcNumber) || txtNumber == "") {
                    return srcNumber;
                }
                else {
                    var rxSplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])');
                    var arrNumber = txtNumber.split('.');
                    arrNumber[0] += '.';
                    do {
                        arrNumber[0] = arrNumber[0].replace(rxSplit, '$1,$2');
                    } while (rxSplit.test(arrNumber[0]));

                    if (arrNumber.length > 1) {
                        return arrNumber.join('');
                    }
                    else {
                        return arrNumber[0].split('.')[0];
                    }
                }
            }

            EquivCalc.handleStartingPoints = function (e) {
                Event.stop(e);
                var typeChoice = $('starting_points')['equiv_type']
                var eType = $F(typeChoice);
                if (eType != "") {
                    var userValue = 0;
                    userValue = this.stripCommas($F($('starting_points')['equivalency']));
                    if (userValue == "" || isNaN(userValue)) {
                        
                        var typeString = typeChoice.options[typeChoice.selectedIndex].innerHTML;
                        this.startErr("<span class=\"calculator-warning\">Please enter a valid numerical value.</span> " + typeString + ".");
                        alert("Please enter a valid numerical value.");
                        return false;
                    }
                    this.clearErrs();

                    var CO2equiv = userValue * EquivCalc.starting_points_factors[eType];

                    var form = $('conversion_table');
                    form.reset();
                    form.co2.value = CO2equiv; // set the value for CO2
                    form.co2units[2].selected = true; // select metric tons
                    this.calculateTotal(); // run the calculator
                    form.co2.value = this.commaSplit(this.roundIt(CO2equiv)); // round the value for CO2
                }
                else
                    {
                        
                    alert("Please choose a unit.");
                    }
            }


            EquivCalc.handleStartingPoints2 = function (e) {
                var typeChoice = $('starting_points')['equiv_type']
                var eType = $F(typeChoice);
                if (eType != "") {
                    var userValue = 0;
                    userValue = this.stripCommas($F($('starting_points')['equivalency']));
                    if (userValue == "" || isNaN(userValue)) {
                        var typeString = typeChoice.options[typeChoice.selectedIndex].innerHTML;
                        this.startErr("<span class=\"calculator-warning\">Please enter a valid numerical value.</span> " + typeString + ".");
                        return false;
                    }
                    this.clearErrs();

                    var CO2equiv = userValue * EquivCalc.starting_points_factors[eType];

                    var form = $('conversion_table');
                    form.reset();
                    form.co2.value = CO2equiv; // set the value for CO2
                    form.co2units[2].selected = true; // select metric tons

                    this.calculateTotal(); // run the calculator
                    form.co2.value = this.commaSplit(this.roundIt(CO2equiv)); // round the value for CO2
                }
            }

            EquivCalc.handleCalcsAndRefs = function (e) {
                var eType = $F($('starting_points')['equiv_type']);
                if (eType != "") {
                    this.href = "https://wcms.epa.gov/energy/ghg-equivalencies-calculator-calculations-and-references #" + eType;
                }
                else {
                    Event.stop(e);
                }
            }

            EquivCalc.startErr = function (errorMessage) {
                $('startError').update(errorMessage);
            }

            EquivCalc.convErr = function (errorMessage) {
                $('convError').update(errorMessage);
            }

            EquivCalc.clearErrs = function () {
                $('convError').update("");
                $('startError').update("");
            }

            document.observe("dom:loaded", function () {
                $$('#starting_points a')[0].observe('click', EquivCalc.handleCalcsAndRefs);
                $('starting_points').observe('submit', EquivCalc.handleStartingPoints.bindAsEventListener(EquivCalc));
                $('conversion_table').observe('submit', EquivCalc.calculateTotal.bindAsEventListener(EquivCalc));
                $('conversion_table').observe('reset', EquivCalc.clearErrs);
                $($('conversion_table')['resultUnits']).observe('change', EquivCalc.setResultUnits.bindAsEventListener(EquivCalc));
                $($('conversion_table')['hfcoptions']).observe('change', EquivCalc.setConvFactors.bindAsEventListener(EquivCalc));
                $($('conversion_table')['pfcoptions']).observe('change', EquivCalc.setConvFactors.bindAsEventListener(EquivCalc));
            });


            EquivCalc.calculateTotalV2 = function (e) {
                this.handleStartingPoints2(); // run the calculator	
            }
        </script>
        
        
     
        <script type="text/javascript" src="https://www3.epa.gov/epafiles/js/epa-core.js"></script>
        <script type="text/javascript" src="https://www3.epa.gov/epafiles/js/extra.js"></script>
	</body>
</html>